From cc47ed6ddebfece0584ad7ee706549614d16c0f0 Mon Sep 17 00:00:00 2001 From: CoprDistGit Date: Tue, 17 Oct 2023 02:15:03 +0000 Subject: automatic import of gcc --- .gitignore | 1 + ...libquadmath-Enable-libquadmath-on-kunpeng.patch | 473 + ...elim-Extend-to-check-non-trapping-for-mor.patch | 318 + 0003-version-Set-version-to-10.3.1.patch | 31 + ...ee-optimization-Avoid-issueing-loads-in-S.patch | 138 + ...-tree-optimization-Fix-load-eliding-in-SM.patch | 66 + 0006-simdmath-Enable-simdmath-on-kunpeng.patch | 289 + ...-skipping-vectorization-on-reduction-chai.patch | 68 + ...ee-optimization-Add-checks-to-avoid-spoil.patch | 97 + ...pand-Simplify-removing-subregs-when-expan.patch | 141 + ...ee-optimization-94963-avoid-bogus-uninit-.patch | 98 + ...able-64-bits-simd-when-test-simd_pcs_attr.patch | 23 + 0012-fp-model-Enable-fp-model-on-kunpeng.patch | 397 + ...m-Redundant-loop-elimination-optimization.patch | 499 + ...ructReorg-Structure-reorganization-optimi.patch | 5966 +++++ ...uctReorg-Complete-Structure-Reorganizatio.patch | 2134 ++ 0016-StructReorg-Bugfix-in-certain-scenarios.patch | 486 + ...-mcmodel-Enable-mcmodel-medium-on-kunpeng.patch | 622 + ...uctReorderFields-Structure-reorder-fields.patch | 5370 +++++ ...rderFields-Fix-bugs-and-improve-mechanism.patch | 296 + ...ct-Fix-an-ICE-in-vect_recog_mask_conversi.patch | 128 + ...-mcmodel-Bugfix-for-mcmodel-medium-on-x86.patch | 23 + ...ReorderFields-Fix-pointer-layer-check-bug.patch | 167 + ...uctReorderFields-Add-pointer-offset-check.patch | 87 + ...rderFields-Add-lto-and-whole-program-gate.patch | 90 + ...AutoPrefetch-Support-cache-misses-profile.patch | 669 + ...ble-discriminator-and-MCF-algorithm-on-Au.patch | 353 + ...toprefetch-Support-auto-feedback-prefetch.patch | 1000 + ...h-Handle-the-case-that-the-basic-block-br.patch | 151 + ...pport-saving-feedback-count-info-to-ELF-s.patch | 548 + 0030-AutoBOLT-Add-bolt-linker-plugin-2-3.patch | 21748 +++++++++++++++++++ ...-Enable-BOLT-linker-plugin-on-aarch64-3-3.patch | 1945 ++ ...h-Prune-invaild-loops-containing-edges-wh.patch | 82 + ...-memory-leaks-in-autofdo-and-autoprefetch.patch | 130 + ...nitizer-Fix-asan-against-glibc-2.34-PR100.patch | 72 + ...other-optimization-opportunity-for-ccmp-i.patch | 342 + ...-Refactoring-reorder-fields-to-struct-lay.patch | 1115 + ...dd-Dead-Field-Elimination-in-Struct-Reorg.patch | 902 + ...a-sra-Fix-thinko-when-overriding-safe_to_.patch | 143 + ...cvt-Allow-constants-for-noce_convert_mult.patch | 59 + ...gister-sysroot-in-the-driver-switches-tab.patch | 40 + 0042-DFE-Fix-bugs.patch | 665 + 0045-Transposed-SLP-Enable-Transposed-SLP.patch | 3009 +++ ...ompare-Add-a-new-optimization-for-array-c.patch | 1982 ++ ...-Fix-the-bug-caused-by-inconsistent-types.patch | 379 + ...g-Type-simplify-limitation-when-in-struct.patch | 146 + 0049-build-Add-some-file-right-to-executable.patch | 21 + ...iopt-Optimize-x-1024-0-to-int-x-10-PR9769.patch | 186 + ...iopt-Fix-up-conditional_replacement-PR993.patch | 92 + ...iopt-Handle-bool-in-two_value_replacement.patch | 122 + ...iopt-Optimize-x-__builtin_clz-x-32-in-GIM.patch | 256 + ...iopt-Optimize-x-__builtin_clz-x-32-in-GIM.patch | 69 + ...phiopt-Optimize-x-0-y-y-to-x-31-y-PR96928.patch | 218 + ...ackport-phiopt-Optimize-x-y-cmp-z-PR94589.patch | 1067 + ...ckport-Add-support-for-__builtin_bswap128.patch | 253 + ...ee-optimization-95393-fold-MIN-MAX_EXPR-g.patch | 113 + ...d-a-couple-of-A-CST1-CST2-match-and-simpl.patch | 91 + ...rt-Optimize-x-0-y-y-to-x-31-y-in-match.pd.patch | 155 + ...place-conditional_replacement-with-match-.patch | 249 + ...low-match-and-simplified-phiopt-to-run-in.patch | 174 + ...prove-match_simplify_replacement-in-phi-o.patch | 259 + ...iopt-Use-gphi-phi-instead-of-gimple-phi-s.patch | 103 + ...t-Optimize-x-bswap-x-0-in-tree-ssa-phiopt.patch | 212 + ...ee-optimization-102880-make-PHI-OPT-recog.patch | 251 + ...ee-Add-vector_element_bits-_tree-PR94980-.patch | 250 + ...wer-VEC_COND_EXPR-into-internal-functions.patch | 1063 + ...mple-match-Add-a-gimple_extract_op-functi.patch | 379 + ...rch64-Fix-subs_compare_2.c-regression-PR1.patch | 1004 + ...ble-the-match-A-CST1-0-when-the-CST1-is-n.patch | 31 + ...g-Merge-struct_layout-pass-into-struct_re.patch | 1770 ++ ...A-B-op-CST-B-match-and-simplify-optimizat.patch | 89 + ...PROP-Fold-series-of-instructions-into-mul.patch | 130 + ...OP-Fold-series-of-instructions-into-umulh.patch | 105 + ...rg-Fix-speccpu2006-462-double-free-I60YUV.patch | 38 + ...rg-Add-Safe-Structure-Pointer-Compression.patch | 1193 + ...istribution-Add-isomorphic-stmts-analysis.patch | 1007 + ...ransfer-arrays-using-registers-between-lo.patch | 267 + ...g-Add-Unsafe-Structure-Pointer-Compressio.patch | 1061 + ...bution-Insert-temp-arrays-built-from-isom.patch | 826 + ...port-tree-optimization-102880-make-PHI-OP.patch | 206 + ...t-reorg-Add-struct-semi-relayout-optimize.patch | 1297 ++ ...-Disable-mull64-transformation-by-default.patch | 64 + ...distribution-Bugfix-for-loop-distribution.patch | 58 + ...-relayout-Bugfix-for-struct-semi-relayout.patch | 26 + ...ee-optimization-97238-fix-typo-causing-IC.patch | 55 + 0088-Backport-fix-typo-causing-ICE.patch | 25 + ...ysroot-option-as-validated-once-processed.patch | 30 + ...ngop-overflow-with-VLA-of-elements-larger.patch | 129 + ...hiopt2-Add-option-to-control-the-simplify.patch | 183 + ...or-the-code-to-avoid-depending-auto-featu.patch | 170 + ...org-Fix-escape_cast_another_ptr-check-bug.patch | 112 + ...x-zero-masking-for-vcvtps2ph-when-dest-op.patch | 172 + 0095-Struct-reorg-Fix-the-use-of-as_a.patch | 49 + ...math-Revert-Enable-libquadmath-on-kunpeng.patch | 474 + ...th-refactor-Enable-libquadmath-on-kunpeng.patch | 197 + 0098-AArch64-Rewrite-the-tsv110-option.patch | 114 + ...g-Add-escape-propagate-on-external-functi.patch | 258 + ...Add-fkernel-pgo-option-to-support-PGO-ker.patch | 46 + ...the-SPEC-.548-fluctuation-problem-revert-.patch | 26 + ...ng-moutline-atomics-improves-libgomp-perf.patch | 34 + ...ption-ftree-fold-phiopt-to-avoid-fail-NFC.patch | 143 + ...-local-frame-vars-in-shrink-wrapping-code.patch | 348 + 0105-aarch64-Avoid-a-use-of-callee_offset.patch | 72 + ...tly-handle-frames-with-no-saved-registers.patch | 47 + ...-Add-bytes_below_saved_regs-to-frame-info.patch | 232 + ...h64-Add-bytes_below_hard_fp-to-frame-info.patch | 83 + ...4-Tweak-aarch64_save-restore_callee_saves.patch | 220 + ...alculate-chain_offset-if-there-is-a-chain.patch | 43 + ...ename-locals_offset-to-bytes_above_locals.patch | 90 + ...ame-hard_fp_offset-to-bytes_above_hard_fp.patch | 147 + 0113-aarch64-Tweak-frame_size-comment.patch | 34 + ...e-reg_offset-from-the-bottom-of-the-frame.patch | 194 + ...-aarch64-Simplify-top-of-frame-allocation.patch | 54 + 0116-aarch64-Minor-initial-adjustment-tweak.patch | 37 + ...ch64-Tweak-stack-clash-boundary-condition.patch | 124 + ...rch64-Put-LR-save-probe-in-first-16-bytes.patch | 269 + ...-Simplif-yprobe-of-final-frame-allocation.patch | 98 + ...itly-record-probe-registers-in-frame-info.patch | 275 + ...ch64-Remove-below_hard_fp_saved_regs_size.patch | 158 + ...tack-smash-canary-protect-saved-registers.patch | 297 + cpp | 3 - gcc.spec | 3554 ++- sources | 1 + 123 files changed, 76208 insertions(+), 632 deletions(-) create mode 100644 0001-libquadmath-Enable-libquadmath-on-kunpeng.patch create mode 100644 0002-Backport-cselim-Extend-to-check-non-trapping-for-mor.patch create mode 100644 0003-version-Set-version-to-10.3.1.patch create mode 100644 0004-Backport-tree-optimization-Avoid-issueing-loads-in-S.patch create mode 100644 0005-Backport-tree-optimization-Fix-load-eliding-in-SM.patch create mode 100644 0006-simdmath-Enable-simdmath-on-kunpeng.patch create mode 100644 0007-Vect-Enable-skipping-vectorization-on-reduction-chai.patch create mode 100644 0008-Backport-tree-optimization-Add-checks-to-avoid-spoil.patch create mode 100644 0009-Backport-expand-Simplify-removing-subregs-when-expan.patch create mode 100644 0010-Backport-tree-optimization-94963-avoid-bogus-uninit-.patch create mode 100644 0011-simdmath-Enable-64-bits-simd-when-test-simd_pcs_attr.patch create mode 100644 0012-fp-model-Enable-fp-model-on-kunpeng.patch create mode 100644 0013-LoopElim-Redundant-loop-elimination-optimization.patch create mode 100644 0014-Backport-StructReorg-Structure-reorganization-optimi.patch create mode 100644 0015-CompleteStructReorg-Complete-Structure-Reorganizatio.patch create mode 100644 0016-StructReorg-Bugfix-in-certain-scenarios.patch create mode 100644 0017-mcmodel-Enable-mcmodel-medium-on-kunpeng.patch create mode 100644 0018-StructReorderFields-Structure-reorder-fields.patch create mode 100644 0019-StructReorderFields-Fix-bugs-and-improve-mechanism.patch create mode 100644 0020-Backport-vect-Fix-an-ICE-in-vect_recog_mask_conversi.patch create mode 100644 0021-mcmodel-Bugfix-for-mcmodel-medium-on-x86.patch create mode 100644 0022-StructReorderFields-Fix-pointer-layer-check-bug.patch create mode 100644 0023-StructReorderFields-Add-pointer-offset-check.patch create mode 100644 0024-StructReorderFields-Add-lto-and-whole-program-gate.patch create mode 100644 0025-AutoPrefetch-Support-cache-misses-profile.patch create mode 100644 0026-AutoFDO-Enable-discriminator-and-MCF-algorithm-on-Au.patch create mode 100644 0027-Autoprefetch-Support-auto-feedback-prefetch.patch create mode 100644 0028-AutoPrefetch-Handle-the-case-that-the-basic-block-br.patch create mode 100644 0029-AutoBOLT-Support-saving-feedback-count-info-to-ELF-s.patch create mode 100644 0030-AutoBOLT-Add-bolt-linker-plugin-2-3.patch create mode 100644 0031-AutoBOLT-Enable-BOLT-linker-plugin-on-aarch64-3-3.patch create mode 100644 0032-Autoprefetch-Prune-invaild-loops-containing-edges-wh.patch create mode 100644 0033-AutoFdo-Fix-memory-leaks-in-autofdo-and-autoprefetch.patch create mode 100644 0034-Backport-sanitizer-Fix-asan-against-glibc-2.34-PR100.patch create mode 100644 0035-ccmp-Add-another-optimization-opportunity-for-ccmp-i.patch create mode 100644 0036-StructReorg-Refactoring-reorder-fields-to-struct-lay.patch create mode 100644 0038-DFE-Add-Dead-Field-Elimination-in-Struct-Reorg.patch create mode 100644 0039-Backport-ipa-sra-Fix-thinko-when-overriding-safe_to_.patch create mode 100644 0040-Backport-ifcvt-Allow-constants-for-noce_convert_mult.patch create mode 100644 0041-Backport-Register-sysroot-in-the-driver-switches-tab.patch create mode 100644 0042-DFE-Fix-bugs.patch create mode 100644 0045-Transposed-SLP-Enable-Transposed-SLP.patch create mode 100644 0046-ArrayWidenCompare-Add-a-new-optimization-for-array-c.patch create mode 100644 0047-DFE-Fix-the-bug-caused-by-inconsistent-types.patch create mode 100644 0048-Struct-Reorg-Type-simplify-limitation-when-in-struct.patch create mode 100644 0049-build-Add-some-file-right-to-executable.patch create mode 100644 0050-Backport-phiopt-Optimize-x-1024-0-to-int-x-10-PR9769.patch create mode 100644 0051-Backport-phiopt-Fix-up-conditional_replacement-PR993.patch create mode 100644 0052-Backport-phiopt-Handle-bool-in-two_value_replacement.patch create mode 100644 0053-Backport-phiopt-Optimize-x-__builtin_clz-x-32-in-GIM.patch create mode 100644 0054-Backport-phiopt-Optimize-x-__builtin_clz-x-32-in-GIM.patch create mode 100644 0055-Backport-phiopt-Optimize-x-0-y-y-to-x-31-y-PR96928.patch create mode 100644 0056-Backport-phiopt-Optimize-x-y-cmp-z-PR94589.patch create mode 100644 0057-Backport-Add-support-for-__builtin_bswap128.patch create mode 100644 0058-Backport-tree-optimization-95393-fold-MIN-MAX_EXPR-g.patch create mode 100644 0059-Backport-Add-a-couple-of-A-CST1-CST2-match-and-simpl.patch create mode 100644 0060-Backport-Optimize-x-0-y-y-to-x-31-y-in-match.pd.patch create mode 100644 0061-Backport-Replace-conditional_replacement-with-match-.patch create mode 100644 0062-Backport-Allow-match-and-simplified-phiopt-to-run-in.patch create mode 100644 0063-Backport-Improve-match_simplify_replacement-in-phi-o.patch create mode 100644 0064-Backport-phiopt-Use-gphi-phi-instead-of-gimple-phi-s.patch create mode 100644 0065-Backport-Optimize-x-bswap-x-0-in-tree-ssa-phiopt.patch create mode 100644 0066-Backport-tree-optimization-102880-make-PHI-OPT-recog.patch create mode 100644 0067-Backport-tree-Add-vector_element_bits-_tree-PR94980-.patch create mode 100644 0068-Backport-Lower-VEC_COND_EXPR-into-internal-functions.patch create mode 100644 0069-Backport-gimple-match-Add-a-gimple_extract_op-functi.patch create mode 100644 0070-Backport-aarch64-Fix-subs_compare_2.c-regression-PR1.patch create mode 100644 0071-PHIOPT-Disable-the-match-A-CST1-0-when-the-CST1-is-n.patch create mode 100644 0072-Struct-Reorg-Merge-struct_layout-pass-into-struct_re.patch create mode 100644 0073-PHIOPT-Add-A-B-op-CST-B-match-and-simplify-optimizat.patch create mode 100644 0074-FORWPROP-Fold-series-of-instructions-into-mul.patch create mode 100644 0075-FORWPROP-Fold-series-of-instructions-into-umulh.patch create mode 100644 0076-Struct-Reorg-Fix-speccpu2006-462-double-free-I60YUV.patch create mode 100644 0077-Struct-Reorg-Add-Safe-Structure-Pointer-Compression.patch create mode 100644 0078-Loop-distribution-Add-isomorphic-stmts-analysis.patch create mode 100644 0079-loop-vect-Transfer-arrays-using-registers-between-lo.patch create mode 100644 0080-Struct-Reorg-Add-Unsafe-Structure-Pointer-Compressio.patch create mode 100644 0081-Loop-distribution-Insert-temp-arrays-built-from-isom.patch create mode 100644 0082-Revert-Backport-tree-optimization-102880-make-PHI-OP.patch create mode 100644 0083-Struct-reorg-Add-struct-semi-relayout-optimize.patch create mode 100644 0084-MULL64-Disable-mull64-transformation-by-default.patch create mode 100644 0085-loop-distribution-Bugfix-for-loop-distribution.patch create mode 100644 0086-semi-relayout-Bugfix-for-struct-semi-relayout.patch create mode 100644 0087-Backport-tree-optimization-97238-fix-typo-causing-IC.patch create mode 100644 0088-Backport-fix-typo-causing-ICE.patch create mode 100644 0089-State-sysroot-option-as-validated-once-processed.patch create mode 100644 0090-bogus-Wstringop-overflow-with-VLA-of-elements-larger.patch create mode 100644 0091-phiopt2-Add-option-to-control-the-simplify.patch create mode 100644 0092-gimple-Factor-the-code-to-avoid-depending-auto-featu.patch create mode 100644 0093-StructReorg-Fix-escape_cast_another_ptr-check-bug.patch create mode 100644 0094-Backport-Fix-zero-masking-for-vcvtps2ph-when-dest-op.patch create mode 100644 0095-Struct-reorg-Fix-the-use-of-as_a.patch create mode 100644 0096-libquadmath-Revert-Enable-libquadmath-on-kunpeng.patch create mode 100644 0097-libquadmath-refactor-Enable-libquadmath-on-kunpeng.patch create mode 100644 0098-AArch64-Rewrite-the-tsv110-option.patch create mode 100644 0099-Struct-Reorg-Add-escape-propagate-on-external-functi.patch create mode 100644 0100-PGO-kernel-Add-fkernel-pgo-option-to-support-PGO-ker.patch create mode 100644 0101-To-resolve-the-SPEC-.548-fluctuation-problem-revert-.patch create mode 100644 0102-GOMP-Enabling-moutline-atomics-improves-libgomp-perf.patch create mode 100644 0103-test-Add-option-ftree-fold-phiopt-to-avoid-fail-NFC.patch create mode 100644 0104-aarch64-Use-local-frame-vars-in-shrink-wrapping-code.patch create mode 100644 0105-aarch64-Avoid-a-use-of-callee_offset.patch create mode 100644 0106-aarch64-Explicitly-handle-frames-with-no-saved-registers.patch create mode 100644 0107-aarch64-Add-bytes_below_saved_regs-to-frame-info.patch create mode 100644 0108-aarch64-Add-bytes_below_hard_fp-to-frame-info.patch create mode 100644 0109-aarch64-Tweak-aarch64_save-restore_callee_saves.patch create mode 100644 0110-aarch64-Only-calculate-chain_offset-if-there-is-a-chain.patch create mode 100644 0111-aarch64-Rename-locals_offset-to-bytes_above_locals.patch create mode 100644 0112-aarch64-Rename-hard_fp_offset-to-bytes_above_hard_fp.patch create mode 100644 0113-aarch64-Tweak-frame_size-comment.patch create mode 100644 0114-aarch64-Measure-reg_offset-from-the-bottom-of-the-frame.patch create mode 100644 0115-aarch64-Simplify-top-of-frame-allocation.patch create mode 100644 0116-aarch64-Minor-initial-adjustment-tweak.patch create mode 100644 0117-aarch64-Tweak-stack-clash-boundary-condition.patch create mode 100644 0118-aarch64-Put-LR-save-probe-in-first-16-bytes.patch create mode 100644 0119-aarch64-Simplif-yprobe-of-final-frame-allocation.patch create mode 100644 0120-aarch64-Explicitly-record-probe-registers-in-frame-info.patch create mode 100644 0121-aarch64-Remove-below_hard_fp_saved_regs_size.patch create mode 100644 0122-aarch64-Make-stack-smash-canary-protect-saved-registers.patch delete mode 100644 cpp diff --git a/.gitignore b/.gitignore index e69de29..a496f53 100644 --- a/.gitignore +++ b/.gitignore @@ -0,0 +1 @@ +/gcc-10.3.0.tar.xz diff --git a/0001-libquadmath-Enable-libquadmath-on-kunpeng.patch b/0001-libquadmath-Enable-libquadmath-on-kunpeng.patch new file mode 100644 index 0000000..33dd94e --- /dev/null +++ b/0001-libquadmath-Enable-libquadmath-on-kunpeng.patch @@ -0,0 +1,473 @@ +From 85740d3cc56fda699beae689b5d73233d16097af Mon Sep 17 00:00:00 2001 +From: bule +Date: Thu, 8 Jul 2021 11:52:47 +0800 +Subject: [PATCH 01/13] [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. + +diff --git a/libquadmath/Makefile.in b/libquadmath/Makefile.in +index 8c011212258..66df9c922f8 100644 +--- a/libquadmath/Makefile.in ++++ b/libquadmath/Makefile.in +@@ -90,7 +90,7 @@ POST_UNINSTALL = : + build_triplet = @build@ + host_triplet = @host@ + target_triplet = @target@ +-@BUILD_LIBQUADMATH_FALSE@libquadmath_la_DEPENDENCIES = ++#libquadmath_la_DEPENDENCIES = + subdir = . + ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 + am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \ +@@ -147,68 +147,68 @@ am__installdirs = "$(DESTDIR)$(toolexeclibdir)" "$(DESTDIR)$(infodir)" \ + "$(DESTDIR)$(libsubincludedir)" + LTLIBRARIES = $(toolexeclib_LTLIBRARIES) + am__dirstamp = $(am__leading_dot)dirstamp +-@BUILD_LIBQUADMATH_TRUE@am_libquadmath_la_OBJECTS = math/x2y2m1q.lo \ +-@BUILD_LIBQUADMATH_TRUE@ math/acoshq.lo math/fmodq.lo \ +-@BUILD_LIBQUADMATH_TRUE@ math/acosq.lo math/frexpq.lo \ +-@BUILD_LIBQUADMATH_TRUE@ math/rem_pio2q.lo math/asinhq.lo \ +-@BUILD_LIBQUADMATH_TRUE@ math/hypotq.lo math/remainderq.lo \ +-@BUILD_LIBQUADMATH_TRUE@ math/asinq.lo math/rintq.lo \ +-@BUILD_LIBQUADMATH_TRUE@ math/atan2q.lo math/isinfq.lo \ +-@BUILD_LIBQUADMATH_TRUE@ math/roundq.lo math/atanhq.lo \ +-@BUILD_LIBQUADMATH_TRUE@ math/isnanq.lo math/scalblnq.lo \ +-@BUILD_LIBQUADMATH_TRUE@ math/atanq.lo math/j0q.lo \ +-@BUILD_LIBQUADMATH_TRUE@ math/scalbnq.lo math/cbrtq.lo \ +-@BUILD_LIBQUADMATH_TRUE@ math/j1q.lo math/signbitq.lo \ +-@BUILD_LIBQUADMATH_TRUE@ math/ceilq.lo math/jnq.lo \ +-@BUILD_LIBQUADMATH_TRUE@ math/sincos_table.lo math/complex.lo \ +-@BUILD_LIBQUADMATH_TRUE@ math/ldexpq.lo math/sincosq.lo \ +-@BUILD_LIBQUADMATH_TRUE@ math/copysignq.lo math/lgammaq.lo \ +-@BUILD_LIBQUADMATH_TRUE@ math/sincosq_kernel.lo math/coshq.lo \ +-@BUILD_LIBQUADMATH_TRUE@ math/llroundq.lo math/sinhq.lo \ +-@BUILD_LIBQUADMATH_TRUE@ math/cosq.lo math/log10q.lo \ +-@BUILD_LIBQUADMATH_TRUE@ math/sinq.lo math/cosq_kernel.lo \ +-@BUILD_LIBQUADMATH_TRUE@ math/log1pq.lo math/sinq_kernel.lo \ +-@BUILD_LIBQUADMATH_TRUE@ math/erfq.lo math/logq.lo \ +-@BUILD_LIBQUADMATH_TRUE@ math/sqrtq.lo math/expm1q.lo \ +-@BUILD_LIBQUADMATH_TRUE@ math/lroundq.lo math/tanhq.lo \ +-@BUILD_LIBQUADMATH_TRUE@ math/expq.lo math/modfq.lo \ +-@BUILD_LIBQUADMATH_TRUE@ math/tanq.lo math/fabsq.lo \ +-@BUILD_LIBQUADMATH_TRUE@ math/nanq.lo math/tgammaq.lo \ +-@BUILD_LIBQUADMATH_TRUE@ math/finiteq.lo math/nextafterq.lo \ +-@BUILD_LIBQUADMATH_TRUE@ math/truncq.lo math/floorq.lo \ +-@BUILD_LIBQUADMATH_TRUE@ math/powq.lo math/fmaq.lo \ +-@BUILD_LIBQUADMATH_TRUE@ math/logbq.lo math/exp2q.lo \ +-@BUILD_LIBQUADMATH_TRUE@ math/issignalingq.lo \ +-@BUILD_LIBQUADMATH_TRUE@ math/lgammaq_neg.lo \ +-@BUILD_LIBQUADMATH_TRUE@ math/lgammaq_product.lo \ +-@BUILD_LIBQUADMATH_TRUE@ math/tanq_kernel.lo \ +-@BUILD_LIBQUADMATH_TRUE@ math/tgammaq_product.lo \ +-@BUILD_LIBQUADMATH_TRUE@ math/casinhq_kernel.lo math/cacoshq.lo \ +-@BUILD_LIBQUADMATH_TRUE@ math/cacosq.lo math/casinhq.lo \ +-@BUILD_LIBQUADMATH_TRUE@ math/casinq.lo math/catanhq.lo \ +-@BUILD_LIBQUADMATH_TRUE@ math/catanq.lo math/cimagq.lo \ +-@BUILD_LIBQUADMATH_TRUE@ math/conjq.lo math/cprojq.lo \ +-@BUILD_LIBQUADMATH_TRUE@ math/crealq.lo math/fdimq.lo \ +-@BUILD_LIBQUADMATH_TRUE@ math/fmaxq.lo math/fminq.lo \ +-@BUILD_LIBQUADMATH_TRUE@ math/ilogbq.lo math/llrintq.lo \ +-@BUILD_LIBQUADMATH_TRUE@ math/log2q.lo math/lrintq.lo \ +-@BUILD_LIBQUADMATH_TRUE@ math/nearbyintq.lo math/remquoq.lo \ +-@BUILD_LIBQUADMATH_TRUE@ math/ccoshq.lo math/cexpq.lo \ +-@BUILD_LIBQUADMATH_TRUE@ math/clog10q.lo math/clogq.lo \ +-@BUILD_LIBQUADMATH_TRUE@ math/csinq.lo math/csinhq.lo \ +-@BUILD_LIBQUADMATH_TRUE@ math/csqrtq.lo math/ctanq.lo \ +-@BUILD_LIBQUADMATH_TRUE@ math/ctanhq.lo printf/addmul_1.lo \ +-@BUILD_LIBQUADMATH_TRUE@ printf/add_n.lo printf/cmp.lo \ +-@BUILD_LIBQUADMATH_TRUE@ printf/divrem.lo printf/flt1282mpn.lo \ +-@BUILD_LIBQUADMATH_TRUE@ printf/fpioconst.lo printf/lshift.lo \ +-@BUILD_LIBQUADMATH_TRUE@ printf/mul_1.lo printf/mul_n.lo \ +-@BUILD_LIBQUADMATH_TRUE@ printf/mul.lo printf/printf_fphex.lo \ +-@BUILD_LIBQUADMATH_TRUE@ printf/printf_fp.lo \ +-@BUILD_LIBQUADMATH_TRUE@ printf/quadmath-printf.lo \ +-@BUILD_LIBQUADMATH_TRUE@ printf/rshift.lo printf/submul_1.lo \ +-@BUILD_LIBQUADMATH_TRUE@ printf/sub_n.lo strtod/strtoflt128.lo \ +-@BUILD_LIBQUADMATH_TRUE@ strtod/mpn2flt128.lo \ +-@BUILD_LIBQUADMATH_TRUE@ strtod/tens_in_limb.lo ++am_libquadmath_la_OBJECTS = math/x2y2m1q.lo \ ++ math/acoshq.lo math/fmodq.lo \ ++ math/acosq.lo math/frexpq.lo \ ++ math/rem_pio2q.lo math/asinhq.lo \ ++ math/hypotq.lo math/remainderq.lo \ ++ math/asinq.lo math/rintq.lo \ ++ math/atan2q.lo math/isinfq.lo \ ++ math/roundq.lo math/atanhq.lo \ ++ math/isnanq.lo math/scalblnq.lo \ ++ math/atanq.lo math/j0q.lo \ ++ math/scalbnq.lo math/cbrtq.lo \ ++ math/j1q.lo math/signbitq.lo \ ++ math/ceilq.lo math/jnq.lo \ ++ math/sincos_table.lo math/complex.lo \ ++ math/ldexpq.lo math/sincosq.lo \ ++ math/copysignq.lo math/lgammaq.lo \ ++ math/sincosq_kernel.lo math/coshq.lo \ ++ math/llroundq.lo math/sinhq.lo \ ++ math/cosq.lo math/log10q.lo \ ++ math/sinq.lo math/cosq_kernel.lo \ ++ math/log1pq.lo math/sinq_kernel.lo \ ++ math/erfq.lo math/logq.lo \ ++ math/sqrtq.lo math/expm1q.lo \ ++ math/lroundq.lo math/tanhq.lo \ ++ math/expq.lo math/modfq.lo \ ++ math/tanq.lo math/fabsq.lo \ ++ math/nanq.lo math/tgammaq.lo \ ++ math/finiteq.lo math/nextafterq.lo \ ++ math/truncq.lo math/floorq.lo \ ++ math/powq.lo math/fmaq.lo \ ++ math/logbq.lo math/exp2q.lo \ ++ math/issignalingq.lo \ ++ math/lgammaq_neg.lo \ ++ math/lgammaq_product.lo \ ++ math/tanq_kernel.lo \ ++ math/tgammaq_product.lo \ ++ math/casinhq_kernel.lo math/cacoshq.lo \ ++ math/cacosq.lo math/casinhq.lo \ ++ math/casinq.lo math/catanhq.lo \ ++ math/catanq.lo math/cimagq.lo \ ++ math/conjq.lo math/cprojq.lo \ ++ math/crealq.lo math/fdimq.lo \ ++ math/fmaxq.lo math/fminq.lo \ ++ math/ilogbq.lo math/llrintq.lo \ ++ math/log2q.lo math/lrintq.lo \ ++ math/nearbyintq.lo math/remquoq.lo \ ++ math/ccoshq.lo math/cexpq.lo \ ++ math/clog10q.lo math/clogq.lo \ ++ math/csinq.lo math/csinhq.lo \ ++ math/csqrtq.lo math/ctanq.lo \ ++ math/ctanhq.lo printf/addmul_1.lo \ ++ printf/add_n.lo printf/cmp.lo \ ++ printf/divrem.lo printf/flt1282mpn.lo \ ++ printf/fpioconst.lo printf/lshift.lo \ ++ printf/mul_1.lo printf/mul_n.lo \ ++ printf/mul.lo printf/printf_fphex.lo \ ++ printf/printf_fp.lo \ ++ printf/quadmath-printf.lo \ ++ printf/rshift.lo printf/submul_1.lo \ ++ printf/sub_n.lo strtod/strtoflt128.lo \ ++ strtod/mpn2flt128.lo \ ++ strtod/tens_in_limb.lo + libquadmath_la_OBJECTS = $(am_libquadmath_la_OBJECTS) + AM_V_lt = $(am__v_lt_@AM_V@) + am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +@@ -218,8 +218,8 @@ libquadmath_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(libquadmath_la_LDFLAGS) $(LDFLAGS) -o \ + $@ +-@BUILD_LIBQUADMATH_TRUE@am_libquadmath_la_rpath = -rpath \ +-@BUILD_LIBQUADMATH_TRUE@ $(toolexeclibdir) ++am_libquadmath_la_rpath = -rpath \ ++ $(toolexeclibdir) + AM_V_P = $(am__v_P_@AM_V@) + am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) + am__v_P_0 = false +@@ -337,7 +337,7 @@ CFLAGS = @CFLAGS@ + CPP = @CPP@ + CPPFLAGS = @CPPFLAGS@ + CYGPATH_W = @CYGPATH_W@ +-DEFS = @DEFS@ ++DEFS = @DEFS@ -D__float128="long double" + DEPDIR = @DEPDIR@ + DSYMUTIL = @DSYMUTIL@ + DUMPBIN = @DUMPBIN@ +@@ -409,7 +409,7 @@ datadir = @datadir@ + datarootdir = @datarootdir@ + docdir = @docdir@ + dvidir = @dvidir@ +-enable_shared = @enable_shared@ ++enable_shared = yes + enable_static = @enable_static@ + exec_prefix = @exec_prefix@ + get_gcc_base_ver = @get_gcc_base_ver@ +@@ -451,109 +451,109 @@ top_build_prefix = @top_build_prefix@ + top_builddir = @top_builddir@ + top_srcdir = @top_srcdir@ + AUTOMAKE_OPTIONS = foreign info-in-builddir +-@BUILD_LIBQUADMATH_TRUE@ACLOCAL_AMFLAGS = -I .. -I ../config +-@BUILD_LIBQUADMATH_TRUE@AM_CPPFLAGS = -I $(top_srcdir)/../include +-@BUILD_LIBQUADMATH_TRUE@AM_CFLAGS = $(XCFLAGS) +-@BUILD_LIBQUADMATH_TRUE@gcc_version := $(shell @get_gcc_base_ver@ $(top_srcdir)/../gcc/BASE-VER) +-@BUILD_LIBQUADMATH_TRUE@@LIBQUAD_USE_SYMVER_FALSE@version_arg = +-@BUILD_LIBQUADMATH_TRUE@@LIBQUAD_USE_SYMVER_GNU_TRUE@@LIBQUAD_USE_SYMVER_TRUE@version_arg = -Wl,--version-script=$(srcdir)/quadmath.map +-@BUILD_LIBQUADMATH_TRUE@@LIBQUAD_USE_SYMVER_SUN_TRUE@@LIBQUAD_USE_SYMVER_TRUE@version_arg = -Wl,-M,quadmath.map-sun +-@BUILD_LIBQUADMATH_TRUE@@LIBQUAD_USE_SYMVER_FALSE@version_dep = +-@BUILD_LIBQUADMATH_TRUE@@LIBQUAD_USE_SYMVER_GNU_TRUE@@LIBQUAD_USE_SYMVER_TRUE@version_dep = $(srcdir)/quadmath.map +-@BUILD_LIBQUADMATH_TRUE@@LIBQUAD_USE_SYMVER_SUN_TRUE@@LIBQUAD_USE_SYMVER_TRUE@version_dep = quadmath.map-sun +-@BUILD_LIBQUADMATH_TRUE@toolexeclib_LTLIBRARIES = libquadmath.la +-@BUILD_LIBQUADMATH_TRUE@libquadmath_la_LIBADD = +-@BUILD_LIBQUADMATH_TRUE@libquadmath_la_LDFLAGS = -version-info `grep -v '^\#' $(srcdir)/libtool-version` \ +-@BUILD_LIBQUADMATH_TRUE@ $(version_arg) $(lt_host_flags) -lm +- +-@BUILD_LIBQUADMATH_TRUE@libquadmath_la_DEPENDENCIES = $(version_dep) $(libquadmath_la_LIBADD) +-@BUILD_LIBQUADMATH_TRUE@nodist_libsubinclude_HEADERS = quadmath.h quadmath_weak.h +-@BUILD_LIBQUADMATH_TRUE@libsubincludedir = $(libdir)/gcc/$(target_alias)/$(gcc_version)/include +-@BUILD_LIBQUADMATH_TRUE@libquadmath_la_SOURCES = \ +-@BUILD_LIBQUADMATH_TRUE@ math/x2y2m1q.c math/acoshq.c math/fmodq.c \ +-@BUILD_LIBQUADMATH_TRUE@ math/acosq.c math/frexpq.c \ +-@BUILD_LIBQUADMATH_TRUE@ math/rem_pio2q.c math/asinhq.c math/hypotq.c math/remainderq.c \ +-@BUILD_LIBQUADMATH_TRUE@ math/asinq.c math/rintq.c math/atan2q.c math/isinfq.c \ +-@BUILD_LIBQUADMATH_TRUE@ math/roundq.c math/atanhq.c math/isnanq.c math/scalblnq.c math/atanq.c \ +-@BUILD_LIBQUADMATH_TRUE@ math/j0q.c math/scalbnq.c math/cbrtq.c math/j1q.c math/signbitq.c \ +-@BUILD_LIBQUADMATH_TRUE@ math/ceilq.c math/jnq.c math/sincos_table.c math/complex.c math/ldexpq.c \ +-@BUILD_LIBQUADMATH_TRUE@ math/sincosq.c math/copysignq.c math/lgammaq.c math/sincosq_kernel.c \ +-@BUILD_LIBQUADMATH_TRUE@ math/coshq.c math/llroundq.c math/sinhq.c math/cosq.c math/log10q.c \ +-@BUILD_LIBQUADMATH_TRUE@ math/sinq.c math/cosq_kernel.c math/log1pq.c math/sinq_kernel.c \ +-@BUILD_LIBQUADMATH_TRUE@ math/erfq.c math/logq.c math/sqrtq.c math/expm1q.c math/lroundq.c \ +-@BUILD_LIBQUADMATH_TRUE@ math/tanhq.c math/expq.c math/modfq.c math/tanq.c math/fabsq.c \ +-@BUILD_LIBQUADMATH_TRUE@ math/nanq.c math/tgammaq.c math/finiteq.c math/nextafterq.c \ +-@BUILD_LIBQUADMATH_TRUE@ math/truncq.c math/floorq.c math/powq.c math/fmaq.c math/logbq.c \ +-@BUILD_LIBQUADMATH_TRUE@ math/exp2q.c math/issignalingq.c math/lgammaq_neg.c math/lgammaq_product.c \ +-@BUILD_LIBQUADMATH_TRUE@ math/tanq_kernel.c math/tgammaq_product.c math/casinhq_kernel.c \ +-@BUILD_LIBQUADMATH_TRUE@ math/cacoshq.c math/cacosq.c math/casinhq.c math/casinq.c \ +-@BUILD_LIBQUADMATH_TRUE@ math/catanhq.c math/catanq.c math/cimagq.c math/conjq.c math/cprojq.c \ +-@BUILD_LIBQUADMATH_TRUE@ math/crealq.c math/fdimq.c math/fmaxq.c math/fminq.c math/ilogbq.c \ +-@BUILD_LIBQUADMATH_TRUE@ math/llrintq.c math/log2q.c math/lrintq.c math/nearbyintq.c math/remquoq.c \ +-@BUILD_LIBQUADMATH_TRUE@ math/ccoshq.c math/cexpq.c math/clog10q.c math/clogq.c math/csinq.c \ +-@BUILD_LIBQUADMATH_TRUE@ math/csinhq.c math/csqrtq.c math/ctanq.c math/ctanhq.c \ +-@BUILD_LIBQUADMATH_TRUE@ printf/addmul_1.c printf/add_n.c printf/cmp.c printf/divrem.c \ +-@BUILD_LIBQUADMATH_TRUE@ printf/flt1282mpn.c printf/fpioconst.c printf/lshift.c printf/mul_1.c \ +-@BUILD_LIBQUADMATH_TRUE@ printf/mul_n.c printf/mul.c printf/printf_fphex.c printf/printf_fp.c \ +-@BUILD_LIBQUADMATH_TRUE@ printf/quadmath-printf.c printf/rshift.c printf/submul_1.c printf/sub_n.c \ +-@BUILD_LIBQUADMATH_TRUE@ strtod/strtoflt128.c strtod/mpn2flt128.c strtod/tens_in_limb.c ++ACLOCAL_AMFLAGS = -I .. -I ../config ++AM_CPPFLAGS = -I $(top_srcdir)/../include ++AM_CFLAGS = $(XCFLAGS) ++gcc_version := $(shell @get_gcc_base_ver@ $(top_srcdir)/../gcc/BASE-VER) ++@LIBQUAD_USE_SYMVER_FALSE@version_arg = ++@LIBQUAD_USE_SYMVER_GNU_TRUE@@LIBQUAD_USE_SYMVER_TRUE@version_arg = -Wl,--version-script=$(srcdir)/quadmath.map ++@LIBQUAD_USE_SYMVER_SUN_TRUE@@LIBQUAD_USE_SYMVER_TRUE@version_arg = -Wl,-M,quadmath.map-sun ++@LIBQUAD_USE_SYMVER_FALSE@version_dep = ++@LIBQUAD_USE_SYMVER_GNU_TRUE@@LIBQUAD_USE_SYMVER_TRUE@version_dep = $(srcdir)/quadmath.map ++@LIBQUAD_USE_SYMVER_SUN_TRUE@@LIBQUAD_USE_SYMVER_TRUE@version_dep = quadmath.map-sun ++toolexeclib_LTLIBRARIES = libquadmath.la ++libquadmath_la_LIBADD = ++libquadmath_la_LDFLAGS = -version-info `grep -v '^\#' $(srcdir)/libtool-version` \ ++ $(version_arg) $(lt_host_flags) -lm ++ ++libquadmath_la_DEPENDENCIES = $(version_dep) $(libquadmath_la_LIBADD) ++nodist_libsubinclude_HEADERS = quadmath.h quadmath_weak.h ++libsubincludedir = $(libdir)/gcc/$(target_alias)/$(gcc_version)/include ++libquadmath_la_SOURCES = \ ++ math/x2y2m1q.c math/acoshq.c math/fmodq.c \ ++ math/acosq.c math/frexpq.c \ ++ math/rem_pio2q.c math/asinhq.c math/hypotq.c math/remainderq.c \ ++ math/asinq.c math/rintq.c math/atan2q.c math/isinfq.c \ ++ math/roundq.c math/atanhq.c math/isnanq.c math/scalblnq.c math/atanq.c \ ++ math/j0q.c math/scalbnq.c math/cbrtq.c math/j1q.c math/signbitq.c \ ++ math/ceilq.c math/jnq.c math/sincos_table.c math/complex.c math/ldexpq.c \ ++ math/sincosq.c math/copysignq.c math/lgammaq.c math/sincosq_kernel.c \ ++ math/coshq.c math/llroundq.c math/sinhq.c math/cosq.c math/log10q.c \ ++ math/sinq.c math/cosq_kernel.c math/log1pq.c math/sinq_kernel.c \ ++ math/erfq.c math/logq.c math/sqrtq.c math/expm1q.c math/lroundq.c \ ++ math/tanhq.c math/expq.c math/modfq.c math/tanq.c math/fabsq.c \ ++ math/nanq.c math/tgammaq.c math/finiteq.c math/nextafterq.c \ ++ math/truncq.c math/floorq.c math/powq.c math/fmaq.c math/logbq.c \ ++ math/exp2q.c math/issignalingq.c math/lgammaq_neg.c math/lgammaq_product.c \ ++ math/tanq_kernel.c math/tgammaq_product.c math/casinhq_kernel.c \ ++ math/cacoshq.c math/cacosq.c math/casinhq.c math/casinq.c \ ++ math/catanhq.c math/catanq.c math/cimagq.c math/conjq.c math/cprojq.c \ ++ math/crealq.c math/fdimq.c math/fmaxq.c math/fminq.c math/ilogbq.c \ ++ math/llrintq.c math/log2q.c math/lrintq.c math/nearbyintq.c math/remquoq.c \ ++ math/ccoshq.c math/cexpq.c math/clog10q.c math/clogq.c math/csinq.c \ ++ math/csinhq.c math/csqrtq.c math/ctanq.c math/ctanhq.c \ ++ printf/addmul_1.c printf/add_n.c printf/cmp.c printf/divrem.c \ ++ printf/flt1282mpn.c printf/fpioconst.c printf/lshift.c printf/mul_1.c \ ++ printf/mul_n.c printf/mul.c printf/printf_fphex.c printf/printf_fp.c \ ++ printf/quadmath-printf.c printf/rshift.c printf/submul_1.c printf/sub_n.c \ ++ strtod/strtoflt128.c strtod/mpn2flt128.c strtod/tens_in_limb.c + + + # Work around what appears to be a GNU make bug handling MAKEFLAGS + # values defined in terms of make variables, as is the case for CC and + # friends when we are called from the top level Makefile. +-@BUILD_LIBQUADMATH_TRUE@AM_MAKEFLAGS = \ +-@BUILD_LIBQUADMATH_TRUE@ "AR_FLAGS=$(AR_FLAGS)" \ +-@BUILD_LIBQUADMATH_TRUE@ "CC_FOR_BUILD=$(CC_FOR_BUILD)" \ +-@BUILD_LIBQUADMATH_TRUE@ "CFLAGS=$(CFLAGS)" \ +-@BUILD_LIBQUADMATH_TRUE@ "CXXFLAGS=$(CXXFLAGS)" \ +-@BUILD_LIBQUADMATH_TRUE@ "CFLAGS_FOR_BUILD=$(CFLAGS_FOR_BUILD)" \ +-@BUILD_LIBQUADMATH_TRUE@ "CFLAGS_FOR_TARGET=$(CFLAGS_FOR_TARGET)" \ +-@BUILD_LIBQUADMATH_TRUE@ "INSTALL=$(INSTALL)" \ +-@BUILD_LIBQUADMATH_TRUE@ "INSTALL_DATA=$(INSTALL_DATA)" \ +-@BUILD_LIBQUADMATH_TRUE@ "INSTALL_PROGRAM=$(INSTALL_PROGRAM)" \ +-@BUILD_LIBQUADMATH_TRUE@ "INSTALL_SCRIPT=$(INSTALL_SCRIPT)" \ +-@BUILD_LIBQUADMATH_TRUE@ "JC1FLAGS=$(JC1FLAGS)" \ +-@BUILD_LIBQUADMATH_TRUE@ "LDFLAGS=$(LDFLAGS)" \ +-@BUILD_LIBQUADMATH_TRUE@ "LIBCFLAGS=$(LIBCFLAGS)" \ +-@BUILD_LIBQUADMATH_TRUE@ "LIBCFLAGS_FOR_TARGET=$(LIBCFLAGS_FOR_TARGET)" \ +-@BUILD_LIBQUADMATH_TRUE@ "MAKE=$(MAKE)" \ +-@BUILD_LIBQUADMATH_TRUE@ "MAKEINFO=$(MAKEINFO) $(MAKEINFOFLAGS)" \ +-@BUILD_LIBQUADMATH_TRUE@ "PICFLAG=$(PICFLAG)" \ +-@BUILD_LIBQUADMATH_TRUE@ "PICFLAG_FOR_TARGET=$(PICFLAG_FOR_TARGET)" \ +-@BUILD_LIBQUADMATH_TRUE@ "SHELL=$(SHELL)" \ +-@BUILD_LIBQUADMATH_TRUE@ "RUNTESTFLAGS=$(RUNTESTFLAGS)" \ +-@BUILD_LIBQUADMATH_TRUE@ "exec_prefix=$(exec_prefix)" \ +-@BUILD_LIBQUADMATH_TRUE@ "infodir=$(infodir)" \ +-@BUILD_LIBQUADMATH_TRUE@ "libdir=$(libdir)" \ +-@BUILD_LIBQUADMATH_TRUE@ "prefix=$(prefix)" \ +-@BUILD_LIBQUADMATH_TRUE@ "includedir=$(includedir)" \ +-@BUILD_LIBQUADMATH_TRUE@ "AR=$(AR)" \ +-@BUILD_LIBQUADMATH_TRUE@ "AS=$(AS)" \ +-@BUILD_LIBQUADMATH_TRUE@ "CC=$(CC)" \ +-@BUILD_LIBQUADMATH_TRUE@ "CXX=$(CXX)" \ +-@BUILD_LIBQUADMATH_TRUE@ "LD=$(LD)" \ +-@BUILD_LIBQUADMATH_TRUE@ "LIBCFLAGS=$(LIBCFLAGS)" \ +-@BUILD_LIBQUADMATH_TRUE@ "NM=$(NM)" \ +-@BUILD_LIBQUADMATH_TRUE@ "PICFLAG=$(PICFLAG)" \ +-@BUILD_LIBQUADMATH_TRUE@ "RANLIB=$(RANLIB)" \ +-@BUILD_LIBQUADMATH_TRUE@ "DESTDIR=$(DESTDIR)" ++AM_MAKEFLAGS = \ ++ "AR_FLAGS=$(AR_FLAGS)" \ ++ "CC_FOR_BUILD=$(CC_FOR_BUILD)" \ ++ "CFLAGS=$(CFLAGS)" \ ++ "CXXFLAGS=$(CXXFLAGS)" \ ++ "CFLAGS_FOR_BUILD=$(CFLAGS_FOR_BUILD)" \ ++ "CFLAGS_FOR_TARGET=$(CFLAGS_FOR_TARGET)" \ ++ "INSTALL=$(INSTALL)" \ ++ "INSTALL_DATA=$(INSTALL_DATA)" \ ++ "INSTALL_PROGRAM=$(INSTALL_PROGRAM)" \ ++ "INSTALL_SCRIPT=$(INSTALL_SCRIPT)" \ ++ "JC1FLAGS=$(JC1FLAGS)" \ ++ "LDFLAGS=$(LDFLAGS)" \ ++ "LIBCFLAGS=$(LIBCFLAGS)" \ ++ "LIBCFLAGS_FOR_TARGET=$(LIBCFLAGS_FOR_TARGET)" \ ++ "MAKE=$(MAKE)" \ ++ "MAKEINFO=$(MAKEINFO) $(MAKEINFOFLAGS)" \ ++ "PICFLAG=$(PICFLAG)" \ ++ "PICFLAG_FOR_TARGET=$(PICFLAG_FOR_TARGET)" \ ++ "SHELL=$(SHELL)" \ ++ "RUNTESTFLAGS=$(RUNTESTFLAGS)" \ ++ "exec_prefix=$(exec_prefix)" \ ++ "infodir=$(infodir)" \ ++ "libdir=$(libdir)" \ ++ "prefix=$(prefix)" \ ++ "includedir=$(includedir)" \ ++ "AR=$(AR)" \ ++ "AS=$(AS)" \ ++ "CC=$(CC)" \ ++ "CXX=$(CXX)" \ ++ "LD=$(LD)" \ ++ "LIBCFLAGS=$(LIBCFLAGS)" \ ++ "NM=$(NM)" \ ++ "PICFLAG=$(PICFLAG)" \ ++ "RANLIB=$(RANLIB)" \ ++ "DESTDIR=$(DESTDIR)" + + + # Subdir rules rely on $(FLAGS_TO_PASS) +-@BUILD_LIBQUADMATH_TRUE@FLAGS_TO_PASS = $(AM_MAKEFLAGS) +-@BUILD_LIBQUADMATH_TRUE@MAKEOVERRIDES = +-@BUILD_LIBQUADMATH_TRUE@@GENINSRC_FALSE@STAMP_GENINSRC = ++FLAGS_TO_PASS = $(AM_MAKEFLAGS) ++MAKEOVERRIDES = ++@GENINSRC_FALSE@STAMP_GENINSRC = + + # AM_CONDITIONAL on configure option --generated-files-in-srcdir +-@BUILD_LIBQUADMATH_TRUE@@GENINSRC_TRUE@STAMP_GENINSRC = stamp-geninsrc +-@BUILD_LIBQUADMATH_TRUE@ALL_LOCAL_DEPS = $(STAMP_GENINSRC) +-@BUILD_INFO_FALSE@@BUILD_LIBQUADMATH_TRUE@STAMP_BUILD_INFO = ++@GENINSRC_TRUE@STAMP_GENINSRC = stamp-geninsrc ++ALL_LOCAL_DEPS = $(STAMP_GENINSRC) ++@BUILD_INFO_FALSE@STAMP_BUILD_INFO = + + # AM_CONDITIONAL on configure check ACX_CHECK_PROG_VER([MAKEINFO]) +-@BUILD_INFO_TRUE@@BUILD_LIBQUADMATH_TRUE@STAMP_BUILD_INFO = stamp-build-info +-@BUILD_LIBQUADMATH_TRUE@CLEANFILES = $(STAMP_GENINSRC) $(STAMP_BUILD_INFO) +-@BUILD_LIBQUADMATH_TRUE@MAINTAINERCLEANFILES = $(srcdir)/libquadmath.info ++@BUILD_INFO_TRUE@STAMP_BUILD_INFO = stamp-build-info ++CLEANFILES = $(STAMP_GENINSRC) $(STAMP_BUILD_INFO) ++MAINTAINERCLEANFILES = $(srcdir)/libquadmath.info + + # Automake Documentation: + # If your package has Texinfo files in many directories, you can use the +@@ -564,8 +564,8 @@ TEXINFO_TEX = ../gcc/doc/include/texinfo.tex + + # Defines info, dvi, pdf and html targets + MAKEINFOFLAGS = -I $(srcdir)/../gcc/doc/include +-@BUILD_LIBQUADMATH_FALSE@info_TEXINFOS = +-@BUILD_LIBQUADMATH_TRUE@info_TEXINFOS = libquadmath.texi ++info_TEXINFOS = ++info_TEXINFOS = libquadmath.texi + libquadmath_TEXINFOS = libquadmath-vers.texi + MULTISRCTOP = + MULTIBUILDTOP = +@@ -1187,6 +1187,7 @@ distclean-tags: + -rm -f cscope.out cscope.in.out cscope.po.out cscope.files + check-am: all-am + check: check-am ++#all-local + all-am: Makefile $(INFO_DEPS) $(LTLIBRARIES) $(HEADERS) config.h \ + all-local + installdirs: +@@ -1425,22 +1426,22 @@ uninstall-am: uninstall-dvi-am uninstall-html-am uninstall-info-am \ + + .PRECIOUS: Makefile + +-@BUILD_LIBQUADMATH_TRUE@@LIBQUAD_USE_SYMVER_SUN_TRUE@@LIBQUAD_USE_SYMVER_TRUE@quadmath.map-sun : $(srcdir)/quadmath.map \ +-@BUILD_LIBQUADMATH_TRUE@@LIBQUAD_USE_SYMVER_SUN_TRUE@@LIBQUAD_USE_SYMVER_TRUE@ $(top_srcdir)/../contrib/make_sunver.pl \ +-@BUILD_LIBQUADMATH_TRUE@@LIBQUAD_USE_SYMVER_SUN_TRUE@@LIBQUAD_USE_SYMVER_TRUE@ $(libquadmath_la_OBJECTS) $(libquadmath_la_LIBADD) +-@BUILD_LIBQUADMATH_TRUE@@LIBQUAD_USE_SYMVER_SUN_TRUE@@LIBQUAD_USE_SYMVER_TRUE@ perl $(top_srcdir)/../contrib/make_sunver.pl \ +-@BUILD_LIBQUADMATH_TRUE@@LIBQUAD_USE_SYMVER_SUN_TRUE@@LIBQUAD_USE_SYMVER_TRUE@ $(srcdir)/quadmath.map \ +-@BUILD_LIBQUADMATH_TRUE@@LIBQUAD_USE_SYMVER_SUN_TRUE@@LIBQUAD_USE_SYMVER_TRUE@ `echo $(libquadmath_la_OBJECTS) $(libquadmath_la_LIBADD) | \ +-@BUILD_LIBQUADMATH_TRUE@@LIBQUAD_USE_SYMVER_SUN_TRUE@@LIBQUAD_USE_SYMVER_TRUE@ sed 's,\([^/ ]*\)\.l\([ao]\),.libs/\1.\2,g'` \ +-@BUILD_LIBQUADMATH_TRUE@@LIBQUAD_USE_SYMVER_SUN_TRUE@@LIBQUAD_USE_SYMVER_TRUE@ > $@ || (rm -f $@ ; exit 1) +- +-@BUILD_LIBQUADMATH_TRUE@stamp-geninsrc: libquadmath.info +-@BUILD_LIBQUADMATH_TRUE@ cp -p $(top_builddir)/libquadmath.info $(srcdir)/libquadmath.info +-@BUILD_LIBQUADMATH_TRUE@ @touch $@ +- +-@BUILD_LIBQUADMATH_TRUE@stamp-build-info: libquadmath.texi $(libquadmath_TEXINFOS) +-@BUILD_LIBQUADMATH_TRUE@ $(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir) -o libquadmath.info $(srcdir)/libquadmath.texi +-@BUILD_LIBQUADMATH_TRUE@ @touch $@ ++@LIBQUAD_USE_SYMVER_SUN_TRUE@@LIBQUAD_USE_SYMVER_TRUE@quadmath.map-sun : $(srcdir)/quadmath.map \ ++@LIBQUAD_USE_SYMVER_SUN_TRUE@@LIBQUAD_USE_SYMVER_TRUE@ $(top_srcdir)/../contrib/make_sunver.pl \ ++@LIBQUAD_USE_SYMVER_SUN_TRUE@@LIBQUAD_USE_SYMVER_TRUE@ $(libquadmath_la_OBJECTS) $(libquadmath_la_LIBADD) ++@LIBQUAD_USE_SYMVER_SUN_TRUE@@LIBQUAD_USE_SYMVER_TRUE@ perl $(top_srcdir)/../contrib/make_sunver.pl \ ++@LIBQUAD_USE_SYMVER_SUN_TRUE@@LIBQUAD_USE_SYMVER_TRUE@ $(srcdir)/quadmath.map \ ++@LIBQUAD_USE_SYMVER_SUN_TRUE@@LIBQUAD_USE_SYMVER_TRUE@ `echo $(libquadmath_la_OBJECTS) $(libquadmath_la_LIBADD) | \ ++@LIBQUAD_USE_SYMVER_SUN_TRUE@@LIBQUAD_USE_SYMVER_TRUE@ sed 's,\([^/ ]*\)\.l\([ao]\),.libs/\1.\2,g'` \ ++@LIBQUAD_USE_SYMVER_SUN_TRUE@@LIBQUAD_USE_SYMVER_TRUE@ > $@ || (rm -f $@ ; exit 1) ++ ++stamp-geninsrc: libquadmath.info ++ cp -p $(top_builddir)/libquadmath.info $(srcdir)/libquadmath.info ++ @touch $@ ++ ++stamp-build-info: libquadmath.texi $(libquadmath_TEXINFOS) ++ $(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir) -o libquadmath.info $(srcdir)/libquadmath.texi ++ @touch $@ + + all-local: $(ALL_LOCAL_DEPS) + +diff --git a/libquadmath/quadmath.h b/libquadmath/quadmath.h +index 81eb957d2fa..faa5977cbc9 100644 +--- a/libquadmath/quadmath.h ++++ b/libquadmath/quadmath.h +@@ -27,6 +27,9 @@ Boston, MA 02110-1301, USA. */ + extern "C" { + #endif + ++#ifdef AARCH64_QUADMATH ++typedef long double __float128; ++#endif + /* Define the complex type corresponding to __float128 + ("_Complex __float128" is not allowed) */ + #if (!defined(_ARCH_PPC)) || defined(__LONG_DOUBLE_IEEE128__) +@@ -160,10 +163,9 @@ extern int quadmath_snprintf (char *str, size_t size, + #define FLT128_MAX_10_EXP 4932 + + +-#define HUGE_VALQ __builtin_huge_valq() + /* 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) + + #define M_Eq 2.718281828459045235360287471352662498Q /* e */ + #define M_LOG2Eq 1.442695040888963407359924681001892137Q /* log_2 e */ +-- +2.21.0.windows.1 + diff --git a/0002-Backport-cselim-Extend-to-check-non-trapping-for-mor.patch b/0002-Backport-cselim-Extend-to-check-non-trapping-for-mor.patch new file mode 100644 index 0000000..c5df4d9 --- /dev/null +++ b/0002-Backport-cselim-Extend-to-check-non-trapping-for-mor.patch @@ -0,0 +1,318 @@ +From d1e1ec0cd539f96be5a86b369b8c20b36ce9567f Mon Sep 17 00:00:00 2001 +From: yangyang +Date: Thu, 8 Jul 2021 14:38:39 +0800 +Subject: [PATCH 02/13] [Backport] cselim: Extend to check non-trapping for + more references + +Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=54ecfb182bc32140722022c1d9818dee4bdc0e45 + +If there is a dominating store, a store to the same reference can not be +trapped. But previously, it only supports such check on MEM_REFs. +So this patch extends it to support ARRAY_REFs and COMPONENT_REFs. + +This patch also supports a special case: if there is a dominating load of +local variable without address escape, a store is not trapped, as local +stack is always writable. Other loads are ignored for simplicity, as they +don't help to check if a store can be trapped (the memory may be read-only). + +diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr89430-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr89430-1.c +index ce242ba569b..8ee1850ac63 100644 +--- a/gcc/testsuite/gcc.dg/tree-ssa/pr89430-1.c ++++ b/gcc/testsuite/gcc.dg/tree-ssa/pr89430-1.c +@@ -9,4 +9,4 @@ unsigned test(unsigned k, unsigned b) { + return a[0]+a[1]; + } + +-/* { dg-final { scan-tree-dump "Conditional store replacement" "cselim" { xfail *-*-* } } } */ ++/* { dg-final { scan-tree-dump "Conditional store replacement" "cselim" } } */ +diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr89430-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr89430-2.c +index 90ae36bfce2..9b96875ac7a 100644 +--- a/gcc/testsuite/gcc.dg/tree-ssa/pr89430-2.c ++++ b/gcc/testsuite/gcc.dg/tree-ssa/pr89430-2.c +@@ -11,4 +11,4 @@ unsigned test(unsigned k, unsigned b) { + return a[0]+a[1]; + } + +-/* { dg-final { scan-tree-dump "Conditional store replacement" "cselim" { xfail *-*-* } } } */ ++/* { dg-final { scan-tree-dump "Conditional store replacement" "cselim" } } */ +diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr89430-5.c b/gcc/testsuite/gcc.dg/tree-ssa/pr89430-5.c +index c633cbe947d..b2d04119381 100644 +--- a/gcc/testsuite/gcc.dg/tree-ssa/pr89430-5.c ++++ b/gcc/testsuite/gcc.dg/tree-ssa/pr89430-5.c +@@ -13,4 +13,4 @@ int test(int b, int k) { + return a.data[0] + a.data[1]; + } + +-/* { dg-final { scan-tree-dump "Conditional store replacement" "cselim" { xfail *-*-* } } } */ ++/* { dg-final { scan-tree-dump "Conditional store replacement" "cselim" } } */ +diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr89430-6.c b/gcc/testsuite/gcc.dg/tree-ssa/pr89430-6.c +index 7cad563128d..8d3c4f7cc6a 100644 +--- a/gcc/testsuite/gcc.dg/tree-ssa/pr89430-6.c ++++ b/gcc/testsuite/gcc.dg/tree-ssa/pr89430-6.c +@@ -16,4 +16,4 @@ int test(int b, int k) { + return a.data[0].x + a.data[1].x; + } + +-/* { dg-final { scan-tree-dump "Conditional store replacement" "cselim" { xfail *-*-* } } } */ ++/* { dg-final { scan-tree-dump "Conditional store replacement" "cselim" } } */ +diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr89430-7-comp-ref.c b/gcc/testsuite/gcc.dg/tree-ssa/pr89430-7-comp-ref.c +new file mode 100644 +index 00000000000..c35a2afc70b +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/tree-ssa/pr89430-7-comp-ref.c +@@ -0,0 +1,17 @@ ++/* { dg-do compile } */ ++/* { dg-options "-O2 -fdump-tree-cselim-details" } */ ++ ++typedef union { ++ int i; ++ float f; ++} U; ++ ++int foo(U *u, int b, int i) ++{ ++ u->i = 0; ++ if (b) ++ u->i = i; ++ return u->i; ++} ++ ++/* { dg-final { scan-tree-dump "Conditional store replacement" "cselim" } } */ +diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr89430-8-mem-ref-size.c b/gcc/testsuite/gcc.dg/tree-ssa/pr89430-8-mem-ref-size.c +new file mode 100644 +index 00000000000..f9e66aefb13 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/tree-ssa/pr89430-8-mem-ref-size.c +@@ -0,0 +1,15 @@ ++/* { dg-do compile } */ ++/* { dg-options "-O2 -fdump-tree-cselim-details" } */ ++ ++int *t; ++ ++int f1 (int tt) ++{ ++ int *t1 = t; ++ *t1 = -5; ++ if (*t1 < tt) ++ *((unsigned *) t1) = 5; ++ return *t1; ++} ++ ++/* { dg-final { scan-tree-dump "Conditional store replacement" "cselim" } } */ +diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-17.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-17.c +index 09313716598..a06f339f0bb 100644 +--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-17.c ++++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-17.c +@@ -1,5 +1,5 @@ + /* { dg-do compile } */ +-/* { dg-options "-O2 -fdump-tree-pre-stats" } */ ++/* { dg-options "-O2 -fdump-tree-pre-stats -fno-tree-cselim" } */ + + typedef union { + int i; +diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c +index b1e0dce93d8..3b5b6907679 100644 +--- a/gcc/tree-ssa-phiopt.c ++++ b/gcc/tree-ssa-phiopt.c +@@ -1986,26 +1986,33 @@ abs_replacement (basic_block cond_bb, basic_block middle_bb, + + ??? We currently are very conservative and assume that a load might + trap even if a store doesn't (write-only memory). This probably is +- overly conservative. */ ++ overly conservative. + +-/* A hash-table of SSA_NAMEs, and in which basic block an MEM_REF +- through it was seen, which would constitute a no-trap region for +- same accesses. */ +-struct name_to_bb ++ We currently support a special case that for !TREE_ADDRESSABLE automatic ++ variables, it could ignore whether something is a load or store because the ++ local stack should be always writable. */ ++ ++/* A hash-table of references (MEM_REF/ARRAY_REF/COMPONENT_REF), and in which ++ basic block an *_REF through it was seen, which would constitute a ++ no-trap region for same accesses. ++ ++ Size is needed to support 2 MEM_REFs of different types, like ++ MEM(s_1) and MEM(s_1), which would compare equal with ++ OEP_ADDRESS_OF. */ ++struct ref_to_bb + { +- unsigned int ssa_name_ver; ++ tree exp; ++ HOST_WIDE_INT size; + unsigned int phase; +- bool store; +- HOST_WIDE_INT offset, size; + basic_block bb; + }; + + /* Hashtable helpers. */ + +-struct ssa_names_hasher : free_ptr_hash ++struct refs_hasher : free_ptr_hash + { +- static inline hashval_t hash (const name_to_bb *); +- static inline bool equal (const name_to_bb *, const name_to_bb *); ++ static inline hashval_t hash (const ref_to_bb *); ++ static inline bool equal (const ref_to_bb *, const ref_to_bb *); + }; + + /* Used for quick clearing of the hash-table when we see calls. +@@ -2015,28 +2022,29 @@ static unsigned int nt_call_phase; + /* The hash function. */ + + inline hashval_t +-ssa_names_hasher::hash (const name_to_bb *n) ++refs_hasher::hash (const ref_to_bb *n) + { +- return n->ssa_name_ver ^ (((hashval_t) n->store) << 31) +- ^ (n->offset << 6) ^ (n->size << 3); ++ inchash::hash hstate; ++ inchash::add_expr (n->exp, hstate, OEP_ADDRESS_OF); ++ hstate.add_hwi (n->size); ++ return hstate.end (); + } + + /* The equality function of *P1 and *P2. */ + + inline bool +-ssa_names_hasher::equal (const name_to_bb *n1, const name_to_bb *n2) ++refs_hasher::equal (const ref_to_bb *n1, const ref_to_bb *n2) + { +- return n1->ssa_name_ver == n2->ssa_name_ver +- && n1->store == n2->store +- && n1->offset == n2->offset +- && n1->size == n2->size; ++ return operand_equal_p (n1->exp, n2->exp, OEP_ADDRESS_OF) ++ && n1->size == n2->size; + } + + class nontrapping_dom_walker : public dom_walker + { + public: + nontrapping_dom_walker (cdi_direction direction, hash_set *ps) +- : dom_walker (direction), m_nontrapping (ps), m_seen_ssa_names (128) {} ++ : dom_walker (direction), m_nontrapping (ps), m_seen_refs (128) ++ {} + + virtual edge before_dom_children (basic_block); + virtual void after_dom_children (basic_block); +@@ -2053,7 +2061,7 @@ private: + hash_set *m_nontrapping; + + /* The hash table for remembering what we've seen. */ +- hash_table m_seen_ssa_names; ++ hash_table m_seen_refs; + }; + + /* Called by walk_dominator_tree, when entering the block BB. */ +@@ -2102,65 +2110,68 @@ nontrapping_dom_walker::after_dom_children (basic_block bb) + } + + /* We see the expression EXP in basic block BB. If it's an interesting +- expression (an MEM_REF through an SSA_NAME) possibly insert the +- expression into the set NONTRAP or the hash table of seen expressions. +- STORE is true if this expression is on the LHS, otherwise it's on +- the RHS. */ ++ expression of: ++ 1) MEM_REF ++ 2) ARRAY_REF ++ 3) COMPONENT_REF ++ possibly insert the expression into the set NONTRAP or the hash table ++ of seen expressions. STORE is true if this expression is on the LHS, ++ otherwise it's on the RHS. */ + void + nontrapping_dom_walker::add_or_mark_expr (basic_block bb, tree exp, bool store) + { + HOST_WIDE_INT size; + +- if (TREE_CODE (exp) == MEM_REF +- && TREE_CODE (TREE_OPERAND (exp, 0)) == SSA_NAME +- && tree_fits_shwi_p (TREE_OPERAND (exp, 1)) ++ if ((TREE_CODE (exp) == MEM_REF || TREE_CODE (exp) == ARRAY_REF ++ || TREE_CODE (exp) == COMPONENT_REF) + && (size = int_size_in_bytes (TREE_TYPE (exp))) > 0) + { +- tree name = TREE_OPERAND (exp, 0); +- struct name_to_bb map; +- name_to_bb **slot; +- struct name_to_bb *n2bb; ++ struct ref_to_bb map; ++ ref_to_bb **slot; ++ struct ref_to_bb *r2bb; + basic_block found_bb = 0; + +- /* Try to find the last seen MEM_REF through the same +- SSA_NAME, which can trap. */ +- map.ssa_name_ver = SSA_NAME_VERSION (name); +- map.phase = 0; +- map.bb = 0; +- map.store = store; +- map.offset = tree_to_shwi (TREE_OPERAND (exp, 1)); +- map.size = size; ++ if (!store) ++ { ++ tree base = get_base_address (exp); ++ /* Only record a LOAD of a local variable without address-taken, as ++ the local stack is always writable. This allows cselim on a STORE ++ with a dominating LOAD. */ ++ if (!auto_var_p (base) || TREE_ADDRESSABLE (base)) ++ return; ++ } + +- slot = m_seen_ssa_names.find_slot (&map, INSERT); +- n2bb = *slot; +- if (n2bb && n2bb->phase >= nt_call_phase) +- found_bb = n2bb->bb; ++ /* Try to find the last seen *_REF, which can trap. */ ++ map.exp = exp; ++ map.size = size; ++ slot = m_seen_refs.find_slot (&map, INSERT); ++ r2bb = *slot; ++ if (r2bb && r2bb->phase >= nt_call_phase) ++ found_bb = r2bb->bb; + +- /* If we've found a trapping MEM_REF, _and_ it dominates EXP +- (it's in a basic block on the path from us to the dominator root) ++ /* If we've found a trapping *_REF, _and_ it dominates EXP ++ (it's in a basic block on the path from us to the dominator root) + then we can't trap. */ + if (found_bb && (((size_t)found_bb->aux) & 1) == 1) + { + m_nontrapping->add (exp); + } + else +- { ++ { + /* EXP might trap, so insert it into the hash table. */ +- if (n2bb) ++ if (r2bb) + { +- n2bb->phase = nt_call_phase; +- n2bb->bb = bb; ++ r2bb->phase = nt_call_phase; ++ r2bb->bb = bb; + } + else + { +- n2bb = XNEW (struct name_to_bb); +- n2bb->ssa_name_ver = SSA_NAME_VERSION (name); +- n2bb->phase = nt_call_phase; +- n2bb->bb = bb; +- n2bb->store = store; +- n2bb->offset = map.offset; +- n2bb->size = size; +- *slot = n2bb; ++ r2bb = XNEW (struct ref_to_bb); ++ r2bb->phase = nt_call_phase; ++ r2bb->bb = bb; ++ r2bb->exp = exp; ++ r2bb->size = size; ++ *slot = r2bb; + } + } + } +-- +2.21.0.windows.1 + diff --git a/0003-version-Set-version-to-10.3.1.patch b/0003-version-Set-version-to-10.3.1.patch new file mode 100644 index 0000000..d069bdd --- /dev/null +++ b/0003-version-Set-version-to-10.3.1.patch @@ -0,0 +1,31 @@ +From 309f459021a3681d728e5cf644a288ecf2b95175 Mon Sep 17 00:00:00 2001 +From: zhanghaijian +Date: Mon, 12 Jul 2021 09:42:11 +0800 +Subject: [PATCH 03/13] [version] Set version to 10.3.1 + +Set version to 10.3.1 and clear DATESTAMP_s. + +diff --git a/gcc/BASE-VER b/gcc/BASE-VER +index 0719d810258..a9368325816 100644 +--- a/gcc/BASE-VER ++++ b/gcc/BASE-VER +@@ -1 +1 @@ +-10.3.0 ++10.3.1 +diff --git a/gcc/Makefile.in b/gcc/Makefile.in +index 646db219460..fdc2857d44a 100644 +--- a/gcc/Makefile.in ++++ b/gcc/Makefile.in +@@ -885,8 +885,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.21.0.windows.1 + diff --git a/0004-Backport-tree-optimization-Avoid-issueing-loads-in-S.patch b/0004-Backport-tree-optimization-Avoid-issueing-loads-in-S.patch new file mode 100644 index 0000000..54b4116 --- /dev/null +++ b/0004-Backport-tree-optimization-Avoid-issueing-loads-in-S.patch @@ -0,0 +1,138 @@ +From bdb0f40cea4aa1a92ead381b645363ae0571c065 Mon Sep 17 00:00:00 2001 +From: zhanghaijian +Date: Mon, 12 Jul 2021 10:36:15 +0800 +Subject: [PATCH 04/13] [Backport]tree-optimization: Avoid issueing loads in SM + when possible + +Reference:https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=f9e1ea10e657af9fb02fafecf1a600740fd34409 + +Currently store-motion emits a load of the value in the loop +preheader even when the original loop does not contain any read +of the reference. This avoids doing this. In the conditional +store-motion case we need to mark the sunk stores with no-warning +since the control dependence is too tricky to figure out for +the uninit warning. + +diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr39612.c b/gcc/testsuite/gcc.dg/tree-ssa/pr39612.c +new file mode 100755 +index 00000000000..884f905148f +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/tree-ssa/pr39612.c +@@ -0,0 +1,21 @@ ++/* { dg-do compile } */ ++/* { dg-options "-O2 -fdump-tree-lim2-details -Wuninitialized" } */ ++ ++void foo(int *); ++void f2(int dst[3], int R) ++{ ++ int i, inter[2]; ++ ++ for (i = 1; i < R; i++) { ++ if (i & 8) ++ { ++ inter[0] = 1; ++ inter[1] = 1; ++ } ++ } ++ ++ foo(inter); ++} ++ ++/* { dg-final { scan-tree-dump-times "Executing store motion" 2 "lim2" } } */ ++/* { dg-final { scan-tree-dump-not " = inter\\\[\[0-1\]\\\];" "lim2" } } */ +diff --git a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c +index abd5f702b91..b3fd1647fbd 100644 +--- a/gcc/tree-ssa-loop-im.c ++++ b/gcc/tree-ssa-loop-im.c +@@ -127,6 +127,8 @@ public: + + bitmap stored; /* The set of loops in that this memory location + is stored to. */ ++ bitmap loaded; /* The set of loops in that this memory location ++ is loaded from. */ + vec accesses_in_loop; + /* The locations of the accesses. Vector + indexed by the loop number. */ +@@ -1395,6 +1397,7 @@ mem_ref_alloc (ao_ref *mem, unsigned hash, unsigned id) + ref->ref_decomposed = false; + ref->hash = hash; + ref->stored = NULL; ++ ref->loaded = NULL; + bitmap_initialize (&ref->indep_loop, &lim_bitmap_obstack); + bitmap_initialize (&ref->dep_loop, &lim_bitmap_obstack); + ref->accesses_in_loop.create (1); +@@ -1435,6 +1438,27 @@ mark_ref_stored (im_mem_ref *ref, class loop *loop) + loop = loop_outer (loop); + } + ++/* Set the LOOP bit in REF loaded bitmap and allocate that if ++ necessary. Return whether a bit was changed. */ ++ ++static bool ++set_ref_loaded_in_loop (im_mem_ref *ref, class loop *loop) ++{ ++ if (!ref->loaded) ++ ref->loaded = BITMAP_ALLOC (&lim_bitmap_obstack); ++ return bitmap_set_bit (ref->loaded, loop->num); ++} ++ ++/* Marks reference REF as loaded in LOOP. */ ++ ++static void ++mark_ref_loaded (im_mem_ref *ref, class loop *loop) ++{ ++ while (loop != current_loops->tree_root ++ && set_ref_loaded_in_loop (ref, loop)) ++ loop = loop_outer (loop); ++} ++ + /* Gathers memory references in statement STMT in LOOP, storing the + information about them in the memory_accesses structure. Marks + the vops accessed through unrecognized statements there as +@@ -1571,6 +1595,8 @@ gather_mem_refs_stmt (class loop *loop, gimple *stmt) + bitmap_set_bit (&memory_accesses.refs_stored_in_loop[loop->num], ref->id); + mark_ref_stored (ref, loop); + } ++ else ++ mark_ref_loaded (ref, loop); + init_lim_data (stmt)->ref = ref->id; + return; + } +@@ -1968,6 +1994,8 @@ execute_sm_if_changed (edge ex, tree mem, tree tmp_var, tree flag, + gsi = gsi_start_bb (then_bb); + /* Insert actual store. */ + stmt = gimple_build_assign (unshare_expr (mem), tmp_var); ++ /* Make sure to not warn about maybe-uninit uses of tmp_var here. */ ++ gimple_set_no_warning (stmt, true); + gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING); + + edge e1 = single_succ_edge (new_bb); +@@ -2115,14 +2143,17 @@ execute_sm (class loop *loop, vec exits, im_mem_ref *ref) + by move_computations after all dependencies. */ + gsi = gsi_for_stmt (first_mem_ref_loc (loop, ref)->stmt); + +- /* FIXME/TODO: For the multi-threaded variant, we could avoid this +- load altogether, since the store is predicated by a flag. We +- could, do the load only if it was originally in the loop. */ +- load = gimple_build_assign (tmp_var, unshare_expr (ref->mem.ref)); +- lim_data = init_lim_data (load); +- lim_data->max_loop = loop; +- lim_data->tgt_loop = loop; +- gsi_insert_before (&gsi, load, GSI_SAME_STMT); ++ /* Avoid doing a load if there was no load of the ref in the loop. ++ Esp. when the ref is not always stored we cannot optimize it ++ away later. */ ++ if (ref->loaded && bitmap_bit_p (ref->loaded, loop->num)) ++ { ++ load = gimple_build_assign (tmp_var, unshare_expr (ref->mem.ref)); ++ lim_data = init_lim_data (load); ++ lim_data->max_loop = loop; ++ lim_data->tgt_loop = loop; ++ gsi_insert_before (&gsi, load, GSI_SAME_STMT); ++ } + + if (multi_threaded_model_p) + { +-- +2.21.0.windows.1 + diff --git a/0005-Backport-tree-optimization-Fix-load-eliding-in-SM.patch b/0005-Backport-tree-optimization-Fix-load-eliding-in-SM.patch new file mode 100644 index 0000000..0ab01ea --- /dev/null +++ b/0005-Backport-tree-optimization-Fix-load-eliding-in-SM.patch @@ -0,0 +1,66 @@ +From dc238e97a75835231939e77e8568ccd9bc5187d5 Mon Sep 17 00:00:00 2001 +From: zhanghaijian +Date: Mon, 12 Jul 2021 10:46:16 +0800 +Subject: [PATCH 05/13] [Backport]tree-optimization: Fix load eliding in SM + +Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=0424a5ece5307cc22bbc0fe97edf4707d7a798ed + +This fixes the case of not using the multithreaded model when +only conditionally storing to the destination. We cannot elide +the load in this case. + +diff --git a/gcc/testsuite/gcc.dg/torture/pr94949.c b/gcc/testsuite/gcc.dg/torture/pr94949.c +new file mode 100755 +index 00000000000..6182d77b3cd +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/torture/pr94949.c +@@ -0,0 +1,17 @@ ++/* { dg-do run } */ ++/* { dg-additional-options "-fallow-store-data-races" } */ ++ ++static int x = 1; ++static volatile int y = -1; ++int ++main() ++{ ++ for (int i = 0; i < 128; ++i) ++ { ++ if (i == y) ++ x = i; ++ } ++ if (x != 1) ++ __builtin_abort (); ++ return 0; ++} +diff --git a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c +index b3fd1647fbd..8c33735b1fa 100644 +--- a/gcc/tree-ssa-loop-im.c ++++ b/gcc/tree-ssa-loop-im.c +@@ -2128,9 +2128,9 @@ execute_sm (class loop *loop, vec exits, im_mem_ref *ref) + fmt_data.orig_loop = loop; + for_each_index (&ref->mem.ref, force_move_till, &fmt_data); + ++ bool always_stored = ref_always_accessed_p (loop, ref, true); + if (bb_in_transaction (loop_preheader_edge (loop)->src) +- || (! flag_store_data_races +- && ! ref_always_accessed_p (loop, ref, true))) ++ || (! flag_store_data_races && ! always_stored)) + multi_threaded_model_p = true; + + if (multi_threaded_model_p) +@@ -2145,8 +2145,10 @@ execute_sm (class loop *loop, vec exits, im_mem_ref *ref) + + /* Avoid doing a load if there was no load of the ref in the loop. + Esp. when the ref is not always stored we cannot optimize it +- away later. */ +- if (ref->loaded && bitmap_bit_p (ref->loaded, loop->num)) ++ away later. But when it is not always stored we must use a conditional ++ store then. */ ++ if ((!always_stored && !multi_threaded_model_p) ++ || (ref->loaded && bitmap_bit_p (ref->loaded, loop->num))) + { + load = gimple_build_assign (tmp_var, unshare_expr (ref->mem.ref)); + lim_data = init_lim_data (load); +-- +2.21.0.windows.1 + diff --git a/0006-simdmath-Enable-simdmath-on-kunpeng.patch b/0006-simdmath-Enable-simdmath-on-kunpeng.patch new file mode 100644 index 0000000..9d7bb57 --- /dev/null +++ b/0006-simdmath-Enable-simdmath-on-kunpeng.patch @@ -0,0 +1,289 @@ +From cfd6920125f7968f0c1f5cb225f9fbd5bc8988b9 Mon Sep 17 00:00:00 2001 +From: bule +Date: Tue, 13 Jul 2021 15:26:54 +0800 +Subject: [PATCH 06/13] [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. + +diff --git a/gcc/c-family/c-opts.c b/gcc/c-family/c-opts.c +index c51d6d34726..dc1a8984871 100644 +--- a/gcc/c-family/c-opts.c ++++ b/gcc/c-family/c-opts.c +@@ -780,6 +780,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 ec5235c3a41..8eb05570418 100644 +--- a/gcc/common.opt ++++ b/gcc/common.opt +@@ -1977,6 +1977,10 @@ fmath-errno + Common Report Var(flag_errno_math) Init(1) Optimization SetByCombined + Set errno after built-in math functions. + ++fsimdmath ++Common Report 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.c b/gcc/config/aarch64/aarch64.c +index 9b400c49ac6..79dc8f186f4 100644 +--- a/gcc/config/aarch64/aarch64.c ++++ b/gcc/config/aarch64/aarch64.c +@@ -23077,8 +23077,12 @@ aarch64_simd_clone_compute_vecsize_and_simdlen (struct cgraph_node *node, + elt_bits = GET_MODE_BITSIZE (SCALAR_TYPE_MODE (base_type)); + if (clonei->simdlen == 0) + { +- 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 = vec_bits / elt_bits; + } + else +diff --git a/gcc/config/aarch64/aarch64.opt b/gcc/config/aarch64/aarch64.opt +index 1b3d942e0f5..4539156d6f4 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.c b/gcc/fortran/scanner.c +index 6f93508f934..42fd5a8be1e 100644 +--- a/gcc/fortran/scanner.c ++++ b/gcc/fortran/scanner.c +@@ -2737,6 +2737,10 @@ gfc_new_file (void) + && !load_file (flag_pre_include, NULL, false)) + exit (FATAL_EXIT_CODE); + ++ if (flag_simdmath ++ && !load_file ("simdmath_f.h", NULL, false)) ++ exit (FATAL_EXIT_CODE); ++ + if (gfc_cpp_enabled ()) + { + result = gfc_cpp_preprocess (gfc_source_file); +diff --git a/gcc/opts.c b/gcc/opts.c +index 73162528938..e31aa560564 100644 +--- a/gcc/opts.c ++++ b/gcc/opts.c +@@ -189,6 +189,7 @@ 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 (enum debug_info_type type, int extended, + const char *arg, struct gcc_options *opts, + struct gcc_options *opts_set, +@@ -2469,6 +2470,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; +@@ -2847,6 +2852,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/libgomp/Makefile.am b/libgomp/Makefile.am +index 669b9e4defd..0d9cc96481c 100644 +--- a/libgomp/Makefile.am ++++ b/libgomp/Makefile.am +@@ -74,10 +74,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 ae5d9d54705..dd4b334895e 100644 +--- a/libgomp/Makefile.in ++++ b/libgomp/Makefile.in +@@ -148,7 +148,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'`; +@@ -609,9 +609,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 \ +@@ -702,6 +702,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 5240f7e9d39..b03036c2738 100644 +--- a/libgomp/configure ++++ b/libgomp/configure +@@ -17050,7 +17050,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" + +@@ -18205,6 +18205,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 ef5d293c31e..569c2065a66 100644 +--- a/libgomp/configure.ac ++++ b/libgomp/configure.ac +@@ -433,7 +433,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 00000000000..ab91a4ec317 +--- /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 00000000000..550595015db +--- /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.21.0.windows.1 + diff --git a/0007-Vect-Enable-skipping-vectorization-on-reduction-chai.patch b/0007-Vect-Enable-skipping-vectorization-on-reduction-chai.patch new file mode 100644 index 0000000..ffe5327 --- /dev/null +++ b/0007-Vect-Enable-skipping-vectorization-on-reduction-chai.patch @@ -0,0 +1,68 @@ +From 07033bcc5b9e4c03846cd84b4587cd493fcf7d53 Mon Sep 17 00:00:00 2001 +From: zhoukaipeng +Date: Wed, 14 Jul 2021 11:24:06 +0800 +Subject: [PATCH 07/13] [Vect] Enable skipping vectorization on reduction + chains + +Sometimes either vectorization on reduction chains or reductions is +possible. But the latter is better. The option "-ftree-vect-analyze +-slp-group" skips the former. + +diff --git a/gcc/common.opt b/gcc/common.opt +index 8eb05570418..55d4eb5a351 100644 +--- a/gcc/common.opt ++++ b/gcc/common.opt +@@ -2968,6 +2968,10 @@ ftree-slp-vectorize + Common Report Var(flag_tree_slp_vectorize) Optimization EnabledBy(ftree-vectorize) + Enable basic block vectorization (SLP) on trees. + ++ftree-vect-analyze-slp-group ++Common Report Var(flag_tree_slp_group) Init(0) ++Disable SLP vectorization for reduction chain on tree. ++ + fvect-cost-model= + Common Joined RejectNegative Enum(vect_cost_model) Var(flag_vect_cost_model) Init(VECT_COST_MODEL_DEFAULT) Optimization + -fvect-cost-model=[unlimited|dynamic|cheap] Specifies the cost model for vectorization. +diff --git a/gcc/testsuite/gcc.dg/vect/vect-reduc-12.c b/gcc/testsuite/gcc.dg/vect/vect-reduc-12.c +new file mode 100644 +index 00000000000..913f1ef28df +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/vect/vect-reduc-12.c +@@ -0,0 +1,20 @@ ++/* { dg-do compile } */ ++/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-details -funsafe-math-optimizations -fno-tree-reassoc -ftree-vect-analyze-slp-group" } */ ++void f(double *a, double *res, double m) { ++ double res1, res0; ++ res1 = 0; ++ res0 = 0; ++ for (int i = 0; i < 1000; i+=8) { ++ res0 += a[i] * m; ++ res1 += a[i+1] * m; ++ res0 += a[i+2] * m; ++ res1 += a[i+3] * m; ++ res0 += a[i+4] * m; ++ res1 += a[i+5] * m; ++ res0 += a[i+6] * m; ++ res1 += a[i+7] * m; ++ } ++ res[0] += res0; ++ res[1] += res1; ++} ++/* { dg-final { scan-tree-dump "vectorized 1 loops" "vect" } } */ +diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c +index adc579ff544..476b3237054 100644 +--- a/gcc/tree-vect-slp.c ++++ b/gcc/tree-vect-slp.c +@@ -2480,7 +2480,8 @@ vect_analyze_slp (vec_info *vinfo, unsigned max_tree_size) + { + /* Find SLP sequences starting from reduction chains. */ + FOR_EACH_VEC_ELT (loop_vinfo->reduction_chains, i, first_element) +- if (! vect_analyze_slp_instance (vinfo, bst_map, first_element, ++ if (flag_tree_slp_group ++ || ! vect_analyze_slp_instance (vinfo, bst_map, first_element, + max_tree_size)) + { + /* Dissolve reduction chain group. */ +-- +2.21.0.windows.1 + diff --git a/0008-Backport-tree-optimization-Add-checks-to-avoid-spoil.patch b/0008-Backport-tree-optimization-Add-checks-to-avoid-spoil.patch new file mode 100644 index 0000000..9b8c4f8 --- /dev/null +++ b/0008-Backport-tree-optimization-Add-checks-to-avoid-spoil.patch @@ -0,0 +1,97 @@ +From 79d1ed2d7f166a498662f6111a4defc55f0061c7 Mon Sep 17 00:00:00 2001 +From: yangyang +Date: Thu, 15 Jul 2021 09:27:27 +0800 +Subject: [PATCH 08/13] [Backport]tree-optimization: Add checks to avoid + spoiling if-conversion + +Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=33d114f570b4a3583421c700396fd5945acebc28 + +Add some checks in pass_splits_paths, so that pass_split_paths can recognize +the missed if-conversion opportunity and do not duplicate the corresponding +block. + +diff --git a/gcc/gimple-ssa-split-paths.c b/gcc/gimple-ssa-split-paths.c +index b3efd43c7ef..9c32da76369 100644 +--- a/gcc/gimple-ssa-split-paths.c ++++ b/gcc/gimple-ssa-split-paths.c +@@ -34,6 +34,7 @@ along with GCC; see the file COPYING3. If not see + #include "gimple-ssa.h" + #include "tree-phinodes.h" + #include "ssa-iterators.h" ++#include "fold-const.h" + + /* Given LATCH, the latch block in a loop, see if the shape of the + path reaching LATCH is suitable for being split by duplication. +@@ -254,6 +255,44 @@ is_feasible_trace (basic_block bb) + } + } + ++ /* Canonicalize the form. */ ++ if (single_pred_p (pred1) && single_pred (pred1) == pred2 ++ && num_stmts_in_pred1 == 0) ++ std::swap (pred1, pred2); ++ ++ /* This is meant to catch another kind of cases that are likely opportunities ++ for if-conversion. After canonicalizing, PRED2 must be an empty block and ++ PRED1 must be the only predecessor of PRED2. Moreover, PRED1 is supposed ++ to end with a cond_stmt which has the same args with the PHI in BB. */ ++ if (single_pred_p (pred2) && single_pred (pred2) == pred1 ++ && num_stmts_in_pred2 == 0) ++ { ++ gimple *cond_stmt = last_stmt (pred1); ++ if (cond_stmt && gimple_code (cond_stmt) == GIMPLE_COND) ++ { ++ tree lhs = gimple_cond_lhs (cond_stmt); ++ tree rhs = gimple_cond_rhs (cond_stmt); ++ ++ gimple_stmt_iterator gsi; ++ for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi)) ++ { ++ gimple *phi = gsi_stmt (gsi); ++ if ((operand_equal_p (gimple_phi_arg_def (phi, 0), lhs) ++ && operand_equal_p (gimple_phi_arg_def (phi, 1), rhs)) ++ || (operand_equal_p (gimple_phi_arg_def (phi, 0), rhs) ++ && (operand_equal_p (gimple_phi_arg_def (phi, 1), lhs)))) ++ { ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ fprintf (dump_file, ++ "Block %d appears to be optimized to a join " ++ "point for if-convertable half-diamond.\n", ++ bb->index); ++ return false; ++ } ++ } ++ } ++ } ++ + /* If the joiner has no PHIs with useful uses there is zero chance + of CSE/DCE/jump-threading possibilities exposed by duplicating it. */ + bool found_useful_phi = false; +diff --git a/gcc/testsuite/gcc.dg/tree-ssa/split-path-12.c b/gcc/testsuite/gcc.dg/tree-ssa/split-path-12.c +new file mode 100644 +index 00000000000..19a130d9bf1 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/tree-ssa/split-path-12.c +@@ -0,0 +1,19 @@ ++/* { dg-do compile } */ ++/* { dg-options "-O2 -fsplit-paths -fdump-tree-split-paths-details " } */ ++ ++double ++foo(double *d1, double *d2, double *d3, int num, double *ip) ++{ ++ double dmax[3]; ++ ++ for (int i = 0; i < num; i++) { ++ dmax[0] = d1[i] < dmax[0] ? dmax[0] : d1[i]; ++ dmax[1] = d2[i] < dmax[1] ? dmax[1] : d2[i]; ++ dmax[2] = d3[i] < dmax[2] ? dmax[2] : d3[i]; ++ ip[i] = dmax[2]; ++ } ++ ++ return dmax[0] + dmax[1] + dmax[2]; ++} ++ ++/* { dg-final { scan-tree-dump "appears to be optimized to a join point for if-convertable half-diamond" "split-paths" } } */ +-- +2.21.0.windows.1 + diff --git a/0009-Backport-expand-Simplify-removing-subregs-when-expan.patch b/0009-Backport-expand-Simplify-removing-subregs-when-expan.patch new file mode 100644 index 0000000..434c669 --- /dev/null +++ b/0009-Backport-expand-Simplify-removing-subregs-when-expan.patch @@ -0,0 +1,141 @@ +From 7bc78d0ab13c37e2b11adb385d9916181ec4cc20 Mon Sep 17 00:00:00 2001 +From: zhanghaijian +Date: Thu, 15 Jul 2021 09:04:55 +0800 +Subject: [PATCH 09/13] [Backport]expand: Simplify removing subregs when + expanding a copy [PR95254] + +Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=9a182ef9ee011935d827ab5c6c9a7cd8e22257d8 + +In rtl expand, if we have a copy that matches one of the following patterns: + (set (subreg:M1 (reg:M2 ...)) (subreg:M1 (reg:M2 ...))) + (set (subreg:M1 (reg:M2 ...)) (mem:M1 ADDR)) + (set (mem:M1 ADDR) (subreg:M1 (reg:M2 ...))) + (set (subreg:M1 (reg:M2 ...)) (constant C)) +where mode M1 is equal in size to M2, try to detect whether the mode change +involves an implicit round trip through memory. If so, see if we can avoid +that by removing the subregs and doing the move in mode M2 instead. + +diff --git a/gcc/expr.c b/gcc/expr.c +index 991b26f3341..d66fdd4e93d 100644 +--- a/gcc/expr.c ++++ b/gcc/expr.c +@@ -3814,6 +3814,78 @@ emit_move_insn (rtx x, rtx y) + gcc_assert (mode != BLKmode + && (GET_MODE (y) == mode || GET_MODE (y) == VOIDmode)); + ++ /* If we have a copy that looks like one of the following patterns: ++ (set (subreg:M1 (reg:M2 ...)) (subreg:M1 (reg:M2 ...))) ++ (set (subreg:M1 (reg:M2 ...)) (mem:M1 ADDR)) ++ (set (mem:M1 ADDR) (subreg:M1 (reg:M2 ...))) ++ (set (subreg:M1 (reg:M2 ...)) (constant C)) ++ where mode M1 is equal in size to M2, try to detect whether the ++ mode change involves an implicit round trip through memory. ++ If so, see if we can avoid that by removing the subregs and ++ doing the move in mode M2 instead. */ ++ ++ rtx x_inner = NULL_RTX; ++ rtx y_inner = NULL_RTX; ++ ++#define CANDIDATE_SUBREG_P(subreg) \ ++ (REG_P (SUBREG_REG (subreg)) \ ++ && known_eq (GET_MODE_SIZE (GET_MODE (SUBREG_REG (subreg))), \ ++ GET_MODE_SIZE (GET_MODE (subreg))) \ ++ && optab_handler (mov_optab, GET_MODE (SUBREG_REG (subreg))) \ ++ != CODE_FOR_nothing) ++ ++#define CANDIDATE_MEM_P(innermode, mem) \ ++ (!targetm.can_change_mode_class ((innermode), GET_MODE (mem), ALL_REGS) \ ++ && !push_operand ((mem), GET_MODE (mem)) \ ++ /* Not a candiate if innermode requires too much alignment. */ \ ++ && (MEM_ALIGN (mem) >= GET_MODE_ALIGNMENT (innermode) \ ++ || targetm.slow_unaligned_access (GET_MODE (mem), \ ++ MEM_ALIGN (mem)) \ ++ || !targetm.slow_unaligned_access ((innermode), \ ++ MEM_ALIGN (mem)))) ++ ++ if (SUBREG_P (x) && CANDIDATE_SUBREG_P (x)) ++ x_inner = SUBREG_REG (x); ++ ++ if (SUBREG_P (y) && CANDIDATE_SUBREG_P (y)) ++ y_inner = SUBREG_REG (y); ++ ++ if (x_inner != NULL_RTX ++ && y_inner != NULL_RTX ++ && GET_MODE (x_inner) == GET_MODE (y_inner) ++ && !targetm.can_change_mode_class (GET_MODE (x_inner), mode, ALL_REGS)) ++ { ++ x = x_inner; ++ y = y_inner; ++ mode = GET_MODE (x_inner); ++ } ++ else if (x_inner != NULL_RTX ++ && MEM_P (y) ++ && CANDIDATE_MEM_P (GET_MODE (x_inner), y)) ++ { ++ x = x_inner; ++ y = adjust_address (y, GET_MODE (x_inner), 0); ++ mode = GET_MODE (x_inner); ++ } ++ else if (y_inner != NULL_RTX ++ && MEM_P (x) ++ && CANDIDATE_MEM_P (GET_MODE (y_inner), x)) ++ { ++ x = adjust_address (x, GET_MODE (y_inner), 0); ++ y = y_inner; ++ mode = GET_MODE (y_inner); ++ } ++ else if (x_inner != NULL_RTX ++ && CONSTANT_P (y) ++ && !targetm.can_change_mode_class (GET_MODE (x_inner), ++ mode, ALL_REGS) ++ && (y_inner = simplify_subreg (GET_MODE (x_inner), y, mode, 0))) ++ { ++ x = x_inner; ++ y = y_inner; ++ mode = GET_MODE (x_inner); ++ } ++ + if (CONSTANT_P (y)) + { + if (optimize +diff --git a/gcc/testsuite/gcc.target/aarch64/pr95254.c b/gcc/testsuite/gcc.target/aarch64/pr95254.c +new file mode 100644 +index 00000000000..10bfc868197 +--- /dev/null ++++ b/gcc/testsuite/gcc.target/aarch64/pr95254.c +@@ -0,0 +1,19 @@ ++/* { dg-do compile } */ ++/* { dg-options "-O2 -ftree-slp-vectorize -march=armv8.2-a+sve -msve-vector-bits=256" } */ ++ ++typedef short __attribute__((vector_size (8))) v4hi; ++ ++typedef union U4HI { v4hi v; short a[4]; } u4hi; ++ ++short b[4]; ++ ++void pass_v4hi (v4hi v) ++{ ++ int i; ++ u4hi u; ++ u.v = v; ++ for (i = 0; i < 4; i++) ++ b[i] = u.a[i]; ++}; ++ ++/* { dg-final { scan-assembler-not "ptrue" } } */ +diff --git a/gcc/testsuite/gcc.target/i386/pr67609.c b/gcc/testsuite/gcc.target/i386/pr67609.c +index 518071bdd86..398cdba5d5f 100644 +--- a/gcc/testsuite/gcc.target/i386/pr67609.c ++++ b/gcc/testsuite/gcc.target/i386/pr67609.c +@@ -1,7 +1,7 @@ + /* { dg-do compile } */ + /* { dg-options "-O2 -msse2" } */ + /* { dg-require-effective-target lp64 } */ +-/* { dg-final { scan-assembler "movdqa" } } */ ++/* { dg-final { scan-assembler "movq\t%xmm0" } } */ + + #include + __m128d reg; +-- +2.21.0.windows.1 + diff --git a/0010-Backport-tree-optimization-94963-avoid-bogus-uninit-.patch b/0010-Backport-tree-optimization-94963-avoid-bogus-uninit-.patch new file mode 100644 index 0000000..e5dbbf2 --- /dev/null +++ b/0010-Backport-tree-optimization-94963-avoid-bogus-uninit-.patch @@ -0,0 +1,98 @@ +From b8b3e29e4cceae2bab6e0774b1af994dbe713d97 Mon Sep 17 00:00:00 2001 +From: zhanghaijian +Date: Thu, 15 Jul 2021 09:13:11 +0800 +Subject: [PATCH 10/13] [Backport]tree-optimization/94963 - avoid bogus uninit + warning with store-motion + +Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=371905d12259c180efb9b1f1b5716e969feb60f9 + +Eliding the load for store-motion causes an uninitialized variable +flowing into the loop, conditionally initialized and used. The +uninit warning cannot relate the flag used to guard the initialization +and use with the actual initialization so the following robustifies +the previous approach of marking the conditional store as not to +be warned on by instead initializing the variable on loop entry +from an uninitialized variable we mark as not to be warned for. + +diff --git a/gcc/testsuite/gcc.dg/pr94963.c b/gcc/testsuite/gcc.dg/pr94963.c +new file mode 100644 +index 00000000000..09c0524fb3a +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/pr94963.c +@@ -0,0 +1,35 @@ ++/* { dg-do compile } */ ++/* { dg-options "-O2 -Wall" } */ ++ ++typedef struct ++{ ++ int p1; ++ int p2; ++ int p3; ++} P; ++struct S ++{ ++ int field; ++}; ++extern int v2; ++extern void foo (struct S *map); ++static struct S var; ++const P *pv; ++int ps; ++void ++f (void) ++{ ++ if (pv != 0) ++ for (const P *ph = pv; ph < &pv[ps]; ++ph) ++ switch (ph->p1) ++ { ++ case 1: ++ v2 = ph->p2; ++ break; ++ case 2: ++ var.field = ph->p3; ++ break; ++ } ++ if (var.field != 0) /* { dg-bogus "uninitialized" } */ ++ foo (&var); ++} +diff --git a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c +index 8c33735b1fa..d74a46ef352 100644 +--- a/gcc/tree-ssa-loop-im.c ++++ b/gcc/tree-ssa-loop-im.c +@@ -1994,8 +1994,6 @@ execute_sm_if_changed (edge ex, tree mem, tree tmp_var, tree flag, + gsi = gsi_start_bb (then_bb); + /* Insert actual store. */ + stmt = gimple_build_assign (unshare_expr (mem), tmp_var); +- /* Make sure to not warn about maybe-uninit uses of tmp_var here. */ +- gimple_set_no_warning (stmt, true); + gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING); + + edge e1 = single_succ_edge (new_bb); +@@ -2149,13 +2147,19 @@ execute_sm (class loop *loop, vec exits, im_mem_ref *ref) + store then. */ + if ((!always_stored && !multi_threaded_model_p) + || (ref->loaded && bitmap_bit_p (ref->loaded, loop->num))) ++ load = gimple_build_assign (tmp_var, unshare_expr (ref->mem.ref)); ++ else + { +- load = gimple_build_assign (tmp_var, unshare_expr (ref->mem.ref)); +- lim_data = init_lim_data (load); +- lim_data->max_loop = loop; +- lim_data->tgt_loop = loop; +- gsi_insert_before (&gsi, load, GSI_SAME_STMT); ++ /* If not emitting a load mark the uninitialized state on the ++ loop entry as not to be warned for. */ ++ tree uninit = create_tmp_reg (TREE_TYPE (tmp_var)); ++ TREE_NO_WARNING (uninit) = 1; ++ load = gimple_build_assign (tmp_var, uninit); + } ++ lim_data = init_lim_data (load); ++ lim_data->max_loop = loop; ++ lim_data->tgt_loop = loop; ++ gsi_insert_before (&gsi, load, GSI_SAME_STMT); + + if (multi_threaded_model_p) + { +-- +2.21.0.windows.1 + diff --git a/0011-simdmath-Enable-64-bits-simd-when-test-simd_pcs_attr.patch b/0011-simdmath-Enable-64-bits-simd-when-test-simd_pcs_attr.patch new file mode 100644 index 0000000..b9f642c --- /dev/null +++ b/0011-simdmath-Enable-64-bits-simd-when-test-simd_pcs_attr.patch @@ -0,0 +1,23 @@ +From 78cf3b95d7b895cfe8d6f1c2a48ebc08a662eef0 Mon Sep 17 00:00:00 2001 +From: bule +Date: Sat, 17 Jul 2021 16:38:10 +0800 +Subject: [PATCH 11/13] [simdmath] Enable 64-bits simd when test + simd_pcs_attribute-3 + +Enable 64-bits simd when test simd_pcs_attribute-3. The 64-bits simd +is default to off without specify the -msimdmath-64. + +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 95f6a6803e8..e0e0efa9d7e 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__)) +-- +2.21.0.windows.1 + diff --git a/0012-fp-model-Enable-fp-model-on-kunpeng.patch b/0012-fp-model-Enable-fp-model-on-kunpeng.patch new file mode 100644 index 0000000..3e99f88 --- /dev/null +++ b/0012-fp-model-Enable-fp-model-on-kunpeng.patch @@ -0,0 +1,397 @@ +From 26ea42402eede6a441c9d74ec6b6086e5bf0bf79 Mon Sep 17 00:00:00 2001 +From: bule +Date: Mon, 19 Jul 2021 12:04:08 +0800 +Subject: [PATCH 12/13] [fp-model] Enable fp-model on kunpeng + +Enable fp-model options on kunpeng for precision control. + +diff --git a/gcc/common.opt b/gcc/common.opt +index 55d4eb5a351..79c9ef6615b 100644 +--- a/gcc/common.opt ++++ b/gcc/common.opt +@@ -1545,6 +1545,32 @@ ffp-int-builtin-inexact + Common Report Var(flag_fp_int_builtin_inexact) Init(1) Optimization + Allow built-in functions ceil, floor, round, trunc to raise \"inexact\" exceptions. + ++fftz ++Common Report 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 e587e2e9ad6..331b12c8702 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 852ea76eaa2..5832298251e 100644 +--- a/gcc/flag-types.h ++++ b/gcc/flag-types.h +@@ -223,6 +223,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.c b/gcc/fortran/options.c +index 4cc8a908417..c59dcf63781 100644 +--- a/gcc/fortran/options.c ++++ b/gcc/fortran/options.c +@@ -250,6 +250,7 @@ form_from_filename (const char *filename) + return f_form; + } + ++static void gfc_handle_fpe_option (const char *arg, bool trap); + + /* Finalize commandline options. */ + +@@ -277,6 +278,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.c b/gcc/opts-common.c +index de9510abd64..bf82b05c8a2 100644 +--- a/gcc/opts-common.c ++++ b/gcc/opts-common.c +@@ -26,7 +26,8 @@ along with GCC; see the file COPYING3. If not see + #include "diagnostic.h" + #include "spellcheck.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, +@@ -988,7 +989,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 +@@ -1009,11 +1010,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 bewteen 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; +@@ -1024,7 +1123,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++) + { +@@ -1048,6 +1152,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]; +@@ -1087,6 +1219,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.c b/gcc/opts.c +index e31aa560564..6924a973a5b 100644 +--- a/gcc/opts.c ++++ b/gcc/opts.c +@@ -195,6 +195,7 @@ static void set_debug_level (enum debug_info_type type, 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, +@@ -2482,6 +2483,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; +@@ -2908,6 +2913,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.21.0.windows.1 + diff --git a/0013-LoopElim-Redundant-loop-elimination-optimization.patch b/0013-LoopElim-Redundant-loop-elimination-optimization.patch new file mode 100644 index 0000000..d50107e --- /dev/null +++ b/0013-LoopElim-Redundant-loop-elimination-optimization.patch @@ -0,0 +1,499 @@ +From 0d14a2b7a3defc82ed16c99a18c2bc2e6be9f5b1 Mon Sep 17 00:00:00 2001 +From: xiezhiheng +Date: Fri, 16 Jul 2021 23:21:38 -0400 +Subject: [PATCH 13/13] [LoopElim] Redundant loop elimination optimization + +Introduce redundant loop elimination optimization controlled +by -floop-elim. And it's often used with -ffinite-loops. + +diff --git a/gcc/common.opt b/gcc/common.opt +index 79c9ef6615b..b2b0aac7fdf 100644 +--- a/gcc/common.opt ++++ b/gcc/common.opt +@@ -1169,6 +1169,10 @@ fcompare-elim + Common Report Var(flag_compare_elim_after_reload) Optimization + Perform comparison elimination after register allocation has finished. + ++floop-elim ++Common Report 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.c b/gcc/tree-ssa-phiopt.c +index 3b5b6907679..591b6435f78 100644 +--- a/gcc/tree-ssa-phiopt.c ++++ b/gcc/tree-ssa-phiopt.c +@@ -69,6 +69,7 @@ static hash_set * get_non_trapping (); + static void replace_phi_edge_with_variable (basic_block, edge, gimple *, 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 +@@ -257,6 +258,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; + +@@ -2819,6 +2824,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.21.0.windows.1
+
diff --git a/0014-Backport-StructReorg-Structure-reorganization-optimi.patch b/0014-Backport-StructReorg-Structure-reorganization-optimi.patch
new file mode 100644
index 0000000..1565e4a
--- /dev/null
+++ b/0014-Backport-StructReorg-Structure-reorganization-optimi.patch
@@ -0,0 +1,5966 @@
+From 9e44d351dec892bf862134720f5906dffb39456e Mon Sep 17 00:00:00 2001
+From: xiezhiheng 
+Date: Wed, 14 Jul 2021 21:32:57 -0400
+Subject: [PATCH 14/22] [Backport][StructReorg] 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.
+
+diff --git a/gcc/Makefile.in b/gcc/Makefile.in
+index fdc2857d44a..23394c64bc3 100644
+--- a/gcc/Makefile.in
++++ b/gcc/Makefile.in
+@@ -1398,6 +1398,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 b2b0aac7fdf..d096ff9c314 100644
+--- a/gcc/common.opt
++++ b/gcc/common.opt
+@@ -1866,8 +1866,8 @@ Common Ignore
+ Does nothing. Preserved for backward compatibility.
+ 
+ fipa-struct-reorg
+-Common Ignore
+-Does nothing. Preserved for backward compatibility.
++Common Report Var(flag_ipa_struct_reorg) Init(0) Optimization
++Perform structure layout optimizations.
+ 
+ fipa-vrp
+ Common Report Var(flag_ipa_vrp) Optimization
+diff --git a/gcc/configure b/gcc/configure
+index 8fe9c91fd7c..27beb6b1e9c 100644
+--- a/gcc/configure
++++ b/gcc/configure
+@@ -32168,7 +32168,7 @@ $as_echo "$as_me: executing $ac_file commands" >&6;}
+     "depdir":C) $SHELL $ac_aux_dir/mkinstalldirs $DEPDIR ;;
+     "gccdepdir":C)
+   ${CONFIG_SHELL-/bin/sh} $ac_aux_dir/mkinstalldirs build/$DEPDIR
+-  for lang in $subdirs c-family common analyzer
++  for lang in $subdirs c-family common analyzer 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 84dceb8074a..82a0ce995f1 100644
+--- a/gcc/configure.ac
++++ b/gcc/configure.ac
+@@ -1245,7 +1245,7 @@ AC_CHECK_HEADERS(ext/hash_map)
+ ZW_CREATE_DEPDIR
+ AC_CONFIG_COMMANDS([gccdepdir],[
+   ${CONFIG_SHELL-/bin/sh} $ac_aux_dir/mkinstalldirs build/$DEPDIR
+-  for lang in $subdirs c-family common analyzer
++  for lang in $subdirs c-family common analyzer 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 eabeec944e7..7b4578e3e44 100644
+--- a/gcc/doc/invoke.texi
++++ b/gcc/doc/invoke.texi
+@@ -478,6 +478,7 @@ Objective-C and Objective-C++ Dialects}.
+ -finline-functions  -finline-functions-called-once  -finline-limit=@var{n} @gol
+ -finline-small-functions  -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
+@@ -10223,6 +10224,19 @@ Enabled by default at @option{-O} and higher.
+ Reduce stack alignment on call sites if possible.
+ Enabled by default.
+ 
++@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-pta
+ @opindex fipa-pta
+ Perform interprocedural pointer analysis and interprocedural modification
+@@ -11981,6 +11995,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/ipa-param-manipulation.c b/gcc/ipa-param-manipulation.c
+index fbeea454084..6ba905fe1ee 100644
+--- a/gcc/ipa-param-manipulation.c
++++ b/gcc/ipa-param-manipulation.c
+@@ -49,7 +49,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 0b038ea57f1..dcda81dc8f8 100644
+--- a/gcc/ipa-param-manipulation.h
++++ b/gcc/ipa-param-manipulation.h
+@@ -131,6 +131,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
+ };
+ 
+@@ -194,7 +195,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 00000000000..929279c8faf
+--- /dev/null
++++ b/gcc/ipa-struct-reorg/escapes.def
+@@ -0,0 +1,60 @@
++/* Copyright (C) 2016 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.c b/gcc/ipa-struct-reorg/ipa-struct-reorg.c
+new file mode 100644
+index 00000000000..8d1ddc82877
+--- /dev/null
++++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.c
+@@ -0,0 +1,3918 @@
++/* Struct-reorg optimizations.
++   Copyright (C) 2016-2017 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:
++       1. A declaration has been marked as having the attribute used or has user defined
++	  alignment (type too).
++       2. Accesses are via a BIT_FIELD_REF. FIXME: Handle VECTOR_TYPE for this case.
++       3. The "allocation" site is not a known builtin function.
++       4. 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 which is 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 "alloc-pool.h"
++#include "ipa-prop.h"
++#include "ipa-struct-reorg.h"
++#include "tree-eh.h"
++#include "bitmap.h"
++#include "ipa-param-manipulation.h"
++#include "tree-ssa-live.h"  /* For remove_unused_locals.  */
++
++#define VOID_POINTER_P(type) (POINTER_TYPE_P (type) && VOID_TYPE_P (TREE_TYPE (type)))
++
++namespace {
++
++using namespace struct_reorg;
++
++/* 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.  */
++
++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.  */
++
++bool
++handled_type (tree type)
++{
++  type = inner_type (type);
++  if (TREE_CODE (type) == RECORD_TYPE)
++    return !is_va_list_type (type);
++  return false;
++}
++
++} // 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 defition, 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 decl 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
++{
++  // 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. */
++
++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. */
++
++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. */
++
++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.  */
++
++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;
++	}
++      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);
++    }
++}
++
++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 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
++  */
++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 was not a multiplicate and it slipped 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 stamtenet:\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);
++}
+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 00000000000..f2163910896
+--- /dev/null
++++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.h
+@@ -0,0 +1,235 @@
++/* Struct-reorg optimizations.
++   Copyright (C) 2016-2017 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 4aec480798b..2db69cc87ea 100644
+--- a/gcc/params.opt
++++ b/gcc/params.opt
+@@ -736,6 +736,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 adc88bb2929..fa744e25038 100644
+--- a/gcc/passes.def
++++ b/gcc/passes.def
+@@ -173,6 +173,8 @@ along with GCC; see the file COPYING3.  If not see
+   INSERT_PASSES_AFTER (all_late_ipa_passes)
+   NEXT_PASS (pass_materialize_all_clones);
+   NEXT_PASS (pass_ipa_pta);
++  /* FIXME: this should 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 00000000000..1bd0e18ea2e
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/struct/struct-reorg.exp
+@@ -0,0 +1,35 @@
++#   Copyright (C) 1997-2019 Free Software Foundation, Inc.
++
++# This program is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; either version 3 of the License, or
++# (at your option) any later version.
++# 
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++# GNU General Public License for more details.
++# 
++# You should have received a copy of the GNU General Public License
++# along with GCC; see the file COPYING3.  If not see
++# .
++
++load_lib gcc-dg.exp
++load_lib target-supports.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 00000000000..6565fe8dd63
+--- /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 00000000000..44babd35b04
+--- /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 00000000000..5864ad46fd3
+--- /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 00000000000..e5a8a6c847f
+--- /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 00000000000..733413a94d0
+--- /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 00000000000..0ef686e74e7
+--- /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 00000000000..23a53be5386
+--- /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 00000000000..0cbb172f269
+--- /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 00000000000..f900b1349ac
+--- /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 00000000000..dcc545964fd
+--- /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 00000000000..6d6375fc1ea
+--- /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 00000000000..9d32134089f
+--- /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 00000000000..d79992a5302
+--- /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 00000000000..ee9b0d76595
+--- /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 00000000000..9ebb2b4cc96
+--- /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 00000000000..d0dce8b536f
+--- /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 00000000000..71167182d50
+--- /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 00000000000..74fa11f3940
+--- /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 00000000000..60d2466e1da
+--- /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 00000000000..baf617816d6
+--- /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 00000000000..33fce3b2350
+--- /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 00000000000..1c5a3aa15e5
+--- /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 00000000000..a0d1467fe9c
+--- /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 00000000000..6c24e1c8b05
+--- /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 00000000000..8f2f8143f65
+--- /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 00000000000..98bf01a6d07
+--- /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 00000000000..66b0f967c80
+--- /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 00000000000..d28bcfb0237
+--- /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 00000000000..37a6a43a859
+--- /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 00000000000..cba92e99555
+--- /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 29479205c41..d6a05562c2f 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 a97c7bd36fb..d8355754ffa 100644
+--- a/gcc/tree-pass.h
++++ b/gcc/tree-pass.h
+@@ -509,6 +509,7 @@ 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_hsa (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.21.0.windows.1
+
diff --git a/0015-CompleteStructReorg-Complete-Structure-Reorganizatio.patch b/0015-CompleteStructReorg-Complete-Structure-Reorganizatio.patch
new file mode 100644
index 0000000..742056e
--- /dev/null
+++ b/0015-CompleteStructReorg-Complete-Structure-Reorganizatio.patch
@@ -0,0 +1,2134 @@
+From 644c3b8f01f2249dd552cda9e2429b479ebe0af8 Mon Sep 17 00:00:00 2001
+From: xiezhiheng 
+Date: Thu, 15 Jul 2021 21:44:03 -0400
+Subject: [PATCH 15/22] [CompleteStructReorg] Complete Structure Reorganization
+
+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.
+
+diff --git a/gcc/ipa-struct-reorg/escapes.def b/gcc/ipa-struct-reorg/escapes.def
+index 929279c8faf..9020cc48952 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.c b/gcc/ipa-struct-reorg/ipa-struct-reorg.c
+index 8d1ddc82877..5a19ea0bb40 100644
+--- a/gcc/ipa-struct-reorg/ipa-struct-reorg.c
++++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.c
+@@ -96,6 +96,7 @@ along with GCC; see the file COPYING3.  If not see
+ #include "ipa-struct-reorg.h"
+ #include "tree-eh.h"
+ #include "bitmap.h"
++#include "cfgloop.h"
+ #include "ipa-param-manipulation.h"
+ #include "tree-ssa-live.h"  /* For remove_unused_locals.  */
+ 
+@@ -104,6 +105,7 @@ along with GCC; see the file COPYING3.  If not see
+ namespace {
+ 
+ using namespace struct_reorg;
++using namespace struct_relayout;
+ 
+ /* Return true iff TYPE is stdarg va_list type.  */
+ 
+@@ -159,6 +161,14 @@ handled_type (tree type)
+   return false;
+ }
+ 
++enum srmode
++{
++  NORMAL = 0,
++  COMPLETE_STRUCT_RELAYOUT
++};
++
++static bool is_result_of_mult (tree arg, tree *num, tree struct_size);
++
+ } // anon namespace
+ 
+ namespace struct_reorg {
+@@ -248,7 +258,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;
+@@ -448,13 +459,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");
+ }
+ 
+@@ -598,15 +602,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++)
+     {
+@@ -620,7 +616,8 @@ 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);
+         }
+     }
+@@ -641,6 +638,10 @@ 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;
+@@ -805,12 +806,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");
+ }
+ 
+@@ -820,7 +815,10 @@ 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. */
+@@ -864,21 +862,123 @@ 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 {
+ 
++/* Structure definition for ipa_struct_reorg and ipa_struct_relayout.  */
++
+ struct ipa_struct_reorg
+ {
++public:
+   // Constructors
+   ipa_struct_reorg(void)
+     : current_function (NULL),
+-      done_recording(false)
++      done_recording (false),
++      current_mode (NORMAL)
+   {
+   }
+ 
+-  // public methods
+-  unsigned execute(void);
++  unsigned execute (enum srmode mode);
+   void mark_type_as_escape (tree type, escape_type, gimple *stmt = NULL);
+-private:
++
+   // fields
+   auto_vec_del types;
+   auto_vec_del functions;
+@@ -886,8 +986,8 @@ private:
+   srfunction *current_function;
+ 
+   bool done_recording;
++  srmode current_mode;
+ 
+-  // private methods
+   void dump_types (FILE *f);
+   void dump_types_escaped (FILE *f);
+   void dump_functions (FILE *f);
+@@ -917,6 +1017,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);
+@@ -932,6 +1033,7 @@ private:
+   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_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&);
+@@ -944,8 +1046,644 @@ 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, gimple_stmt_iterator *gsi)
++{
++  /* 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
+@@ -1141,8 +1879,10 @@ ipa_struct_reorg::record_type (tree type)
+ 		  f->type = t1;
+ 		  t1->add_field_site (f);
+ 		}
+-	      if (t1 == type1)
+-		type1->mark_escape (escape_rescusive_type, NULL);
++	      if (t1 == type1 && current_mode != COMPLETE_STRUCT_RELAYOUT)
++		{
++		  type1->mark_escape (escape_rescusive_type, NULL);
++		}
+ 	    }
+         }
+     }
+@@ -1279,6 +2019,14 @@ 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);
+     }
+@@ -1315,6 +2063,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)
+         {
+@@ -1328,8 +2077,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);
+@@ -1354,7 +2113,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);
+@@ -1379,6 +2139,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:
+@@ -1460,9 +2246,23 @@ 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;
+@@ -1532,15 +2332,19 @@ 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
++      && (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;
+ }
+@@ -1582,7 +2386,8 @@ ipa_struct_reorg::allocate_size (srtype *type, gimple *stmt)
+       /* 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.  */
++      /* ??? 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))
+@@ -1699,6 +2504,29 @@ ipa_struct_reorg::maybe_record_assign (cgraph_node *node, gassign *stmt)
+     }
+ }
+ 
++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;
++}
++
+ tree
+ get_ref_base_and_offset (tree &e, HOST_WIDE_INT &offset, bool &realpart, bool &imagpart, tree &accesstype)
+ {
+@@ -1738,7 +2566,10 @@ get_ref_base_and_offset (tree &e, HOST_WIDE_INT &offset, bool &realpart, bool &i
+ 	    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:
+@@ -2115,6 +2946,39 @@ ipa_struct_reorg::check_type_and_push (tree newdecl, srtype *type, vec
+ 
+ }
+ 
++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
+@@ -2158,6 +3022,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, just mark the type as escaping.  */
+@@ -2196,6 +3061,24 @@ 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))
+     {
+@@ -2258,6 +3141,13 @@ ipa_struct_reorg::check_other_side (srdecl *decl, tree other, gimple *stmt, vec<
+   srtype *t1 = find_type (inner_type (t));
+   if (t1 == type)
+     {
++      /* In Complete Struct Relayout opti, 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;
+@@ -2305,8 +3195,11 @@ ipa_struct_reorg::check_use (srdecl *decl, gimple *stmt, vec &worklist)
+       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);
+@@ -2336,8 +3229,11 @@ ipa_struct_reorg::check_use (srdecl *decl, gimple *stmt, vec &worklist)
+       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);
+@@ -2618,6 +3514,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))
+@@ -2734,8 +3636,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))
+     {
+@@ -3862,16 +4767,82 @@ 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 ();
++    }
+ 
+-  return rewrite_functions ();
++  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;
++      /* 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 ret;
+ }
+ 
+ const pass_data pass_data_ipa_struct_reorg =
+@@ -3896,17 +4867,27 @@ public:
+ 
+   /* opt_pass methods: */
+   virtual bool gate (function *);
+-  virtual unsigned int execute (function *) { return ipa_struct_reorg ().execute(); }
++  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;
++  }
+ 
+ }; // class pass_ipa_struct_reorg
+ 
+ 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 f2163910896..d8fe399bdf8 100644
+--- a/gcc/ipa-struct-reorg/ipa-struct-reorg.h
++++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.h
+@@ -121,6 +121,7 @@ public:
+ 
+   tree newtype[max_split];
+   bool visited;
++  int has_alloc_array;
+ 
+   // Constructors
+   srtype(tree type);
+@@ -232,4 +233,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 00000000000..4e56e73fcae
+--- /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 00000000000..6ab71abe140
+--- /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 00000000000..72b7db8a9ce
+--- /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 00000000000..771164a96e7
+--- /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 00000000000..4307f69e2cd
+--- /dev/null
++++ b/gcc/testsuite/g++.dg/struct/struct-reorg.exp
+@@ -0,0 +1,26 @@
++#   Copyright (C) 2021-2021 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
+diff --git a/gcc/testsuite/gcc.dg/struct/complete_struct_relayout.c b/gcc/testsuite/gcc.dg/struct/complete_struct_relayout.c
+new file mode 100644
+index 00000000000..811030bf167
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/struct/complete_struct_relayout.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 00000000000..63bb695ae14
+--- /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 00000000000..0f75d5d121c
+--- /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 00000000000..3dcb674c6e9
+--- /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 00000000000..6907158c9b0
+--- /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 00000000000..9e5e05838e6
+--- /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 00000000000..9d58edab80a
+--- /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 00000000000..a99ee0de484
+--- /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 00000000000..fb135ef0bb5
+--- /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 00000000000..9a4b10d9aef
+--- /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 00000000000..9a82da0d6e1
+--- /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.21.0.windows.1
+
diff --git a/0016-StructReorg-Bugfix-in-certain-scenarios.patch b/0016-StructReorg-Bugfix-in-certain-scenarios.patch
new file mode 100644
index 0000000..f16f352
--- /dev/null
+++ b/0016-StructReorg-Bugfix-in-certain-scenarios.patch
@@ -0,0 +1,486 @@
+From 2194d59a20be1ab627089d2f0c082b5a0a217f52 Mon Sep 17 00:00:00 2001
+From: xiezhiheng 
+Date: Tue, 3 Aug 2021 03:49:52 -0400
+Subject: [PATCH 16/22] [StructReorg] Bugfix in certain scenarios
+
+Some bugfix in certain scenarios,
+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
+
+diff --git a/gcc/ipa-struct-reorg/ipa-struct-reorg.c b/gcc/ipa-struct-reorg/ipa-struct-reorg.c
+index 5a19ea0bb40..1cb544ec3b0 100644
+--- a/gcc/ipa-struct-reorg/ipa-struct-reorg.c
++++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.c
+@@ -97,6 +97,7 @@ along with GCC; see the file COPYING3.  If not see
+ #include "tree-eh.h"
+ #include "bitmap.h"
+ #include "cfgloop.h"
++#include "langhooks.h"
+ #include "ipa-param-manipulation.h"
+ #include "tree-ssa-live.h"  /* For remove_unused_locals.  */
+ 
+@@ -161,6 +162,44 @@ handled_type (tree type)
+   return false;
+ }
+ 
++/* 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 (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,
+@@ -999,7 +1038,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);
+@@ -2127,7 +2165,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))
+@@ -2136,7 +2179,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
+@@ -2816,8 +2864,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;
+     }
+ 
+@@ -3753,49 +3807,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
+@@ -4652,7 +4663,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 ())
+@@ -4887,7 +4897,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 fa1df5c8015..a223b4dadea 100644
+--- a/gcc/symbol-summary.h
++++ b/gcc/symbol-summary.h
+@@ -59,6 +59,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 ()
+@@ -71,7 +77,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 00000000000..273baa9a368
+--- /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 00000000000..455f9b501d6
+--- /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 00000000000..afc0bd86ca5
+--- /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 00000000000..9bcfaf3681b
+--- /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 00000000000..052f4e3bdc1
+--- /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;
++}
+diff --git a/gcc/tree.c b/gcc/tree.c
+index 3c17694c703..5c1374d6fb1 100644
+--- a/gcc/tree.c
++++ b/gcc/tree.c
+@@ -5216,6 +5216,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
+@@ -5454,6 +5460,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.  */
+-- 
+2.21.0.windows.1
+
diff --git a/0017-mcmodel-Enable-mcmodel-medium-on-kunpeng.patch b/0017-mcmodel-Enable-mcmodel-medium-on-kunpeng.patch
new file mode 100644
index 0000000..6651392
--- /dev/null
+++ b/0017-mcmodel-Enable-mcmodel-medium-on-kunpeng.patch
@@ -0,0 +1,622 @@
+From 4d76b521d9bb539556011304b8a76dea1e2657a1 Mon Sep 17 00:00:00 2001
+From: bule 
+Date: Fri, 6 Aug 2021 10:20:54 +0800
+Subject: [PATCH 17/22] [mcmodel] Enable mcmodel=medium on kunpeng
+
+Enable mcmodel=medium on kunpeng
+
+diff --git a/gcc/combine.c b/gcc/combine.c
+index 35505cc5311..497e53289ca 100644
+--- a/gcc/combine.c
++++ b/gcc/combine.c
+@@ -1923,6 +1923,12 @@ can_combine_p (rtx_insn *insn, rtx_insn *i3, rtx_insn *pred ATTRIBUTE_UNUSED,
+ 	      break;
+ 
+ 	    case SET:
++	      /* If the set is a symbol loaded by medium code model unspec
++		 escape this combine.  */
++	      if (GET_CODE (SET_SRC (elt)) == UNSPEC
++		  && XVECLEN (SET_SRC (elt), 0) != 0
++		  && targetm.medium_symbol_p (SET_SRC (elt)))
++		return 0;
+ 	      /* Ignore SETs whose result isn't used but not those that
+ 		 have side-effects.  */
+ 	      if (find_reg_note (insn, REG_UNUSED, SET_DEST (elt))
+diff --git a/gcc/config/aarch64/aarch64-opts.h b/gcc/config/aarch64/aarch64-opts.h
+index ee7bed34924..21828803480 100644
+--- a/gcc/config/aarch64/aarch64-opts.h
++++ b/gcc/config/aarch64/aarch64-opts.h
+@@ -66,6 +66,10 @@ enum aarch64_code_model {
+   /* -fpic for small memory model.
+      GOT size to 28KiB (4K*8-4K) or 3580 entries.  */
+   AARCH64_CMODEL_SMALL_SPIC,
++  /* Using movk insn sequence to do 64bit PC relative relocation.  */
++  AARCH64_CMODEL_MEDIUM,
++  /* Using movk insn sequence to do 64bit PC relative got relocation.  */
++  AARCH64_CMODEL_MEDIUM_PIC,
+   /* No assumptions about addresses of code and data.
+      The PIC variant is not yet implemented.  */
+   AARCH64_CMODEL_LARGE
+diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
+index bebd1b36228..226f3a8ff01 100644
+--- a/gcc/config/aarch64/aarch64-protos.h
++++ b/gcc/config/aarch64/aarch64-protos.h
+@@ -95,9 +95,11 @@
+  */
+ enum aarch64_symbol_type
+ {
++  SYMBOL_MEDIUM_ABSOLUTE,
+   SYMBOL_SMALL_ABSOLUTE,
+   SYMBOL_SMALL_GOT_28K,
+   SYMBOL_SMALL_GOT_4G,
++  SYMBOL_MEDIUM_GOT_4G,
+   SYMBOL_SMALL_TLSGD,
+   SYMBOL_SMALL_TLSDESC,
+   SYMBOL_SMALL_TLSIE,
+diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
+index 79dc8f186f4..f78942b04c6 100644
+--- a/gcc/config/aarch64/aarch64.c
++++ b/gcc/config/aarch64/aarch64.c
+@@ -3127,6 +3127,29 @@ aarch64_load_symref_appropriately (rtx dest, rtx imm,
+ 	emit_insn (gen_add_losym (dest, tmp_reg, imm));
+ 	return;
+       }
++    case SYMBOL_MEDIUM_ABSOLUTE:
++      {
++	rtx tmp_reg = dest;
++	machine_mode mode = GET_MODE (dest);
++
++	gcc_assert (mode == Pmode || mode == ptr_mode);
++	if (can_create_pseudo_p ())
++	  tmp_reg = gen_reg_rtx (mode);
++
++	if (mode == DImode)
++	  {
++	    emit_insn (gen_load_symbol_medium_di (dest, tmp_reg, imm));
++	  }
++	else
++	  {
++	    emit_insn (gen_load_symbol_medium_si (dest, tmp_reg, imm));
++	  }
++	if (REG_P (dest))
++	  {
++	    set_unique_reg_note (get_last_insn (), REG_EQUAL, copy_rtx (imm));
++	  }
++	return;
++      }
+ 
+     case SYMBOL_TINY_ABSOLUTE:
+       emit_insn (gen_rtx_SET (dest, imm));
+@@ -3249,6 +3272,60 @@ aarch64_load_symref_appropriately (rtx dest, rtx imm,
+ 	return;
+       }
+ 
++    case SYMBOL_MEDIUM_GOT_4G:
++      {
++	rtx tmp_reg = dest;
++	machine_mode mode = GET_MODE (dest);
++	if (can_create_pseudo_p ())
++	  {
++	    tmp_reg = gen_reg_rtx (mode);
++	  }
++	rtx insn;
++	rtx mem;
++	rtx s = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
++
++	if (mode == DImode)
++	  {
++	    emit_insn (gen_load_symbol_medium_di (tmp_reg, dest, s));
++	  }
++	else
++	  {
++	    emit_insn (gen_load_symbol_medium_si (tmp_reg, dest, s));
++	  }
++	if (REG_P (dest))
++	  {
++	    set_unique_reg_note (get_last_insn (), REG_EQUAL, copy_rtx (s));
++	  }
++
++	if (mode == ptr_mode)
++	  {
++	    if (mode == DImode)
++	      {
++		emit_insn (gen_get_gotoff_di (dest, imm));
++		insn = gen_ldr_got_medium_di (dest, tmp_reg, dest);
++	      }
++	    else
++	      {
++		emit_insn (gen_get_gotoff_si (dest, imm));
++		insn = gen_ldr_got_medium_si (dest, tmp_reg, dest);
++	      }
++	    mem = XVECEXP (SET_SRC (insn), 0, 0);
++	  }
++	else
++	  {
++	    gcc_assert (mode == Pmode);
++	    emit_insn (gen_get_gotoff_di (dest, imm));
++	    insn = gen_ldr_got_medium_sidi (dest, tmp_reg, dest);
++	    mem = XVECEXP (XEXP (SET_SRC (insn), 0), 0, 0);
++	  }
++
++	gcc_assert (GET_CODE (mem) == MEM);
++	MEM_READONLY_P (mem) = 1;
++	MEM_NOTRAP_P (mem) = 1;
++	emit_insn (insn);
++	return;
++      }
++
+     case SYMBOL_SMALL_TLSGD:
+       {
+ 	rtx_insn *insns;
+@@ -5256,11 +5333,12 @@ aarch64_expand_mov_immediate (rtx dest, rtx imm)
+ 
+ 	  return;
+ 
+-        case SYMBOL_SMALL_TLSGD:
+-        case SYMBOL_SMALL_TLSDESC:
++	case SYMBOL_SMALL_TLSGD:
++	case SYMBOL_SMALL_TLSDESC:
+ 	case SYMBOL_SMALL_TLSIE:
+ 	case SYMBOL_SMALL_GOT_28K:
+ 	case SYMBOL_SMALL_GOT_4G:
++	case SYMBOL_MEDIUM_GOT_4G:
+ 	case SYMBOL_TINY_GOT:
+ 	case SYMBOL_TINY_TLSIE:
+ 	  if (const_offset != 0)
+@@ -5279,6 +5357,7 @@ aarch64_expand_mov_immediate (rtx dest, rtx imm)
+ 	case SYMBOL_TLSLE24:
+ 	case SYMBOL_TLSLE32:
+ 	case SYMBOL_TLSLE48:
++	case SYMBOL_MEDIUM_ABSOLUTE:
+ 	  aarch64_load_symref_appropriately (dest, imm, sty);
+ 	  return;
+ 
+@@ -9389,7 +9468,14 @@ aarch64_classify_address (struct aarch64_address_info *info,
+ 	  if (GET_CODE (sym) == SYMBOL_REF
+ 	      && offset.is_constant (&const_offset)
+ 	      && (aarch64_classify_symbol (sym, const_offset)
+-		  == SYMBOL_SMALL_ABSOLUTE))
++		  == SYMBOL_SMALL_ABSOLUTE
++		  /* Fix fail on dbl_mov_immediate_1.c.  If end up here with
++		     MEDIUM_ABSOLUTE, the symbol is a constant number that is
++		     forced to memory in reload pass, which is ok to go on with
++		     the original design that subtitude the mov to
++		     'adrp and ldr :losum'.  */
++		  || aarch64_classify_symbol (sym, const_offset)
++		     == SYMBOL_MEDIUM_ABSOLUTE))
+ 	    {
+ 	      /* The symbol and offset must be aligned to the access size.  */
+ 	      unsigned int align;
+@@ -11346,7 +11432,13 @@ static inline bool
+ aarch64_can_use_per_function_literal_pools_p (void)
+ {
+   return (aarch64_pcrelative_literal_loads
+-	  || aarch64_cmodel == AARCH64_CMODEL_LARGE);
++	  || aarch64_cmodel == AARCH64_CMODEL_LARGE
++	  /* Fix const9.C so that constants goes to function_literal_pools.
++	     According to the orignal design of aarch64 mcmodel=medium, we
++	     don't care where this symbol is put.  For the benefit of code size
++	     and behaviour consistent with other mcmodel, put it into
++	     function_literal_pools.  */
++	  || aarch64_cmodel == AARCH64_CMODEL_MEDIUM);
+ }
+ 
+ static bool
+@@ -13003,6 +13095,13 @@ cost_plus:
+ 	  if (speed)
+ 	    *cost += extra_cost->alu.arith;
+ 	}
++      else if (aarch64_cmodel == AARCH64_CMODEL_MEDIUM
++	       || aarch64_cmodel == AARCH64_CMODEL_MEDIUM_PIC)
++	{
++	  /* 4 movs  adr  sub  add  2movs  ldr.  */
++	  if (speed)
++	    *cost += 7*extra_cost->alu.arith;
++	}
+ 
+       if (flag_pic)
+ 	{
+@@ -13010,6 +13109,8 @@ cost_plus:
+ 	  *cost += COSTS_N_INSNS (1);
+ 	  if (speed)
+ 	    *cost += extra_cost->ldst.load;
++	  if (aarch64_cmodel == AARCH64_CMODEL_MEDIUM_PIC)
++	    *cost += 2*extra_cost->alu.arith;
+ 	}
+       return true;
+ 
+@@ -14373,6 +14474,7 @@ initialize_aarch64_tls_size (struct gcc_options *opts)
+       if (aarch64_tls_size > 32)
+ 	aarch64_tls_size = 32;
+       break;
++    case AARCH64_CMODEL_MEDIUM:
+     case AARCH64_CMODEL_LARGE:
+       /* The maximum TLS size allowed under large is 16E.
+ 	 FIXME: 16E should be 64bit, we only support 48bit offset now.  */
+@@ -15266,6 +15368,12 @@ initialize_aarch64_code_model (struct gcc_options *opts)
+ #endif
+ 	}
+       break;
++    case AARCH64_CMODEL_MEDIUM:
++      if (opts->x_flag_pic)
++      {
++	aarch64_cmodel = AARCH64_CMODEL_MEDIUM_PIC;
++      }
++      break;
+     case AARCH64_CMODEL_LARGE:
+       if (opts->x_flag_pic)
+ 	sorry ("code model %qs with %<-f%s%>", "large",
+@@ -15276,6 +15384,7 @@ initialize_aarch64_code_model (struct gcc_options *opts)
+     case AARCH64_CMODEL_TINY_PIC:
+     case AARCH64_CMODEL_SMALL_PIC:
+     case AARCH64_CMODEL_SMALL_SPIC:
++    case AARCH64_CMODEL_MEDIUM_PIC:
+       gcc_unreachable ();
+     }
+ }
+@@ -15286,6 +15395,7 @@ static void
+ aarch64_option_save (struct cl_target_option *ptr, struct gcc_options *opts)
+ {
+   ptr->x_aarch64_override_tune_string = opts->x_aarch64_override_tune_string;
++  ptr->x_aarch64_data_threshold = opts->x_aarch64_data_threshold;
+   ptr->x_aarch64_branch_protection_string
+     = opts->x_aarch64_branch_protection_string;
+ }
+@@ -15301,6 +15411,7 @@ aarch64_option_restore (struct gcc_options *opts, struct cl_target_option *ptr)
+   opts->x_explicit_arch = ptr->x_explicit_arch;
+   selected_arch = aarch64_get_arch (ptr->x_explicit_arch);
+   opts->x_aarch64_override_tune_string = ptr->x_aarch64_override_tune_string;
++  opts->x_aarch64_data_threshold = ptr->x_aarch64_data_threshold;
+   opts->x_aarch64_branch_protection_string
+     = ptr->x_aarch64_branch_protection_string;
+   if (opts->x_aarch64_branch_protection_string)
+@@ -16169,6 +16280,8 @@ aarch64_classify_symbol (rtx x, HOST_WIDE_INT offset)
+ 
+ 	case AARCH64_CMODEL_SMALL_SPIC:
+ 	case AARCH64_CMODEL_SMALL_PIC:
++	case AARCH64_CMODEL_MEDIUM_PIC:
++	case AARCH64_CMODEL_MEDIUM:
+ 	case AARCH64_CMODEL_SMALL:
+ 	  return SYMBOL_SMALL_ABSOLUTE;
+ 
+@@ -16205,6 +16318,7 @@ aarch64_classify_symbol (rtx x, HOST_WIDE_INT offset)
+ 	  return SYMBOL_TINY_ABSOLUTE;
+ 
+ 	case AARCH64_CMODEL_SMALL:
++	AARCH64_SMALL_ROUTINE:
+ 	  /* Same reasoning as the tiny code model, but the offset cap here is
+ 	     1MB, allowing +/-3.9GB for the offset to the symbol.  */
+ 
+@@ -16228,7 +16342,50 @@ aarch64_classify_symbol (rtx x, HOST_WIDE_INT offset)
+ 		    ?  SYMBOL_SMALL_GOT_28K : SYMBOL_SMALL_GOT_4G);
+ 	  return SYMBOL_SMALL_ABSOLUTE;
+ 
++	case AARCH64_CMODEL_MEDIUM:
++	  {
++	    tree decl_local = SYMBOL_REF_DECL (x);
++	    if (decl_local != NULL
++		&& tree_fits_uhwi_p (DECL_SIZE_UNIT (decl_local)))
++	      {
++		HOST_WIDE_INT size = tree_to_uhwi (DECL_SIZE_UNIT (decl_local));
++		/* If the data is smaller than the threshold, goto
++		   the small code model.  Else goto the large code
++		   model.  */
++		if (size >= HOST_WIDE_INT (aarch64_data_threshold))
++		  goto AARCH64_LARGE_ROUTINE;
++	      }
++	    goto AARCH64_SMALL_ROUTINE;
++	  }
++
++	case AARCH64_CMODEL_MEDIUM_PIC:
++	  {
++	    tree decl_local = SYMBOL_REF_DECL (x);
++	    if (decl_local != NULL
++		&& tree_fits_uhwi_p (DECL_SIZE_UNIT (decl_local)))
++	      {
++		HOST_WIDE_INT size = tree_to_uhwi (DECL_SIZE_UNIT (decl_local));
++		if (size < HOST_WIDE_INT (aarch64_data_threshold))
++		  {
++		    if (!aarch64_symbol_binds_local_p (x))
++		      {
++			/* flag_pic is 2 only when -fPIC is on, when we should
++			   use 4G GOT.  */
++			return flag_pic == 2 ? SYMBOL_SMALL_GOT_4G
++					     : SYMBOL_SMALL_GOT_28K ;
++		      }
++		    return SYMBOL_SMALL_ABSOLUTE;
++		  }
++	      }
++	    if (!aarch64_symbol_binds_local_p (x))
++	      {
++		return SYMBOL_MEDIUM_GOT_4G;
++	      }
++	    return SYMBOL_MEDIUM_ABSOLUTE;
++	  }
++
+ 	case AARCH64_CMODEL_LARGE:
++	AARCH64_LARGE_ROUTINE:
+ 	  /* This is alright even in PIC code as the constant
+ 	     pool reference is always PC relative and within
+ 	     the same translation unit.  */
+@@ -19352,6 +19509,8 @@ aarch64_asm_preferred_eh_data_format (int code ATTRIBUTE_UNUSED, int global)
+      case AARCH64_CMODEL_SMALL:
+      case AARCH64_CMODEL_SMALL_PIC:
+      case AARCH64_CMODEL_SMALL_SPIC:
++     case AARCH64_CMODEL_MEDIUM:
++     case AARCH64_CMODEL_MEDIUM_PIC:
+        /* text+got+data < 4Gb.  4-byte signed relocs are sufficient
+ 	  for everything.  */
+        type = DW_EH_PE_sdata4;
+@@ -22605,7 +22764,14 @@ aarch64_empty_mask_is_expensive (unsigned)
+ bool
+ aarch64_use_pseudo_pic_reg (void)
+ {
+-  return aarch64_cmodel == AARCH64_CMODEL_SMALL_SPIC;
++  /* flag_pic is 2 when -fPIC is on, where we do not need the pseudo
++     pic reg.  In medium code mode, when combine with -fpie/-fpic, there are
++     possibility that some symbol size smaller than the -mlarge-data-threshold
++     will still use SMALL_SPIC relocation, which need the pseudo pic reg.
++     Fix spill_1.c fail.  */
++  return aarch64_cmodel == AARCH64_CMODEL_SMALL_SPIC
++	 || (aarch64_cmodel == AARCH64_CMODEL_MEDIUM_PIC
++	     && flag_pic != 2);
+ }
+ 
+ /* Implement TARGET_UNSPEC_MAY_TRAP_P.  */
+@@ -22615,6 +22781,7 @@ aarch64_unspec_may_trap_p (const_rtx x, unsigned flags)
+ {
+   switch (XINT (x, 1))
+     {
++    case UNSPEC_GOTMEDIUMPIC4G:
+     case UNSPEC_GOTSMALLPIC:
+     case UNSPEC_GOTSMALLPIC28K:
+     case UNSPEC_GOTTINYPIC:
+@@ -22976,6 +23143,18 @@ aarch64_estimated_poly_value (poly_int64 val)
+   return val.coeffs[0] + val.coeffs[1] * over_128 / 128;
+ }
+ 
++/* Implement TARGET_MEDIUM_SYMBOL_P.
++   Return true if x is a symbol loaded by UNSPEC_LOAD_SYMBOL_MEDIUM.  */
++bool
++aarch64_medium_symbol_p (rtx x)
++{
++  if (GET_CODE (x) != UNSPEC)
++    {
++      return false;
++    }
++  return XINT (x, 1) == UNSPEC_LOAD_SYMBOL_MEDIUM;
++}
++
+ 
+ /* Return true for types that could be supported as SIMD return or
+    argument types.  */
+@@ -24015,6 +24194,9 @@ aarch64_libgcc_floating_mode_supported_p
+ #undef TARGET_ESTIMATED_POLY_VALUE
+ #define TARGET_ESTIMATED_POLY_VALUE aarch64_estimated_poly_value
+ 
++#undef TARGET_MEDIUM_SYMBOL_P
++#define TARGET_MEDIUM_SYMBOL_P aarch64_medium_symbol_p
++
+ #undef TARGET_ATTRIBUTE_TABLE
+ #define TARGET_ATTRIBUTE_TABLE aarch64_attribute_table
+ 
+diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
+index 51148846345..8fc92d13dcb 100644
+--- a/gcc/config/aarch64/aarch64.h
++++ b/gcc/config/aarch64/aarch64.h
+@@ -33,6 +33,10 @@
+ 
+ #define REGISTER_TARGET_PRAGMAS() aarch64_register_pragmas ()
+ 
++/* Default threshold 64-bit relocation data
++    with aarch64 medium memory model.  */
++#define AARCH64_DEFAULT_LARGE_DATA_THRESHOLD 65536
++
+ /* Target machine storage layout.  */
+ 
+ #define PROMOTE_MODE(MODE, UNSIGNEDP, TYPE)	\
+diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
+index 58445dea941..ee80261f1ac 100644
+--- a/gcc/config/aarch64/aarch64.md
++++ b/gcc/config/aarch64/aarch64.md
+@@ -224,6 +224,9 @@
+     UNSPEC_RSQRTS
+     UNSPEC_NZCV
+     UNSPEC_XPACLRI
++    UNSPEC_GOTMEDIUMPIC4G
++    UNSPEC_GET_GOTOFF
++    UNSPEC_LOAD_SYMBOL_MEDIUM
+     UNSPEC_LD1_SVE
+     UNSPEC_ST1_SVE
+     UNSPEC_LDNT1_SVE
+@@ -6792,6 +6795,39 @@
+   [(set_attr "type" "load_4")]
+ )
+ 
++(define_insn "get_gotoff_"
++  [(set (match_operand:GPI 0 "register_operand" "=r")
++	(unspec:GPI [(match_operand 1 "aarch64_valid_symref" "S")]
++		  UNSPEC_GET_GOTOFF))]
++  ""
++  "movz\\t%x0, :gotoff_g1:%A1\;movk\\t%x0, :gotoff_g0_nc:%A1"
++  [(set_attr "type" "multiple")
++   (set_attr "length" "8")]
++)
++
++(define_insn "ldr_got_medium_"
++  [(set (match_operand:PTR 0 "register_operand" "=r")
++	(unspec:PTR [(mem:PTR (lo_sum:PTR
++			      (match_operand:PTR 1 "register_operand" "r")
++			      (match_operand:PTR 2 "register_operand" "r")))]
++		    UNSPEC_GOTMEDIUMPIC4G))]
++  ""
++  "ldr\\t%0, [%1, %2]"
++  [(set_attr "type" "load_4")]
++)
++
++(define_insn "ldr_got_medium_sidi"
++  [(set (match_operand:DI 0 "register_operand" "=r")
++	(zero_extend:DI
++	 (unspec:SI [(mem:SI (lo_sum:DI
++			     (match_operand:DI 1 "register_operand" "r")
++			     (match_operand:DI 2 "register_operand" "r")))]
++		    UNSPEC_GOTMEDIUMPIC4G)))]
++  "TARGET_ILP32"
++  "ldr\\t%0, [%1, %2]"
++  [(set_attr "type" "load_4")]
++)
++
+ (define_insn "ldr_got_small_28k_"
+   [(set (match_operand:PTR 0 "register_operand" "=r")
+ 	(unspec:PTR [(mem:PTR (lo_sum:PTR
+@@ -6955,6 +6991,23 @@
+    (set_attr "length" "12")]
+ )
+ 
++(define_insn "load_symbol_medium_"
++   [(set (match_operand:GPI 0 "register_operand" "=r")
++		(unspec:GPI [(match_operand 2 "aarch64_valid_symref" "S")]
++		  UNSPEC_LOAD_SYMBOL_MEDIUM))
++	(clobber (match_operand:GPI 1 "register_operand" "=r"))]
++  ""
++  "movz\\t%x0, :prel_g3:%A2\;\\
++movk\\t%x0, :prel_g2_nc:%A2\;\\
++movk\\t%x0, :prel_g1_nc:%A2\;\\
++movk\\t%x0, :prel_g0_nc:%A2\;\\
++adr\\t%x1, .\;\\
++sub\\t%x1, %x1, 0x4\;\\
++add\\t%x0, %x0, %x1"
++  [(set_attr "type" "multiple")
++   (set_attr "length" "28")]
++)
++
+ (define_expand "tlsdesc_small_"
+   [(unspec:PTR [(match_operand 0 "aarch64_valid_symref")] UNSPEC_TLSDESC)]
+   "TARGET_TLS_DESC"
+diff --git a/gcc/config/aarch64/aarch64.opt b/gcc/config/aarch64/aarch64.opt
+index 4539156d6f4..bb888461ab0 100644
+--- a/gcc/config/aarch64/aarch64.opt
++++ b/gcc/config/aarch64/aarch64.opt
+@@ -27,6 +27,10 @@ enum aarch64_processor explicit_tune_core = aarch64_none
+ TargetVariable
+ enum aarch64_arch explicit_arch = aarch64_no_arch
+ 
++;; -mlarge-data-threshold=
++TargetSave
++int x_aarch64_data_threshold
++
+ TargetSave
+ const char *x_aarch64_override_tune_string
+ 
+@@ -60,9 +64,16 @@ Enum(cmodel) String(tiny) Value(AARCH64_CMODEL_TINY)
+ EnumValue
+ Enum(cmodel) String(small) Value(AARCH64_CMODEL_SMALL)
+ 
++EnumValue
++Enum(cmodel) String(medium) Value(AARCH64_CMODEL_MEDIUM)
++
+ EnumValue
+ Enum(cmodel) String(large) Value(AARCH64_CMODEL_LARGE)
+ 
++mlarge-data-threshold=
++Target RejectNegative Joined UInteger Var(aarch64_data_threshold) Init(AARCH64_DEFAULT_LARGE_DATA_THRESHOLD)
++-mlarge-data-threshold= Data greater than given threshold will be assume that it should be relocated using 64-bit relocation.
++
+ mbig-endian
+ Target Report RejectNegative Mask(BIG_END)
+ Assume target CPU is configured as big endian.
+diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
+index fcb7245e95c..0508fce57a7 100644
+--- a/gcc/doc/tm.texi
++++ b/gcc/doc/tm.texi
+@@ -6983,6 +6983,11 @@ things like cost calculations or profiling frequencies.  The default
+ implementation returns the lowest possible value of @var{val}.
+ @end deftypefn
+ 
++@deftypefn {Target Hook} bool TARGET_MEDIUM_SYMBOL_P (rtx @var{x})
++Return true if the input rtx is a symbol loaded by kunpeng medium code
++model.
++@end deftypefn
++
+ @node Scheduling
+ @section Adjusting the Instruction Scheduler
+ 
+diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
+index c17209daa51..3b70ea4841a 100644
+--- a/gcc/doc/tm.texi.in
++++ b/gcc/doc/tm.texi.in
+@@ -4701,6 +4701,8 @@ Define this macro if a non-short-circuit operation produced by
+ 
+ @hook TARGET_ESTIMATED_POLY_VALUE
+ 
++@hook TARGET_MEDIUM_SYMBOL_P
++
+ @node Scheduling
+ @section Adjusting the Instruction Scheduler
+ 
+diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
+index d61cadb5208..bad8208cd22 100644
+--- a/gcc/dwarf2out.c
++++ b/gcc/dwarf2out.c
+@@ -14501,14 +14501,17 @@ const_ok_for_output_1 (rtx rtl)
+       /* If delegitimize_address couldn't do anything with the UNSPEC, and
+ 	 the target hook doesn't explicitly allow it in debug info, assume
+ 	 we can't express it in the debug info.  */
+-      /* Don't complain about TLS UNSPECs, those are just too hard to
+-	 delegitimize.  Note this could be a non-decl SYMBOL_REF such as
+-	 one in a constant pool entry, so testing SYMBOL_REF_TLS_MODEL
+-	 rather than DECL_THREAD_LOCAL_P is not just an optimization.  */
++      /* Don't complain about TLS UNSPECs and aarch64 medium code model
++	 related UNSPECs, those are just too hard to delegitimize.  Note
++	 this could be a non-decl SYMBOL_REF such as one in a constant
++	 pool entry, so testing SYMBOL_REF_TLS_MODEL rather than
++	 DECL_THREAD_LOCAL_P is not just an optimization.  */
+       if (flag_checking
+ 	  && (XVECLEN (rtl, 0) == 0
+ 	      || GET_CODE (XVECEXP (rtl, 0, 0)) != SYMBOL_REF
+-	      || SYMBOL_REF_TLS_MODEL (XVECEXP (rtl, 0, 0)) == TLS_MODEL_NONE))
++	      || (!targetm.medium_symbol_p (rtl)
++		  && SYMBOL_REF_TLS_MODEL (XVECEXP (rtl, 0, 0))
++		     == TLS_MODEL_NONE)))
+ 	inform (current_function_decl
+ 		? DECL_SOURCE_LOCATION (current_function_decl)
+ 		: UNKNOWN_LOCATION,
+diff --git a/gcc/target.def b/gcc/target.def
+index f5a6d507e91..2020564118b 100644
+--- a/gcc/target.def
++++ b/gcc/target.def
+@@ -3869,6 +3869,13 @@ implementation returns the lowest possible value of @var{val}.",
+  HOST_WIDE_INT, (poly_int64 val),
+  default_estimated_poly_value)
+ 
++DEFHOOK
++(medium_symbol_p,
++ "Return true if the input rtx is a symbol loaded by kunpeng medium code\n\
++model.",
++ bool, (rtx x),
++ default_medium_symbol_p)
++
+ /* Permit speculative instructions in delay slots during delayed-branch 
+    scheduling.  */
+ DEFHOOK
+diff --git a/gcc/targhooks.c b/gcc/targhooks.c
+index 7cb04f30bdb..43a9f0cdf5b 100644
+--- a/gcc/targhooks.c
++++ b/gcc/targhooks.c
+@@ -1708,6 +1708,13 @@ default_estimated_poly_value (poly_int64 x)
+   return x.coeffs[0];
+ }
+ 
++/* The default implementation of TARGET_MEDIUM_SYMBOL_P.  */
++bool
++default_medium_symbol_p (rtx x ATTRIBUTE_UNUSED)
++{
++  return false;
++}
++
+ /* For hooks which use the MOVE_RATIO macro, this gives the legacy default
+    behavior.  SPEED_P is true if we are compiling for speed.  */
+ 
+-- 
+2.21.0.windows.1
+
diff --git a/0018-StructReorderFields-Structure-reorder-fields.patch b/0018-StructReorderFields-Structure-reorder-fields.patch
new file mode 100644
index 0000000..689f066
--- /dev/null
+++ b/0018-StructReorderFields-Structure-reorder-fields.patch
@@ -0,0 +1,5370 @@
+From bc86209da93f71d9fd48cb65ad3200b6c88cf75b Mon Sep 17 00:00:00 2001
+From: huangxiaoquan 
+Date: Tue, 20 Jul 2021 10:09:08 +0800
+Subject: [PATCH 18/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.
+
+diff --git a/gcc/common.opt b/gcc/common.opt
+index d096ff9c314..73c24f28d22 100644
+--- a/gcc/common.opt
++++ b/gcc/common.opt
+@@ -1865,6 +1865,10 @@ fipa-matrix-reorg
+ Common Ignore
+ Does nothing. Preserved for backward compatibility.
+ 
++fipa-reorder-fields
++Common Report Var(flag_ipa_reorder_fields) Init(0) Optimization
++Perform structure fields reorder optimizations.
++
+ fipa-struct-reorg
+ Common Report 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 7b4578e3e44..4b0fd2ffb38 100644
+--- a/gcc/doc/invoke.texi
++++ b/gcc/doc/invoke.texi
+@@ -478,6 +478,7 @@ Objective-C and Objective-C++ Dialects}.
+ -finline-functions  -finline-functions-called-once  -finline-limit=@var{n} @gol
+ -finline-small-functions  -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
+@@ -10224,6 +10225,14 @@ Enabled by default at @option{-O} and higher.
+ Reduce stack alignment on call sites if possible.
+ Enabled by default.
+ 
++@item -fipa-reorder-fields
++@opindex fipa-reorder-fields
++Introduce structure fields reordering optimization, that change fields
++ordering of C-like structures in order to better utilize spatial locality.
++This transformation is affective for programs containing arrays of structures.
++It works only in whole program mode, so it requires @option{-fwhole-program}
++to be enabled.
++
+ @item -fipa-struct-reorg
+ @opindex fipa-struct-reorg
+ Perform structure reorganization optimization, that change C-like structures
+diff --git a/gcc/ipa-struct-reorg/escapes.def b/gcc/ipa-struct-reorg/escapes.def
+index 9020cc48952..03adc30811a 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.c b/gcc/ipa-struct-reorg/ipa-struct-reorg.c
+index 1cb544ec3b0..384aa81583c 100644
+--- a/gcc/ipa-struct-reorg/ipa-struct-reorg.c
++++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.c
+@@ -198,27 +198,66 @@ lang_c_p (void)
+     }
+ 
+   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 arg, tree *num, tree struct_size);
++bool isptrptr (tree type);
++
++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)
+ {
+ }
+ 
+@@ -370,12 +409,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;
+@@ -399,17 +439,25 @@ 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.
++  /* 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;
+ }
+@@ -473,31 +521,29 @@ 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 = {");
++  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 = {");
++  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");
++  fprintf (f, "}\n");
+   fprintf (f, "}\n");
+ }
+ 
+@@ -507,6 +553,10 @@ 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. */
+@@ -544,6 +594,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++)
+@@ -592,6 +648,117 @@ 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
+@@ -627,7 +794,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;
+@@ -636,6 +804,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];
+ 
+@@ -654,7 +823,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), newtype[i]);
+           free (name);
+@@ -691,6 +861,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");
+ 	}
+     }
+@@ -749,7 +920,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);
+@@ -794,7 +970,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);
+ 		}
+@@ -818,7 +995,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++)
+@@ -845,7 +1021,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");
+ }
+ 
+ 
+@@ -880,7 +1056,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");
+   
+ }
+ 
+@@ -1010,8 +1186,7 @@ public:
+   // Constructors
+   ipa_struct_reorg(void)
+     : current_function (NULL),
+-      done_recording (false),
+-      current_mode (NORMAL)
++      done_recording (false)
+   {
+   }
+ 
+@@ -1023,11 +1198,12 @@ public:
+   auto_vec_del functions;
+   srglobal globals;
+   srfunction *current_function;
++  hash_set  safe_functions;
+ 
+   bool done_recording;
+-  srmode current_mode;
+ 
+   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);
+@@ -1035,6 +1211,8 @@ 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 analyze_types (void);
+   void clear_visited (void);
+   bool create_new_types (void);
+@@ -1044,8 +1222,11 @@ public:
+   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);
++  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);
+@@ -1056,7 +1237,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);
+ 
+@@ -1068,15 +1249,22 @@ public:
+   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 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, vec &worklist, gimple *stmt);
++  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);
+@@ -1731,9 +1919,45 @@ 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. */
+@@ -1763,7 +1987,6 @@ 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)
+@@ -1829,6 +2052,10 @@ bool isarraytype (tree type)
+ 
+ bool isptrptr (tree type)
+ {
++  if (type == NULL)
++    {
++      return false;
++    }
+   bool firstptr = false;
+   while (POINTER_TYPE_P (type) || TREE_CODE (type) == ARRAY_TYPE)
+     {
+@@ -1843,129 +2070,808 @@ bool 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.  */
+ 
+-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))
+     {
+-      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)
++      fprintf (dump_file, "\n======== check node definition ========\n");
++    }
++  for (unsigned i = 1; i < num_ssa_names; ++i)
++    {
++      tree name = ssa_name (i);
++      if (name && ptr_layers.get (name) != 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)
+ 	    {
+-	      type1->mark_escape (escape_union, NULL);
++	      res = check_def_phi (name, ptr_layers);
+ 	    }
+-	  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))
++	  else if (gimple_code (def_stmt) == GIMPLE_ASSIGN)
+ 	    {
+-	      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);
+-		}
++	      res = check_def_assign (name, ptr_layers);
+ 	    }
+-        }
++	  else if (gimple_code (def_stmt) == GIMPLE_NOP)
++	    {
++	      continue;
++	    }
++	  else
++	    {
++	      return false;
++	    }
++	}
+     }
+-
+-  return type1;
++  return res;
+ }
+ 
+-/* Mark TYPE as escaping with ESCAPES as the reason.  */
++/* Check pointer usage.  */
+ 
+-void
+-ipa_struct_reorg::mark_type_as_escape (tree type, escape_type escapes, gimple *stmt)
++bool
++check_record_ptr_usage (gimple *use_stmt, tree ¤t_node,
++			hash_map  &ptr_layers,
++			auto_vec  &ssa_name_stack)
+ {
+-  if (handled_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);
++  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))
+     {
+-      srtype *stype = record_type (inner_type (type));
+-
+-      if (!stype)
+-	return;
++      return false;
++    }
+ 
+-      stype->mark_escape (escapes, stmt);
++  bool res = true;
++  /* MEM[(long int *)a_1] = _57; (record).
++     If lhs is ssa_name, lhs cannot be the current node.
++     _283 = _282->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;
+ }
+ 
+-/* Maybe process the union of type TYPE, such that marking all of the fields'
+-   types as being escaping. */
++/* Check and record a single node.  */
+ 
+-void
+-ipa_struct_reorg::process_union (tree type)
++bool
++check_record_single_node (gimple *use_stmt, tree ¤t_node,
++			  hash_map  &ptr_layers,
++			  auto_vec  &ssa_name_stack)
+ {
+-  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;
++  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);
+ 
+-  for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
++  if ((TREE_CODE (rhs1) != SSA_NAME && TREE_CODE (rhs1) != MEM_REF)
++      || (TREE_CODE (lhs) != SSA_NAME && TREE_CODE (lhs) != MEM_REF))
+     {
+-      if (TREE_CODE (field) == FIELD_DECL)
++      return false;
++    }
++
++  bool res = true;
++  if (TREE_CODE (lhs) == SSA_NAME && TREE_CODE (rhs1) == MEM_REF)
++    {
++      /* _257 = MEM[(struct arc_t * *)_17].  */
++      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)
++    {
++      /* MEM[(long int *)a_1] = _57.  */
++      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;
++}
++
++/* Check and record multiple nodes.  */
++
++bool
++check_record_mult_node (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_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;
++    }
++
++  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;
++}
++
++/* Check whether gimple assign is correctly used and record node.  */
++
++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;
++	}
++
++      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 (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;
++}
++
++/* Check the use of callee.  */
++
++bool
++check_callee (cgraph_node *node, gimple *stmt,
++	      hash_map  &ptr_layers, int input_layers)
++{
++  /* 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++)
++    {
++      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;
++}
++
++/* 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.  */
++  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)
++      || !handled_type (TREE_TYPE (input)))
++    {
++      return false;
++    }
++  input_layers = get_ptr_layers (TREE_TYPE (input));
++
++  /* 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); }  */
++  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.  */
++
++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);
++
++  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));
+@@ -2022,7 +2928,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)));
+@@ -2059,7 +2966,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;
+@@ -2138,8 +3046,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);
+ }
+ 
+ 
+@@ -2157,10 +3067,26 @@ 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);
+@@ -2172,9 +3098,11 @@ ipa_struct_reorg::find_vars (gimple *stmt)
+ 		    current_function->record_decl (t, var, -1);
+ 		}
+ 	    }
++	  /* 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);
+@@ -2187,6 +3115,26 @@ ipa_struct_reorg::find_vars (gimple *stmt)
+ 		}
+ 	    }
+ 	}
++      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);
++	}
++      /* _23 = _21 - old_arcs_12.  */
++      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,
+@@ -2279,8 +3227,122 @@ ipa_struct_reorg::maybe_record_stmt (cgraph_node *node, gimple *stmt)
+     }
+ }
+ 
++/* 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);
++
++  /* _480 = -_479; _479 = _478 * 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.  */
++
++static bool
++trace_calculate_diff (gimple *size_def_stmt, tree *num)
++{
++  gcc_assert (gimple_assign_rhs_code (size_def_stmt) == NOP_EXPR);
++
++  /* _25 = (long unsigned int) _23; _23 = _21 - old_arcs_12.  */
++  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)
++    {
++      *num = NULL_TREE;
++      return true;
++    }
++  *num = NULL_TREE;
++  return false;
++}
++
+ /* This function checks whether ARG is a result of multiplication
+-   of some number by STRUCT_SIZE. If yes, the function returns true
++   of some number by STRUCT_SIZE.  If yes, the function returns true
+    and this number is filled into NUM.  */
+ 
+ static bool
+@@ -2291,30 +3353,12 @@ is_result_of_mult (tree arg, tree *num, tree struct_size)
+       || integer_zerop (struct_size))
+     return false;
+ 
+-  /* If we have a integer, just check if it is a multiply of 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
+@@ -2330,43 +3374,28 @@ 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;
++      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);
+ 	}
+-      if (gimple_assign_rhs_code (size_def_stmt) == MULT_EXPR)
++      else if (rhs_code == 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;
++	  return trace_calculate_mult (size_def_stmt, num, struct_size);
+ 	}
+-      else if (gimple_assign_rhs_code (size_def_stmt) == SSA_NAME)
++      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;
+@@ -2383,10 +3412,17 @@ 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 ((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)
+@@ -2402,7 +3438,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
+@@ -2422,6 +3458,12 @@ 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)
+@@ -2435,7 +3477,9 @@ ipa_struct_reorg::allocate_size (srtype *type, gimple *stmt)
+       if (operand_equal_p (arg1, struct_size, 0))
+ 	return size;
+       /* ??? Check that first argument is a constant
+-	 equal to the size of structure.  */
++      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))
+@@ -2479,17 +3523,38 @@ ipa_struct_reorg::maybe_mark_or_record_other_side (tree side, tree other, gimple
+ 
+   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,
++		find_decl (other) ? find_decl (other)->orig_type : NULL);
++	}
+       else
+-	type->mark_escape (escape_cast_another_ptr, stmt);
++	{
++	  /* *_1 = &MEM[(void *)&x + 8B].  */
++	  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);
+     }
++  /* 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.  */
+@@ -2515,7 +3580,11 @@ 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. */
+-      if (is_result_of_mult (rhs2, &num, TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (lhs)))))
++      /* The size adjustment and judgment of multi-layer pointers
++	 are added.  */
++      if (is_result_of_mult (rhs2, &num, 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);
+@@ -2553,9 +3622,8 @@ ipa_struct_reorg::maybe_record_assign (cgraph_node *node, gassign *stmt)
+ }
+ 
+ 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)
+@@ -2570,13 +3638,18 @@ check_mem_ref_offset (tree 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;
+ }
+ 
+ tree
+-get_ref_base_and_offset (tree &e, HOST_WIDE_INT &offset, bool &realpart, bool &imagpart, tree &accesstype)
++get_ref_base_and_offset (tree &e, HOST_WIDE_INT &offset,
++			 bool &realpart, bool &imagpart,
++			 tree &accesstype, tree *num)
+ {
+   offset = 0;
+   realpart = false;
+@@ -2599,22 +3672,29 @@ get_ref_base_and_offset (tree &e, HOST_WIDE_INT &offset, bool &realpart, bool &i
+ 	{
+ 	  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);
+ 	      }
+@@ -2655,8 +3735,13 @@ ipa_struct_reorg::wholeaccess (tree expr, tree base, tree accesstype, srtype *t)
+ }
+ 
+ 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)
++ipa_struct_reorg::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,
++				  bool can_escape)
+ {
++  tree num = NULL_TREE;
+   HOST_WIDE_INT offset;
+   tree accesstype;
+   address = false;
+@@ -2668,7 +3753,9 @@ ipa_struct_reorg::get_type_field (tree expr, tree &base, bool &indirect, srtype
+       mark_as_bit_field = true;
+     }
+ 
+-  base = get_ref_base_and_offset (expr, offset, realpart, imagpart, accesstype);
++  /* ref is classified into two types: COMPONENT_REF or MER_REF.  */
++  base = get_ref_base_and_offset (expr, offset, realpart, imagpart,
++				  accesstype, &num);
+ 
+   /* Variable access, unkown type. */
+   if (base == NULL)
+@@ -2706,6 +3793,8 @@ ipa_struct_reorg::get_type_field (tree expr, tree &base, bool &indirect, srtype
+       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)
+@@ -2717,15 +3806,54 @@ ipa_struct_reorg::get_type_field (tree expr, tree &base, bool &indirect, srtype
+ 	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.). */
++      /* _607 = MEM[(struct arc_t * *)pl_100].
++	 then base pl_100:ssa_name  - pointer_type - integer_type.  */
++      if (current_mode == STRUCT_REORDER_FIELDS)
++	{
++	  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
+ 	{
+-          gcc_assert (can_escape);
+-	  t->mark_escape (escape_cast_another_ptr, NULL);
+-	  return false;
++	  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;
+@@ -2733,7 +3861,10 @@ ipa_struct_reorg::get_type_field (tree expr, tree &base, bool &indirect, srtype
+     t = d->type;
+ 
+   if (t->has_escaped ())
++  {
++    escape_from_base = true;
+     return false;
++  }
+ 
+   if (mark_as_bit_field)
+     {
+@@ -2759,7 +3890,6 @@ ipa_struct_reorg::get_type_field (tree expr, tree &base, bool &indirect, srtype
+ 	  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);
+@@ -2773,9 +3903,8 @@ ipa_struct_reorg::get_type_field (tree expr, tree &base, bool &indirect, srtype
+ 	  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);
+@@ -2797,7 +3926,9 @@ ipa_struct_reorg::mark_expr_escape (tree expr, escape_type escapes, gimple *stmt
+   srtype *type;
+   srfield *field;
+   bool realpart, imagpart, address;
+-  if (!get_type_field (expr, base, indirect, type, field, realpart, imagpart, address))
++  bool escape_from_base = false;
++  if (!get_type_field (expr, base, indirect, type, field,
++		       realpart, imagpart, address, escape_from_base))
+     return;
+ 
+   type->mark_escape (escapes, stmt);
+@@ -2875,6 +4006,7 @@ ipa_struct_reorg::maybe_record_call (cgraph_node *node, gcall *stmt)
+       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++)
+     {
+@@ -2882,9 +4014,16 @@ 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);
+ 	}
+@@ -2905,11 +4044,26 @@ ipa_struct_reorg::record_stmt_expr (tree expr, cgraph_node *node, gimple *stmt)
+   srtype *type;
+   srfield *field;
+   bool realpart, imagpart, address;
+-  if (!get_type_field (expr, base, indirect, type, field, realpart, imagpart, address))
++  bool escape_from_base = false;
++  if (!get_type_field (expr, base, indirect, type, field,
++		       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));
+@@ -2927,8 +4081,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;
+ 
+@@ -2940,8 +4096,9 @@ ipa_struct_reorg::check_type_and_push (tree newdecl, srtype *type, vec
+           type->mark_escape (escape_cast_another_ptr, stmt);
+ 	  return;
+ 	}
+-      if (d->type == type)
+-        return;
++      if (d->type == type
++	  && cmp_ptr_layers (TREE_TYPE (newdecl), TREE_TYPE (decl->decl)))
++	return;
+ 
+       srtype *type1 = d->type;
+       type->mark_escape (escape_cast_another_ptr, stmt);
+@@ -2991,7 +4148,9 @@ ipa_struct_reorg::check_type_and_push (tree newdecl, srtype *type, vec
+   /* 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;
+@@ -3033,6 +4192,111 @@ 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
+@@ -3058,9 +4322,16 @@ 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);
+ 
+   /*
+@@ -3069,15 +4340,7 @@ ipa_struct_reorg::check_definition (srdecl *decl, vec &worklist)
+   */
+   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)
+@@ -3091,61 +4354,16 @@ ipa_struct_reorg::check_definition (srdecl *decl, vec &worklist)
+   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;
+-    }
+-
+-  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);
++	  check_type_and_push (gimple_phi_arg_def (stmt, i),
++			       decl, worklist, stmt);
+ 	}
+       return;
+     }
+-
+-  /* Casts between pointers and integer are escaping.  */
+-  if (gimple_assign_cast_p (stmt))
++  if (gimple_code (stmt) == GIMPLE_ASSIGN)
+     {
+-      type->mark_escape (escape_cast_int, stmt);
+-      return;
++      check_definition_assign (decl, worklist);
+     }
+-
+-  /*
+-     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
+@@ -3177,11 +4395,10 @@ ipa_struct_reorg::check_other_side (srdecl *decl, tree other, gimple *stmt, vec<
+ {
+   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;
+     }
+ 
+@@ -3207,8 +4424,29 @@ ipa_struct_reorg::check_other_side (srdecl *decl, tree other, gimple *stmt, vec<
+       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);
++      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;
+     }
+@@ -3220,6 +4458,71 @@ ipa_struct_reorg::check_other_side (srdecl *decl, tree other, gimple *stmt, vec<
+ }
+ 
+ 
++/* 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)
++    {
++      a->type->mark_escape (escape_cast_another_ptr, stmt);
++      return;
++    }
++  else if (b && a == NULL && TREE_CODE (a_expr) != INTEGER_CST)
++    {
++      b->type->mark_escape (escape_cast_another_ptr, stmt);
++      return;
++    }
++  else if (a == NULL && b == NULL)
++    {
++      return;
++    }
++
++  if (cmp_ptr_layers (TREE_TYPE (a_expr), TREE_TYPE (b_expr)))
++    {
++      return;
++    }
++  a->type->mark_escape (escape_cast_another_ptr, stmt);
++  b->type->mark_escape (escape_cast_another_ptr, stmt);
++}
++
+ void
+ ipa_struct_reorg::check_use (srdecl *decl, gimple *stmt, vec &worklist)
+ {
+@@ -3234,7 +4537,7 @@ ipa_struct_reorg::check_use (srdecl *decl, gimple *stmt, vec &worklist)
+      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;
+     }
+ 
+@@ -3250,10 +4553,15 @@ ipa_struct_reorg::check_use (srdecl *decl, gimple *stmt, vec &worklist)
+       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);
+@@ -3264,7 +4572,7 @@ ipa_struct_reorg::check_use (srdecl *decl, gimple *stmt, vec &worklist)
+ 	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;
+     }
+ 
+@@ -3284,9 +4592,14 @@ ipa_struct_reorg::check_use (srdecl *decl, gimple *stmt, vec &worklist)
+       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);
+@@ -3298,7 +4611,7 @@ ipa_struct_reorg::check_use (srdecl *decl, gimple *stmt, vec &worklist)
+ 	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;
+     }
+ 
+@@ -3312,6 +4625,7 @@ ipa_struct_reorg::check_use (srdecl *decl, gimple *stmt, vec &worklist)
+ 	  check_other_side (decl, lhs, stmt, worklist);
+ 	  return;
+ 	}
++      check_ptr_layers (lhs, rhs, stmt);
+     }
+ 
+   if (is_gimple_assign (stmt)
+@@ -3321,10 +4635,26 @@ ipa_struct_reorg::check_use (srdecl *decl, gimple *stmt, vec &worklist)
+       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;
++    }
++
+ }
+ 
+ /*
+@@ -3388,17 +4718,51 @@ 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)
+    {
+@@ -3529,6 +4893,49 @@ ipa_struct_reorg::record_function (cgraph_node *node)
+ }
+ 
+ 
++/* 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
+@@ -3560,6 +4967,12 @@ 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 ())
+@@ -3578,11 +4991,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;
+ }
+ 
+@@ -3606,6 +5022,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))
+ 	{
+@@ -3685,22 +5102,99 @@ 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[i]->fields.length (); j++)
++	{
++	  srfield *field = types[i]->fields[j];
++	  if (handled_type (field->fieldtype) && field->type)
++	    {
++	      for (unsigned k = 0; k < types.length (); k++)
++		{
++		  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 && types[k]->has_escaped ())
++		    {
++		      if (!field->type->has_escaped ())
++			{
++			  field->type->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);
++		}
++	    }
++	}
++    }
++}
++
+ /* 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 ();
++    }
+ 
+   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);
+     }
+ 
+@@ -3748,7 +5242,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);
+@@ -3773,24 +5268,33 @@ 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);
+     }
+ }
+@@ -3817,6 +5321,28 @@ 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)
+@@ -3919,7 +5445,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);
+     }
+@@ -4005,9 +5532,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;
+@@ -4047,6 +5575,7 @@ ipa_struct_reorg::rewrite_expr (tree expr, tree newexpr[max_split], bool ignore_
+   srfield *f;
+   bool realpart, imagpart;
+   bool address;
++  bool escape_from_base = false;
+ 
+   tree newbase[max_split];
+   memset (newexpr, 0, sizeof(tree[max_split]));
+@@ -4064,7 +5593,8 @@ ipa_struct_reorg::rewrite_expr (tree expr, tree newexpr[max_split], bool ignore_
+       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. */
+@@ -4122,7 +5652,40 @@ ipa_struct_reorg::rewrite_expr (tree expr, tree newexpr[max_split], bool ignore_
+       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_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;
++	      */
++	      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)
+@@ -4162,8 +5725,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);
+@@ -4171,6 +5738,12 @@ 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;
+@@ -4208,19 +5781,88 @@ ipa_struct_reorg::rewrite_assign (gassign *stmt, gimple_stmt_iterator *gsi)
+       if (!is_result_of_mult (rhs2, &num, size))
+ 	internal_error ("the rhs of pointer was not a multiplicate and it slipped 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);
+@@ -4228,21 +5870,20 @@ ipa_struct_reorg::rewrite_assign (gassign *stmt, gimple_stmt_iterator *gsi)
+ 
+       if (dump_file && (dump_flags & TDF_DETAILS))
+ 	{
+-	  fprintf (dump_file, "rewriting stamtenet:\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];
+       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;
+ 	}
+ 
+       if (dump_file && (dump_flags & TDF_DETAILS))
+-	fprintf (dump_file, "\nreplaced with:\n");
++	fprintf (dump_file, "replaced 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);
+@@ -4276,7 +5917,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));
+ 
+@@ -4296,7 +5937,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. */
+ 	  if (!gimple_call_builtin_p (stmt, BUILT_IN_CALLOC))
+@@ -4356,6 +6000,25 @@ 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)
+@@ -4440,7 +6103,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
+@@ -4453,8 +6116,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
+@@ -4466,48 +6128,58 @@ 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++)
+-    {
+-      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)
++  /*  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++)
+     {
+-      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;
+ }
+@@ -4518,6 +6190,11 @@ 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))
+     {
+@@ -4570,7 +6247,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);
+     }
+ 
+@@ -4581,7 +6258,17 @@ 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]);
+@@ -4592,7 +6279,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);
+@@ -4666,12 +6353,58 @@ 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 ());
++	      dump_function_to_file (current_function_decl, dump_file,
++				     dump_flags | TDF_VOPS);
++	    }
++	  pop_cfun ();
++	}
+     }
+ 
+   create_new_decls ();
+@@ -4694,8 +6427,12 @@ ipa_struct_reorg::rewrite_functions (void)
+ 
+       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);
++	  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)
+ 	{
+@@ -4763,10 +6500,12 @@ 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");
+-          dump_function_to_file (current_function_decl, dump_file, dump_flags | TDF_VOPS);
++	  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);
+ 	}
+ 
+       pop_cfun ();
+@@ -4820,9 +6559,9 @@ ipa_struct_reorg::execute (enum srmode mode)
+ {
+   unsigned int ret = 0;
+ 
+-  if (mode == NORMAL)
++  if (mode == NORMAL || mode == STRUCT_REORDER_FIELDS)
+     {
+-      current_mode = NORMAL;
++      current_mode = mode;
+       /* If there is a top-level inline-asm,
+ 	 the pass immediately returns.  */
+       if (symtab->first_asm_symbol ())
+@@ -4831,7 +6570,10 @@ ipa_struct_reorg::execute (enum srmode mode)
+ 	}
+       record_accesses ();
+       prune_escaped_types ();
+-      analyze_types ();
++      if (current_mode == NORMAL)
++	{
++	  analyze_types ();
++	}
+ 
+       ret = rewrite_functions ();
+     }
+@@ -4903,6 +6645,47 @@ pass_ipa_struct_reorg::gate (function *)
+ 	  && lang_c_p ());
+ }
+ 
++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);
++}
++
+ } // anon namespace
+ 
+ simple_ipa_opt_pass *
+@@ -4910,3 +6693,9 @@ 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/ipa-struct-reorg/ipa-struct-reorg.h b/gcc/ipa-struct-reorg/ipa-struct-reorg.h
+index d8fe399bdf8..8fb6ce9c448 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);
+ 
+@@ -183,6 +185,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
+@@ -219,8 +226,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 fa744e25038..63303ab65bb 100644
+--- a/gcc/passes.def
++++ b/gcc/passes.def
+@@ -173,6 +173,7 @@ along with GCC; see the file COPYING3.  If not see
+   INSERT_PASSES_AFTER (all_late_ipa_passes)
+   NEXT_PASS (pass_materialize_all_clones);
+   NEXT_PASS (pass_ipa_pta);
++  NEXT_PASS (pass_ipa_reorder_fields);
+   /* FIXME: this should a normal IP pass */
+   NEXT_PASS (pass_ipa_struct_reorg);
+   NEXT_PASS (pass_omp_simd_clone);
+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 00000000000..b95be2dabc2
+--- /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 00000000000..3d243313ba9
+--- /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_create_fields_bug.c b/gcc/testsuite/gcc.dg/struct/rf_create_fields_bug.c
+new file mode 100644
+index 00000000000..886706ae913
+--- /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 00000000000..f3785f392e3
+--- /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 00000000000..1415d759ad6
+--- /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 00000000000..003da0b57bf
+--- /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_int_cast_ptr.c b/gcc/testsuite/gcc.dg/struct/rf_int_cast_ptr.c
+new file mode 100644
+index 00000000000..10dcf098c3c
+--- /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 00000000000..8d1a9a114c1
+--- /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_pass_conflict.c b/gcc/testsuite/gcc.dg/struct/rf_pass_conflict.c
+new file mode 100644
+index 00000000000..8d687c58b30
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/struct/rf_pass_conflict.c
+@@ -0,0 +1,110 @@
++// 针对 
++/*
++Compile options: /home/hxq/hcc_gcc9.3.0_org_debug/bin/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, copy.tail, copy.head);
++    }
++  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 00000000000..190b9418275
+--- /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 "Number of structures to transform is 1" "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 00000000000..3a3c10b70ba
+--- /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 00000000000..7b7d110df4c
+--- /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_ptr.c b/gcc/testsuite/gcc.dg/struct/rf_ptr_ptr.c
+new file mode 100644
+index 00000000000..01a33f66962
+--- /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 00000000000..a38556533f1
+--- /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 00000000000..5c17ee528c8
+--- /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 00000000000..710517ee9e2
+--- /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 00000000000..6ed0a5d2d6b
+--- /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 00000000000..5a2dd964fc2
+--- /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 00000000000..faa90b42ddc
+--- /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 00000000000..2bb326ff200
+--- /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 00000000000..8f2da99ccdf
+--- /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 00000000000..723142c5975
+--- /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 1bd0e18ea2e..c8db4675f11 100644
+--- a/gcc/testsuite/gcc.dg/struct/struct-reorg.exp
++++ b/gcc/testsuite/gcc.dg/struct/struct-reorg.exp
+@@ -27,8 +27,25 @@ 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_prof_*.c]] \
++ 	"" "-fipa-struct-reorg -fdump-ipa-all -flto-partition=one -fwhole-program"
++gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/w_ratio_*.c]] \
+ 	"" "-fipa-struct-reorg -fdump-ipa-all -flto-partition=one -fwhole-program"
++gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/w_prof_*.c]] \
++	"" "-fipa-struct-reorg -fdump-ipa-all -flto-partition=one -fwhole-program"
++gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/struct_reorg*.c]] \
++	"" "-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"
++gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/complete_struct_relayout.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/timevar.def b/gcc/timevar.def
+index d6a05562c2f..ee25eccbb67 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 d8355754ffa..eb32c5d441b 100644
+--- a/gcc/tree-pass.h
++++ b/gcc/tree-pass.h
+@@ -509,6 +509,7 @@ 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_hsa (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.21.0.windows.1
+
diff --git a/0019-StructReorderFields-Fix-bugs-and-improve-mechanism.patch b/0019-StructReorderFields-Fix-bugs-and-improve-mechanism.patch
new file mode 100644
index 0000000..b5370ff
--- /dev/null
+++ b/0019-StructReorderFields-Fix-bugs-and-improve-mechanism.patch
@@ -0,0 +1,296 @@
+From 5392e41dcb7d58a80f2864b3c3f600c538fba799 Mon Sep 17 00:00:00 2001
+From: huangxiaoquan 
+Date: Wed, 4 Aug 2021 14:21:08 +0800
+Subject: [PATCH 19/22] [StructReorderFields] Fix bugs and improve mechanism
+
+Fix bugs and improve mechanism:
+
+1. Fixed a bug in multi-layer pointer recording.
+2. Use new to initialize allocated memory in symbol-summary.h.
+3. Only enable optimizations in C language.
+
+diff --git a/gcc/ipa-struct-reorg/ipa-struct-reorg.c b/gcc/ipa-struct-reorg/ipa-struct-reorg.c
+index 384aa81583c..fe364f742d8 100644
+--- a/gcc/ipa-struct-reorg/ipa-struct-reorg.c
++++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.c
+@@ -173,31 +173,30 @@ lang_c_p (void)
+       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.  */
+ 
+@@ -1262,7 +1261,7 @@ public:
+   void check_uses (srdecl *decl, vec&);
+   void check_use (srdecl *decl, gimple *stmt, vec&);
+   void check_type_and_push (tree newdecl, srdecl *decl,
+-  			    vec &worklist, gimple *stmt);
++			    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);
+ 
+@@ -3010,11 +3009,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)
+ 		{
+@@ -3092,10 +3089,12 @@ ipa_struct_reorg::find_vars (gimple *stmt)
+ 	      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);
+ 		}
+ 	    }
+ 	  /* void * _1; struct arc * _2;
+@@ -3108,10 +3107,12 @@ ipa_struct_reorg::find_vars (gimple *stmt)
+ 	      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);
+ 		}
+ 	    }
+ 	}
+@@ -3529,7 +3530,7 @@ ipa_struct_reorg::maybe_mark_or_record_other_side (tree side, tree other, gimple
+ 	{
+ 	  /* The type is other, the declaration is side.  */
+ 	  current_function->record_decl (type, side, -1,
+-		find_decl (other) ? find_decl (other)->orig_type : NULL);
++		isptrptr (TREE_TYPE (other)) ? TREE_TYPE (other) : NULL);
+ 	}
+       else
+ 	{
+@@ -5111,31 +5112,23 @@ ipa_struct_reorg::propagate_escape_via_original (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 (handled_type (field->fieldtype) && field->type)
+-	    {
+-	      for (unsigned k = 0; k < types.length (); k++)
+-		{
+-		  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 && types[k]->has_escaped ())
+-		    {
+-		      if (!field->type->has_escaped ())
+-			{
+-			  field->type->mark_escape (
+-				       escape_via_orig_escape, NULL);
+-			}
+-		      break;
+-		    }
+-		}
+-	    }
+-	}
++      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;
++	  }
++      }
+     }
+ }
+ 
+@@ -6683,7 +6676,10 @@ pass_ipa_reorder_fields::gate (function *)
+ 	  && flag_ipa_reorder_fields
+ 	  /* 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 a223b4dadea..ddf5e35776e 100644
+--- a/gcc/symbol-summary.h
++++ b/gcc/symbol-summary.h
+@@ -61,10 +61,9 @@ 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_reorder_fields || 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 ()
+@@ -78,7 +77,7 @@ protected:
+       ggc_delete (item);
+     else
+       {
+-	if (flag_ipa_struct_reorg)
++	if (flag_ipa_reorder_fields || flag_ipa_struct_reorg)
+ 	  delete item;
+ 	else
+ 	  m_allocator.remove (item);
+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 00000000000..23765fc5615
+--- /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
+index 8d687c58b30..54e737ee856 100644
+--- a/gcc/testsuite/gcc.dg/struct/rf_pass_conflict.c
++++ b/gcc/testsuite/gcc.dg/struct/rf_pass_conflict.c
+@@ -1,6 +1,6 @@
+-// 针对 
++// For testing:
+ /*
+-Compile options: /home/hxq/hcc_gcc9.3.0_org_debug/bin/gcc -O3 -g 
++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
+ 
+@@ -94,12 +94,11 @@ switch_arcs(arc_t** deleted_arcs, arc_t* arcnew)
+       copy = *test_arc;
+       count++;
+       *test_arc = arcnew[0];
+-      replace_weaker_arc(arcnew, copy.tail, copy.head);
++      replace_weaker_arc(arcnew, NULL, NULL);
+     }
+   return count;
+ }
+ 
+-
+ int
+ main ()
+ {
+diff --git a/gcc/tree.c b/gcc/tree.c
+index 5c1374d6fb1..89fa469c359 100644
+--- a/gcc/tree.c
++++ b/gcc/tree.c
+@@ -5219,7 +5219,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_reorder_fields || flag_ipa_struct_reorg)
+     return TYPE_NAME (type);
+ 
+   if (!TYPE_NAME (type) || TREE_CODE (TYPE_NAME (type)) != TYPE_DECL)
+@@ -5463,7 +5463,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_reorder_fields || flag_ipa_struct_reorg)
+     return t;
+   if (POINTER_TYPE_P (t))
+     return fld_incomplete_type_of (t, fld);
+-- 
+2.21.0.windows.1
+
diff --git a/0020-Backport-vect-Fix-an-ICE-in-vect_recog_mask_conversi.patch b/0020-Backport-vect-Fix-an-ICE-in-vect_recog_mask_conversi.patch
new file mode 100644
index 0000000..44b98b5
--- /dev/null
+++ b/0020-Backport-vect-Fix-an-ICE-in-vect_recog_mask_conversi.patch
@@ -0,0 +1,128 @@
+From 633dd654347b6146d6e94d6434e7028617019134 Mon Sep 17 00:00:00 2001
+From: zhanghaijian 
+Date: Mon, 9 Aug 2021 20:18:26 +0800
+Subject: [PATCH 20/22] [Backport]vect: Fix an ICE in
+ vect_recog_mask_conversion_pattern
+
+Reference:https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=91d80cf4bd2827dd9c40fe6a7c719c909d79083d
+
+When processing the cond expression, vect_recog_mask_conversion_pattern
+doesn't consider the situation that two operands of rhs1 are different
+vectypes, leading to a vect ICE. This patch adds the identification and
+handling of the situation to fix the problem.
+
+diff --git a/gcc/testsuite/gcc.target/aarch64/pr96757.c b/gcc/testsuite/gcc.target/aarch64/pr96757.c
+new file mode 100644
+index 00000000000..122e39dca0e
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/pr96757.c
+@@ -0,0 +1,23 @@
++/* PR target/96757 */
++/* { dg-do compile } */
++/* { dg-options "-O3" } */
++
++short 
++fun1(short i, short j)
++{ 
++  return i * j; 
++}
++
++int 
++fun(int a, int b, int c) 
++{
++  int *v, z, k, m;
++  short f, d;
++  for (int i=0; i m;
++    z = f > k;
++    *v += fun1(z,b);
++  }
++}
+diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c
+index 310165084a3..84d7ddb170f 100644
+--- a/gcc/tree-vect-patterns.c
++++ b/gcc/tree-vect-patterns.c
+@@ -4237,6 +4237,8 @@ vect_recog_mask_conversion_pattern (stmt_vec_info stmt_vinfo, tree *type_out)
+   tree vectype1, vectype2;
+   stmt_vec_info pattern_stmt_info;
+   vec_info *vinfo = stmt_vinfo->vinfo;
++  tree rhs1_op0 = NULL_TREE, rhs1_op1 = NULL_TREE;
++  tree rhs1_op0_type = NULL_TREE, rhs1_op1_type = NULL_TREE;
+ 
+   /* Check for MASK_LOAD ans MASK_STORE calls requiring mask conversion.  */
+   if (is_gimple_call (last_stmt)
+@@ -4336,9 +4338,37 @@ vect_recog_mask_conversion_pattern (stmt_vec_info stmt_vinfo, tree *type_out)
+ 
+ 	     it is better for b1 and b2 to use the mask type associated
+ 	     with int elements rather bool (byte) elements.  */
+-	  rhs1_type = integer_type_for_mask (TREE_OPERAND (rhs1, 0), vinfo);
+-	  if (!rhs1_type)
+-	    rhs1_type = TREE_TYPE (TREE_OPERAND (rhs1, 0));
++	  rhs1_op0 = TREE_OPERAND (rhs1, 0);
++	  rhs1_op1 = TREE_OPERAND (rhs1, 1);
++	  if (!rhs1_op0 || !rhs1_op1)
++	    return NULL;
++	  rhs1_op0_type = integer_type_for_mask (rhs1_op0, vinfo);
++	  rhs1_op1_type = integer_type_for_mask (rhs1_op1, vinfo);
++
++	  if (!rhs1_op0_type)
++	    rhs1_type = TREE_TYPE (rhs1_op0);
++	  else if (!rhs1_op1_type)
++	    rhs1_type = TREE_TYPE (rhs1_op1);
++	  else if (TYPE_PRECISION (rhs1_op0_type)
++		   != TYPE_PRECISION (rhs1_op1_type))
++	    {
++	      int tmp0 = (int) TYPE_PRECISION (rhs1_op0_type)
++			 - (int) TYPE_PRECISION (TREE_TYPE (lhs));
++	      int tmp1 = (int) TYPE_PRECISION (rhs1_op1_type)
++			 - (int) TYPE_PRECISION (TREE_TYPE (lhs));
++	      if ((tmp0 > 0 && tmp1 > 0) || (tmp0 < 0 && tmp1 < 0))
++		{
++		  if (abs (tmp0) > abs (tmp1))
++		    rhs1_type = rhs1_op1_type;
++		  else
++		    rhs1_type = rhs1_op0_type;
++		}
++	      else
++		rhs1_type = build_nonstandard_integer_type
++		  (TYPE_PRECISION (TREE_TYPE (lhs)), 1);
++	    }
++	  else
++	    rhs1_type = rhs1_op0_type;
+ 	}
+       else
+ 	return NULL;
+@@ -4356,8 +4386,8 @@ vect_recog_mask_conversion_pattern (stmt_vec_info stmt_vinfo, tree *type_out)
+ 	 name from the outset.  */
+       if (known_eq (TYPE_VECTOR_SUBPARTS (vectype1),
+ 		    TYPE_VECTOR_SUBPARTS (vectype2))
+-	  && (TREE_CODE (rhs1) == SSA_NAME
+-	      || rhs1_type == TREE_TYPE (TREE_OPERAND (rhs1, 0))))
++	  && !rhs1_op0_type
++	  && !rhs1_op1_type)
+ 	return NULL;
+ 
+       /* If rhs1 is invariant and we can promote it leave the COND_EXPR
+@@ -4390,7 +4420,16 @@ vect_recog_mask_conversion_pattern (stmt_vec_info stmt_vinfo, tree *type_out)
+       if (TREE_CODE (rhs1) != SSA_NAME)
+ 	{
+ 	  tmp = vect_recog_temp_ssa_var (TREE_TYPE (rhs1), NULL);
+-	  pattern_stmt = gimple_build_assign (tmp, rhs1);
++	  if (rhs1_op0_type
++	      && TYPE_PRECISION (rhs1_op0_type) != TYPE_PRECISION (rhs1_type))
++	    rhs1_op0 = build_mask_conversion (rhs1_op0,
++					      vectype2, stmt_vinfo);
++	  if (rhs1_op1_type
++	      && TYPE_PRECISION (rhs1_op1_type) != TYPE_PRECISION (rhs1_type))
++	    rhs1_op1 = build_mask_conversion (rhs1_op1,
++					      vectype2, stmt_vinfo);
++	  pattern_stmt = gimple_build_assign (tmp, TREE_CODE (rhs1),
++					      rhs1_op0, rhs1_op1);
+ 	  rhs1 = tmp;
+ 	  append_pattern_def_seq (stmt_vinfo, pattern_stmt, vectype2,
+ 				  rhs1_type);
+-- 
+2.21.0.windows.1
+
diff --git a/0021-mcmodel-Bugfix-for-mcmodel-medium-on-x86.patch b/0021-mcmodel-Bugfix-for-mcmodel-medium-on-x86.patch
new file mode 100644
index 0000000..063da4e
--- /dev/null
+++ b/0021-mcmodel-Bugfix-for-mcmodel-medium-on-x86.patch
@@ -0,0 +1,23 @@
+From 023c92ac45b727768599a95f7da748158a270753 Mon Sep 17 00:00:00 2001
+From: bule 
+Date: Mon, 16 Aug 2021 11:20:35 +0800
+Subject: [PATCH 21/22] [mcmodel] Bugfix for mcmodel=medium on x86
+
+Declare default_medium_symbol_p in targhooks.h which otherwise
+cause the build failure on x86 platform.
+
+diff --git a/gcc/targhooks.h b/gcc/targhooks.h
+index 72f3064e8f8..95c136edc79 100644
+--- a/gcc/targhooks.h
++++ b/gcc/targhooks.h
+@@ -218,6 +218,7 @@ extern int default_register_move_cost (machine_mode, reg_class_t,
+ 				       reg_class_t);
+ extern bool default_slow_unaligned_access (machine_mode, unsigned int);
+ extern HOST_WIDE_INT default_estimated_poly_value (poly_int64);
++extern bool default_medium_symbol_p (rtx);
+ 
+ extern bool default_use_by_pieces_infrastructure_p (unsigned HOST_WIDE_INT,
+ 						    unsigned int,
+-- 
+2.21.0.windows.1
+
diff --git a/0022-StructReorderFields-Fix-pointer-layer-check-bug.patch b/0022-StructReorderFields-Fix-pointer-layer-check-bug.patch
new file mode 100644
index 0000000..effad4e
--- /dev/null
+++ b/0022-StructReorderFields-Fix-pointer-layer-check-bug.patch
@@ -0,0 +1,167 @@
+From 1c69390a01d3bf7226fce2a670a0f71731744b04 Mon Sep 17 00:00:00 2001
+From: huangxiaoquan 
+Date: Tue, 17 Aug 2021 15:50:31 +0800
+Subject: [PATCH 22/22] [StructReorderFields] Fix pointer layer check bug
+
+In the pointer layer check, the NULL pointer check is added
+for the escape type mark.
+
+diff --git a/gcc/ipa-struct-reorg/ipa-struct-reorg.c b/gcc/ipa-struct-reorg/ipa-struct-reorg.c
+index fe364f742d8..85986ce5803 100644
+--- a/gcc/ipa-struct-reorg/ipa-struct-reorg.c
++++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.c
+@@ -2235,9 +2235,9 @@ check_record_ptr_usage (gimple *use_stmt, tree ¤t_node,
+     }
+ 
+   bool res = true;
+-  /* MEM[(long int *)a_1] = _57; (record).
++  /* MEM[(long int *)a_1] = _1; (record).
+      If lhs is ssa_name, lhs cannot be the current node.
+-     _283 = _282->flow; (No record).  */
++     _2 = _1->flow; (No record).  */
+   if (TREE_CODE (rhs1) == SSA_NAME)
+     {
+       tree tmp = (rhs1 != current_node) ? rhs1 : lhs;
+@@ -2285,13 +2285,13 @@ check_record_single_node (gimple *use_stmt, tree ¤t_node,
+   bool res = true;
+   if (TREE_CODE (lhs) == SSA_NAME && TREE_CODE (rhs1) == MEM_REF)
+     {
+-      /* _257 = MEM[(struct arc_t * *)_17].  */
++      /* 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)
+     {
+-      /* MEM[(long int *)a_1] = _57.  */
++      /* add such as: MEM[(long int *)a_1] = _1.  */
+       if (rhs1 == current_node)
+ 	{
+ 	  res = add_node (TREE_OPERAND (lhs, 0),
+@@ -3097,7 +3097,8 @@ ipa_struct_reorg::find_vars (gimple *stmt)
+ 			isptrptr (TREE_TYPE (rhs)) ? TREE_TYPE (rhs) : NULL);
+ 		}
+ 	    }
+-	  /* void * _1; struct arc * _2;
++	  /* 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))
+@@ -3126,7 +3127,7 @@ ipa_struct_reorg::find_vars (gimple *stmt)
+ 	  find_var (gimple_assign_rhs1 (stmt), stmt);
+ 	  find_var (gimple_assign_rhs2 (stmt), stmt);
+ 	}
+-      /* _23 = _21 - old_arcs_12.  */
++      /* 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 (
+@@ -3310,7 +3311,7 @@ trace_calculate_negate (gimple *size_def_stmt, tree *num, tree struct_size)
+ {
+   gcc_assert (gimple_assign_rhs_code (size_def_stmt) == NEGATE_EXPR);
+ 
+-  /* _480 = -_479; _479 = _478 * 72.  */
++  /* 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)
+@@ -3329,7 +3330,8 @@ trace_calculate_diff (gimple *size_def_stmt, tree *num)
+ {
+   gcc_assert (gimple_assign_rhs_code (size_def_stmt) == NOP_EXPR);
+ 
+-  /* _25 = (long unsigned int) _23; _23 = _21 - old_arcs_12.  */
++  /* 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)
+@@ -3811,8 +3813,8 @@ ipa_struct_reorg::get_type_field (tree expr, tree &base, bool &indirect,
+ 	 release INTEGER_TYPE cast to struct pointer.
+ 	 (If t has escpaed above, then directly returns
+ 	 and doesn't mark escape follow.). */
+-      /* _607 = MEM[(struct arc_t * *)pl_100].
+-	 then base pl_100:ssa_name  - pointer_type - integer_type.  */
++      /* _1 = MEM[(struct arc_t * *)a_1].
++	 then base a_1: ssa_name  - pointer_type - integer_type.  */
+       if (current_mode == STRUCT_REORDER_FIELDS)
+ 	{
+ 	  bool is_int_ptr = POINTER_TYPE_P (TREE_TYPE (base))
+@@ -4520,8 +4522,15 @@ ipa_struct_reorg::check_ptr_layers (tree a_expr, tree b_expr, gimple* stmt)
+     {
+       return;
+     }
+-  a->type->mark_escape (escape_cast_another_ptr, stmt);
+-  b->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
+@@ -5649,9 +5658,9 @@ ipa_struct_reorg::rewrite_expr (tree expr, tree newexpr[max_split], bool ignore_
+ 	  if (current_mode == STRUCT_REORDER_FIELDS)
+ 	    {
+ 	      /* Supports the MEM_REF offset.
+-		 _1 = MEM[(struct arc *)ap_4 + 72B].flow;
+-		 Old rewrite:_1 = ap.reorder.0_8->flow;
+-		 New rewrite:_1
++		 _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;
+@@ -6150,10 +6159,10 @@ ipa_struct_reorg::rewrite_cond (gcond *stmt, gimple_stmt_iterator *gsi)
+       return false;
+     }
+ 
+-  /*  Old rewrite:if (x_1 != 0B)
++  /*  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)
++      New rewrite: if (x_1 != 0B)
+ 		-> if (x.reorder.0_1 != 0B);*/
+   for (unsigned i = 0; i < max_split && (newlhs[i] || newrhs[i]); i++)
+     {
+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 00000000000..a5477dcc9be
+--- /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 "No structures to transform." "reorder_fields" } } */
+\ No newline at end of file
+-- 
+2.21.0.windows.1
+
diff --git a/0023-StructReorderFields-Add-pointer-offset-check.patch b/0023-StructReorderFields-Add-pointer-offset-check.patch
new file mode 100644
index 0000000..896b7d5
--- /dev/null
+++ b/0023-StructReorderFields-Add-pointer-offset-check.patch
@@ -0,0 +1,87 @@
+From 83a35da4910fc7d8f29ced3e0ff8adddeb537731 Mon Sep 17 00:00:00 2001
+From: huangxiaoquan 
+Date: Fri, 27 Aug 2021 14:53:18 +0800
+Subject: [PATCH 23/24] [StructReorderFields] Add pointer offset check
+
+The pointer offset check is added for the expr that is dereferenced
+in the memory, and escapes struct pointer offset operations involving
+field order.
+
+diff --git a/gcc/ipa-struct-reorg/ipa-struct-reorg.c b/gcc/ipa-struct-reorg/ipa-struct-reorg.c
+index 85986ce5803..b0d4fe80797 100644
+--- a/gcc/ipa-struct-reorg/ipa-struct-reorg.c
++++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.c
+@@ -3876,6 +3876,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;
+diff --git a/gcc/testsuite/gcc.dg/struct/rf_ptr2void_lto.c b/gcc/testsuite/gcc.dg/struct/rf_ptr2void_lto.c
+index 190b9418275..2ae46fb3112 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 "Number of structures to transform is 1" "reorder_fields" } } */
+\ No newline at end of file
++/* { 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_offset.c b/gcc/testsuite/gcc.dg/struct/rf_ptr_offset.c
+new file mode 100644
+index 00000000000..317aafa5f72
+--- /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
+-- 
+2.21.0.windows.1
+
diff --git a/0024-StructReorderFields-Add-lto-and-whole-program-gate.patch b/0024-StructReorderFields-Add-lto-and-whole-program-gate.patch
new file mode 100644
index 0000000..b8043fa
--- /dev/null
+++ b/0024-StructReorderFields-Add-lto-and-whole-program-gate.patch
@@ -0,0 +1,90 @@
+From 0ee0f0ebeb098787cb9698887c237606b6ab10c6 Mon Sep 17 00:00:00 2001
+From: huangxiaoquan 
+Date: Wed, 1 Sep 2021 17:07:22 +0800
+Subject: [PATCH 24/24] [StructReorderFields] Add lto and whole-program gate
+
+Only enable struct reorder fields optimizations in lto or whole-program.
+This prevents some .c files from being struct reorder fields optimized
+while some of them are not optimized during project compilation.
+
+diff --git a/gcc/ipa-struct-reorg/ipa-struct-reorg.c b/gcc/ipa-struct-reorg/ipa-struct-reorg.c
+index b0d4fe80797..2bf41e0d83b 100644
+--- a/gcc/ipa-struct-reorg/ipa-struct-reorg.c
++++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.c
+@@ -6655,7 +6655,9 @@ 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 =
+@@ -6699,7 +6701,9 @@ pass_ipa_reorder_fields::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));
+ }
+ 
+ } // anon namespace
+diff --git a/gcc/testsuite/gcc.dg/struct/struct_reorg-1.c b/gcc/testsuite/gcc.dg/struct/struct_reorg-1.c
+index 6565fe8dd63..23444fe8b0d 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 5864ad46fd3..2d1f95c9935 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" } } */
+-- 
+2.21.0.windows.1
+
diff --git a/0025-AutoPrefetch-Support-cache-misses-profile.patch b/0025-AutoPrefetch-Support-cache-misses-profile.patch
new file mode 100644
index 0000000..1daa2db
--- /dev/null
+++ b/0025-AutoPrefetch-Support-cache-misses-profile.patch
@@ -0,0 +1,669 @@
+From 26e4ba63112f55c27b7dd3d5f8c4497ef9a2f459 Mon Sep 17 00:00:00 2001
+From: benniaobufeijiushiji 
+Date: Thu, 6 Jan 2022 15:33:29 +0800
+Subject: [PATCH 25/28] [AutoPrefetch] Support cache misses profile
+
+Add pass ex-afdo after pass afdo in auto-profile.c.
+Add flag -fcache-misses-profile.
+Read profile of different types of perf events and build maps for
+function and gimple location to its count of each perf event.
+Currently, instruction execution and cahce misses are supported.
+---
+ gcc/auto-profile.c | 415 +++++++++++++++++++++++++++++++++++++++++++++
+ gcc/auto-profile.h |  28 +++
+ gcc/common.opt     |  14 ++
+ gcc/opts.c         |  26 +++
+ gcc/passes.def     |   1 +
+ gcc/timevar.def    |   1 +
+ gcc/toplev.c       |   6 +
+ gcc/tree-pass.h    |   2 +
+ 8 files changed, 493 insertions(+)
+
+diff --git a/gcc/auto-profile.c b/gcc/auto-profile.c
+index 7d09887c9..aced8fca5 100644
+--- a/gcc/auto-profile.c
++++ b/gcc/auto-profile.c
+@@ -49,6 +49,9 @@ along with GCC; see the file COPYING3.  If not see
+ #include "auto-profile.h"
+ #include "tree-pretty-print.h"
+ #include "gimple-pretty-print.h"
++#include 
++#include 
++#include 
+ 
+ /* The following routines implements AutoFDO optimization.
+ 
+@@ -95,6 +98,7 @@ along with GCC; see the file COPYING3.  If not see
+ */
+ 
+ #define DEFAULT_AUTO_PROFILE_FILE "fbdata.afdo"
++#define DEFAULT_CACHE_MISSES_PROFILE_FILE "cmsdata.gcov"
+ #define AUTO_PROFILE_VERSION 1
+ 
+ namespace autofdo
+@@ -117,6 +121,14 @@ private:
+   bool annotated_;
+ };
+ 
++/* pair   */
++static bool
++event_count_cmp (std::pair &a,
++		 std::pair &b)
++{
++  return a.second > b.second;
++}
++
+ /* Represent a source location: (function_decl, lineno).  */
+ typedef std::pair decl_lineno;
+ 
+@@ -338,6 +350,206 @@ static autofdo_source_profile *afdo_source_profile;
+ /* gcov_summary structure to store the profile_info.  */
+ static gcov_summary *afdo_profile_info;
+ 
++/* Check opts->x_flags and put file name into EVENT_FILES.  */
++
++static bool
++get_all_profile_names (const char **event_files)
++{
++  if (!(flag_auto_profile || flag_cache_misses_profile))
++    {
++      return false;
++    }
++
++  event_files[INST_EXEC] = auto_profile_file;
++
++  if (cache_misses_profile_file == NULL)
++    {
++      cache_misses_profile_file = DEFAULT_CACHE_MISSES_PROFILE_FILE;
++    }
++  event_files[CACHE_MISSES] = cache_misses_profile_file;
++
++  return true;
++}
++
++static void read_profile (void);
++
++/* Maintain multiple profile data of different events with event_loc_count_map
++   and event_func_count_map.  */
++
++class extend_auto_profile
++{
++public:
++  bool auto_profile_exist (enum event_type type);
++  gcov_type get_loc_count (location_t, event_type);
++  gcov_type get_func_count (unsigned, event_type);
++  struct rank_info get_func_rank (unsigned, enum event_type);
++  /* There should be only one instance of class EXTEND_AUTO_PROFILE.  */
++  static extend_auto_profile *create ()
++    {
++      extend_auto_profile *map = new extend_auto_profile ();
++      if (map->read ())
++	{
++	  return map;
++	}
++      delete map;
++      return NULL;
++    }
++private:
++  /* Basic maps of extend_auto_profile.  */
++  typedef std::map loc_count_map;
++  typedef std::map func_count_map;
++
++  /* Map of function_uid to its descending order rank of counts.  */
++  typedef std::map rank_map;
++
++  /* Mapping hardware events to corresponding basic maps.  */
++  typedef std::map event_loc_count_map;
++  typedef std::map event_func_count_map;
++  typedef std::map event_rank_map;
++
++  extend_auto_profile () {}
++  bool read ();
++  void set_loc_count ();
++  void process_extend_source_profile ();
++  void read_extend_afdo_file (const char*, event_type);
++  void rank_all_func ();
++  void dump_event ();
++  event_loc_count_map event_loc_map;
++  event_func_count_map event_func_map;
++  event_rank_map func_rank;
++  event_type profile_type;
++};
++
++/* Member functions for extend_auto_profile.  */
++
++bool
++extend_auto_profile::auto_profile_exist (enum event_type type)
++{
++  switch (type)
++    {
++      case INST_EXEC:
++	return event_func_map.count (INST_EXEC) != 0
++	       || event_loc_map.count (INST_EXEC) != 0;
++      case CACHE_MISSES:
++	return event_func_map.count (CACHE_MISSES) != 0
++	       || event_loc_map.count (CACHE_MISSES) != 0;
++      default:
++	  return false;
++    }
++}
++
++void
++extend_auto_profile::dump_event ()
++{
++  if (dump_file)
++    {
++      switch (profile_type)
++	{
++	  case INST_EXEC:
++	    fprintf (dump_file, "Processing event instruction execution.\n");
++	    break;
++	  case CACHE_MISSES:
++	    fprintf (dump_file, "Processing event cache misses.\n");
++	    break;
++	  default:
++	    break;
++	}
++    }
++}
++
++/* Return true if any profile data was read.  */
++
++bool
++extend_auto_profile::read ()
++{
++  const char *event_files[EVENT_NUMBER] = {NULL};
++  if (!get_all_profile_names (event_files))
++    {
++      return false;
++    }
++
++  /* Backup AFDO_STRING_TABLE and AFDO_SOURCE_PROFILE since we will create
++     new ones for each event_type.  */
++  autofdo::string_table *string_table_afdo = afdo_string_table;
++  autofdo::autofdo_source_profile *source_profile_afdo = afdo_source_profile;
++
++  for (unsigned i = 0; i < EVENT_NUMBER; i++)
++    {
++      if (event_files[i] == NULL)
++	{
++	  continue;
++	}
++      profile_type = (enum event_type) i;
++      dump_event ();
++      gcov_close ();
++      auto_profile_file = event_files[i];
++      read_profile ();
++      gcov_close ();
++
++      process_extend_source_profile ();
++
++      delete afdo_source_profile;
++      delete afdo_string_table;
++    }
++
++  /* Restore AFDO_STRING_TABLE and AFDO_SOURCE_PROFILE.  Function
++     END_AUTO_PROFILE will free them at the end of compilation.  */
++  afdo_string_table = string_table_afdo;
++  afdo_source_profile = source_profile_afdo;
++  return true;
++}
++
++/* Helper functions.  */
++
++gcov_type
++extend_auto_profile::get_loc_count (location_t loc, event_type type)
++{
++  event_loc_count_map::iterator event_iter = event_loc_map.find (type);
++  if (event_iter != event_loc_map.end ())
++    {
++      loc_count_map::iterator loc_iter = event_iter->second.find (loc);
++      if (loc_iter != event_iter->second.end ())
++	{
++	  return loc_iter->second;
++	}
++    }
++  return 0;
++}
++
++struct rank_info
++extend_auto_profile::get_func_rank (unsigned decl_uid, enum event_type type)
++{
++  struct rank_info info = {0, 0};
++  event_rank_map::iterator event_iter = func_rank.find (type);
++  if (event_iter != func_rank.end ())
++    {
++      rank_map::iterator func_iter = event_iter->second.find (decl_uid);
++      if (func_iter != event_iter->second.end ())
++	{
++	  info.rank = func_iter->second;
++	  info.total = event_iter->second.size ();
++	}
++    }
++  return info;
++}
++
++gcov_type
++extend_auto_profile::get_func_count (unsigned decl_uid, event_type type)
++{
++  event_func_count_map::iterator event_iter = event_func_map.find (type);
++  if (event_iter != event_func_map.end ())
++    {
++      func_count_map::iterator func_iter = event_iter->second.find (decl_uid);
++      if (func_iter != event_iter->second.end ())
++	{
++	  return func_iter->second;
++	}
++    }
++  return 0;
++}
++
++static extend_auto_profile *extend_profile;
++
+ /* Helper functions.  */
+ 
+ /* Return the original name of NAME: strip the suffix that starts
+@@ -1654,6 +1866,131 @@ auto_profile (void)
+ 
+   return TODO_rebuild_cgraph_edges;
+ }
++
++void
++extend_auto_profile::rank_all_func ()
++{
++  std::vector > func_sorted;
++  event_func_count_map::iterator event_iter
++				 = event_func_map.find (profile_type);
++  if (event_iter != event_func_map.end ())
++    {
++      func_count_map::iterator func_iter;
++      for (func_iter = event_iter->second.begin ();
++	   func_iter != event_iter->second.end (); func_iter++)
++	{
++	  func_sorted.push_back (std::make_pair (func_iter->first,
++						 func_iter->second));
++	}
++
++      std::sort (func_sorted.begin (), func_sorted.end (), event_count_cmp);
++
++      for (unsigned i = 0; i < func_sorted.size (); ++i)
++	{
++	  func_rank[profile_type][func_sorted[i].first] = i + 1;
++	}
++    }
++}
++
++/* Iterate stmts in cfun and maintain its count to EVENT_LOC_MAP.  */
++
++void
++extend_auto_profile::set_loc_count ()
++{
++  basic_block bb;
++  FOR_EACH_BB_FN (bb, cfun)
++    {
++      gimple_stmt_iterator gsi;
++      for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
++	{
++	  count_info info;
++	  gimple *stmt = gsi_stmt (gsi);
++	  if (gimple_clobber_p (stmt) || is_gimple_debug (stmt))
++	    {
++	      continue;
++	    }
++	  if (afdo_source_profile->get_count_info (stmt, &info))
++	    {
++	      location_t loc = gimple_location (stmt);
++	      event_loc_map[profile_type][loc] += info.count;
++	      if (dump_file && (dump_flags & TDF_DETAILS))
++		{
++		  fprintf (dump_file, "stmt ");
++		  print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
++		  fprintf (dump_file, "counts %ld\n",
++			   event_loc_map[profile_type][loc]);
++		}
++	    }
++	}
++    }
++}
++
++/* Process data in extend_auto_source_profile, save them into two maps.
++   1. gimple_location to count.
++   2. function_index to count.  */
++void
++extend_auto_profile::process_extend_source_profile ()
++{
++  struct cgraph_node *node;
++  if (symtab->state == FINISHED)
++    {
++      return;
++    }
++  FOR_EACH_FUNCTION (node)
++    {
++      if (!gimple_has_body_p (node->decl) || node->inlined_to)
++	{
++	  continue;
++	}
++
++      /* Don't profile functions produced for builtin stuff.  */
++      if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION)
++	{
++	  continue;
++	}
++
++      function *fn = DECL_STRUCT_FUNCTION (node->decl);
++      push_cfun (fn);
++
++      const function_instance *s
++      = afdo_source_profile->get_function_instance_by_decl (
++	  current_function_decl);
++
++      if (s == NULL)
++	{
++	  pop_cfun ();
++	  continue;
++	}
++      unsigned int decl_uid = DECL_UID (current_function_decl);
++      gcov_type count = s->total_count ();
++      if (dump_file)
++	{
++	  fprintf (dump_file, "Extend auto-profile for function %s.\n",
++			       node->dump_name ());
++	}
++      event_func_map[profile_type][decl_uid] += count;
++      set_loc_count ();
++      pop_cfun ();
++    }
++  rank_all_func ();
++}
++
++/* Main entry of extend_auto_profile.  */
++
++static void
++extend_source_profile ()
++{
++  extend_profile = autofdo::extend_auto_profile::create ();
++  if (dump_file)
++    {
++      if (extend_profile == NULL)
++	{
++	  fprintf (dump_file, "No profile file is found.\n");
++	  return;
++	}
++      fprintf (dump_file, "Extend profile info generated.\n");
++    }
++}
+ } /* namespace autofdo.  */
+ 
+ /* Read the profile from the profile data file.  */
+@@ -1682,6 +2019,42 @@ end_auto_profile (void)
+   profile_info = NULL;
+ }
+ 
++/* Extern function to get profile info in other passes.  */
++
++bool
++profile_exist (enum event_type type)
++{
++  return autofdo::extend_profile != NULL
++	 && autofdo::extend_profile->auto_profile_exist (type);
++}
++
++gcov_type
++event_get_loc_count (location_t loc, event_type type)
++{
++  return autofdo::extend_profile->get_loc_count (loc, type);
++}
++
++gcov_type
++event_get_func_count (unsigned decl_uid, event_type type)
++{
++  return autofdo::extend_profile->get_func_count (decl_uid, type);
++}
++
++struct rank_info
++event_get_func_rank (unsigned decl_uid, enum event_type type)
++{
++  return autofdo::extend_profile->get_func_rank (decl_uid, type);
++}
++
++void
++free_extend_profile_info ()
++{
++  if (autofdo::extend_profile != NULL)
++    {
++      delete autofdo::extend_profile;
++    }
++}
++
+ /* Returns TRUE if EDGE is hot enough to be inlined early.  */
+ 
+ bool
+@@ -1743,8 +2116,50 @@ public:
+ 
+ } // anon namespace
+ 
++namespace
++{
++const pass_data pass_data_ipa_extend_auto_profile =
++{
++  SIMPLE_IPA_PASS, /* type */
++  "ex-afdo", /* name */
++  OPTGROUP_NONE, /* optinfo_flags */
++  TV_IPA_EXTEND_AUTO_PROFILE, /* tv_id */
++  0, /* properties_required */
++  0, /* properties_provided */
++  0, /* properties_destroyed */
++  0, /* todo_flags_start */
++  0, /* todo_flags_finish */
++};
++
++class pass_ipa_extend_auto_profile : public simple_ipa_opt_pass
++{
++public:
++  pass_ipa_extend_auto_profile (gcc::context *ctxt)
++    : simple_ipa_opt_pass (pass_data_ipa_extend_auto_profile, ctxt)
++  {}
++
++  /* opt_pass methods: */
++  virtual bool gate (function *) {return (flag_ipa_extend_auto_profile > 0);}
++  virtual unsigned int execute (function *);
++
++};
++
++unsigned int
++pass_ipa_extend_auto_profile::execute (function *fun)
++{
++  autofdo::extend_source_profile ();
++  return 0;
++}
++} // anon namespace
++
+ simple_ipa_opt_pass *
+ make_pass_ipa_auto_profile (gcc::context *ctxt)
+ {
+   return new pass_ipa_auto_profile (ctxt);
+ }
++
++simple_ipa_opt_pass *
++make_pass_ipa_extend_auto_profile (gcc::context *ctxt)
++{
++  return new pass_ipa_extend_auto_profile (ctxt);
++}
+\ No newline at end of file
+diff --git a/gcc/auto-profile.h b/gcc/auto-profile.h
+index f5cff091d..230d7e68a 100644
+--- a/gcc/auto-profile.h
++++ b/gcc/auto-profile.h
+@@ -21,6 +21,13 @@ along with GCC; see the file COPYING3.  If not see
+ #ifndef AUTO_PROFILE_H
+ #define AUTO_PROFILE_H
+ 
++enum event_type
++{
++  INST_EXEC = 0,
++  CACHE_MISSES,
++  EVENT_NUMBER
++};
++
+ /* Read, process, finalize AutoFDO data structures.  */
+ extern void read_autofdo_file (void);
+ extern void end_auto_profile (void);
+@@ -28,4 +35,25 @@ extern void end_auto_profile (void);
+ /* Returns TRUE if EDGE is hot enough to be inlined early.  */
+ extern bool afdo_callsite_hot_enough_for_early_inline (struct cgraph_edge *);
+ 
++/* Chcek if profile exists before using this profile.  */
++extern bool profile_exist (enum event_type);
++
++/* Given func decl_uid or gimple location and event_type, return count.
++   Count is 0 if function or gimple is not sampled.  */
++extern gcov_type event_get_func_count (unsigned, enum event_type);
++extern gcov_type event_get_loc_count (location_t, enum event_type);
++
++struct rank_info
++{
++  unsigned total;
++  unsigned rank;
++};
++
++/* Given function decl_uid and event type, return rank_info.  Rank_info
++   is {0, 0} if function was not sampled.  */
++extern struct rank_info event_get_func_rank (unsigned, enum event_type);
++
++/* Free memory allocated by autofdo::extern_profile.  */
++extern void free_extend_profile_info ();
++
+ #endif /* AUTO_PROFILE_H */
+diff --git a/gcc/common.opt b/gcc/common.opt
+index 73c24f28d..37cbbd8c0 100644
+--- a/gcc/common.opt
++++ b/gcc/common.opt
+@@ -1074,6 +1074,16 @@ Common Joined RejectNegative Var(auto_profile_file)
+ Use sample profile information for call graph node weights. The profile
+ file is specified in the argument.
+ 
++fcache-misses-profile
++Common Report Var(flag_cache_misses_profile)
++Use sample profile information for source code cache miss count.  The default
++profile file is cmsdata.gcov in `pwd`.
++
++fcache-misses-profile=
++Common Joined RejectNegative Var(cache_misses_profile_file)
++Use sample profile information for source code cache miss count.  The profile
++file is specified in the argument.
++
+ ; -fcheck-bounds causes gcc to generate array bounds checks.
+ ; For C, C++ and ObjC: defaults off.
+ ; For Java: defaults to on.
+@@ -1873,6 +1883,10 @@ fipa-struct-reorg
+ Common Report Var(flag_ipa_struct_reorg) Init(0) Optimization
+ Perform structure layout optimizations.
+ 
++fipa-extend-auto-profile
++Common Report Var(flag_ipa_extend_auto_profile)
++Use sample profile information for source code.
++
+ fipa-vrp
+ Common Report Var(flag_ipa_vrp) Optimization
+ Perform IPA Value Range Propagation.
+diff --git a/gcc/opts.c b/gcc/opts.c
+index 6924a973a..642327296 100644
+--- a/gcc/opts.c
++++ b/gcc/opts.c
+@@ -1742,6 +1742,13 @@ enable_fdo_optimizations (struct gcc_options *opts,
+   SET_OPTION_IF_UNSET (opts, opts_set, flag_tree_loop_distribution, value);
+ }
+ 
++static void
++set_cache_misses_profile_params (struct gcc_options *opts,
++			       struct gcc_options *opts_set)
++{
++  SET_OPTION_IF_UNSET (opts, opts_set, flag_prefetch_loop_arrays, 1);
++}
++
+ /* -f{,no-}sanitize{,-recover}= suboptions.  */
+ const struct sanitizer_opts_s sanitizer_opts[] =
+ {
+@@ -2604,6 +2611,25 @@ common_handle_option (struct gcc_options *opts,
+ 			   param_early_inliner_max_iterations, 10);
+       break;
+ 
++    case OPT_fipa_extend_auto_profile:
++      opts->x_flag_ipa_extend_auto_profile = opts->x_flag_cache_misses_profile
++					     ? true : value;
++      break;
++
++    case OPT_fcache_misses_profile_:
++      opts->x_cache_misses_profile_file = xstrdup (arg);
++      opts->x_flag_cache_misses_profile = true;
++      value = true;
++      /* No break here - do -fcache-misses-profile processing. */
++      /* FALLTHRU */
++    case OPT_fcache_misses_profile:
++      opts->x_flag_ipa_extend_auto_profile = value;
++      if (value)
++	{
++	  set_cache_misses_profile_params (opts, opts_set);
++	}
++      break;
++
+     case OPT_fprofile_generate_:
+       opts->x_profile_data_prefix = xstrdup (arg);
+       value = true;
+diff --git a/gcc/passes.def b/gcc/passes.def
+index 63303ab65..e9c91d26e 100644
+--- a/gcc/passes.def
++++ b/gcc/passes.def
+@@ -133,6 +133,7 @@ along with GCC; see the file COPYING3.  If not see
+ 
+   NEXT_PASS (pass_target_clone);
+   NEXT_PASS (pass_ipa_auto_profile);
++  NEXT_PASS (pass_ipa_extend_auto_profile);
+   NEXT_PASS (pass_ipa_tree_profile);
+   PUSH_INSERT_PASSES_WITHIN (pass_ipa_tree_profile)
+       NEXT_PASS (pass_feedback_split_functions);
+diff --git a/gcc/timevar.def b/gcc/timevar.def
+index ee25eccbb..e873747a8 100644
+--- a/gcc/timevar.def
++++ b/gcc/timevar.def
+@@ -82,6 +82,7 @@ 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_EXTEND_AUTO_PROFILE, "ipa extend auto profile")
+ 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/toplev.c b/gcc/toplev.c
+index eaed6f6c7..51e6bd400 100644
+--- a/gcc/toplev.c
++++ b/gcc/toplev.c
+@@ -577,6 +577,12 @@ compile_file (void)
+       targetm.asm_out.output_ident (ident_str);
+     }
+ 
++  /* Extend auto profile finalization.  */
++  if (flag_ipa_extend_auto_profile)
++    {
++      free_extend_profile_info ();
++    }
++
+   /* Auto profile finalization. */
+   if (flag_auto_profile)
+     end_auto_profile ();
+diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
+index eb32c5d44..be6387768 100644
+--- a/gcc/tree-pass.h
++++ b/gcc/tree-pass.h
+@@ -511,6 +511,8 @@ extern ipa_opt_pass_d *make_pass_ipa_hsa (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_extend_auto_profile (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.27.0.windows.1
+
diff --git a/0026-AutoFDO-Enable-discriminator-and-MCF-algorithm-on-Au.patch b/0026-AutoFDO-Enable-discriminator-and-MCF-algorithm-on-Au.patch
new file mode 100644
index 0000000..bbc98c6
--- /dev/null
+++ b/0026-AutoFDO-Enable-discriminator-and-MCF-algorithm-on-Au.patch
@@ -0,0 +1,353 @@
+From eb58d920a95696d8d5a7db9a6d640d4494fb023f Mon Sep 17 00:00:00 2001
+From: liyancheng <412998149@qq.com>
+Date: Tue, 25 Jan 2022 16:57:28 +0800
+Subject: [PATCH 26/28] [AutoFDO] Enable discriminator and MCF algorithm on
+ AutoFDO
+
+1. Support discriminator for distinguishes among several
+   basic blocks that share a common locus, allowing for
+   more accurate autofdo.
+
+2. Using option -fprofile-correction for calling MCF algorithm
+   to smooth non conservative BB counts.
+---
+ gcc/auto-profile.c | 172 ++++++++++++++++++++++++++++++++++++++++++++-
+ gcc/cfghooks.c     |   7 ++
+ gcc/ipa-cp.c       |  21 ++++++
+ gcc/opts.c         |   5 +-
+ gcc/tree-inline.c  |  14 ++++
+ 5 files changed, 215 insertions(+), 4 deletions(-)
+
+diff --git a/gcc/auto-profile.c b/gcc/auto-profile.c
+index aced8fca5..e6164b91b 100644
+--- a/gcc/auto-profile.c
++++ b/gcc/auto-profile.c
+@@ -678,6 +678,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;
+ 
+@@ -866,7 +877,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;
+@@ -945,6 +956,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);
+ }
+ 
+@@ -1583,6 +1598,68 @@ 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 each 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_p (bb1) && single_succ_p (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.  */
+ 
+@@ -1608,6 +1685,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)
+@@ -1711,6 +1789,82 @@ 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.  */
+ 
+@@ -1762,8 +1916,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 enabled 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.c b/gcc/cfghooks.c
+index ea558b469..4ea490a8a 100644
+--- a/gcc/cfghooks.c
++++ b/gcc/cfghooks.c
+@@ -526,6 +526,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))
+@@ -1091,6 +1094,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/ipa-cp.c b/gcc/ipa-cp.c
+index b1f0881bd..c208070c9 100644
+--- a/gcc/ipa-cp.c
++++ b/gcc/ipa-cp.c
+@@ -4365,6 +4365,27 @@ update_profiling_info (struct cgraph_node *orig_node,
+ 	  orig_node_count.dump (dump_file);
+ 	  fprintf (dump_file, "\n");
+ 	}
++
++      /* When autofdo uses PMU as the sampling unit, the count of
++	 cgraph_node->count cannot be obtained directly and will
++	 be zero. It using for apply_scale will cause the node
++	 count incorrectly overestimated. So set orig_new_node_count
++	 equal to orig_node_count, which is same as known error
++	 handling.  */
++      if (orig_node->count == profile_count::zero ().afdo ()
++	  && new_node->count == profile_count::zero ().global0adjusted ())
++	{
++	  orig_new_node_count = (orig_sum + new_sum).apply_scale (12, 10);
++
++	  if (dump_file)
++	    {
++	      fprintf (dump_file, "      node %s with zero count from afdo ",
++		       new_node->dump_name ());
++	      fprintf (dump_file, "      proceeding by pretending it was ");
++	      orig_new_node_count.dump (dump_file);
++	      fprintf (dump_file, "\n");
++	    }
++	}
+     }
+ 
+   remainder = orig_node_count.combine_with_ipa_count (orig_node_count.ipa ()
+diff --git a/gcc/opts.c b/gcc/opts.c
+index 642327296..7a39f618b 100644
+--- a/gcc/opts.c
++++ b/gcc/opts.c
+@@ -2606,7 +2606,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));
+       SET_OPTION_IF_UNSET (opts, opts_set,
+ 			   param_early_inliner_max_iterations, 10);
+       break;
+diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
+index efde5d158..8405a959c 100644
+--- a/gcc/tree-inline.c
++++ b/gcc/tree-inline.c
+@@ -2015,6 +2015,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);
+ 
+@@ -3028,6 +3032,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.27.0.windows.1
+
diff --git a/0027-Autoprefetch-Support-auto-feedback-prefetch.patch b/0027-Autoprefetch-Support-auto-feedback-prefetch.patch
new file mode 100644
index 0000000..c3dcf50
--- /dev/null
+++ b/0027-Autoprefetch-Support-auto-feedback-prefetch.patch
@@ -0,0 +1,1000 @@
+From 6b944bed1158d3454b1db27aeab4ec1f2b8e5866 Mon Sep 17 00:00:00 2001
+From: huangxiaoquan 
+Date: Thu, 27 Jan 2022 18:24:53 +0800
+Subject: [PATCH 27/28] [Autoprefetch] Support auto feedback prefetch
+
+1.Add option -fprefetch-loop-arrays=[value].
+
+2.A prefetch distance analysis algorithm based on branch weight
+  is proposed to improve the accuracy of prefetch distance.
+
+3.Propose automatic feedback prefetching:
+  use the cache-miss profile information to guide the insertion of
+  prefetching instructions.
+---
+ gcc/auto-profile.c           |   5 +-
+ gcc/common.opt               |   5 +
+ gcc/opts.c                   |   7 +
+ gcc/params.opt               |  16 +
+ gcc/tree-ssa-loop-prefetch.c | 735 ++++++++++++++++++++++++++++++++++-
+ 5 files changed, 748 insertions(+), 20 deletions(-)
+
+diff --git a/gcc/auto-profile.c b/gcc/auto-profile.c
+index e6164b91b..f221978fc 100644
+--- a/gcc/auto-profile.c
++++ b/gcc/auto-profile.c
+@@ -21,6 +21,8 @@ along with GCC; see the file COPYING3.  If not see
+ #include "config.h"
+ #define INCLUDE_MAP
+ #define INCLUDE_SET
++#define INCLUDE_ALGORITHM
++#define INCLUDE_VECTOR
+ #include "system.h"
+ #include "coretypes.h"
+ #include "backend.h"
+@@ -49,9 +51,6 @@ along with GCC; see the file COPYING3.  If not see
+ #include "auto-profile.h"
+ #include "tree-pretty-print.h"
+ #include "gimple-pretty-print.h"
+-#include 
+-#include 
+-#include 
+ 
+ /* The following routines implements AutoFDO optimization.
+ 
+diff --git a/gcc/common.opt b/gcc/common.opt
+index 37cbbd8c0..9488bd90f 100644
+--- a/gcc/common.opt
++++ b/gcc/common.opt
+@@ -2201,6 +2201,11 @@ fprefetch-loop-arrays
+ Common Report Var(flag_prefetch_loop_arrays) Init(-1) Optimization
+ Generate prefetch instructions, if available, for arrays in loops.
+ 
++fprefetch-loop-arrays=
++Common Joined RejectNegative UInteger Var(prefetch_level) Init(0) IntegerRange(0, 3)
++Generate prefetch instructions, if available, for arrays in loops. The prefetch
++level can control the optimize level to array prefetch.
++
+ fprofile
+ Common Report Var(profile_flag)
+ Enable basic program profiling code.
+diff --git a/gcc/opts.c b/gcc/opts.c
+index 7a39f618b..f49f5ee58 100644
+--- a/gcc/opts.c
++++ b/gcc/opts.c
+@@ -1747,6 +1747,8 @@ set_cache_misses_profile_params (struct gcc_options *opts,
+ 			       struct gcc_options *opts_set)
+ {
+   SET_OPTION_IF_UNSET (opts, opts_set, flag_prefetch_loop_arrays, 1);
++  SET_OPTION_IF_UNSET (opts, opts_set, prefetch_level, 2);
++  SET_OPTION_IF_UNSET (opts, opts_set, param_simultaneous_prefetches, 100);
+ }
+ 
+ /* -f{,no-}sanitize{,-recover}= suboptions.  */
+@@ -2645,6 +2647,11 @@ common_handle_option (struct gcc_options *opts,
+       SET_OPTION_IF_UNSET (opts, opts_set, flag_ipa_bit_cp, value);
+       break;
+ 
++    case OPT_fprefetch_loop_arrays_:
++      opts->x_prefetch_level = value;
++      opts->x_flag_prefetch_loop_arrays = true;
++      break;
++
+     case OPT_fpatchable_function_entry_:
+       {
+ 	char *patch_area_arg = xstrdup (arg);
+diff --git a/gcc/params.opt b/gcc/params.opt
+index 2db69cc87..9d1faa7ab 100644
+--- a/gcc/params.opt
++++ b/gcc/params.opt
+@@ -968,4 +968,20 @@ Bound on number of runtime checks inserted by the vectorizer's loop versioning f
+ 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.
+ 
++-param=param-prefetch-func-topn=
++Common Joined UInteger Var(param_prefetch_func_topn) Init(3) Param Optimization
++TopN functions of cache miss counts to be analyzed in prefetching.
++
++-param=param-prefetch-ref-topn=
++Common Joined UInteger Var(param_prefetch_ref_topn) Init(5) Param Optimization
++TopN ref of cache miss counts to be analyzed in prefetching.
++
++-param=param-high-loop-execution-rate=
++Common Joined UInteger Var(param_high_loop_execution_rate) Init(95) IntegerRange(0, 100) Param Optimization
++High execution rate loops to be analyzed in prefetch (in%).
++
++-param=param-prefetch-func-counts-threshold=
++Common Joined UInteger Var(param_prefetch_func_counts_threshold) Init(100) Param Optimization
++Threshold functions of cache miss counts to be analyzed in prefetching.
++
+ ; This comment is to ensure we retain the blank line above.
+diff --git a/gcc/tree-ssa-loop-prefetch.c b/gcc/tree-ssa-loop-prefetch.c
+index d19ece641..3a5aef0fc 100644
+--- a/gcc/tree-ssa-loop-prefetch.c
++++ b/gcc/tree-ssa-loop-prefetch.c
+@@ -18,6 +18,9 @@ along with GCC; see the file COPYING3.  If not see
+ .  */
+ 
+ #include "config.h"
++#define INCLUDE_ALGORITHM
++#define INCLUDE_MAP
++#define INCLUDE_VECTOR
+ #include "system.h"
+ #include "coretypes.h"
+ #include "backend.h"
+@@ -48,6 +51,11 @@ along with GCC; see the file COPYING3.  If not see
+ #include "tree-data-ref.h"
+ #include "diagnostic-core.h"
+ #include "dbgcnt.h"
++#include "gimple-pretty-print.h"
++#include "tree-cfg.h"
++#include "auto-profile.h"
++#include "cgraph.h"
++#include "print-tree.h"
+ 
+ /* This pass inserts prefetch instructions to optimize cache usage during
+    accesses to arrays in loops.  It processes loops sequentially and:
+@@ -253,6 +261,22 @@ struct mem_ref_group
+ #define PREFETCH_MAX_MEM_REFS_PER_LOOP 200
+ #endif
+ 
++#ifndef PREFETCH_FUNC_TOPN
++#define PREFETCH_FUNC_TOPN param_prefetch_func_topn
++#endif
++
++#ifndef PREFETCH_FUNC_COUNTS_THRESHOLD
++#define PREFETCH_FUNC_COUNTS_THRESHOLD param_prefetch_func_counts_threshold
++#endif
++
++#ifndef PREFETCH_REF_TOPN
++#define PREFETCH_REF_TOPN param_prefetch_ref_topn
++#endif
++
++#ifndef LOOP_EXECUTION_RATE
++#define LOOP_EXECUTION_RATE param_high_loop_execution_rate
++#endif
++
+ /* The memory reference.  */
+ 
+ struct mem_ref
+@@ -279,6 +303,131 @@ struct mem_ref
+ 				   nontemporal one.  */
+ };
+ 
++/* Probability information of basic blocks and branches.  */
++struct bb_bp
++{
++  basic_block bb;
++  basic_block true_edge_bb;
++  basic_block false_edge_bb;
++  float true_edge_prob;
++  float false_edge_prob;
++  float bb_prob;
++};
++
++typedef struct bb_bp bb_bp;
++
++enum PREFETCH_MODE
++{
++  ORIGINAL_MODE=0,		/* Original prefetch method.  */
++  REFINE_BB_AHEAD,
++				/* Prefetch distance algorithm for removing
++				   irrelevant bb.  */
++  BRANCH_WEIGHTED_AHEAD,
++				/* Branch weighted prefetch
++				   distance algorithm.  */
++  INDIRECT_MODE			/* Indirect array prefetch mode.  */
++};
++
++typedef std::map  uid_rank_map;
++typedef std::map  loc_rank_map;
++typedef std::vector  > loc_gcov_type_vec;
++typedef std::map  > loc_gimple_vec_map;
++
++static loc_rank_map ref_rank;
++
++/* Callback function for event_count comparison.  */
++
++static bool
++event_count_cmp (std::pair &a,
++		 std::pair &b)
++{
++  return a.second > b.second;
++}
++
++/* Prepared mappings from location to counts and from location
++   to stmt list.  */
++
++static void
++prepare_loc_count_info (function *fun, loc_gcov_type_vec &ref_sorted,
++			loc_gimple_vec_map &loc_stmt, event_type event)
++{
++  basic_block bb = NULL;
++  gimple_stmt_iterator bsi;
++  gimple *stmt;
++  tree lhs = NULL_TREE;
++  tree rhs = NULL_TREE;
++
++  FOR_EACH_BB_FN (bb, fun)
++    {
++      for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi))
++	{
++	  stmt = gsi_stmt (bsi);
++	  if (gimple_code (stmt) != GIMPLE_ASSIGN)
++	    {
++	      continue;
++	    }
++	  if (!gimple_vuse (stmt))
++	   {
++	      continue;
++	   }
++	  lhs = gimple_assign_lhs (stmt);
++	  rhs = gimple_assign_rhs1 (stmt);
++	  if (REFERENCE_CLASS_P (rhs) || REFERENCE_CLASS_P (lhs))
++	    {
++	      gcov_type loc_count =
++	        event_get_loc_count (gimple_location (stmt), event);
++	      if (loc_count > 0)
++		{
++		  /* There may be multiple gimple correspond to the same
++		     location.  */
++		  if (loc_stmt.count (gimple_location (stmt)) == 0)
++		    {
++		      ref_sorted.push_back (std::make_pair (gimple_location (stmt),
++					loc_count));
++		    }
++		  loc_stmt[gimple_location (stmt)].push_back (stmt);
++		}
++	    }
++	}
++    }
++}
++
++/* Sort references by event_count and dump loc count information after 
++   sorting.  */
++
++static void
++sort_ref_by_event_count (function *fun, event_type event)
++{
++  loc_gcov_type_vec ref_sorted;
++  loc_gimple_vec_map loc_stmt;
++
++  prepare_loc_count_info (fun, ref_sorted, loc_stmt, event);
++  sort (ref_sorted.begin (), ref_sorted.end (), event_count_cmp);
++
++  for (unsigned i = 0; i < ref_sorted.size (); ++i)
++    {
++      ref_rank[ref_sorted[i].first] = i + 1;
++      /* Print the stmt and count of the topn ref.  */
++      if (i < PREFETCH_REF_TOPN && dump_file && (dump_flags & TDF_DETAILS))
++	{
++	  fprintf (dump_file, "stmt: \n");
++	  for (unsigned j = 0; j < loc_stmt[ref_sorted[i].first].size ();
++		++j)
++	    {
++	      print_gimple_stmt (dump_file,
++				 loc_stmt[ref_sorted[i].first][j], 0);
++	    }
++	  gcov_type loc_count =
++	    event_get_loc_count (ref_sorted[i].first, event);
++	  fprintf (dump_file, "stmt loc %u counts is %lu: "
++			      "rank %d in top %d, (candidate analysis)\n\n",
++		   ref_sorted[i].first, loc_count,
++		   ref_rank[ref_sorted[i].first], PREFETCH_REF_TOPN);
++	}
++    }
++  return;
++}
++
+ /* Dumps information about memory reference */
+ static void
+ dump_mem_details (FILE *file, tree base, tree step,
+@@ -479,6 +628,30 @@ idx_analyze_ref (tree base, tree *index, void *data)
+   return true;
+ }
+ 
++/* Dumps information about ar_data structure.  */
++
++static void
++dump_ar_data_details (FILE *file, tree ref, struct ar_data &ar_data)
++{
++  print_generic_expr (file, ref, TDF_SLIM);
++  fprintf (file, "\n");
++  if (*(ar_data.step))
++    {
++      fprintf (file, " step ");
++      if (cst_and_fits_in_hwi (*(ar_data.step)))
++	fprintf (file, HOST_WIDE_INT_PRINT_DEC,
++		 int_cst_value (*(ar_data.step)));
++      else
++	print_generic_expr (file, *(ar_data.step), TDF_SLIM);
++    }
++  fprintf (file, "\n");
++  if (*(ar_data.delta))
++    {
++      fprintf (file, " delta " HOST_WIDE_INT_PRINT_DEC "\n",
++	       *(ar_data.delta));
++    }
++}
++
+ /* Tries to express REF_P in shape &BASE + STEP * iter + DELTA, where DELTA and
+    STEP are integer constants and iter is number of iterations of LOOP.  The
+    reference occurs in statement STMT.  Strips nonaddressable component
+@@ -526,7 +699,17 @@ analyze_ref (class loop *loop, tree *ref_p, tree *base,
+   ar_data.stmt = stmt;
+   ar_data.step = step;
+   ar_data.delta = delta;
+-  return for_each_index (base, idx_analyze_ref, &ar_data);
++
++  if (dump_file && (dump_flags & TDF_DETAILS))
++    {
++      dump_ar_data_details (dump_file, ref, ar_data);
++    }
++  bool idx_flag = for_each_index (base, idx_analyze_ref, &ar_data);
++  if (dump_file && (dump_flags & TDF_DETAILS))
++    {
++      fprintf (dump_file, "idx_flag = %d \n\n", idx_flag);
++    }
++  return idx_flag;
+ }
+ 
+ /* Record a memory reference REF to the list REFS.  The reference occurs in
+@@ -601,6 +784,55 @@ gather_memory_references_ref (class loop *loop, struct mem_ref_group **refs,
+   return true;
+ }
+ 
++/* Determine whether to collect the memory references based on the
++   ranking of ref cache miss counts.  */
++
++static bool
++should_gather_memory_references (gimple *stmt)
++{
++  if (!(profile_exist (CACHE_MISSES)))
++    {
++      return true;
++    }
++
++  if (dump_file && (dump_flags & TDF_DETAILS))
++    {
++      fprintf (dump_file, "stmt:");
++      print_gimple_stmt (dump_file, stmt, 0);
++      fprintf (dump_file, "\n");
++    }
++  if (ref_rank.count (gimple_location (stmt)) == 0)
++    {
++      if (dump_file && (dump_flags & TDF_DETAILS))
++	{
++	  fprintf (dump_file, "stmt location no found, skip prefetch "
++			      "analysis\n");
++	}
++      return false;
++    }
++  gcov_type loc_count = event_get_loc_count (gimple_location (stmt), CACHE_MISSES);
++  if (ref_rank[gimple_location (stmt)] > PREFETCH_REF_TOPN)
++    {
++      if (dump_file && (dump_flags & TDF_DETAILS))
++	{
++	  fprintf (dump_file, "stmt loc %u counts is %lu:"
++			      "rank %d exceed topn %d, skip prefetch "
++			      "analysis\n",
++		   gimple_location (stmt), loc_count,
++		   ref_rank[gimple_location (stmt)], PREFETCH_REF_TOPN);
++	}
++      return false;
++    }
++  if (dump_file && (dump_flags & TDF_DETAILS))
++    {
++      fprintf (dump_file, "stmt loc %u counts is %lu: rank %d in top %d,"
++			  "continue prefetch analysis\n",
++	       gimple_location (stmt), loc_count,
++	       ref_rank[gimple_location (stmt)], PREFETCH_REF_TOPN);
++    }
++  return true;
++}
++
+ /* Record the suitable memory references in LOOP.  NO_OTHER_REFS is set to
+    true if there are no other memory references inside the loop.  */
+ 
+@@ -626,6 +858,13 @@ gather_memory_references (class loop *loop, bool *no_other_refs, unsigned *ref_c
+       if (bb->loop_father != loop)
+ 	continue;
+ 
++      if (dump_file && (dump_flags & TDF_DETAILS))
++	{
++	  fprintf (dump_file, "==== the %dth loop bb body ====\n", i);
++	  gimple_dump_bb (dump_file, bb, 0, dump_flags);
++	  fprintf (dump_file, "\n");
++	}
++
+       for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi))
+ 	{
+ 	  stmt = gsi_stmt (bsi);
+@@ -642,20 +881,31 @@ gather_memory_references (class loop *loop, bool *no_other_refs, unsigned *ref_c
+ 	  if (! gimple_vuse (stmt))
+ 	    continue;
+ 
++	  if (!should_gather_memory_references (stmt))
++	    continue;
++
+ 	  lhs = gimple_assign_lhs (stmt);
+ 	  rhs = gimple_assign_rhs1 (stmt);
+ 
+ 	  if (REFERENCE_CLASS_P (rhs))
+ 	    {
+-	    *no_other_refs &= gather_memory_references_ref (loop, &refs,
+-							    rhs, false, stmt);
+-	    *ref_count += 1;
++	      if (dump_file && (dump_flags & TDF_DETAILS))
++		{
++		  fprintf (dump_file, "====> the %dth ref \n", *ref_count);
++		}
++	      *no_other_refs &= gather_memory_references_ref (loop, &refs, rhs,
++							      false, stmt);
++	      *ref_count += 1;
+ 	    }
+ 	  if (REFERENCE_CLASS_P (lhs))
+ 	    {
+-	    *no_other_refs &= gather_memory_references_ref (loop, &refs,
+-							    lhs, true, stmt);
+-	    *ref_count += 1;
++	      if (dump_file && (dump_flags & TDF_DETAILS))
++		{
++		  fprintf (dump_file, "====> the %dth ref \n", *ref_count);
++		}
++	      *no_other_refs &= gather_memory_references_ref (loop, &refs, lhs,
++							      true, stmt);
++	      *ref_count += 1;
+ 	    }
+ 	}
+     }
+@@ -1168,9 +1418,9 @@ issue_prefetch_ref (struct mem_ref *ref, unsigned unroll_factor, unsigned ahead)
+   bool nontemporal = ref->reuse_distance >= L2_CACHE_SIZE_BYTES;
+ 
+   if (dump_file && (dump_flags & TDF_DETAILS))
+-    fprintf (dump_file, "Issued%s prefetch for reference %u:%u.\n",
+-	     nontemporal ? " nontemporal" : "",
+-	     ref->group->uid, ref->uid);
++      fprintf (dump_file, "Issued%s prefetch for reference %u:%u.\n",
++	       nontemporal ? " nontemporal" : "",
++	       ref->group->uid, ref->uid);
+ 
+   bsi = gsi_for_stmt (ref->stmt);
+ 
+@@ -1875,6 +2125,306 @@ insn_to_prefetch_ratio_too_small_p (unsigned ninsns, unsigned prefetch_count,
+   return false;
+ }
+ 
++/* Obtain the edge probability information of each basic block in the loop.  */
++
++static float
++get_edge_prob (edge e)
++{
++  /* Limit the minimum probability value.  */
++  const float MINNUM_PROB = 0.00001f;
++  float fvalue = 1;
++
++  profile_probability probability = e->probability;
++  if (probability.initialized_p ())
++    {
++      fvalue = probability.to_reg_br_prob_base () / float (REG_BR_PROB_BASE);
++      if (fvalue < MINNUM_PROB && probability.to_reg_br_prob_base ())
++	{
++	  fvalue = MINNUM_PROB;
++	}
++    }
++  return fvalue;
++}
++
++
++/* 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 loop bb body ======= \n", i);
++	  gimple_dump_bb (dump_file, bb, 0, dump_flags);
++	  fprintf (dump_file, "\n");
++	}
++    }
++  free (body);
++}
++
++
++/* Obtain the branch probability information of each basic block
++   in the loop.  */
++
++static void
++get_bb_branch_prob (hash_map  &bb_branch_prob,
++		 struct loop *loop)
++{
++  basic_block *body = get_loop_body (loop);
++  basic_block bb = NULL;
++  for (unsigned i = 0; i < loop->num_nodes; i++)
++    {
++      bb = body[i];
++      if (bb->loop_father != loop)
++	{
++	  continue;
++	}
++      bb_bp &branch_prob = bb_branch_prob.get_or_insert (bb);
++      branch_prob.bb = bb;
++      branch_prob.true_edge_bb = NULL;
++      branch_prob.false_edge_bb = NULL;
++      branch_prob.true_edge_prob = 0;
++      branch_prob.false_edge_prob = 0;
++      branch_prob.bb_prob = 0;
++
++      gimple *stmt = last_stmt (bb);
++      if (stmt && gimple_code (stmt) == GIMPLE_COND)
++	{
++	  if (EDGE_COUNT (bb->succs) != 2)
++	    {
++	      if (dump_file && (dump_flags & TDF_DETAILS))
++		fprintf (dump_file, "The number of successful edges of bb"
++				    "is abnormal\n");
++	      continue;
++	    }
++	  edge true_edge = NULL;
++	  edge false_edge = NULL;
++	  extract_true_false_edges_from_block (bb, &true_edge, &false_edge);
++
++	  /* If it is exiting bb, and the destination bb of the edge does not
++	     belong to the current loop, the information of the edge is not
++	     recorded.  */
++	  if (true_edge->dest->loop_father == loop)
++	    {
++	      branch_prob.true_edge_bb = true_edge->dest;
++	      branch_prob.true_edge_prob = get_edge_prob (true_edge);
++	    }
++	  if (false_edge->dest->loop_father == loop)
++	    {
++	      branch_prob.false_edge_bb = false_edge->dest;
++	      branch_prob.false_edge_prob = get_edge_prob (false_edge);
++	    }
++	}
++
++      edge e = find_fallthru_edge (bb->succs);
++      if (e)
++	{
++	  branch_prob.true_edge_bb = e->dest;
++	  branch_prob.true_edge_prob = get_edge_prob (e);
++	}
++    }
++}
++
++/* Traverse each bb in the loop and prune fake loops.  */
++
++static bool
++traverse_prune_bb_branch (hash_map  &bb_branch_prob,
++			  int& max_path, hash_set  &path_node,
++			  basic_block current_bb, basic_block latch_bb)
++{
++  /* Limit the maximum number of analysis paths.  */
++  if (max_path <= 0 || current_bb == NULL)
++    return false;
++
++  /* Do not join edges that do not form a complete loop.  */
++  bb_bp *bb_bp_node = bb_branch_prob.get (current_bb);
++  if (bb_bp_node == NULL || (bb_bp_node->true_edge_bb == NULL
++			     && bb_bp_node->false_edge_bb == NULL))
++    return false;
++
++  if (current_bb == latch_bb)
++    {
++      max_path--;
++      return true;
++    }
++
++  /* Do not join edges that return to non-dominate nodes.  */
++  if (path_node.contains (bb_bp_node->true_edge_bb)
++      || path_node.contains (bb_bp_node->false_edge_bb))
++    {
++      if (dump_file && (dump_flags & TDF_DETAILS))
++	fprintf (dump_file, "fake loop: in bb%d\n", current_bb->index);
++      return false;
++    }
++
++  path_node.add (current_bb);
++  if (bb_bp_node->true_edge_bb)
++    {
++      if (traverse_prune_bb_branch (bb_branch_prob, max_path,
++		path_node, bb_bp_node->true_edge_bb, latch_bb) == false)
++	return false;
++    }
++  if (bb_bp_node->false_edge_bb)
++    {
++      if (traverse_prune_bb_branch (bb_branch_prob, max_path,
++		path_node, bb_bp_node->false_edge_bb, latch_bb) == false)
++	return false;
++    }
++  path_node.remove (current_bb);
++
++  max_path--;
++  return true;
++}
++
++/* Traverse and calculate the probability of basic block.  */
++
++static void
++traverse_calculate_bb_prob (hash_map  &bb_branch_prob,
++			    basic_block current_bb, basic_block latch_bb,
++			    float prob)
++{
++  /* Limit bb block access probability, the probability is
++     less than 100% and include delta.  */
++  const float MAX_BB_PROBABILITY = 1.001f;
++
++  if (current_bb == NULL)
++    {
++      return;
++    }
++  bb_bp *bb_bp_node = bb_branch_prob.get (current_bb);
++  bb_bp_node->bb_prob += prob;
++
++  gcc_assert (bb_bp_node->bb_prob <= MAX_BB_PROBABILITY);
++
++  if (bb_bp_node == NULL || (bb_bp_node->true_edge_bb == NULL
++			     && bb_bp_node->false_edge_bb == NULL))
++    {
++      return;
++    }
++  if (current_bb == latch_bb)
++    {
++      return;
++    }
++
++  bool assign = (bb_bp_node->true_edge_bb && bb_bp_node->false_edge_bb);
++  if (bb_bp_node->true_edge_bb)
++    {
++      float assign_prob = assign ? bb_bp_node->true_edge_prob * prob : prob;
++      traverse_calculate_bb_prob (bb_branch_prob,
++			    bb_bp_node->true_edge_bb, latch_bb, assign_prob);
++    }
++  if (bb_bp_node->false_edge_bb)
++    {
++      float assign_prob = assign ? bb_bp_node->false_edge_prob * prob : prob;
++      traverse_calculate_bb_prob (bb_branch_prob,
++			    bb_bp_node->false_edge_bb, latch_bb, assign_prob);
++    }
++  return;
++}
++
++/* Obtain the probability of basic block.  */
++
++static bool
++get_bb_prob (hash_map  &bb_branch_prob, struct loop *loop)
++{
++  /* The upper limit of the branch path in the loop is 10000.  */
++  const int MAX_BB_BRANCH_PATH = 10000;
++
++  if (loop->header == NULL || loop->latch == NULL
++      || loop->header == loop->latch)
++    {
++      if (dump_file && (dump_flags & TDF_DETAILS))
++	fprintf (dump_file, "get_bb_prob failed: without the header bb or "
++			    "latch bb\n");
++      return false;
++    }
++
++  bb_bp *latch_branch_prob = bb_branch_prob.get (loop->latch);
++  bb_bp *header_branch_prob = bb_branch_prob.get (loop->header);
++  if (header_branch_prob == NULL || latch_branch_prob == NULL
++      || (latch_branch_prob->true_edge_bb != header_branch_prob->bb
++	  && latch_branch_prob->false_edge_bb != header_branch_prob->bb))
++    {
++      if (dump_file && (dump_flags & TDF_DETAILS))
++	fprintf (dump_file, "get_bb_prob failed: loop data exception\n");
++      return false;
++    }
++
++  hash_set  path_node;
++  int max_path = MAX_BB_BRANCH_PATH;
++  if (traverse_prune_bb_branch (bb_branch_prob, max_path, path_node,
++			    header_branch_prob->bb, loop->latch) == false)
++    {
++      if (dump_file && (dump_flags & TDF_DETAILS))
++	fprintf (dump_file, "traverse_prune_bb_branch false.\n");
++      return false;
++    }
++  traverse_calculate_bb_prob (bb_branch_prob,
++			      header_branch_prob->bb, loop->latch, 1);
++
++  return true;
++}
++
++/* Computes an estimated number of insns in LOOP, weighted by WEIGHTS.  */
++
++static unsigned
++estimate_num_loop_insns (struct loop *loop, eni_weights *weights)
++{
++  basic_block *body = get_loop_body_in_dom_order (loop);
++  gimple_stmt_iterator gsi;
++  float size = 0;
++  basic_block bb = NULL;
++  hash_map  bb_branch_prob;
++
++  if (prefetch_level >= BRANCH_WEIGHTED_AHEAD)
++    {
++      get_bb_branch_prob (bb_branch_prob, loop);
++      if (get_bb_prob (bb_branch_prob, loop) == false)
++	{
++	  dump_loop_bb (loop);
++	  return 0;
++	}
++    }
++
++  for (unsigned i = 0; i < loop->num_nodes; i++)
++    {
++      bb = body[i];
++      /* For nested loops, the bb of the inner loop is not calculated.  */
++      if (bb->loop_father != loop)
++	{
++	  continue;
++	}
++
++      float size_tmp = 0;
++      for (gsi = gsi_start_bb (body[i]); !gsi_end_p (gsi); gsi_next (&gsi))
++	{
++	  size_tmp += estimate_num_insns (gsi_stmt (gsi), weights);
++	}
++
++      if (prefetch_level >= BRANCH_WEIGHTED_AHEAD)
++	{
++	  float bb_prob = bb_branch_prob.get (bb)->bb_prob;
++	  size += size_tmp * bb_prob;
++	}
++      else
++	{
++	  size += size_tmp;
++	}
++    }
++  free (body);
++
++  return unsigned (size);
++}
+ 
+ /* Issue prefetch instructions for array references in LOOP.  Returns
+    true if the LOOP was unrolled.  */
+@@ -1899,7 +2449,15 @@ loop_prefetch_arrays (class loop *loop)
+ 
+   /* FIXME: the time should be weighted by the probabilities of the blocks in
+      the loop body.  */
+-  time = tree_num_loop_insns (loop, &eni_time_weights);
++
++  if (prefetch_level >= REFINE_BB_AHEAD)
++    {
++      time = estimate_num_loop_insns (loop, &eni_time_weights);
++    }
++  else
++    {
++      time = tree_num_loop_insns (loop, &eni_time_weights);
++    }
+   if (time == 0)
+     return false;
+ 
+@@ -1913,7 +2471,14 @@ loop_prefetch_arrays (class loop *loop)
+   if (trip_count_to_ahead_ratio_too_small_p (ahead, est_niter))
+     return false;
+ 
+-  ninsns = tree_num_loop_insns (loop, &eni_size_weights);
++  if (prefetch_level >= REFINE_BB_AHEAD)
++    {
++      ninsns = estimate_num_loop_insns (loop, &eni_size_weights);
++    }
++  else
++    {
++      ninsns = tree_num_loop_insns (loop, &eni_size_weights);
++    }
+ 
+   /* Step 1: gather the memory references.  */
+   refs = gather_memory_references (loop, &no_other_refs, &mem_ref_count);
+@@ -1978,10 +2543,49 @@ fail:
+   return unrolled;
+ }
+ 
++/* Determine if it is a high execution rate loop.  */
++
++static bool
++is_high_exec_rate_loop (struct loop *loop)
++{
++  vec exit_edges = get_loop_exit_edges (loop);
++  if (exit_edges == vNULL)
++    {
++      return false;
++    }
++
++  unsigned i = 0;
++  gcov_type exit_count = 0;
++  edge e = NULL;
++  float loop_exec_rate = 0;
++  gcov_type header_bb_count = loop->header->count.to_gcov_type ();
++  FOR_EACH_VEC_ELT (exit_edges, i, e)
++    {
++      gcov_type exiting_bb_count = e->src->count.to_gcov_type ();
++      float exit_edge_prob = get_edge_prob (e);
++      exit_count += exit_edge_prob * exiting_bb_count;
++
++      loop_exec_rate = 1.0 - ((double) exit_count / header_bb_count);
++
++      if (loop_exec_rate < (float) LOOP_EXECUTION_RATE / 100.0)
++	{
++	  return false;
++	}
++    }
++
++  if (dump_file && (dump_flags & TDF_DETAILS))
++    {
++      fprintf (dump_file, "loop with high execution rate: %f >= %f\n\n",
++	       loop_exec_rate, (float) LOOP_EXECUTION_RATE / 100.0);
++      dump_loop_bb (loop);
++    }
++  return true;
++}
++
+ /* Issue prefetch instructions for array references in loops.  */
+ 
+ unsigned int
+-tree_ssa_prefetch_arrays (void)
++tree_ssa_prefetch_arrays (function *fun)
+ {
+   class loop *loop;
+   bool unrolled = false;
+@@ -2012,6 +2616,12 @@ tree_ssa_prefetch_arrays (void)
+ 	       param_min_insn_to_prefetch_ratio);
+       fprintf (dump_file, "    min insn-to-mem ratio: %d \n",
+ 	       param_prefetch_min_insn_to_mem_ratio);
++      fprintf (dump_file, "    prefetch_func_topn: %d \n",
++	       param_prefetch_func_topn);
++      fprintf (dump_file, "    prefetch_ref_topn: %d \n",
++	       param_prefetch_ref_topn);
++      fprintf (dump_file, "    high_loop_execution_rate: %d \n",
++	       LOOP_EXECUTION_RATE);
+       fprintf (dump_file, "\n");
+     }
+ 
+@@ -2028,13 +2638,42 @@ tree_ssa_prefetch_arrays (void)
+       set_builtin_decl (BUILT_IN_PREFETCH, decl, false);
+     }
+ 
+-  FOR_EACH_LOOP (loop, LI_FROM_INNERMOST)
++  enum li_flags LI = LI_FROM_INNERMOST;
++
++  if (profile_exist (CACHE_MISSES))
++    {
++      LI = LI_ONLY_INNERMOST;
++    }
++  if (dump_file && (dump_flags & TDF_DETAILS))
++    {
++      fprintf (dump_file, "Processing model %d:\n", LI);
++    }
++
++  if (profile_exist (CACHE_MISSES))
++    {
++      sort_ref_by_event_count (fun, CACHE_MISSES);
++    }
++
++  FOR_EACH_LOOP (loop, LI)
+     {
+       if (dump_file && (dump_flags & TDF_DETAILS))
+-	fprintf (dump_file, "Processing loop %d:\n", loop->num);
++	{
++	  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");
++	}
+ 
+-      unrolled |= loop_prefetch_arrays (loop);
++      if (profile_exist (CACHE_MISSES))
++	{
++	  if (!is_high_exec_rate_loop (loop))
++	    {
++	      continue;
++	    }
++	}
+ 
++      unrolled |= loop_prefetch_arrays (loop);
+       if (dump_file && (dump_flags & TDF_DETAILS))
+ 	fprintf (dump_file, "\n\n");
+     }
+@@ -2049,6 +2688,56 @@ tree_ssa_prefetch_arrays (void)
+   return todo_flags;
+ }
+ 
++/* Determine whether to analyze the function according to
++   the sorting of the function containing cache-miss counts.  */
++
++static bool
++should_analyze_func_p (void)
++{
++  gcov_type decl_uid = DECL_UID (current_function_decl);
++  struct rank_info func_rank_info =
++    event_get_func_rank (decl_uid, CACHE_MISSES);
++  if (func_rank_info.total == 0)
++    {
++      return false;
++    }
++  gcov_type func_count = event_get_func_count (decl_uid, CACHE_MISSES);
++  if (func_count == 0)
++    {
++      if (dump_file && (dump_flags & TDF_DETAILS))
++	{
++	  fprintf (dump_file, "function uid %d cannot find profile data "
++			      "and skip prefetch analysis\n",
++		   decl_uid);
++	}
++      return false;
++    }
++  if (func_rank_info.rank > PREFETCH_FUNC_TOPN
++      || func_count < PREFETCH_FUNC_COUNTS_THRESHOLD)
++    {
++      if (dump_file && (dump_flags & TDF_DETAILS))
++	{
++	  fprintf (dump_file, "function uid %d total counts is %lu: "
++			      "rank %d > topn %d, counts %lu < threshold %lu "
++			      "skip prefetch analysis\n",
++		   decl_uid, func_count,
++		   func_rank_info.rank, PREFETCH_FUNC_TOPN,
++		   func_count, PREFETCH_FUNC_COUNTS_THRESHOLD);
++	}
++      return false;
++    }
++  if (dump_file && (dump_flags & TDF_DETAILS))
++    {
++      fprintf (dump_file, "function uid %d total counts is %lu: "
++			  "rank %d in topn %d, counts %lu > threshold %lu "
++			  "continue prefetch analysis\n",
++	       decl_uid, func_count,
++	       func_rank_info.rank, PREFETCH_FUNC_TOPN,
++	       func_count, PREFETCH_FUNC_COUNTS_THRESHOLD);
++    }
++  return true;
++}
++
+ /* Prefetching.  */
+ 
+ namespace {
+@@ -2085,6 +2774,18 @@ pass_loop_prefetch::execute (function *fun)
+   if (number_of_loops (fun) <= 1)
+     return 0;
+ 
++  /* Filter only when combined with cache-miss. When the should_analyze_func_p
++     analysis fails (for example, the function without cache-miss count),
++     in order to ensure the accuracy of the prefetch analysis, the function
++     does not perform native prefetch processing.  */
++  if (profile_exist (CACHE_MISSES))
++    {
++      if (!should_analyze_func_p ())
++	{
++	  return 0;
++	}
++    }
++
+   if ((PREFETCH_BLOCK & (PREFETCH_BLOCK - 1)) != 0)
+     {
+       static bool warned = false;
+@@ -2099,7 +2800,7 @@ pass_loop_prefetch::execute (function *fun)
+       return 0;
+     }
+ 
+-  return tree_ssa_prefetch_arrays ();
++  return tree_ssa_prefetch_arrays (fun);
+ }
+ 
+ } // anon namespace
+-- 
+2.27.0.windows.1
+
diff --git a/0028-AutoPrefetch-Handle-the-case-that-the-basic-block-br.patch b/0028-AutoPrefetch-Handle-the-case-that-the-basic-block-br.patch
new file mode 100644
index 0000000..48c2e52
--- /dev/null
+++ b/0028-AutoPrefetch-Handle-the-case-that-the-basic-block-br.patch
@@ -0,0 +1,151 @@
+From 3d20b13bc2e5af8d52e221a33881423e38c3dfdd Mon Sep 17 00:00:00 2001
+From: dingguangya 
+Date: Thu, 17 Feb 2022 21:53:31 +0800
+Subject: [PATCH 28/28] [AutoPrefetch] Handle the case that the basic block
+ branch probability is invalid
+
+ When the node branch probability value is not initialized,
+ the branch probability must be set to 0 to ensure that
+ the calculation of the basic block execution probability
+ must be less than or equal to 100%.
+---
+ .../gcc.dg/autoprefetch/autoprefetch.exp      | 27 +++++++++++++++++++
+ .../autoprefetch/branch-weighted-prefetch.c   | 22 +++++++++++++++
+ .../autoprefetch/get-edge-prob-non-init.c     | 24 +++++++++++++++++
+ gcc/tree-ssa-loop-prefetch.c                  | 17 +++++++++++-
+ 4 files changed, 89 insertions(+), 1 deletion(-)
+ create mode 100644 gcc/testsuite/gcc.dg/autoprefetch/autoprefetch.exp
+ create mode 100644 gcc/testsuite/gcc.dg/autoprefetch/branch-weighted-prefetch.c
+ create mode 100644 gcc/testsuite/gcc.dg/autoprefetch/get-edge-prob-non-init.c
+
+diff --git a/gcc/testsuite/gcc.dg/autoprefetch/autoprefetch.exp b/gcc/testsuite/gcc.dg/autoprefetch/autoprefetch.exp
+new file mode 100644
+index 000000000..a7408e338
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/autoprefetch/autoprefetch.exp
+@@ -0,0 +1,27 @@
++#   Copyright (C) 1997-2022 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 target-supports.exp
++
++# Initialize `dg'.
++dg-init
++
++gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] \
++	"" "-fprefetch-loop-arrays"
++
++# All done.
++dg-finish
+\ No newline at end of file
+diff --git a/gcc/testsuite/gcc.dg/autoprefetch/branch-weighted-prefetch.c b/gcc/testsuite/gcc.dg/autoprefetch/branch-weighted-prefetch.c
+new file mode 100644
+index 000000000..c63c5e5cb
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/autoprefetch/branch-weighted-prefetch.c
+@@ -0,0 +1,22 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -fprefetch-loop-arrays=2 --param min-insn-to-prefetch-ratio=5 --param simultaneous-prefetches=100 -fdump-tree-aprefetch-details -fdump-tree-optimized" } */
++#define N 10000000
++
++long long a[N];
++
++long long func ()
++{
++  long long i;
++  long long sum = 0;
++
++  for (i = 0; i < N; i+=1) {
++	if (i < 100000)
++		sum += a[i];
++	else
++		continue;
++  }
++
++  return sum;
++}
++/* { dg-final { scan-tree-dump-times "Ahead 40" 1 "aprefetch" } } */
++/* { dg-final { scan-tree-dump-times "builtin_prefetch" 1 "optimized" } } */
+\ No newline at end of file
+diff --git a/gcc/testsuite/gcc.dg/autoprefetch/get-edge-prob-non-init.c b/gcc/testsuite/gcc.dg/autoprefetch/get-edge-prob-non-init.c
+new file mode 100644
+index 000000000..f55481008
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/autoprefetch/get-edge-prob-non-init.c
+@@ -0,0 +1,24 @@
++/* { dg-do compile } */
++/* { dg-options "-Ofast -fprefetch-loop-arrays=2 -fdump-tree-aprefetch-details" } */
++
++int a, c, f;
++static int *b = &a;
++int *d;
++int e[0];
++void g() {
++  int h;
++  for (;;) {
++    h = 1;
++    for (; h >= 0; h--) {
++      c = 2;
++      for (; c; c--)
++        if (e[0])
++          if (e[c])
++            *b = 0;
++      f || (*d = 0);
++    }
++  }
++}
++int main() {}
++
++/* { dg-final } */
+diff --git a/gcc/tree-ssa-loop-prefetch.c b/gcc/tree-ssa-loop-prefetch.c
+index 3a5aef0fc..673f453a4 100644
+--- a/gcc/tree-ssa-loop-prefetch.c
++++ b/gcc/tree-ssa-loop-prefetch.c
+@@ -2132,7 +2132,7 @@ get_edge_prob (edge e)
+ {
+   /* Limit the minimum probability value.  */
+   const float MINNUM_PROB = 0.00001f;
+-  float fvalue = 1;
++  float fvalue = 0;
+ 
+   profile_probability probability = e->probability;
+   if (probability.initialized_p ())
+@@ -2143,6 +2143,21 @@ get_edge_prob (edge e)
+ 	  fvalue = MINNUM_PROB;
+ 	}
+     }
++  else
++    {
++      /* When the node branch probability value is not initialized, the branch
++	 probability must be set to 0 to ensure that the calculation of the
++	 basic block execution probability must be less than or equal to 100%.
++	 i.e,
++	 ...
++	  [local count: 20000]
++	 if (f_2 != 0)
++	   goto ; [INV]
++	 else
++	   goto ; [100.00%]
++	 ...  */
++      fvalue = 0;
++    }
+   return fvalue;
+ }
+ 
+-- 
+2.27.0.windows.1
+
diff --git a/0029-AutoBOLT-Support-saving-feedback-count-info-to-ELF-s.patch b/0029-AutoBOLT-Support-saving-feedback-count-info-to-ELF-s.patch
new file mode 100644
index 0000000..42053fc
--- /dev/null
+++ b/0029-AutoBOLT-Support-saving-feedback-count-info-to-ELF-s.patch
@@ -0,0 +1,548 @@
+From c34a02199b1dfd362e81e78cb90fbd11e02eb93e Mon Sep 17 00:00:00 2001
+From: liyancheng <412998149@qq.com>
+Date: Mon, 14 Feb 2022 14:34:41 +0800
+Subject: [PATCH 29/32] [AutoBOLT] Support saving feedback count info to ELF
+ segment 1/3
+
+Add flag -fauto-bolt to save the feedback count info from PGO or
+AutoFDO to segment .text.fdo. The bolt plugin will read and parse
+it into the profile of llvm-bolt.
+---
+ gcc/common.opt |   8 +
+ gcc/final.c    | 400 +++++++++++++++++++++++++++++++++++++++++++++++++
+ gcc/opts.c     |  61 ++++++++
+ 3 files changed, 469 insertions(+)
+
+diff --git a/gcc/common.opt b/gcc/common.opt
+index 9488bd90f..5eaa667b3 100644
+--- a/gcc/common.opt
++++ b/gcc/common.opt
+@@ -2403,6 +2403,14 @@ freorder-functions
+ Common Report Var(flag_reorder_functions) Optimization
+ Reorder functions to improve code placement.
+ 
++fauto-bolt
++Common Report 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 Report Var(flag_rerun_cse_after_loop) Optimization
+ Add a common subexpression elimination pass after loop optimizations.
+diff --git a/gcc/final.c b/gcc/final.c
+index a3601964a..b9affd3a7 100644
+--- a/gcc/final.c
++++ b/gcc/final.c
+@@ -81,6 +81,7 @@ along with GCC; see the file COPYING3.  If not see
+ #include "rtl-iter.h"
+ #include "print-rtl.h"
+ #include "function-abi.h"
++#include "insn-codes.h"
+ 
+ #ifdef XCOFF_DEBUGGING_INFO
+ #include "xcoffout.h"		/* Needed for external data declarations.  */
+@@ -4640,6 +4641,399 @@ 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;
++	}
++
++      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 offset 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 AFDO.  */
++
++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];
++}
++
++/* Dump 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 void
++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 info 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 turned 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-sections");
++      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 supported with -falign-labels");
++      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 -fprofile-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)
+@@ -4707,6 +5101,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.c b/gcc/opts.c
+index f49f5ee58..0b389ae1d 100644
+--- a/gcc/opts.c
++++ b/gcc/opts.c
+@@ -1166,6 +1166,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,
+@@ -1183,6 +1187,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;
++	}
++    }
+ }
+ 
+ #define LEFT_COLUMN	27
+@@ -2881,6 +2937,11 @@ common_handle_option (struct gcc_options *opts,
+       check_alignment_argument (loc, arg, "functions");
+       break;
+ 
++    case OPT_fauto_bolt_:
++    case OPT_fauto_bolt:
++      /* Deferred.  */
++      break;
++
+     default:
+       /* If the flag was handled in a standard way, assume the lack of
+ 	 processing here is intentional.  */
+-- 
+2.27.0
+
diff --git a/0030-AutoBOLT-Add-bolt-linker-plugin-2-3.patch b/0030-AutoBOLT-Add-bolt-linker-plugin-2-3.patch
new file mode 100644
index 0000000..b3455e4
--- /dev/null
+++ b/0030-AutoBOLT-Add-bolt-linker-plugin-2-3.patch
@@ -0,0 +1,21748 @@
+From e2d5ed57fef0f731d253947a60035464b02f6c21 Mon Sep 17 00:00:00 2001
+From: liyancheng <412998149@qq.com>
+Date: Mon, 14 Feb 2022 14:59:18 +0800
+Subject: [PATCH 30/32] [AutoBOLT] Add bolt linker plugin 2/3
+
+Add option -fbolt-use for perform bolt optimization.
+Add option -fbolt-target to specify bolt optimization target.
+Add option -fbolt-option to specify bolt optimization options.
+
+Add the bolt linker plugin to read the profile count info when
+processing the .text.fdo segment in each .o, and generate the
+profile required by llvm-bolt at the end of linkage. Finally,
+use profile from -fauto-bolt or -fbolt-use to complete bolt
+optimization.
+---
+ bolt-plugin/Makefile.am    |    42 +
+ bolt-plugin/Makefile.in    |   685 ++
+ bolt-plugin/aclocal.m4     |  1163 +++
+ bolt-plugin/bolt-plugin.cc |  1152 +++
+ bolt-plugin/config.h.in    |   121 +
+ bolt-plugin/configure      | 18379 +++++++++++++++++++++++++++++++++++
+ bolt-plugin/configure.ac   |    59 +
+ gcc/common.opt             |    16 +
+ gcc/opts.c                 |    23 +
+ 9 files changed, 21640 insertions(+)
+ 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.am b/bolt-plugin/Makefile.am
+new file mode 100644
+index 000000000..1fb93bd6e
+--- /dev/null
++++ b/bolt-plugin/Makefile.am
+@@ -0,0 +1,42 @@
++## 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..3336fe48c
+--- /dev/null
++++ b/bolt-plugin/Makefile.in
+@@ -0,0 +1,685 @@
++# Makefile.in generated by automake 1.16.1 from Makefile.am.
++# @configure_input@
++
++# Copyright (C) 1994-2018 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)/../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 \
++	$(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)`
++ETAGS = etags
++CTAGS = ctags
++CSCOPE = cscope
++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@
++CPP = @CPP@
++CPPFLAGS = @CPPFLAGS@
++CXX = @CXX@
++CXXCPP = @CXXCPP@
++CXXDEPMODE = @CXXDEPMODE@
++CXXFLAGS = @CXXFLAGS@
++CYGPATH_W = @CYGPATH_W@
++DEFS = @DEFS@
++DEPDIR = @DEPDIR@
++DSYMUTIL = @DSYMUTIL@
++DUMPBIN = @DUMPBIN@
++ECHO_C = @ECHO_C@
++ECHO_N = @ECHO_N@
++ECHO_T = @ECHO_T@
++EGREP = @EGREP@
++EXEEXT = @EXEEXT@
++FGREP = @FGREP@
++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@
++MAINT = @MAINT@
++MAKEINFO = @MAKEINFO@
++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_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@
++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_libsubdir = @build_libsubdir@
++build_os = @build_os@
++build_subdir = @build_subdir@
++build_vendor = @build_vendor@
++builddir = @builddir@
++datadir = @datadir@
++datarootdir = @datarootdir@
++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@
++infodir = @infodir@
++install_sh = @install_sh@
++libdir = @libdir@
++libexecdir = @libexecdir@
++localedir = @localedir@
++localstatedir = @localstatedir@
++lt_host_flags = @lt_host_flags@
++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@
++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_subdir = @target_subdir@
++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 --ignore-deps'; \
++	      $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign --ignore-deps \
++		&& exit 0; \
++	      exit 1;; \
++	  esac; \
++	done; \
++	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign --ignore-deps Makefile'; \
++	$(am__cd) $(top_srcdir) && \
++	  $(AUTOMAKE) --foreign --ignore-deps 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..22bc33401
+--- /dev/null
++++ b/bolt-plugin/aclocal.m4
+@@ -0,0 +1,1163 @@
++# generated automatically by aclocal 1.16.1 -*- Autoconf -*-
++
++# Copyright (C) 1996-2018 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.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'.])])
++
++# Copyright (C) 2002-2018 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.1], [],
++      [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.1])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-2018 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-2018 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-2018 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-2018 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.  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-2018 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
++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_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
++ 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
++])
++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-2018 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])])
++
++# Add --enable-maintainer-mode option to configure.         -*- Autoconf -*-
++# From Jim Meyering
++
++# Copyright (C) 1996-2018 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-2018 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-2018 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
++  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=
++  AC_MSG_WARN(['missing' script is too old or missing])
++fi
++])
++
++# Helper functions for option handling.                     -*- Autoconf -*-
++
++# Copyright (C) 2001-2018 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-2018 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-2018 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-2018 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-2018 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-2018 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-2018 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-2018 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
++
++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/bolt-plugin.cc b/bolt-plugin/bolt-plugin.cc
+new file mode 100644
+index 000000000..f357b00dd
+--- /dev/null
++++ b/bolt-plugin/bolt-plugin.cc
+@@ -0,0 +1,1152 @@
++/* bolt plugin for gold and/or GNU ld.
++   Copyright (C) 2022-2022 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..ddbde7619
+--- /dev/null
++++ b/bolt-plugin/config.h.in
+@@ -0,0 +1,121 @@
++/* 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_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_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 the sub-directory in which 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 you have the ANSI C header files. */
++#undef STDC_HEADERS
++
++/* Enable extensions on AIX 3, Interix.  */
++#ifndef _ALL_SOURCE
++# undef _ALL_SOURCE
++#endif
++/* Enable GNU extensions on systems that have them.  */
++#ifndef _GNU_SOURCE
++# undef _GNU_SOURCE
++#endif
++/* Enable threading extensions on Solaris.  */
++#ifndef _POSIX_PTHREAD_SEMANTICS
++# undef _POSIX_PTHREAD_SEMANTICS
++#endif
++/* Enable extensions on HP NonStop.  */
++#ifndef _TANDEM_SOURCE
++# undef _TANDEM_SOURCE
++#endif
++/* 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. */
++#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..62cf7c714
+--- /dev/null
++++ b/bolt-plugin/configure
+@@ -0,0 +1,18379 @@
++#! /bin/sh
++# Guess values for system-dependent variables and create Makefiles.
++# Generated by GNU Autoconf 2.69 for bolt plugin for ld 0.1.
++#
++#
++# Copyright (C) 1992-1996, 1998-2012 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
++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
++  case `(set -o) 2>/dev/null` in #(
++  *posix*) :
++    set -o posix ;; #(
++  *) :
++     ;;
++esac
++fi
++
++
++as_nl='
++'
++export as_nl
++# 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 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 ||
++      PATH_SEPARATOR=';'
++  }
++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 #((
++  *[\\/]* ) as_myself=$0 ;;
++  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  test -z "$as_dir" && as_dir=.
++    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
++  $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.
++  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'.
++$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="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
++  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
++  exitcode=1; echo positional parameters were not saved.
++fi
++test x\$exitcode = x0 || 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='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
++    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"
++  if (eval "$as_required") 2>/dev/null; then :
++  as_have_required=yes
++else
++  as_have_required=no
++fi
++  if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
++
++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
++  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
++	     if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
++		    { $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_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
++  break 2
++fi
++fi
++	   done;;
++       esac
++  as_found=false
++done
++$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; }
++IFS=$as_save_IFS
++
++
++      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'.
++$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
++exit 255
++fi
++
++    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
++    $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."
++  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_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=`$as_echo "$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 ||
++$as_echo 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_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_fn_arith ()
++  {
++    as_val=`expr "$@" || test $? -eq 1`
++  }
++fi # as_fn_arith
++
++
++# 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
++    $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
++  fi
++  $as_echo "$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 ||
++$as_echo 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" ||
++    { $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
++  # 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
++}
++
++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
++
++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_SYS_TYPES_H
++# include 
++#endif
++#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_UNISTD_H
++# include 
++#endif"
++
++ac_subst_vars='am__EXEEXT_FALSE
++am__EXEEXT_TRUE
++LTLIBOBJS
++LIBOBJS
++target_noncanonical
++lt_host_flags
++CXXCPP
++OTOOL64
++OTOOL
++LIPO
++NMEDIT
++DSYMUTIL
++RANLIB
++AR
++OBJDUMP
++LN_S
++NM
++ac_ct_DUMPBIN
++DUMPBIN
++LD
++FGREP
++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
++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
++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_subdir
++host_subdir
++build_subdir
++build_libsubdir
++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
++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
++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_gnu_ld
++enable_libtool_lock
++'
++      ac_precious_vars='build_alias
++host_alias
++target_alias
++CC
++CFLAGS
++LDFLAGS
++LIBS
++CPPFLAGS
++CPP
++CXX
++CXXFLAGS
++CCC
++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'
++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
++
++  # Accept the important Cygnus configure options, so we can diagnose typos.
++
++  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=`$as_echo "$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=`$as_echo "$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 ;;
++
++  -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=`$as_echo "$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=`$as_echo "$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.
++    $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
++    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
++      $as_echo "$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" ;;
++    *)     $as_echo "$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
++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 ||
++$as_echo 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]
++  --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-build-libsubdir=DIR  Directory where to find libraries for build system
++  --with-libiberty=PATH   specify the directory where to find libiberty
++                          [../libiberty]
++  --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-gnu-ld           assume the C compiler uses GNU ld [default=no]
++
++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 
++  CPP         C preprocessor
++  CXX         C++ compiler command
++  CXXFLAGS    C++ compiler flags
++  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=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
++  # A ".." for each directory in $ac_dir_suffix.
++  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/ ;;
++  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 guested configure.
++    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
++      $as_echo "$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.69
++
++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
++  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
++  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\""
++$as_echo "$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
++  $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 :
++  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_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
++# 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
++  { $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 :
++  eval "$3=yes"
++else
++  eval "$3=no"
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
++fi
++eval ac_res=\$$3
++	       { $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
++
++# 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
++  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\""
++$as_echo "$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
++  $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 :
++  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_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$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\""
++$as_echo "$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
++  $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 :
++  ac_retval=0
++else
++  $as_echo "$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
++  { $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.
++   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.
++    Prefer  to  if __STDC__ is defined, since
++     exists even on freestanding compilers.  */
++
++#ifdef __STDC__
++# include 
++#else
++# include 
++#endif
++
++#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 ()
++{
++return $2 ();
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_c_try_link "$LINENO"; then :
++  eval "$3=yes"
++else
++  eval "$3=no"
++fi
++rm -f core conftest.err conftest.$ac_objext \
++    conftest$ac_exeext conftest.$ac_ext
++fi
++eval ac_res=\$$3
++	       { $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
++
++# 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\""
++$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_cxx_preproc_warn_flag$ac_cxx_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_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$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\""
++$as_echo "$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
++  $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 :
++  ac_retval=0
++else
++  $as_echo "$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
++  { $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.
++     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 ()
++{
++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 ()
++{
++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
++  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.$ac_ext
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
++       if eval test \"x\$"$3"\" = x"no"; then :
++
++else
++  break
++fi
++     done
++fi
++eval ac_res=\$$3
++	       { $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
++
++# 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
++  { $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.
++     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 ()
++{
++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.$ac_ext
++       if eval test \"x\$"$3"\" = x"no"; then :
++
++else
++  break
++fi
++     done
++fi
++eval ac_res=\$$3
++	       { $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
++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.69.  Invocation command line was
++
++  $ $0 $@
++
++_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
++  test -z "$as_dir" && as_dir=.
++    $as_echo "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=`$as_echo "$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=$?
++  # Save into config.log some information that might help in debugging.
++  {
++    echo
++
++    $as_echo "## ---------------- ##
++## 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_*) { $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) ;; #(
++      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
++
++    $as_echo "## ----------------- ##
++## Output variables. ##
++## ----------------- ##"
++    echo
++    for ac_var in $ac_subst_vars
++    do
++      eval ac_val=\$$ac_var
++      case $ac_val in
++      *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
++      esac
++      $as_echo "$ac_var='\''$ac_val'\''"
++    done | sort
++    echo
++
++    if test -n "$ac_subst_files"; then
++      $as_echo "## ------------------- ##
++## File substitutions. ##
++## ------------------- ##"
++      echo
++      for ac_var in $ac_subst_files
++      do
++	eval ac_val=\$$ac_var
++	case $ac_val in
++	*\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
++	esac
++	$as_echo "$ac_var='\''$ac_val'\''"
++      done | sort
++      echo
++    fi
++
++    if test -s confdefs.h; then
++      $as_echo "## ----------- ##
++## confdefs.h. ##
++## ----------- ##"
++      echo
++      cat confdefs.h
++      echo
++    fi
++    test "$ac_signal" != 0 &&
++      $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 &&
++    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
++
++$as_echo "/* confdefs.h */" > confdefs.h
++
++# Predefined preprocessor variables.
++
++cat >>confdefs.h <<_ACEOF
++#define PACKAGE_NAME "$PACKAGE_NAME"
++_ACEOF
++
++cat >>confdefs.h <<_ACEOF
++#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
++_ACEOF
++
++cat >>confdefs.h <<_ACEOF
++#define PACKAGE_VERSION "$PACKAGE_VERSION"
++_ACEOF
++
++cat >>confdefs.h <<_ACEOF
++#define PACKAGE_STRING "$PACKAGE_STRING"
++_ACEOF
++
++cat >>confdefs.h <<_ACEOF
++#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
++_ACEOF
++
++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
++  # 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_file1=$prefix/share/config.site
++  ac_site_file2=$prefix/etc/config.site
++else
++  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_file1" "$ac_site_file2"
++do
++  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" \
++      || { { $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
++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
++    { $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
++  { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
++$as_echo "$as_me: creating cache $cache_file" >&6;}
++  >$cache_file
++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,)
++      { $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. ##
++## -------------------- ##
++
++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_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
++done
++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.
++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.
++
++
++# 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
++
++{ $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"`
++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
++{ $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;;
++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
++
++
++{ $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
++fi
++
++fi
++{ $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;;
++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
++
++
++{ $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
++fi
++
++fi
++{ $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;;
++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}-
++
++ 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),
++# 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.
++{ $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 ${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
++  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/* ) ;;
++  *)
++    # 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+set}" = set; 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
++{ $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.
++test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
++
++test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
++
++test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
++
++{ $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='
++'
++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
++{ $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=
++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=`$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
++  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=
++  { $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
++  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
++{ $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
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  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_STRIP="${ac_tool_prefix}strip"
++    $as_echo "$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
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5
++$as_echo "$STRIP" >&6; }
++else
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "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
++{ $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
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  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_STRIP="strip"
++    $as_echo "$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
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5
++$as_echo "$ac_ct_STRIP" >&6; }
++else
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
++fi
++
++  if test "x$ac_ct_STRIP" = x; then
++    STRIP=":"
++  else
++    case $cross_compiling:$ac_tool_warned in
++yes:)
++{ $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
++  fi
++else
++  STRIP="$ac_cv_prog_STRIP"
++fi
++
++fi
++INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
++
++{ $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 ${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
++  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 (GNU coreutils) '* | \
++	     'mkdir (coreutils) '* | \
++	     '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+set}" = set; 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
++{ $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
++{ $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
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  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_AWK="$ac_prog"
++    $as_echo "$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
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5
++$as_echo "$AWK" >&6; }
++else
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
++fi
++
++
++  test -n "$AWK" && break
++done
++
++{ $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=`$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:
++	@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
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
++$as_echo "yes" >&6; }
++  SET_MAKE=
++else
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "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+set}" = set; 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}
++{ $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
++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
++{ $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)'
++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'
++
++
++cat >>confdefs.h <<_ACEOF
++#define PACKAGE "$PACKAGE"
++_ACEOF
++
++
++cat >>confdefs.h <<_ACEOF
++#define VERSION "$VERSION"
++_ACEOF
++
++# 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 -'
++
++
++
++
++
++
++# 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
++
++
++{ $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+set}" = set; then :
++  enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval
++else
++  USE_MAINTAINER_MODE=no
++fi
++
++  { $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='#'
++else
++  MAINTAINER_MODE_TRUE='#'
++  MAINTAINER_MODE_FALSE=
++fi
++
++  MAINT=$MAINTAINER_MODE_TRUE
++
++
++
++# Check whether --with-libiberty was given.
++if test "${with_libiberty+set}" = set; then :
++  withval=$with_libiberty;
++else
++  with_libiberty=../libiberty
++fi
++
++
++DEPDIR="${am__leading_dot}deps"
++
++ac_config_commands="$ac_config_commands depfiles"
++
++{ $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
++.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.*
++{ $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+set}" = set; 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
++{ $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
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  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_CC="${ac_tool_prefix}gcc"
++    $as_echo "$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
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
++$as_echo "$CC" >&6; }
++else
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "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
++{ $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
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  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="gcc"
++    $as_echo "$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
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
++$as_echo "$ac_ct_CC" >&6; }
++else
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
++fi
++
++  if test "x$ac_ct_CC" = x; then
++    CC=""
++  else
++    case $cross_compiling:$ac_tool_warned in
++yes:)
++{ $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
++
++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
++{ $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
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  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_CC="${ac_tool_prefix}cc"
++    $as_echo "$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
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
++$as_echo "$CC" >&6; }
++else
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "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
++{ $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
++  ac_prog_rejected=no
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  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
++       ac_prog_rejected=yes
++       continue
++     fi
++    ac_cv_prog_CC="cc"
++    $as_echo "$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
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
++$as_echo "$CC" >&6; }
++else
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "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
++{ $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
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  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_CC="$ac_tool_prefix$ac_prog"
++    $as_echo "$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
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
++$as_echo "$CC" >&6; }
++else
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "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
++{ $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
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  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="$ac_prog"
++    $as_echo "$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
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
++$as_echo "$ac_ct_CC" >&6; }
++else
++  { $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:)
++{ $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
++fi
++
++fi
++
++
++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.
++$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
++  { { 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\""
++$as_echo "$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
++  $as_echo "$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 ()
++{
++
++  ;
++  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.
++{ $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.*"
++
++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\""
++$as_echo "$ac_try_echo"; } >&5
++  (eval "$ac_link_default") 2>&5
++  ac_status=$?
++  $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,
++# 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+set}" = set && 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
++  ac_file=''
++fi
++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
++
++{ { $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_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
++{ $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\""
++$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; }; 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_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
++{ $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
++ac_exeext=$EXEEXT
++cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++#include 
++int
++main ()
++{
++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.
++{ $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
++  *\"* | *\`* | *\\*) 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; }
++  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\""
++$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
++    cross_compiling=no
++  else
++    if test "$cross_compiling" = maybe; then
++	cross_compiling=yes
++    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 run C compiled programs.
++If you meant to cross compile, use \`--host'.
++See \`config.log' for more details" "$LINENO" 5; }
++    fi
++  fi
++fi
++{ $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
++{ $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 ()
++{
++
++  ;
++  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\""
++$as_echo "$ac_try_echo"; } >&5
++  (eval "$ac_compile") 2>&5
++  ac_status=$?
++  $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
++    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
++    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
++       break;;
++  esac
++done
++else
++  $as_echo "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
++{ { $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
++{ $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
++{ $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 ()
++{
++#ifndef __GNUC__
++       choke me
++#endif
++
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_c_try_compile "$LINENO"; then :
++  ac_compiler_gnu=yes
++else
++  ac_compiler_gnu=no
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
++ac_cv_c_compiler_gnu=$ac_compiler_gnu
++
++fi
++{ $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+set}
++ac_save_CFLAGS=$CFLAGS
++{ $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
++   CFLAGS="-g"
++   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++
++int
++main ()
++{
++
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_c_try_compile "$LINENO"; then :
++  ac_cv_prog_cc_g=yes
++else
++  CFLAGS=""
++      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++
++int
++main ()
++{
++
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_c_try_compile "$LINENO"; then :
++
++else
++  ac_c_werror_flag=$ac_save_c_werror_flag
++	 CFLAGS="-g"
++	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++
++int
++main ()
++{
++
++  ;
++  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.$ac_ext
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
++   ac_c_werror_flag=$ac_save_c_werror_flag
++fi
++{ $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
++    CFLAGS="-g -O2"
++  else
++    CFLAGS="-g"
++  fi
++else
++  if test "$GCC" = yes; then
++    CFLAGS="-O2"
++  else
++    CFLAGS=
++  fi
++fi
++{ $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.  */
++#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__"
++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
++  test "x$ac_cv_prog_cc_c89" != "xno" && break
++done
++rm -f conftest.$ac_ext
++CC=$ac_save_CC
++
++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
++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
++{ $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 ()
++{
++
++  ;
++  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
++{ $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.
++   # 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=
++
++{ $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
++  # 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
++{ $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
++
++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"
++
++
++{ $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
++  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
++    # 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"
++
++
++{ $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 
++
++int
++main ()
++{
++
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_c_try_compile "$LINENO"; then :
++  ac_cv_header_stdc=yes
++else
++  ac_cv_header_stdc=no
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
++
++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 
++
++_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 
++
++_ACEOF
++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*
++
++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 XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
++int
++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_run "$LINENO"; then :
++
++else
++  ac_cv_header_stdc=no
++fi
++rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
++  conftest.$ac_objext conftest.beam conftest.$ac_ext
++fi
++
++fi
++fi
++{ $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
++
++$as_echo "#define STDC_HEADERS 1" >>confdefs.h
++
++fi
++
++# 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
++
++fi
++
++done
++
++
++
++  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
++
++
++  if test "$MINIX" = yes; then
++
++$as_echo "#define _POSIX_SOURCE 1" >>confdefs.h
++
++
++$as_echo "#define _POSIX_1_SOURCE 2" >>confdefs.h
++
++
++$as_echo "#define _MINIX 1" >>confdefs.h
++
++  fi
++
++
++  { $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.  */
++
++#         define __EXTENSIONS__ 1
++          $ac_includes_default
++int
++main ()
++{
++
++  ;
++  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
++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
++fi
++{ $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
++
++
++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
++{ $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
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  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_CC="${ac_tool_prefix}gcc"
++    $as_echo "$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
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
++$as_echo "$CC" >&6; }
++else
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "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
++{ $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
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  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="gcc"
++    $as_echo "$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
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
++$as_echo "$ac_ct_CC" >&6; }
++else
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
++fi
++
++  if test "x$ac_ct_CC" = x; then
++    CC=""
++  else
++    case $cross_compiling:$ac_tool_warned in
++yes:)
++{ $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
++
++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
++{ $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
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  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_CC="${ac_tool_prefix}cc"
++    $as_echo "$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
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
++$as_echo "$CC" >&6; }
++else
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "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
++{ $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
++  ac_prog_rejected=no
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  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
++       ac_prog_rejected=yes
++       continue
++     fi
++    ac_cv_prog_CC="cc"
++    $as_echo "$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
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
++$as_echo "$CC" >&6; }
++else
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "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
++{ $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
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  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_CC="$ac_tool_prefix$ac_prog"
++    $as_echo "$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
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
++$as_echo "$CC" >&6; }
++else
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "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
++{ $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
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  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="$ac_prog"
++    $as_echo "$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
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
++$as_echo "$ac_ct_CC" >&6; }
++else
++  { $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:)
++{ $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
++fi
++
++fi
++
++
++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.
++$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
++  { { 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\""
++$as_echo "$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
++  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  test $ac_status = 0; }
++done
++
++{ $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 ()
++{
++#ifndef __GNUC__
++       choke me
++#endif
++
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_c_try_compile "$LINENO"; then :
++  ac_compiler_gnu=yes
++else
++  ac_compiler_gnu=no
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
++ac_cv_c_compiler_gnu=$ac_compiler_gnu
++
++fi
++{ $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+set}
++ac_save_CFLAGS=$CFLAGS
++{ $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
++   CFLAGS="-g"
++   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++
++int
++main ()
++{
++
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_c_try_compile "$LINENO"; then :
++  ac_cv_prog_cc_g=yes
++else
++  CFLAGS=""
++      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++
++int
++main ()
++{
++
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_c_try_compile "$LINENO"; then :
++
++else
++  ac_c_werror_flag=$ac_save_c_werror_flag
++	 CFLAGS="-g"
++	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++
++int
++main ()
++{
++
++  ;
++  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.$ac_ext
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
++   ac_c_werror_flag=$ac_save_c_werror_flag
++fi
++{ $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
++    CFLAGS="-g -O2"
++  else
++    CFLAGS="-g"
++  fi
++else
++  if test "$GCC" = yes; then
++    CFLAGS="-O2"
++  else
++    CFLAGS=
++  fi
++fi
++{ $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.  */
++#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__"
++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
++  test "x$ac_cv_prog_cc_c89" != "xno" && break
++done
++rm -f conftest.$ac_ext
++CC=$ac_save_CC
++
++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
++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
++{ $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 ()
++{
++
++  ;
++  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
++{ $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.
++   # 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=
++
++{ $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
++  # 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
++{ $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=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
++  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
++{ $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
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  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_CXX="$ac_tool_prefix$ac_prog"
++    $as_echo "$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
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5
++$as_echo "$CXX" >&6; }
++else
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "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
++do
++  # Extract the first word of "$ac_prog", so it can be a program name with args.
++set dummy $ac_prog; 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_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
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  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_CXX="$ac_prog"
++    $as_echo "$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
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5
++$as_echo "$ac_ct_CXX" >&6; }
++else
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "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:)
++{ $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
++  fi
++fi
++
++  fi
++fi
++# Provide some information about the compiler.
++$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
++  { { 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\""
++$as_echo "$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
++  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  test $ac_status = 0; }
++done
++
++{ $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 ()
++{
++#ifndef __GNUC__
++       choke me
++#endif
++
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_cxx_try_compile "$LINENO"; then :
++  ac_compiler_gnu=yes
++else
++  ac_compiler_gnu=no
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
++ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
++
++fi
++{ $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+set}
++ac_save_CXXFLAGS=$CXXFLAGS
++{ $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
++   CXXFLAGS="-g"
++   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++
++int
++main ()
++{
++
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_cxx_try_compile "$LINENO"; then :
++  ac_cv_prog_cxx_g=yes
++else
++  CXXFLAGS=""
++      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++
++int
++main ()
++{
++
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_cxx_try_compile "$LINENO"; then :
++
++else
++  ac_cxx_werror_flag=$ac_save_cxx_werror_flag
++	 CXXFLAGS="-g"
++	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++
++int
++main ()
++{
++
++  ;
++  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.$ac_ext
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
++   ac_cxx_werror_flag=$ac_save_cxx_werror_flag
++fi
++{ $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
++    CXXFLAGS="-g -O2"
++  else
++    CXXFLAGS="-g"
++  fi
++else
++  if test "$GXX" = yes; then
++    CXXFLAGS="-O2"
++  else
++    CXXFLAGS=
++  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=
++
++{ $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
++  # 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
++{ $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
++  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+set}" = set; then :
++  enableval=$enable_largefile;
++fi
++
++if test "$enable_largefile" != no; then
++
++  { $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
++       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 << 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 ()
++{
++
++  ;
++  return 0;
++}
++_ACEOF
++	 if ac_fn_c_try_compile "$LINENO"; then :
++  break
++fi
++rm -f core conftest.err conftest.$ac_objext
++	 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
++	 break
++       done
++       CC=$ac_save_CC
++       rm -f conftest.$ac_ext
++    fi
++fi
++{ $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
++
++  { $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.  */
++#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 << 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 ()
++{
++
++  ;
++  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.$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 << 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 ()
++{
++
++  ;
++  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.$ac_ext
++  ac_cv_sys_file_offset_bits=unknown
++  break
++done
++fi
++{ $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) ;;
++  *)
++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
++    { $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.  */
++#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 << 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 ()
++{
++
++  ;
++  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.$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 << 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 ()
++{
++
++  ;
++  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.$ac_ext
++  ac_cv_sys_large_files=unknown
++  break
++done
++fi
++{ $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) ;;
++  *)
++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"
++{ $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 :
++  have_static_libgcc=yes
++else
++  have_static_libgcc=no
++fi
++rm -f core conftest.err conftest.$ac_objext \
++    conftest$ac_exeext conftest.$ac_ext
++{ $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
++   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.
++
++  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
++  *\ * | *\	*)
++    { $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.2.7a'
++macro_revision='1.3134'
++
++
++
++
++
++
++
++
++
++
++
++
++
++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
++
++{ $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 && \
++   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*) { $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
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++{ $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"
++     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
++  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"
++      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
++  $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 '' >> "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
++{ $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//"
++
++
++
++
++
++
++
++
++
++
++
++{ $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
++     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
++  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"
++      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
++  $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 '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
++{ $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"
++
++
++test -z "$GREP" && GREP=grep
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++# Check whether --with-gnu-ld was given.
++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 "$GCC" = yes; then
++  # Check if gcc -print-prog-name=ld gives a path.
++  { $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
++    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 "$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
++  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5
++$as_echo_n "checking for non-GNU ld... " >&6; }
++fi
++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
++  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
++$as_echo "$LD" >&6; }
++else
++  { $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
++{ $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 &5
++$as_echo "$lt_cv_prog_gnu_ld" >&6; }
++with_gnu_ld=$lt_cv_prog_gnu_ld
++
++
++
++
++
++
++
++
++
++{ $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"
++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
++	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
++	  ;;
++	*)
++	  case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
++	  */dev/null*)
++	    lt_cv_path_NM="$tmp_nm -p"
++	    break
++	    ;;
++	  *)
++	    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
++{ $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 :
++    # 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
++{ $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
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  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_DUMPBIN="$ac_tool_prefix$ac_prog"
++    $as_echo "$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
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5
++$as_echo "$DUMPBIN" >&6; }
++else
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "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
++{ $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
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  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_DUMPBIN="$ac_prog"
++    $as_echo "$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
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5
++$as_echo "$ac_ct_DUMPBIN" >&6; }
++else
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "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:)
++{ $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 /dev/null 2>&1 | sed '1q'` in
++    *COFF*)
++      DUMPBIN="$DUMPBIN -symbols"
++      ;;
++    *)
++      DUMPBIN=:
++      ;;
++    esac
++  fi
++
++  if test "$DUMPBIN" != ":"; then
++    NM="$DUMPBIN"
++  fi
++fi
++test -z "$NM" && NM=nm
++
++
++
++
++
++
++{ $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)
++  (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
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5
++$as_echo "$lt_cv_nm_interface" >&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
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
++$as_echo "yes" >&6; }
++else
++  { $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
++{ $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"
++
++  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;
++    ;;
++
++  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`
++    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
++    ;;
++
++  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"; 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"`func_fallback_echo "$teststring$teststring" 2>/dev/null` \
++	         = "X$teststring$teststring"; } >/dev/null 2>&1 &&
++	      test $i != 17 # 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
++  { $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
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5
++$as_echo "none" >&6; }
++fi
++max_cmd_len=$lt_cv_sys_max_cmd_len
++
++
++
++
++
++
++: ${CP="cp -f"}
++: ${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
++  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
++
++
++
++
++
++
++
++
++
++{ $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
++{ $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
++"" | " "*) ;;
++*) reload_flag=" $reload_flag" ;;
++esac
++reload_cmds='$LD$reload_flag -o $output$reload_objs'
++case $host_os in
++  darwin*)
++    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
++    ;;
++esac
++
++
++
++
++
++
++
++
++
++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
++{ $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
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  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_OBJDUMP="${ac_tool_prefix}objdump"
++    $as_echo "$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
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5
++$as_echo "$OBJDUMP" >&6; }
++else
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "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
++{ $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
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  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_OBJDUMP="objdump"
++    $as_echo "$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
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5
++$as_echo "$ac_ct_OBJDUMP" >&6; }
++else
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
++fi
++
++  if test "x$ac_ct_OBJDUMP" = x; then
++    OBJDUMP="false"
++  else
++    case $cross_compiling:$ac_tool_warned in
++yes:)
++{ $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
++  fi
++else
++  OBJDUMP="$ac_cv_prog_OBJDUMP"
++fi
++
++test -z "$OBJDUMP" && OBJDUMP=objdump
++
++
++
++
++
++
++
++
++
++{ $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.
++# '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
++# 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]*)
++  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='/usr/bin/file -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.
++  # 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
++    lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
++    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*)
++  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=/usr/bin/file
++      lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
++      ;;
++    esac
++  else
++    lt_cv_deplibs_check_method=pass_all
++  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=/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'
++    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 Linux ELF.
++linux* | k*bsd*-gnu | kopensolaris*-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=/usr/bin/file
++  lt_cv_file_magic_test_file=/usr/lib/libnls.so
++  ;;
++
++*nto* | *qnx*)
++  lt_cv_deplibs_check_method=pass_all
++  ;;
++
++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)$'
++  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
++  ;;
++esac
++
++fi
++{ $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
++
++
++
++
++
++
++
++
++
++
++
++
++if test -n "$ac_tool_prefix"; then
++  # 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
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  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}ar"
++    $as_echo "$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
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
++$as_echo "$AR" >&6; }
++else
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
++fi
++
++
++fi
++if test -z "$ac_cv_prog_AR"; then
++  ac_ct_AR=$AR
++  # 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
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  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="ar"
++    $as_echo "$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
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
++$as_echo "$ac_ct_AR" >&6; }
++else
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
++fi
++
++  if test "x$ac_ct_AR" = x; then
++    AR="false"
++  else
++    case $cross_compiling:$ac_tool_warned in
++yes:)
++{ $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
++
++test -z "$AR" && AR=ar
++test -z "$AR_FLAGS" && AR_FLAGS=cru
++
++
++
++
++
++
++
++
++
++
++
++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
++{ $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
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  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_STRIP="${ac_tool_prefix}strip"
++    $as_echo "$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
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5
++$as_echo "$STRIP" >&6; }
++else
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "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
++{ $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
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  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_STRIP="strip"
++    $as_echo "$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
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5
++$as_echo "$ac_ct_STRIP" >&6; }
++else
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
++fi
++
++  if test "x$ac_ct_STRIP" = x; then
++    STRIP=":"
++  else
++    case $cross_compiling:$ac_tool_warned in
++yes:)
++{ $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
++  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
++{ $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
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  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_RANLIB="${ac_tool_prefix}ranlib"
++    $as_echo "$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
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
++$as_echo "$RANLIB" >&6; }
++else
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "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
++{ $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
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  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_RANLIB="ranlib"
++    $as_echo "$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
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
++$as_echo "$ac_ct_RANLIB" >&6; }
++else
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
++fi
++
++  if test "x$ac_ct_RANLIB" = x; then
++    RANLIB=":"
++  else
++    case $cross_compiling:$ac_tool_warned in
++yes:)
++{ $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
++  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
++  openbsd*)
++    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib"
++    ;;
++  *)
++    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib"
++    ;;
++  esac
++  old_archive_cmds="$old_archive_cmds~\$RANLIB \$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.
++{ $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?!! ;)]
++
++# 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 "$host_cpu" = ia64; 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
++
++# 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 -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 -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=
++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
++    # 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};"\
++"     /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\
++"     \$ 0!~/External *\|/{next};"\
++"     / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\
++"     {if(hide[section]) next};"\
++"     {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'"
++  fi
++
++  # 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=$?
++  $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=$?
++  $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
++	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
++#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.  */
++const struct {
++  const char *name;
++  void       *address;
++}
++lt__PROGRAM__LTX_preloaded_symbols[] =
++{
++  { "@PROGRAM@", (void *) 0 },
++_LT_EOF
++	  $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/  {\"\2\", (void *) \&\2},/" < "$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_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=$?
++  $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_save_LIBS"
++	  CFLAGS="$lt_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 "$pipe_works" = yes; 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
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5
++$as_echo "failed" >&6; }
++else
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5
++$as_echo "ok" >&6; }
++fi
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++# Check whether --enable-libtool-lock was given.
++if test "${enable_libtool_lock+set}" = set; then :
++  enableval=$enable_libtool_lock;
++fi
++
++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 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=$?
++  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  test $ac_status = 0; }; then
++    case `/usr/bin/file conftest.$ac_objext` in
++      *ELF-32*)
++	HPUX_IA64_MODE="32"
++	;;
++      *ELF-64*)
++	HPUX_IA64_MODE="64"
++	;;
++    esac
++  fi
++  rm -rf conftest*
++  ;;
++*-*-irix6*)
++  # 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=$?
++  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  test $ac_status = 0; }; then
++    if test "$lt_cv_prog_gnu_ld" = yes; then
++      case `/usr/bin/file conftest.$ac_objext` in
++	*32-bit*)
++	  LD="${LD-ld} -melf32bsmip"
++	  ;;
++	*N32*)
++	  LD="${LD-ld} -melf32bmipn32"
++	  ;;
++	*64-bit*)
++	  LD="${LD-ld} -melf64bmip"
++	;;
++      esac
++    else
++      case `/usr/bin/file 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*
++  ;;
++
++x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \
++s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
++  # 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=$?
++  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  test $ac_status = 0; }; then
++    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 `/usr/bin/file 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"
++  { $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'
++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 ()
++{
++
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_c_try_link "$LINENO"; then :
++  lt_cv_cc_needs_belf=yes
++else
++  lt_cv_cc_needs_belf=no
++fi
++rm -f core conftest.err conftest.$ac_objext \
++    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
++{ $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"
++  fi
++  ;;
++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=$?
++  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  test $ac_status = 0; }; then
++    case `/usr/bin/file conftest.o` in
++    *64-bit*)
++      case $lt_cv_prog_gnu_ld in
++      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"
++	fi
++	;;
++      esac
++      ;;
++    esac
++  fi
++  rm -rf conftest*
++  ;;
++esac
++
++need_locks="$enable_libtool_lock"
++
++
++  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
++{ $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
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  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_DSYMUTIL="${ac_tool_prefix}dsymutil"
++    $as_echo "$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
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5
++$as_echo "$DSYMUTIL" >&6; }
++else
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "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
++{ $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
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  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_DSYMUTIL="dsymutil"
++    $as_echo "$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
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5
++$as_echo "$ac_ct_DSYMUTIL" >&6; }
++else
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
++fi
++
++  if test "x$ac_ct_DSYMUTIL" = x; then
++    DSYMUTIL=":"
++  else
++    case $cross_compiling:$ac_tool_warned in
++yes:)
++{ $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
++  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
++{ $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
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  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_NMEDIT="${ac_tool_prefix}nmedit"
++    $as_echo "$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
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5
++$as_echo "$NMEDIT" >&6; }
++else
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "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
++{ $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
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  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_NMEDIT="nmedit"
++    $as_echo "$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
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5
++$as_echo "$ac_ct_NMEDIT" >&6; }
++else
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
++fi
++
++  if test "x$ac_ct_NMEDIT" = x; then
++    NMEDIT=":"
++  else
++    case $cross_compiling:$ac_tool_warned in
++yes:)
++{ $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
++  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
++{ $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
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  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_LIPO="${ac_tool_prefix}lipo"
++    $as_echo "$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
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5
++$as_echo "$LIPO" >&6; }
++else
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "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
++{ $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
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  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_LIPO="lipo"
++    $as_echo "$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
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5
++$as_echo "$ac_ct_LIPO" >&6; }
++else
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
++fi
++
++  if test "x$ac_ct_LIPO" = x; then
++    LIPO=":"
++  else
++    case $cross_compiling:$ac_tool_warned in
++yes:)
++{ $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
++  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
++{ $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
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  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_OTOOL="${ac_tool_prefix}otool"
++    $as_echo "$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
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5
++$as_echo "$OTOOL" >&6; }
++else
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "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
++{ $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
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  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_OTOOL="otool"
++    $as_echo "$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
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5
++$as_echo "$ac_ct_OTOOL" >&6; }
++else
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
++fi
++
++  if test "x$ac_ct_OTOOL" = x; then
++    OTOOL=":"
++  else
++    case $cross_compiling:$ac_tool_warned in
++yes:)
++{ $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
++  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
++{ $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
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  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_OTOOL64="${ac_tool_prefix}otool64"
++    $as_echo "$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
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5
++$as_echo "$OTOOL64" >&6; }
++else
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "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
++{ $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
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  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_OTOOL64="otool64"
++    $as_echo "$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
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5
++$as_echo "$ac_ct_OTOOL64" >&6; }
++else
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
++fi
++
++  if test "x$ac_ct_OTOOL64" = x; then
++    OTOOL64=":"
++  else
++    case $cross_compiling:$ac_tool_warned in
++yes:)
++{ $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
++  fi
++else
++  OTOOL64="$ac_cv_prog_OTOOL64"
++fi
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++    { $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
++	# 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 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
++	fi
++	rm -rf libconftest.dylib*
++	rm -f conftest.*
++      fi
++fi
++{ $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
++      LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym"
++      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++
++int
++main ()
++{
++
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_c_try_link "$LINENO"; then :
++  lt_cv_ld_exported_symbols_list=yes
++else
++  lt_cv_ld_exported_symbols_list=no
++fi
++rm -f core conftest.err conftest.$ac_objext \
++    conftest$ac_exeext conftest.$ac_ext
++	LDFLAGS="$save_LDFLAGS"
++
++fi
++{ $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 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 -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
++      fi
++        rm -f conftest.err libconftest.a conftest conftest.c
++        rm -rf conftest.dSYM
++
++fi
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5
++$as_echo "$lt_cv_ld_force_load" >&6; }
++    case $host_os in
++    rhapsody* | darwin1.[012])
++      _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;;
++    darwin1.*)
++      _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
++    darwin*) # darwin 5.x on
++      # if running on 10.5 or later, the deployment target defaults
++      # to the OS version, if on x86, and 10.4, the deployment
++      # target defaults to 10.4. Don't you love it?
++      case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in
++	10.0,*86*-darwin8*|10.0,*-darwin[91]*)
++	  _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
++	10.[012][,.]*)
++	  _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
++	10.*)
++	  _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
++      esac
++    ;;
++  esac
++    if test "$lt_cv_apple_cc_single_mod" = "yes"; then
++      _lt_dar_single_mod='$single_module'
++    fi
++    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}'
++    fi
++    if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then
++      _lt_dsymutil='~$DSYMUTIL $lib || :'
++    else
++      _lt_dsymutil=
++    fi
++    ;;
++  esac
++
++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 :
++  cat >>confdefs.h <<_ACEOF
++#define HAVE_DLFCN_H 1
++_ACEOF
++
++fi
++
++done
++
++
++
++
++
++
++# Set options
++
++
++
++        enable_dlopen=no
++
++
++  enable_win32_dll=no
++
++
++            # Check whether --enable-shared was given.
++if test "${enable_shared+set}" = set; 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
++  enable_shared=yes
++fi
++
++
++
++
++
++
++
++
++
++  # Check whether --enable-static was given.
++if test "${enable_static+set}" = set; 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
++  enable_static=yes
++fi
++
++
++
++
++
++
++
++
++
++
++# Check whether --with-pic was given.
++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
++
++
++
++
++
++
++
++  # Check whether --enable-fast-install was given.
++if test "${enable_fast_install+set}" = set; 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
++  enable_fast_install=yes
++fi
++
++
++
++
++
++
++
++
++
++
++
++# 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
++
++{ $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
++  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
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5
++$as_echo "$lt_cv_objdir" >&6; }
++objdir=$lt_cv_objdir
++
++
++
++
++
++cat >>confdefs.h <<_ACEOF
++#define LT_OBJDIR "$lt_cv_objdir/"
++_ACEOF
++
++
++
++
++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 "X${COLLECT_NAMES+set}" != Xset; 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,
++# which needs '.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
++
++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
++test -z "$MAGIC_CMD" && MAGIC_CMD=file
++case $deplibs_check_method in
++file_magic*)
++  if test "$file_magic_cmd" = '$MAGIC_CMD'; then
++    { $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_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
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5
++$as_echo "$MAGIC_CMD" >&6; }
++else
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
++fi
++
++
++
++
++
++if test -z "$lt_cv_path_MAGIC_CMD"; then
++  if test -n "$ac_tool_prefix"; then
++    { $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_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
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5
++$as_echo "$MAGIC_CMD" >&6; }
++else
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "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*
++
++
++## 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 "$GCC" = yes; then
++  case $cc_basename in
++  nvcc*)
++    lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;;
++  *)
++    lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;;
++  esac
++
++  { $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"
++   # 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
++{ $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 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
++    :
++fi
++
++fi
++
++
++
++
++
++
++  lt_prog_compiler_wl=
++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 "$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 "$host_cpu" = ia64; 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'
++      ;;
++
++    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 '
++      lt_prog_compiler_pic='-Xcompiler -fPIC'
++      ;;
++    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 "$host_cpu" = ia64; then
++	# AIX 5 now supports IA64 processor
++	lt_prog_compiler_static='-Bstatic'
++      else
++	lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp'
++      fi
++      ;;
++
++    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'
++      ;;
++
++    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)
++      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'
++	;;
++      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\ 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\ C*)
++	  # Sun C 5.9
++	  lt_prog_compiler_pic='-KPIC'
++	  lt_prog_compiler_static='-Bstatic'
++	  lt_prog_compiler_wl='-Wl,'
++	  ;;
++	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*)
++	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 which do not support PIC, -DPIC is meaningless:
++  *djgpp*)
++    lt_prog_compiler_pic=
++    ;;
++  *)
++    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; }
++
++
++
++
++
++
++#
++# Check to make sure the PIC flag actually works.
++#
++if test -n "$lt_prog_compiler_pic"; then
++  { $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"
++   # 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
++{ $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 x"$lt_cv_prog_compiler_pic_works" = xyes; 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\"
++{ $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"
++   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
++{ $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 x"$lt_cv_prog_compiler_static_works" = xyes; then
++    :
++else
++    lt_prog_compiler_static=
++fi
++
++
++
++
++
++
++
++  { $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
++   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
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5
++$as_echo "$lt_cv_prog_compiler_c_o" >&6; }
++
++
++
++
++
++
++  { $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
++   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
++{ $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 "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then
++  # do not overwrite the value of need_locks provided by the user
++  { $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
++  { $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
++  need_locks=no
++fi
++
++
++
++
++
++
++  { $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=
++  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_flag_spec_ld=
++  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++ port hasn't been tested in a loooong time
++    # When not using gcc, we currently assume that we are using
++    # 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++)
++    with_gnu_ld=yes
++    ;;
++  openbsd*)
++    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 "$with_gnu_ld" = yes; 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 "$lt_use_gnu_ld_interface" = yes; 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 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 "$host_cpu" != ia64; 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/'\'' | $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 (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'
++      link_all_deplibs=yes
++      ;;
++
++    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 "$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 "$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'
++	  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' ;;
++	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 "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'
++        fi
++
++	case $cc_basename in
++	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=
++	  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 $compiler_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 $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
++      ;;
++
++    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 $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
++      ;;
++
++    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 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
++*** 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 $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 "$ld_shlibs" = no; 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 "$GCC" = yes && 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 "$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=""
++      else
++	# If we're using GNU nm, then we don't want the "-C" option.
++	# -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) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
++	else
++	  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
++	# need to do runtime linking.
++	case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*)
++	  for ld_flag in $LDFLAGS; do
++	  if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
++	    aix_use_runtimelinking=yes
++	    break
++	  fi
++	  done
++	  ;;
++	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,'
++
++      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`
++	  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 "$aix_use_runtimelinking" = yes; then
++	  shared_flag="$shared_flag "'${wl}-G'
++	fi
++      else
++	# not using gcc
++	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 "$aix_use_runtimelinking" = yes; then
++	    shared_flag='${wl}-G'
++	  else
++	    shared_flag='${wl}-bM:SRE'
++	  fi
++	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_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.
++        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++
++int
++main ()
++{
++
++  ;
++  return 0;
++}
++_ACEOF
++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
++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 "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 "$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"
++	else
++	 # Determine the default libpath from the value encoded in an
++	 # empty executable.
++	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++
++int
++main ()
++{
++
++  ;
++  return 0;
++}
++_ACEOF
++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
++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"
++	  # 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 "$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'
++	  else
++	    # Exported symbols can be pulled into shared objects from archives
++	    whole_archive_flag_spec='$convenience'
++	  fi
++	  archive_cmds_need_lc=yes
++	  # 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
++      ;;
++
++    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++.
++      # hardcode_libdir_flag_spec is actually meaningless, as there is
++      # no search path for DLLs.
++      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*)
++
++
++  archive_cmds_need_lc=no
++  hardcode_direct=no
++  hardcode_automatic=yes
++  hardcode_shlibpath_var=unsupported
++  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"
++  case $cc_basename in
++     ifort*) _lt_dar_can_shared=yes ;;
++     *) _lt_dar_can_shared=$GCC ;;
++  esac
++  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}"
++
++  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*)
++      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 "$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 $output_objdir/$soname = $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 "$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 "$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'
++	# 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 "$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'
++	  ;;
++	ia64*)
++	  archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -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'
++	  ;;
++	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)
++	  { $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"
++   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
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5
++$as_echo "$lt_cv_prog_compiler__b" >&6; }
++
++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
++
++	  ;;
++	esac
++      fi
++      if test "$with_gnu_ld" = no; 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 "$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.
++        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) {}
++_ACEOF
++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$ac_exeext conftest.$ac_ext
++        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'
++      fi
++      archive_cmds_need_lc='no'
++      hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
++      hardcode_libdir_separator=:
++      inherit_rpath=yes
++      link_all_deplibs=yes
++      ;;
++
++    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*)
++      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__`" || 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'
++	else
++	  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
++      fi
++      ;;
++
++    os2*)
++      hardcode_libdir_flag_spec='-L$libdir'
++      hardcode_minus_L=yes
++      allow_undefined_flag=unsupported
++      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 "$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'
++      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 "$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_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 "$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 ${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 "$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
++	;;
++      esac
++      link_all_deplibs=yes
++      ;;
++
++    sunos4*)
++      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'
++      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 "$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'
++      fi
++      ;;
++
++    sysv5* | sco3.2v5* | sco5v6*)
++      # 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'
++      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 "$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'
++      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 x$host_vendor = xsni; then
++      case $host in
++      sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
++	export_dynamic_flag_spec='${wl}-Blargedynsym'
++	;;
++      esac
++    fi
++  fi
++
++{ $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
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++#
++# 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 "$enable_shared" = yes && test "$GCC" = yes; 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.
++      { $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=$?
++  $as_echo "$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=$?
++  $as_echo "$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
++{ $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
++  fi
++  ;;
++esac
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++  { $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:/" ;;
++  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`
++  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"
++    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;
++  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
++  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
++  need_lib_prefix=no
++  need_version=no
++  hardcode_into_libs=yes
++  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}'
++    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
++    # 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.
++    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}'
++    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'
++    fi
++    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%'\''`; 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}'
++  dynamic_linker="$host_os ld.so"
++  shlibpath_var=LIBRARY_PATH
++  ;;
++
++bsdi[45]*)
++  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'
++  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,$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'\''`~
++      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
++    ;;
++
++  *)
++    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
++  ;;
++
++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
++  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*)
++  # 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} $libname${shared_ext}'
++      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
++  ;;
++
++gnu*)
++  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'
++  shlibpath_var=LD_LIBRARY_PATH
++  hardcode_into_libs=yes
++  ;;
++
++haiku*)
++  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'
++  shlibpath_var=LIBRARY_PATH
++  shlibpath_overrides_runpath=yes
++  sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/beos/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 "X$HPUX_IA64_MODE" = X32; then
++      sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
++    else
++      sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
++    fi
++    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
++    ;;
++  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
++  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 "$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}'
++  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
++  ;;
++
++# This must be Linux ELF.
++linux* | k*bsd*-gnu | kopensolaris*-gnu)
++  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'
++  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 ${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
++    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 ()
++{
++
++  ;
++  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$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
++
++  # 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="/lib /usr/lib $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
++  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*)
++  version_type=sunos
++  sys_lib_dlsearch_path_spec="/usr/lib"
++  need_lib_prefix=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
++    shlibpath_overrides_runpath=yes
++  fi
++  ;;
++
++os2*)
++  libname_spec='$name'
++  shrext_cmds=".dll"
++  need_lib_prefix=no
++  library_names_spec='$libname${shared_ext} $libname.a'
++  dynamic_linker='OS/2 ld.exe'
++  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}'
++  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
++  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 "$with_gnu_ld" = yes; then
++    need_lib_prefix=no
++  fi
++  need_version=yes
++  ;;
++
++sysv4 | sysv4.3*)
++  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)
++      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
++    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=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'
++  shlibpath_var=LD_LIBRARY_PATH
++  shlibpath_overrides_runpath=yes
++  hardcode_into_libs=yes
++  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'
++    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
++  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
++  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
++{ $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 "$GCC" = yes; then
++  variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
++fi
++
++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 "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then
++  sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec"
++fi
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++  { $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 "X$hardcode_automatic" = "Xyes" ; then
++
++  # We can hardcode non-existent directories.
++  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 "$_LT_TAGVAR(hardcode_shlibpath_var, )" != no &&
++     test "$hardcode_minus_L" != no; 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
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5
++$as_echo "$hardcode_action" >&6; }
++
++if test "$hardcode_action" = relink ||
++   test "$inherit_rpath" = yes; then
++  # Fast installation is not supported
++  enable_fast_install=no
++elif test "$shlibpath_overrides_runpath" = yes ||
++     test "$enable_shared" = no; then
++  # Fast installation is not necessary
++  enable_fast_install=needless
++fi
++
++
++
++
++
++
++  if test "x$enable_dlopen" != xyes; 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
++    { $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
++/* 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.  */
++#ifdef __cplusplus
++extern "C"
++#endif
++char dlopen ();
++int
++main ()
++{
++return dlopen ();
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_c_try_link "$LINENO"; then :
++  ac_cv_lib_dl_dlopen=yes
++else
++  ac_cv_lib_dl_dlopen=no
++fi
++rm -f core conftest.err conftest.$ac_objext \
++    conftest$ac_exeext conftest.$ac_ext
++LIBS=$ac_check_lib_save_LIBS
++fi
++{ $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_libs=
++    lt_cv_dlopen_self=yes
++
++fi
++
++    ;;
++
++  *)
++    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_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
++/* 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.  */
++#ifdef __cplusplus
++extern "C"
++#endif
++char shl_load ();
++int
++main ()
++{
++return shl_load ();
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_c_try_link "$LINENO"; then :
++  ac_cv_lib_dld_shl_load=yes
++else
++  ac_cv_lib_dld_shl_load=no
++fi
++rm -f core conftest.err conftest.$ac_objext \
++    conftest$ac_exeext conftest.$ac_ext
++LIBS=$ac_check_lib_save_LIBS
++fi
++{ $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_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
++/* 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.  */
++#ifdef __cplusplus
++extern "C"
++#endif
++char dlopen ();
++int
++main ()
++{
++return dlopen ();
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_c_try_link "$LINENO"; then :
++  ac_cv_lib_dl_dlopen=yes
++else
++  ac_cv_lib_dl_dlopen=no
++fi
++rm -f core conftest.err conftest.$ac_objext \
++    conftest$ac_exeext conftest.$ac_ext
++LIBS=$ac_check_lib_save_LIBS
++fi
++{ $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
++/* 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.  */
++#ifdef __cplusplus
++extern "C"
++#endif
++char dlopen ();
++int
++main ()
++{
++return dlopen ();
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_c_try_link "$LINENO"; then :
++  ac_cv_lib_svld_dlopen=yes
++else
++  ac_cv_lib_svld_dlopen=no
++fi
++rm -f core conftest.err conftest.$ac_objext \
++    conftest$ac_exeext conftest.$ac_ext
++LIBS=$ac_check_lib_save_LIBS
++fi
++{ $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
++/* 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.  */
++#ifdef __cplusplus
++extern "C"
++#endif
++char dld_link ();
++int
++main ()
++{
++return dld_link ();
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_c_try_link "$LINENO"; then :
++  ac_cv_lib_dld_dld_link=yes
++else
++  ac_cv_lib_dld_dld_link=no
++fi
++rm -f core conftest.err conftest.$ac_objext \
++    conftest$ac_exeext conftest.$ac_ext
++LIBS=$ac_check_lib_save_LIBS
++fi
++{ $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
++
++
++fi
++
++
++fi
++
++
++fi
++
++
++fi
++
++
++fi
++
++    ;;
++  esac
++
++  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 "x$ac_cv_header_dlfcn_h" = xyes && 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"
++
++    { $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 12290 "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 -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))
++void fnord () __attribute__((visibility("default")));
++#endif
++
++void fnord () { int i=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=$?
++  $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
++      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
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5
++$as_echo "$lt_cv_dlopen_self" >&6; }
++
++    if test "x$lt_cv_dlopen_self" = xyes; then
++      wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
++      { $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 12396 "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 -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))
++void fnord () __attribute__((visibility("default")));
++#endif
++
++void fnord () { int i=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=$?
++  $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
++      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
++{ $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"
++    ;;
++  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=
++{ $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"
++      { $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
++
++
++
++
++
++
++
++
++
++
++
++
++  # 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; }
++
++  { $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 "$enable_shared" = yes && enable_static=no
++    if test -n "$RANLIB"; then
++      archive_cmds="$archive_cmds~\$RANLIB \$lib"
++      postinstall_cmds='$RANLIB $lib'
++    fi
++    ;;
++
++  aix[4-9]*)
++    if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
++      test "$enable_shared" = yes && enable_static=no
++    fi
++    ;;
++  esac
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5
++$as_echo "$enable_shared" >&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 "$enable_shared" = yes || enable_static=yes
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5
++$as_echo "$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 "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
++{ $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 ${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.  */
++#ifdef __STDC__
++# include 
++#else
++# include 
++#endif
++		     Syntax error
++_ACEOF
++if ac_fn_cxx_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_cxx_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_CXXCPP=$CXXCPP
++
++fi
++  CXXCPP=$ac_cv_prog_CXXCPP
++else
++  ac_cv_prog_CXXCPP=$CXXCPP
++fi
++{ $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.  */
++#ifdef __STDC__
++# include 
++#else
++# include 
++#endif
++		     Syntax error
++_ACEOF
++if ac_fn_cxx_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_cxx_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 \"$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_flag_spec_ld_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 "$_lt_caught_CXX_error" != yes; 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_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++"}
++  compiler=$CC
++  compiler_CXX=$CC
++  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 "$GXX" = yes; then
++      lt_prog_compiler_no_builtin_flag_CXX=' -fno-builtin'
++    else
++      lt_prog_compiler_no_builtin_flag_CXX=
++    fi
++
++    if test "$GXX" = yes; then
++      # Set up default GNU C++ configuration
++
++
++
++# Check whether --with-gnu-ld was given.
++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 "$GCC" = yes; then
++  # Check if gcc -print-prog-name=ld gives a path.
++  { $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
++    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 "$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
++  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5
++$as_echo_n "checking for non-GNU ld... " >&6; }
++fi
++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
++  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
++$as_echo "$LD" >&6; }
++else
++  { $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
++{ $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 &5
++$as_echo "$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 "$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'
++
++        # 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
++    { $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*)
++        # FIXME: insert proper C++ library support
++        ld_shlibs_CXX=no
++        ;;
++      aix[4-9]*)
++        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=""
++        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
++          # 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
++	      *-brtl*)
++	        aix_use_runtimelinking=yes
++	        break
++	        ;;
++	      esac
++	    done
++	    ;;
++          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,'
++
++        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`
++	  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 "$aix_use_runtimelinking" = yes; then
++	    shared_flag="$shared_flag "'${wl}-G'
++	  fi
++        else
++          # not using gcc
++          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 "$aix_use_runtimelinking" = yes; then
++	      shared_flag='${wl}-G'
++	    else
++	      shared_flag='${wl}-bM:SRE'
++	    fi
++          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_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_CXX='-berok'
++          # Determine the default libpath from the value encoded in an empty
++          # executable.
++          cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++
++int
++main ()
++{
++
++  ;
++  return 0;
++}
++_ACEOF
++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
++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"
++
++          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 "$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"
++          else
++	    # Determine the default libpath from the value encoded in an
++	    # empty executable.
++	    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++
++int
++main ()
++{
++
++  ;
++  return 0;
++}
++_ACEOF
++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
++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"
++	    # 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 "$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'
++	    else
++	      # Exported symbols can be pulled into shared objects from archives
++	      whole_archive_flag_spec_CXX='$convenience'
++	    fi
++	    archive_cmds_need_lc_CXX=yes
++	    # 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
++        ;;
++
++      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*)
++        # _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*)
++
++
++  archive_cmds_need_lc_CXX=no
++  hardcode_direct_CXX=no
++  hardcode_automatic_CXX=yes
++  hardcode_shlibpath_var_CXX=unsupported
++  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"
++  case $cc_basename in
++     ifort*) _lt_dar_can_shared=yes ;;
++     *) _lt_dar_can_shared=$GCC ;;
++  esac
++  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 "$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
++  ld_shlibs_CXX=no
++  fi
++
++	;;
++
++      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*)
++        # 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'
++        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 $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.
++            #
++            # 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 "$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
++            fi
++            ;;
++        esac
++        ;;
++
++      hpux10*|hpux11*)
++        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'
++              ;;
++          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 "$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'
++	            ;;
++	          ia64*)
++	            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 -fPIC ${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 "$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 -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)
++        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 "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'
++	    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
++	;;
++
++      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__`" || 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
++	  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 "$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}-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*)
++	    # 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 "$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 -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 -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
++	        # platform.
++	        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 -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 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'
++	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
++
++    { $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"
++
++    ## 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
++
++if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
++  (eval $ac_compile) 2>&5
++  ac_status=$?
++  $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.
++
++  # 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 $p in
++
++    -L* | -R* | -l*)
++       # Some compilers place space between "-{L,R}" and the path.
++       # Remove the space.
++       if test $p = "-L" ||
++          test $p = "-R"; then
++	 prev=$p
++	 continue
++       else
++	 prev=
++       fi
++
++       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}"
++	   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
++       ;;
++
++    *.$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 "$pre_test_object_deps_done" = no; 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
++
++# 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=
++  ;;
++
++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
++
++
++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=
++
++{ $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 "$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 "$host_cpu" = ia64; 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'
++      ;;
++    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 "$host_cpu" = ia64; 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
++	;;
++      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*)
++	# 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 "$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'
++	    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)
++	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*)
++	    # 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 which 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
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_prog_compiler_pic_CXX" >&5
++$as_echo "$lt_prog_compiler_pic_CXX" >&6; }
++
++
++
++#
++# Check to make sure the PIC flag actually works.
++#
++if test -n "$lt_prog_compiler_pic_CXX"; then
++  { $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"
++   # 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
++{ $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 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" ;;
++     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\"
++{ $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"
++   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
++{ $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 x"$lt_cv_prog_compiler_static_works_CXX" = xyes; then
++    :
++else
++    lt_prog_compiler_static_CXX=
++fi
++
++
++
++
++    { $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
++   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
++{ $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; }
++
++
++
++    { $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
++   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
++{ $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 "$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
++  { $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
++  { $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
++  need_locks=no
++fi
++
++
++
++    { $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'
++  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 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) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
++    else
++      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"
++  ;;
++  cygwin* | mingw* | cegcc*)
++    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]_.*'
++
++{ $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
++
++
++
++
++
++
++#
++# 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 "$enable_shared" = yes && test "$GCC" = yes; 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.
++      { $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=$?
++  $as_echo "$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=$?
++  $as_echo "$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
++{ $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
++  fi
++  ;;
++esac
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++    { $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"
++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
++  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
++  need_lib_prefix=no
++  need_version=no
++  hardcode_into_libs=yes
++  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}'
++    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
++    # 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.
++    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}'
++    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'
++    fi
++    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%'\''`; 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}'
++  dynamic_linker="$host_os ld.so"
++  shlibpath_var=LIBRARY_PATH
++  ;;
++
++bsdi[45]*)
++  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'
++  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,$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'\''`~
++      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
++    ;;
++
++  *)
++    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
++  ;;
++
++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
++  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*)
++  # 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} $libname${shared_ext}'
++      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
++  ;;
++
++gnu*)
++  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'
++  shlibpath_var=LD_LIBRARY_PATH
++  hardcode_into_libs=yes
++  ;;
++
++haiku*)
++  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'
++  shlibpath_var=LIBRARY_PATH
++  shlibpath_overrides_runpath=yes
++  sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/beos/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 "X$HPUX_IA64_MODE" = X32; then
++      sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
++    else
++      sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
++    fi
++    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
++    ;;
++  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
++  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 "$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}'
++  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
++  ;;
++
++# This must be Linux ELF.
++linux* | k*bsd*-gnu | kopensolaris*-gnu)
++  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'
++  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 ${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
++    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 ()
++{
++
++  ;
++  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$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
++
++  # 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="/lib /usr/lib $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
++  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*)
++  version_type=sunos
++  sys_lib_dlsearch_path_spec="/usr/lib"
++  need_lib_prefix=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
++    shlibpath_overrides_runpath=yes
++  fi
++  ;;
++
++os2*)
++  libname_spec='$name'
++  shrext_cmds=".dll"
++  need_lib_prefix=no
++  library_names_spec='$libname${shared_ext} $libname.a'
++  dynamic_linker='OS/2 ld.exe'
++  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}'
++  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
++  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 "$with_gnu_ld" = yes; then
++    need_lib_prefix=no
++  fi
++  need_version=yes
++  ;;
++
++sysv4 | sysv4.3*)
++  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)
++      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
++    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=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'
++  shlibpath_var=LD_LIBRARY_PATH
++  shlibpath_overrides_runpath=yes
++  hardcode_into_libs=yes
++  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'
++    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
++  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
++  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
++{ $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 "$GCC" = yes; then
++  variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
++fi
++
++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 "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then
++  sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec"
++fi
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++    { $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 "X$hardcode_automatic_CXX" = "Xyes" ; then
++
++  # We can hardcode non-existent directories.
++  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 "$_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
++    # 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
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action_CXX" >&5
++$as_echo "$hardcode_action_CXX" >&6; }
++
++if test "$hardcode_action_CXX" = relink ||
++   test "$inherit_rpath_CXX" = yes; then
++  # Fast installation is not supported
++  enable_fast_install=no
++elif test "$shlibpath_overrides_runpath" = yes ||
++     test "$enable_shared" = no; then
++  # Fast installation is not necessary
++  enable_fast_install=needless
++fi
++
++
++
++
++
++
++
++  fi # test -n "$compiler"
++
++  CC=$lt_save_CC
++  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 "$_lt_caught_CXX_error" != yes
++
++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:
++
++
++
++
++
++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) ;; #(
++  *)
++
++cat >>confdefs.h <<_ACEOF
++#define int64_t $ac_cv_c_int64_t
++_ACEOF
++;;
++esac
++
++ac_fn_c_find_uintX_t "$LINENO" "64" "ac_cv_c_uint64_t"
++case $ac_cv_c_uint64_t in #(
++  no|yes) ;; #(
++  *)
++
++$as_echo "#define _UINT64_T 1" >>confdefs.h
++
++
++cat >>confdefs.h <<_ACEOF
++#define uint64_t $ac_cv_c_uint64_t
++_ACEOF
++;;
++  esac
++
++{ $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 
++#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 ()
++{
++  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
++  ac_cv_header_sys_wait_h=no
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
++fi
++{ $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
++
++$as_echo "#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_*) { $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) ;; #(
++      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+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
++      { $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
++        case $cache_file in #(
++        */* | ?:*)
++	  mv -f confcache "$cache_file"$$ &&
++	  mv -f "$cache_file"$$ "$cache_file" ;; #(
++        *)
++	  mv -f confcache "$cache_file" ;;
++	esac
++      fi
++    fi
++  else
++    { $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
++
++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=`$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"
++  as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
++done
++LIBOBJS=$ac_libobjs
++
++LTLIBOBJS=$ac_ltlibobjs
++
++
++{ $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
++   { $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='#'
++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"
++{ $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
++# 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
++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
++  case `(set -o) 2>/dev/null` in #(
++  *posix*) :
++    set -o posix ;; #(
++  *) :
++     ;;
++esac
++fi
++
++
++as_nl='
++'
++export as_nl
++# 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 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 ||
++      PATH_SEPARATOR=';'
++  }
++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 #((
++  *[\\/]* ) as_myself=$0 ;;
++  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  test -z "$as_dir" && as_dir=.
++    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
++  $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]
++# ----------------------------------------
++# 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
++    $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
++  fi
++  $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.
++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_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_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 ||
++$as_echo 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
++
++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
++
++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=`$as_echo "$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 ||
++$as_echo 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.69.  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
++cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
++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.69,
++  with options \\"\$ac_cs_config\\"
++
++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."
++
++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 )
++    $as_echo "$ac_cs_version"; exit ;;
++  --config | --confi | --conf | --con | --co | --c )
++    $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=`$as_echo "$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=`$as_echo "$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 )
++    $as_echo "$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
++  \$as_echo "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
++  $as_echo "$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"`'
++SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`'
++ECHO='`$ECHO "$ECHO" | $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"`'
++reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`'
++reload_cmds='`$ECHO "$reload_cmds" | $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"`'
++AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`'
++AR_FLAGS='`$ECHO "$AR_FLAGS" | $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_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"`'
++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_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"`'
++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_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"`'
++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"`'
++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"`'
++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"`'
++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"`'
++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_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"`'
++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_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"`'
++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"`'
++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"`'
++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 \
++SED \
++GREP \
++EGREP \
++FGREP \
++LD \
++NM \
++LN_S \
++lt_SP2NL \
++lt_NL2SP \
++reload_flag \
++OBJDUMP \
++deplibs_check_method \
++file_magic_cmd \
++AR \
++AR_FLAGS \
++STRIP \
++RANLIB \
++CC \
++CFLAGS \
++compiler \
++lt_cv_sys_global_symbol_pipe \
++lt_cv_sys_global_symbol_to_cdecl \
++lt_cv_sys_global_symbol_to_c_name_address \
++lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \
++lt_prog_compiler_no_builtin_flag \
++lt_prog_compiler_wl \
++lt_prog_compiler_pic \
++lt_prog_compiler_static \
++lt_cv_prog_compiler_c_o \
++need_locks \
++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_flag_spec_ld \
++hardcode_libdir_separator \
++fix_srcfile_path \
++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_wl_CXX \
++lt_prog_compiler_pic_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_flag_spec_ld_CXX \
++hardcode_libdir_separator_CXX \
++fix_srcfile_path_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\\"\\\`\\\\\\""
++      ;;
++    *)
++      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 \
++postinstall_cmds \
++postuninstall_cmds \
++finish_cmds \
++sys_lib_search_path_spec \
++sys_lib_dlsearch_path_spec \
++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; do
++    case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
++    *[\\\\\\\`\\"\\\$]*)
++      eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\""
++      ;;
++    *)
++      eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
++      ;;
++    esac
++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 which 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'
++    TIMESTAMP='$TIMESTAMP'
++    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+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
++# 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=`$as_echo "$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 '`
++	  $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
++	`' by configure.'
++    if test x"$ac_file" != x-; then
++      configure_input="$ac_file.  $configure_input"
++      { $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=`$as_echo "$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 ||
++$as_echo 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=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
++  # A ".." for each directory in $ac_dir_suffix.
++  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/ ;;
++  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@*)
++  { $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='
++  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"; } &&
++  { $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
++$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"
++  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
++    {
++      $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
++      { $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
++    $as_echo "/* $configure_input  */" \
++      && 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 ||
++$as_echo 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)  { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5
++$as_echo "$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=`$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" ||
++$as_expr X"$am_mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
++	 X"$am_mf" : 'X\(//\)[^/]' \| \
++	 X"$am_mf" : 'X\(//\)$' \| \
++	 X"$am_mf" : 'X\(/\)' \| . 2>/dev/null ||
++$as_echo 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 ||
++$as_echo 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
++    { { $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.  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 which 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
++
++# `$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.
++#
++#   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
++#                 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
++#   Written by Gordon Matzigkeit, 1996
++#
++#   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 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 "
++
++# ### 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
++
++# Shell to use when invoking shell scripts.
++SHELL=$lt_SHELL
++
++# An echo program that protects backslashes.
++ECHO=$lt_ECHO
++
++# 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
++
++# 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
++
++# The archiver.
++AR=$lt_AR
++AR_FLAGS=$lt_AR_FLAGS
++
++# 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 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 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
++
++# 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
++
++# 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
++
++# 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
++
++# 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
++
++# 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
++
++# 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
++# 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
++
++# 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
++
++# 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
++
++# 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
++
++  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 "X${COLLECT_NAMES+set}" != Xset; 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 '/^# 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=$(( $* ))
++}
++
++# 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"
++
++
++    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
++
++# 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
++
++# 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
++
++# 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
++# 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
++
++# 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
++
++# 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
++
++# 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
++  { $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
++
+diff --git a/bolt-plugin/configure.ac b/bolt-plugin/configure.ac
+new file mode 100644
+index 000000000..f7d4343e9
+--- /dev/null
++++ b/bolt-plugin/configure.ac
+@@ -0,0 +1,59 @@
++AC_INIT([bolt plugin for ld], 0.1,,[bolt-plugin])
++AC_CANONICAL_SYSTEM
++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
++
++AM_PROG_LIBTOOL
++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 5eaa667b3..24834cf60 100644
+--- a/gcc/common.opt
++++ b/gcc/common.opt
+@@ -2411,6 +2411,22 @@ fauto-bolt=
+ Common Joined RejectNegative
+ Specify the feedback data directory required by BOLT-plugin.  The default is the current directory.
+ 
++fbolt-use
++Common Report 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 Report Var(flag_rerun_cse_after_loop) Optimization
+ Add a common subexpression elimination pass after loop optimizations.
+diff --git a/gcc/opts.c b/gcc/opts.c
+index 0b389ae1d..479d726df 100644
+--- a/gcc/opts.c
++++ b/gcc/opts.c
+@@ -1170,6 +1170,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,
+@@ -2938,7 +2942,26 @@ common_handle_option (struct gcc_options *opts,
+       break;
+ 
+     case OPT_fauto_bolt_:
++      opts->x_flag_auto_bolt = true;
++      /* FALLTHRU */
+     case OPT_fauto_bolt:
++      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_:
+       /* Deferred.  */
+       break;
+ 
+-- 
+2.27.0
+
diff --git a/0031-AutoBOLT-Enable-BOLT-linker-plugin-on-aarch64-3-3.patch b/0031-AutoBOLT-Enable-BOLT-linker-plugin-on-aarch64-3-3.patch
new file mode 100644
index 0000000..d276591
--- /dev/null
+++ b/0031-AutoBOLT-Enable-BOLT-linker-plugin-on-aarch64-3-3.patch
@@ -0,0 +1,1945 @@
+From dd17ea263e762209dada859c12d13ed9fb468459 Mon Sep 17 00:00:00 2001
+From: liyancheng <412998149@qq.com>
+Date: Mon, 14 Feb 2022 15:32:25 +0800
+Subject: [PATCH 31/32] [AutoBOLT] Enable BOLT linker plugin on aarch64 3/3
+
+Enable the BOLT linker plugin on aarch64 when configured
+with --enable-bolt.
+---
+ Makefile.def     |   10 +
+ Makefile.in      | 1292 ++++++++++++++++++++++++++++++++++++++++++++++
+ configure        |   27 +-
+ configure.ac     |   22 +-
+ gcc/config.host  |    7 +-
+ gcc/config.in    |    7 +
+ gcc/configure    |   10 +-
+ gcc/configure.ac |    4 +
+ gcc/gcc.c        |   22 +
+ 9 files changed, 1396 insertions(+), 5 deletions(-)
+ mode change 100644 => 100755 configure
+ mode change 100644 => 100755 gcc/configure
+
+diff --git a/Makefile.def b/Makefile.def
+index 36fd26b03..5dda3c228 100644
+--- a/Makefile.def
++++ b/Makefile.def
+@@ -129,6 +129,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; no_install=true; no_check=true;
+@@ -327,6 +330,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; };
+@@ -351,6 +355,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; };
+@@ -358,8 +363,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; };
+@@ -378,6 +385,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/Makefile.in b/Makefile.in
+index 36e369df6..cfdca3d18 100644
+--- a/Makefile.in
++++ b/Makefile.in
+@@ -1039,6 +1039,7 @@ configure-host:  \
+     maybe-configure-utils \
+     maybe-configure-gnattools \
+     maybe-configure-lto-plugin \
++    maybe-configure-bolt-plugin \
+     maybe-configure-libcc1 \
+     maybe-configure-gotools \
+     maybe-configure-libctf
+@@ -1197,6 +1198,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
+@@ -1303,6 +1307,7 @@ info-host: maybe-info-libtermcap
+ info-host: maybe-info-utils
+ 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
+@@ -1392,6 +1397,7 @@ dvi-host: maybe-dvi-libtermcap
+ dvi-host: maybe-dvi-utils
+ 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
+@@ -1481,6 +1487,7 @@ pdf-host: maybe-pdf-libtermcap
+ pdf-host: maybe-pdf-utils
+ 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
+@@ -1570,6 +1577,7 @@ html-host: maybe-html-libtermcap
+ html-host: maybe-html-utils
+ 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
+@@ -1659,6 +1667,7 @@ TAGS-host: maybe-TAGS-libtermcap
+ TAGS-host: maybe-TAGS-utils
+ 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
+@@ -1748,6 +1757,7 @@ install-info-host: maybe-install-info-libtermcap
+ install-info-host: maybe-install-info-utils
+ 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
+@@ -1837,6 +1847,7 @@ install-pdf-host: maybe-install-pdf-libtermcap
+ install-pdf-host: maybe-install-pdf-utils
+ 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
+@@ -1926,6 +1937,7 @@ install-html-host: maybe-install-html-libtermcap
+ install-html-host: maybe-install-html-utils
+ 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
+@@ -2015,6 +2027,7 @@ installcheck-host: maybe-installcheck-libtermcap
+ installcheck-host: maybe-installcheck-utils
+ 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
+@@ -2104,6 +2117,7 @@ mostlyclean-host: maybe-mostlyclean-libtermcap
+ mostlyclean-host: maybe-mostlyclean-utils
+ 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
+@@ -2193,6 +2207,7 @@ clean-host: maybe-clean-libtermcap
+ clean-host: maybe-clean-utils
+ 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
+@@ -2282,6 +2297,7 @@ distclean-host: maybe-distclean-libtermcap
+ distclean-host: maybe-distclean-utils
+ 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
+@@ -2371,6 +2387,7 @@ maintainer-clean-host: maybe-maintainer-clean-libtermcap
+ maintainer-clean-host: maybe-maintainer-clean-utils
+ 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
+@@ -2516,6 +2533,7 @@ check-host:  \
+     maybe-check-utils \
+     maybe-check-gnattools \
+     maybe-check-lto-plugin \
++    maybe-check-bolt-plugin \
+     maybe-check-libcc1 \
+     maybe-check-gotools \
+     maybe-check-libctf
+@@ -2652,6 +2670,7 @@ install-host-nogcc:  \
+     maybe-install-utils \
+     maybe-install-gnattools \
+     maybe-install-lto-plugin \
++    maybe-install-bolt-plugin \
+     maybe-install-libcc1 \
+     maybe-install-gotools \
+     maybe-install-libctf
+@@ -2705,6 +2724,7 @@ install-host:  \
+     maybe-install-utils \
+     maybe-install-gnattools \
+     maybe-install-lto-plugin \
++    maybe-install-bolt-plugin \
+     maybe-install-libcc1 \
+     maybe-install-gotools \
+     maybe-install-libctf
+@@ -2814,6 +2834,7 @@ install-strip-host:  \
+     maybe-install-strip-utils \
+     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
+@@ -38628,6 +38649,1129 @@ 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-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
+@@ -55735,6 +56879,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; \
+@@ -55855,6 +57004,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; \
+@@ -56040,6 +57194,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; \
+@@ -56184,6 +57344,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; \
+@@ -56394,6 +57560,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; \
+@@ -56538,6 +57710,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; \
+@@ -56804,6 +57982,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; \
+@@ -56948,6 +58132,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; \
+@@ -57202,6 +58392,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; \
+@@ -57346,6 +58542,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; \
+@@ -57533,6 +58735,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; \
+@@ -57677,6 +58885,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; \
+@@ -57864,6 +59078,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; \
+@@ -58008,6 +59228,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; \
+@@ -58218,6 +59444,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; \
+@@ -58362,6 +59594,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; \
+@@ -58549,6 +59787,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; \
+@@ -58693,6 +59937,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; \
+@@ -58985,6 +60235,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
+@@ -59225,6 +60485,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
+@@ -59277,8 +60547,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
+@@ -59370,6 +60642,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/configure b/configure
+old mode 100644
+new mode 100755
+index f2ec106a8..97d5ca4fc
+--- a/configure
++++ b/configure
+@@ -814,6 +814,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
+@@ -1529,6 +1530,7 @@ Optional Features:
+   --enable-bootstrap      enable bootstrapping [yes if native 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
+@@ -6187,6 +6189,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 :
+@@ -6216,6 +6227,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
+@@ -6391,6 +6412,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
+@@ -6779,7 +6804,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 115db3f40..90ccd5ef8 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -1810,6 +1810,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])],
+@@ -1818,6 +1824,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*) ;;
+@@ -1983,6 +1999,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
+@@ -2358,7 +2378,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 84f0433e2..230ab61ac 100644
+--- a/gcc/config.host
++++ b/gcc/config.host
+@@ -59,7 +59,11 @@
+ #  host_lto_plugin_soname Set this to the name to which the LTO linker
+ #			plugin gets compiled on this host, if it is
+ #			different from the default "liblto_plugin.so".
+-
++#
++#  host_bolt_plugin_soname Set this to the name to which the BOLT
++#			plugin gets compiled on this host, if it is
++#			different from the default "libbolt_plugin.so".
++#
+ # When setting any of these variables, check to see if a corresponding
+ # variable is present in config.build; if so, you will likely want to 
+ # set it in both places.
+@@ -75,6 +79,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 364eba477..80b421d99 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
+diff --git a/gcc/configure b/gcc/configure
+old mode 100644
+new mode 100755
+index 27beb6b1e..d4f97834f
+--- a/gcc/configure
++++ b/gcc/configure
+@@ -12922,6 +12922,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
+@@ -19022,7 +19028,7 @@ else
+   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+   lt_status=$lt_dlunknown
+   cat > conftest.$ac_ext <<_LT_EOF
+-#line 19025 "configure"
++#line 19031 "configure"
+ #include "confdefs.h"
+ 
+ #if HAVE_DLFCN_H
+@@ -19128,7 +19134,7 @@ else
+   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+   lt_status=$lt_dlunknown
+   cat > conftest.$ac_ext <<_LT_EOF
+-#line 19131 "configure"
++#line 19137 "configure"
+ #include "confdefs.h"
+ 
+ #if HAVE_DLFCN_H
+diff --git a/gcc/configure.ac b/gcc/configure.ac
+index 82a0ce995..44154f69f 100644
+--- a/gcc/configure.ac
++++ b/gcc/configure.ac
+@@ -2357,6 +2357,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.c b/gcc/gcc.c
+index 9f790db0d..b55075b14 100644
+--- a/gcc/gcc.c
++++ b/gcc/gcc.c
+@@ -1036,6 +1036,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: Mon, 28 Feb 2022 16:52:58 +0800
+Subject: [PATCH 32/32] [Autoprefetch] Prune invaild loops containing edges whose
+ probability exceeds 1
+
+Skip auto prefetch analysis if the loop contains the bb in which the sum
+of its outgoing edge probabilities is greater than 1.
+---
+ gcc/testsuite/gcc.dg/autoprefetch/autoprefetch.exp   |  2 +-
+ .../gcc.dg/autoprefetch/branch-weighted-prefetch.c   |  8 ++++----
+ gcc/tree-ssa-loop-prefetch.c                         | 12 ++++++++++++
+ 3 files changed, 17 insertions(+), 5 deletions(-)
+
+diff --git a/gcc/testsuite/gcc.dg/autoprefetch/autoprefetch.exp b/gcc/testsuite/gcc.dg/autoprefetch/autoprefetch.exp
+index a7408e338..7cae630a2 100644
+--- a/gcc/testsuite/gcc.dg/autoprefetch/autoprefetch.exp
++++ b/gcc/testsuite/gcc.dg/autoprefetch/autoprefetch.exp
+@@ -20,7 +20,7 @@ load_lib target-supports.exp
+ # Initialize `dg'.
+ dg-init
+ 
+-gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] \
++dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] \
+ 	"" "-fprefetch-loop-arrays"
+ 
+ # All done.
+diff --git a/gcc/testsuite/gcc.dg/autoprefetch/branch-weighted-prefetch.c b/gcc/testsuite/gcc.dg/autoprefetch/branch-weighted-prefetch.c
+index c63c5e5cb..ab537cb29 100644
+--- a/gcc/testsuite/gcc.dg/autoprefetch/branch-weighted-prefetch.c
++++ b/gcc/testsuite/gcc.dg/autoprefetch/branch-weighted-prefetch.c
+@@ -1,5 +1,5 @@
+-/* { dg-do compile } */
+-/* { dg-options "-O2 -fprefetch-loop-arrays=2 --param min-insn-to-prefetch-ratio=5 --param simultaneous-prefetches=100 -fdump-tree-aprefetch-details -fdump-tree-optimized" } */
++/* { dg-do compile { target { aarch64*-*-linux* } } } */
++/* { dg-options "-O2 -fprefetch-loop-arrays=2 --param min-insn-to-prefetch-ratio=5 --param simultaneous-prefetches=100 --param l1-cache-size=64 --param l1-cache-line-size=32 -fdump-tree-aprefetch-details -fdump-tree-optimized" } */
+ #define N 10000000
+ 
+ long long a[N];
+@@ -18,5 +18,5 @@ long long func ()
+ 
+   return sum;
+ }
+-/* { dg-final { scan-tree-dump-times "Ahead 40" 1 "aprefetch" } } */
+-/* { dg-final { scan-tree-dump-times "builtin_prefetch" 1 "optimized" } } */
+\ No newline at end of file
++/* { dg-final { scan-tree-dump "Calculating prefetch distance using bb branch weighting method" "aprefetch" } } */
++/* { dg-final { scan-tree-dump "builtin_prefetch" "optimized" } } */
+\ No newline at end of file
+diff --git a/gcc/tree-ssa-loop-prefetch.c b/gcc/tree-ssa-loop-prefetch.c
+index 673f453a4..0d992d8f6 100644
+--- a/gcc/tree-ssa-loop-prefetch.c
++++ b/gcc/tree-ssa-loop-prefetch.c
+@@ -2267,6 +2267,15 @@ traverse_prune_bb_branch (hash_map  &bb_branch_prob,
+ 			     && bb_bp_node->false_edge_bb == NULL))
+     return false;
+ 
++  /* Do not process the loop with a bb branch probability of an abnormal
++     value.  */
++  if (bb_bp_node->true_edge_prob + bb_bp_node->false_edge_prob > 1)
++    {
++      if (dump_file && (dump_flags & TDF_DETAILS))
++	fprintf (dump_file, "bb branch probability is abnormal\n");
++      return false;
++    }
++
+   if (current_bb == latch_bb)
+     {
+       max_path--;
+@@ -2409,6 +2418,9 @@ estimate_num_loop_insns (struct loop *loop, eni_weights *weights)
+ 	  dump_loop_bb (loop);
+ 	  return 0;
+ 	}
++      if (dump_file && (dump_flags & TDF_DETAILS))
++	fprintf (dump_file, "Calculating prefetch distance using bb branch "
++			    "weighting method\n");
+     }
+ 
+   for (unsigned i = 0; i < loop->num_nodes; i++)
+-- 
+2.27.0
+
diff --git a/0033-AutoFdo-Fix-memory-leaks-in-autofdo-and-autoprefetch.patch b/0033-AutoFdo-Fix-memory-leaks-in-autofdo-and-autoprefetch.patch
new file mode 100644
index 0000000..3286140
--- /dev/null
+++ b/0033-AutoFdo-Fix-memory-leaks-in-autofdo-and-autoprefetch.patch
@@ -0,0 +1,130 @@
+From adfcca263996bf174f7108b477e81e7ec58f19c4 Mon Sep 17 00:00:00 2001
+From: dingguangya 
+Date: Mon, 14 Mar 2022 10:42:07 +0800
+Subject: [PATCH] [AutoFdo] Fix memory leaks in autofdo and autoprefetch
+
+Fix memory leaks in autofdo and autoprefetch.
+---
+ gcc/final.c                  | 23 +++++++++++++++--------
+ gcc/tree-ssa-loop-prefetch.c |  4 ++++
+ 2 files changed, 19 insertions(+), 8 deletions(-)
+
+diff --git a/gcc/final.c b/gcc/final.c
+index b9affd3a7..da8d20958 100644
+--- a/gcc/final.c
++++ b/gcc/final.c
+@@ -4770,12 +4770,16 @@ 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);
+@@ -4826,12 +4830,14 @@ 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)));
++		       func_name);
+ 
+ 	      fprintf (asm_out_file,
+ 		       "\t.string \"" HOST_WIDE_INT_PRINT_DEC "\"\n",
+@@ -4841,9 +4847,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);
+ 	    }
+ 	}
+     }
+@@ -4917,8 +4923,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",
+@@ -4926,8 +4933,7 @@ dump_function_info_to_asm (const char *fnname)
+ 
+   if (dump_file)
+     {
+-      fprintf (dump_file, "\n FUNC_NAME: %s\n",
+-	       alias_local_functions (fnname));
++      fprintf (dump_file, "\n FUNC_NAME: %s\n", func_name);
+       fprintf (dump_file, " file: %s\n",
+ 	       dump_base_name);
+       fprintf (dump_file, " profile_status: %s\n",
+@@ -4937,6 +4943,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 info form AutoFDO or PGO to asm.  */
+diff --git a/gcc/tree-ssa-loop-prefetch.c b/gcc/tree-ssa-loop-prefetch.c
+index 0d992d8f6..781831c39 100644
+--- a/gcc/tree-ssa-loop-prefetch.c
++++ b/gcc/tree-ssa-loop-prefetch.c
+@@ -2248,6 +2248,7 @@ get_bb_branch_prob (hash_map  &bb_branch_prob,
+ 	  branch_prob.true_edge_prob = get_edge_prob (e);
+ 	}
+     }
++  free (body);
+ }
+ 
+ /* Traverse each bb in the loop and prune fake loops.  */
+@@ -2416,6 +2417,7 @@ estimate_num_loop_insns (struct loop *loop, eni_weights *weights)
+       if (get_bb_prob (bb_branch_prob, loop) == false)
+ 	{
+ 	  dump_loop_bb (loop);
++	  free (body);
+ 	  return 0;
+ 	}
+       if (dump_file && (dump_flags & TDF_DETAILS))
+@@ -2596,6 +2598,7 @@ is_high_exec_rate_loop (struct loop *loop)
+ 
+       if (loop_exec_rate < (float) LOOP_EXECUTION_RATE / 100.0)
+ 	{
++	  exit_edges.release ();
+ 	  return false;
+ 	}
+     }
+@@ -2606,6 +2609,7 @@ is_high_exec_rate_loop (struct loop *loop)
+ 	       loop_exec_rate, (float) LOOP_EXECUTION_RATE / 100.0);
+       dump_loop_bb (loop);
+     }
++  exit_edges.release ();
+   return true;
+ }
+ 
+-- 
+2.27.0.windows.1
+
diff --git a/0034-Backport-sanitizer-Fix-asan-against-glibc-2.34-PR100.patch b/0034-Backport-sanitizer-Fix-asan-against-glibc-2.34-PR100.patch
new file mode 100644
index 0000000..10c4485
--- /dev/null
+++ b/0034-Backport-sanitizer-Fix-asan-against-glibc-2.34-PR100.patch
@@ -0,0 +1,72 @@
+From 2969f5190561e26a8ce42d5dcda43ef59e0b6d32 Mon Sep 17 00:00:00 2001
+From: liyancheng <412998149@qq.com>
+Date: Tue, 26 Apr 2022 19:59:09 +0800
+Subject: [PATCH] [Backport] sanitizer: Fix asan against glibc 2.34 [PR100114]
+
+Reference: https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=d9f462fb372fb02da032cefd6b091d7582c425ae
+
+sanitizer: Fix asan against glibc 2.34 [PR100114]
+
+As mentioned in the PR, SIGSTKSZ is no longer a compile time constant in
+glibc 2.34 and later, so
+static const uptr kAltStackSize = SIGSTKSZ * 4;
+needs dynamic initialization, but is used by a function called indirectly
+from .preinit_array and therefore before the variable is constructed.
+This results in using 0 size instead and all asan instrumented programs
+die with:
+==91==ERROR: AddressSanitizer failed to allocate 0x0 (0) bytes of SetAlternateSignalStack (error code: 22)
+
+Here is a cherry-pick from upstream to fix this.
+
+2021-04-17  Jakub Jelinek  
+
+PR sanitizer/100114
+* sanitizer_common/sanitizer_posix_libcdep.cpp: Cherry-pick
+llvm-project revisions 82150606fb11d28813ae6da1101f5bda638165fe
+and b93629dd335ffee2fc4b9b619bf86c3f9e6b0023.
+---
+ .../sanitizer_common/sanitizer_posix_libcdep.cpp    | 13 ++++++++-----
+ 1 file changed, 8 insertions(+), 5 deletions(-)
+
+diff --git a/libsanitizer/sanitizer_common/sanitizer_posix_libcdep.cpp b/libsanitizer/sanitizer_common/sanitizer_posix_libcdep.cpp
+index 304b3a01a..ac88fbe07 100644
+--- a/libsanitizer/sanitizer_common/sanitizer_posix_libcdep.cpp
++++ b/libsanitizer/sanitizer_common/sanitizer_posix_libcdep.cpp
+@@ -169,7 +169,11 @@ bool SupportsColoredOutput(fd_t fd) {
+ 
+ #if !SANITIZER_GO
+ // TODO(glider): different tools may require different altstack size.
+-static const uptr kAltStackSize = SIGSTKSZ * 4;  // SIGSTKSZ is not enough.
++static uptr GetAltStackSize() {
++  // SIGSTKSZ is not enough.
++  static const uptr kAltStackSize = SIGSTKSZ * 4;
++  return kAltStackSize;
++}
+ 
+ void SetAlternateSignalStack() {
+   stack_t altstack, oldstack;
+@@ -180,10 +184,9 @@ void SetAlternateSignalStack() {
+   // TODO(glider): the mapped stack should have the MAP_STACK flag in the
+   // future. It is not required by man 2 sigaltstack now (they're using
+   // malloc()).
+-  void* base = MmapOrDie(kAltStackSize, __func__);
+-  altstack.ss_sp = (char*) base;
++  altstack.ss_size = GetAltStackSize();
++  altstack.ss_sp = (char *)MmapOrDie(altstack.ss_size, __func__);
+   altstack.ss_flags = 0;
+-  altstack.ss_size = kAltStackSize;
+   CHECK_EQ(0, sigaltstack(&altstack, nullptr));
+ }
+ 
+@@ -191,7 +194,7 @@ void UnsetAlternateSignalStack() {
+   stack_t altstack, oldstack;
+   altstack.ss_sp = nullptr;
+   altstack.ss_flags = SS_DISABLE;
+-  altstack.ss_size = kAltStackSize;  // Some sane value required on Darwin.
++  altstack.ss_size = GetAltStackSize();  // Some sane value required on Darwin.
+   CHECK_EQ(0, sigaltstack(&altstack, &oldstack));
+   UnmapOrDie(oldstack.ss_sp, oldstack.ss_size);
+ }
+-- 
+2.25.1
+
diff --git a/0035-ccmp-Add-another-optimization-opportunity-for-ccmp-i.patch b/0035-ccmp-Add-another-optimization-opportunity-for-ccmp-i.patch
new file mode 100644
index 0000000..fe0b533
--- /dev/null
+++ b/0035-ccmp-Add-another-optimization-opportunity-for-ccmp-i.patch
@@ -0,0 +1,342 @@
+From cf0f086ec274d794a2a180047123920bf8a5224b Mon Sep 17 00:00:00 2001
+From: dingguangya 
+Date: Mon, 17 Jan 2022 21:03:47 +0800
+Subject: [PATCH 01/12] [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.c                                |  33 ++++
+ gcc/ccmp.h                                |   1 +
+ gcc/common.opt                            |   4 +
+ gcc/testsuite/gcc.target/aarch64/ccmp_3.c |  15 ++
+ gcc/tree-ssa-coalesce.c                   | 197 ++++++++++++++++++++++
+ 5 files changed, 250 insertions(+)
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/ccmp_3.c
+
+diff --git a/gcc/ccmp.c b/gcc/ccmp.c
+index ca77375a9..8d2d73e52 100644
+--- a/gcc/ccmp.c
++++ b/gcc/ccmp.c
+@@ -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 199dd581d..ac862f0f6 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 24834cf60..4dd566def 100644
+--- a/gcc/common.opt
++++ b/gcc/common.opt
+@@ -1942,6 +1942,10 @@ fira-verbose=
+ Common RejectNegative Joined UInteger Var(flag_ira_verbose) Init(5)
+ -fira-verbose=	Control IRA's level of diagnostic messages.
+ 
++fccmp2
++Common Report Var(flag_ccmp2) Init(0) Optimization
++Optimize potential ccmp instruction in complex scenarios.
++
+ fivopts
+ Common Report 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.c b/gcc/tree-ssa-coalesce.c
+index 0b0b1b18d..e0120a4a4 100644
+--- a/gcc/tree-ssa-coalesce.c
++++ b/gcc/tree-ssa-coalesce.c
+@@ -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.27.0.windows.1
+
diff --git a/0036-StructReorg-Refactoring-reorder-fields-to-struct-lay.patch b/0036-StructReorg-Refactoring-reorder-fields-to-struct-lay.patch
new file mode 100644
index 0000000..41d01f7
--- /dev/null
+++ b/0036-StructReorg-Refactoring-reorder-fields-to-struct-lay.patch
@@ -0,0 +1,1115 @@
+From 3c06a2cda7220a48866ae2dbe3f365e300cbaeca Mon Sep 17 00:00:00 2001
+From: liyancheng <412998149@qq.com>
+Date: Wed, 1 Jun 2022 17:22:12 +0800
+Subject: [PATCH 02/12] [StructReorg] Refactoring reorder fields to struct
+ layout optimization
+
+Refactor the reorder_fields optimization into struct layout optimization. Add
+flag -fipa-struct-reorg=[0,1,2] to enable none, strcut reorg, reorder fields
+optimizations.
+---
+ gcc/common.opt                                |   6 +-
+ gcc/ipa-struct-reorg/ipa-struct-reorg.c       | 167 +++++++++---------
+ gcc/ipa-struct-reorg/ipa-struct-reorg.h       |   2 +-
+ gcc/opts.c                                    |  12 ++
+ gcc/passes.def                                |   2 +-
+ gcc/symbol-summary.h                          |   4 +-
+ .../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/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.dg/struct/sr_pointer_minus.c          |   2 +-
+ gcc/testsuite/gcc.dg/struct/struct-reorg.exp  |  19 ++
+ gcc/timevar.def                               |   2 +-
+ gcc/tree-pass.h                               |   2 +-
+ gcc/tree.c                                    |   4 +-
+ 35 files changed, 153 insertions(+), 117 deletions(-)
+
+diff --git a/gcc/common.opt b/gcc/common.opt
+index 4dd566def..7fc075d35 100644
+--- a/gcc/common.opt
++++ b/gcc/common.opt
+@@ -1876,13 +1876,17 @@ Common Ignore
+ Does nothing. Preserved for backward compatibility.
+ 
+ fipa-reorder-fields
+-Common Report Var(flag_ipa_reorder_fields) Init(0) Optimization
++Common Report Var(flag_ipa_struct_layout) Init(0) Optimization
+ Perform structure fields reorder optimizations.
+ 
+ fipa-struct-reorg
+ Common Report 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, 2)
++-fipa-struct-reorg=[0,1,2] adding none, struct-reorg, reorder-fields optimizations.
++
+ fipa-extend-auto-profile
+ Common Report Var(flag_ipa_extend_auto_profile)
+ Use sample profile information for source code.
+diff --git a/gcc/ipa-struct-reorg/ipa-struct-reorg.c b/gcc/ipa-struct-reorg/ipa-struct-reorg.c
+index 2bf41e0d8..9214ee74a 100644
+--- a/gcc/ipa-struct-reorg/ipa-struct-reorg.c
++++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.c
+@@ -235,7 +235,7 @@ enum srmode
+ {
+   NORMAL = 0,
+   COMPLETE_STRUCT_RELAYOUT,
+-  STRUCT_REORDER_FIELDS
++  STRUCT_LAYOUT_OPTIMIZE
+ };
+ 
+ static bool is_result_of_mult (tree arg, tree *num, tree struct_size);
+@@ -552,7 +552,7 @@ void
+ srtype::simple_dump (FILE *f)
+ {
+   print_generic_expr (f, type);
+-  if (current_mode == STRUCT_REORDER_FIELDS)
++  if (current_mode == STRUCT_LAYOUT_OPTIMIZE)
+     {
+       fprintf (f, "(%d)", TYPE_UID (type));
+     }
+@@ -593,9 +593,9 @@ srfield::create_new_fields (tree newtype[max_split],
+ 			    tree newfields[max_split],
+ 			    tree newlast[max_split])
+ {
+-  if (current_mode == STRUCT_REORDER_FIELDS)
++  if (current_mode == STRUCT_LAYOUT_OPTIMIZE)
+     {
+-      create_new_reorder_fields (newtype, newfields, newlast);
++      create_new_optimized_fields (newtype, newfields, newlast);
+       return;
+     }
+ 
+@@ -689,15 +689,15 @@ srfield::reorder_fields (tree newfields[max_split], tree newlast[max_split],
+     }
+ }
+ 
+-/* Create the new reorder fields for this field.
++/* Create the new optimized 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])
++srfield::create_new_optimized_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;
+@@ -794,7 +794,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_mode != STRUCT_LAYOUT_OPTIMIZE)
+     {
+       newtype[0] = type;
+       return false;
+@@ -822,8 +822,8 @@ 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, current_mode == STRUCT_LAYOUT_OPTIMIZE
++			 ? ".slo." : ".reorg.", id, NULL);
+ 	  TYPE_NAME (newtype[i]) = build_decl (UNKNOWN_LOCATION, TYPE_DECL,
+ 				   get_identifier (name), newtype[i]);
+           free (name);
+@@ -969,8 +969,8 @@ 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, current_mode == STRUCT_LAYOUT_OPTIMIZE
++					? ".slo." : ".reorg.", id, NULL);
+ 		  new_name = get_identifier (name);
+ 		  free (name);
+ 		}
+@@ -2718,7 +2718,7 @@ escape_type 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_mode != STRUCT_LAYOUT_OPTIMIZE))
+     return escape_ptr_ptr;
+   return does_not_escape;
+ }
+@@ -2740,13 +2740,13 @@ ipa_struct_reorg::record_field_type (tree field, srtype *base_srtype)
+       field_srtype->add_field_site (field_srfield);
+     }
+   if (field_srtype == base_srtype && current_mode != COMPLETE_STRUCT_RELAYOUT
+-      && current_mode != STRUCT_REORDER_FIELDS)
++      && current_mode != STRUCT_LAYOUT_OPTIMIZE)
+     {
+       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_mode == STRUCT_LAYOUT_OPTIMIZE
+       && TREE_CODE (field_type) == RECORD_TYPE)
+     {
+       field_srtype->mark_escape (escape_instance_field, NULL);
+@@ -2781,7 +2781,7 @@ ipa_struct_reorg::record_struct_field_types (tree base_type,
+ 	  }
+ 	/* 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_mode == STRUCT_LAYOUT_OPTIMIZE
+ 	    && TREE_CODE (field_type) == RECORD_TYPE)
+ 	  {
+ 	    base_srtype->mark_escape (escape_instance_field, NULL);
+@@ -2966,7 +2966,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)
++	   || current_mode == STRUCT_LAYOUT_OPTIMIZE)
+ 	  && TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE)
+ 	{
+ 	  e = escape_separate_instance;
+@@ -3071,7 +3071,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_mode == STRUCT_LAYOUT_OPTIMIZE)
+ 	    {
+ 	      l_find = !(current_function->is_safe_func
+ 			 && TREE_CODE (lhs) == SSA_NAME
+@@ -3117,7 +3117,7 @@ ipa_struct_reorg::find_vars (gimple *stmt)
+ 		}
+ 	    }
+ 	}
+-      else if ((current_mode == STRUCT_REORDER_FIELDS)
++      else if ((current_mode == STRUCT_LAYOUT_OPTIMIZE)
+ 	       && (gimple_assign_rhs_code (stmt) == LE_EXPR
+ 		   || gimple_assign_rhs_code (stmt) == LT_EXPR
+ 		   || gimple_assign_rhs_code (stmt) == GE_EXPR
+@@ -3128,7 +3128,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_mode == STRUCT_LAYOUT_OPTIMIZE)
+ 	       && gimple_assign_rhs_code (stmt) == POINTER_DIFF_EXPR
+ 	       && types_compatible_p (
+ 		  TYPE_MAIN_VARIANT (TREE_TYPE (gimple_assign_rhs1 (stmt))),
+@@ -3391,11 +3391,12 @@ 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_mode == STRUCT_LAYOUT_OPTIMIZE)
+ 	{
+ 	  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_mode == STRUCT_LAYOUT_OPTIMIZE)
+ 	{
+ 	  return trace_calculate_diff (size_def_stmt, num);
+ 	}
+@@ -3415,7 +3416,7 @@ 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_mode == STRUCT_LAYOUT_OPTIMIZE)
+       && (gimple_call_builtin_p (stmt, BUILT_IN_REALLOC)
+ 	  || gimple_call_builtin_p (stmt, BUILT_IN_MALLOC)
+ 	  || gimple_call_builtin_p (stmt, BUILT_IN_CALLOC)))
+@@ -3548,7 +3549,7 @@ ipa_struct_reorg::maybe_mark_or_record_other_side (tree side, tree other, gimple
+   /* 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_mode == STRUCT_LAYOUT_OPTIMIZE
+ 	   && TREE_CODE (side) == SSA_NAME
+ 	   && VOID_POINTER_P (TREE_TYPE (side))
+ 	   && SSA_NAME_VAR (side)
+@@ -3815,7 +3816,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_mode == STRUCT_LAYOUT_OPTIMIZE)
+ 	{
+ 	  bool is_int_ptr = POINTER_TYPE_P (TREE_TYPE (base))
+ 			    && (TREE_CODE (inner_type (TREE_TYPE (base)))
+@@ -4031,7 +4032,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_mode == STRUCT_LAYOUT_OPTIMIZE
+ 		    && safe_functions.contains (
+ 		       node->get_edge (stmt)->callee)))
+ 	      && VOID_POINTER_P (argtypet))
+@@ -4063,9 +4064,9 @@ 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 (current_mode == STRUCT_LAYOUT_OPTIMIZE)
+     {
+-      if (!opt_for_fn (current_function_decl, flag_ipa_reorder_fields))
++      if (!opt_for_fn (current_function_decl, flag_ipa_struct_layout))
+ 	{
+ 	  type->mark_escape (escape_non_optimize, stmt);
+ 	}
+@@ -4287,7 +4288,7 @@ ipa_struct_reorg::check_definition_call (srdecl *decl, vec &worklist)
+       check_type_and_push (gimple_call_arg (stmt, 0), decl, worklist, stmt);
+     }
+ 
+-  if (current_mode == STRUCT_REORDER_FIELDS)
++  if (current_mode == STRUCT_LAYOUT_OPTIMIZE)
+     {
+       if (!handled_allocation_stmt (stmt))
+ 	{
+@@ -4341,7 +4342,7 @@ ipa_struct_reorg::check_definition (srdecl *decl, vec &worklist)
+ 	}
+       return;
+     }
+-  if (current_mode == STRUCT_REORDER_FIELDS && SSA_NAME_VAR (ssa_name)
++  if (current_mode == STRUCT_LAYOUT_OPTIMIZE && 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));
+@@ -4442,7 +4443,7 @@ ipa_struct_reorg::check_other_side (srdecl *decl, tree other, gimple *stmt, vec<
+       if (!get_type_field (other, base, indirect, type1, field,
+ 			   realpart, imagpart, address, escape_from_base))
+ 	{
+-	  if (current_mode == STRUCT_REORDER_FIELDS)
++	  if (current_mode == STRUCT_LAYOUT_OPTIMIZE)
+ 	    {
+ 	      /* release INTEGER_TYPE cast to struct pointer.  */
+ 	      bool cast_from_int_ptr = current_function->is_safe_func && base
+@@ -4498,7 +4499,7 @@ 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_mode != STRUCT_LAYOUT_OPTIMIZE || 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))
+@@ -4579,7 +4580,7 @@ ipa_struct_reorg::check_use (srdecl *decl, gimple *stmt, vec &worklist)
+ 	       && (code != EQ_EXPR && code != NE_EXPR
+ 		   && code != LT_EXPR && code != LE_EXPR
+ 		   && code != GT_EXPR && code != GE_EXPR))
+-	   || (current_mode == STRUCT_REORDER_FIELDS
++	   || (current_mode == STRUCT_LAYOUT_OPTIMIZE
+ 	       && (code != EQ_EXPR && code != NE_EXPR
+ 		   && code != LT_EXPR && code != LE_EXPR
+ 		   && code != GT_EXPR && code != GE_EXPR)))
+@@ -4618,7 +4619,7 @@ ipa_struct_reorg::check_use (srdecl *decl, gimple *stmt, vec &worklist)
+ 	       && (code != EQ_EXPR && code != NE_EXPR
+ 		   && code != LT_EXPR && code != LE_EXPR
+ 		   && code != GT_EXPR && code != GE_EXPR))
+-	   || (current_mode == STRUCT_REORDER_FIELDS
++	   || (current_mode == STRUCT_LAYOUT_OPTIMIZE
+ 	       && (code != EQ_EXPR && code != NE_EXPR
+ 		   && code != LT_EXPR && code != LE_EXPR
+ 		  && code != GT_EXPR && code != GE_EXPR)))
+@@ -4740,11 +4741,11 @@ 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_mode != STRUCT_LAYOUT_OPTIMIZE)
+ 	{
+ 	  escapes = escape_visible_function;
+ 	}
+-      if (current_mode == STRUCT_REORDER_FIELDS && node->externally_visible)
++      if (current_mode == STRUCT_LAYOUT_OPTIMIZE && node->externally_visible)
+ 	{
+ 	  escapes = escape_visible_function;
+ 	}
+@@ -4754,9 +4755,9 @@ 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 (current_mode == STRUCT_LAYOUT_OPTIMIZE)
+     {
+-      if (!opt_for_fn (node->decl, flag_ipa_reorder_fields))
++      if (!opt_for_fn (node->decl, flag_ipa_struct_layout))
+ 	{
+ 	  escapes = escape_non_optimize;
+ 	}
+@@ -4773,7 +4774,7 @@ 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_mode == STRUCT_LAYOUT_OPTIMIZE)
+     {
+       current_function->is_safe_func = safe_functions.contains (node);
+       if (dump_file)
+@@ -4989,7 +4990,7 @@ ipa_struct_reorg::record_accesses (void)
+     }
+ 
+   /* Add a safe func mechanism.  */
+-  if (current_mode == STRUCT_REORDER_FIELDS)
++  if (current_mode == STRUCT_LAYOUT_OPTIMIZE)
+     {
+       record_safe_func_with_void_ptr_parm ();
+     }
+@@ -5188,7 +5189,7 @@ void
+ ipa_struct_reorg::prune_escaped_types (void)
+ {
+   if (current_mode != COMPLETE_STRUCT_RELAYOUT
+-      && current_mode != STRUCT_REORDER_FIELDS)
++      && current_mode != STRUCT_LAYOUT_OPTIMIZE)
+     {
+       /* Detect recusive types and mark them as escaping.  */
+       detect_cycles ();
+@@ -5196,7 +5197,7 @@ ipa_struct_reorg::prune_escaped_types (void)
+ 	 mark them as escaping.  */
+       propagate_escape ();
+     }
+-  if (current_mode == STRUCT_REORDER_FIELDS)
++  if (current_mode == STRUCT_LAYOUT_OPTIMIZE)
+     {
+       propagate_escape_via_original ();
+       propagate_escape_via_empty_with_no_original ();
+@@ -5256,7 +5257,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_mode != STRUCT_LAYOUT_OPTIMIZE)
+ 	{
+ 	  delete function;
+ 	  functions.ordered_remove (i);
+@@ -5281,10 +5282,10 @@ 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,
++  /* The escape type is not deleted in STRUCT_LAYOUT_OPTIMIZE,
+      Then the type that contains the escaped type fields
+      can find complete information.  */
+-  if (current_mode != STRUCT_REORDER_FIELDS)
++  if (current_mode != STRUCT_LAYOUT_OPTIMIZE)
+     {
+       for (unsigned i = 0; i < types.length ();)
+ 	{
+@@ -5334,7 +5335,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_mode == STRUCT_LAYOUT_OPTIMIZE)
+     {
+       for (unsigned i = 0; i < types.length (); i++)
+ 	{
+@@ -5458,8 +5459,8 @@ 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, current_mode == STRUCT_LAYOUT_OPTIMIZE
++			    ? ".slo.0" : ".reorg.0", NULL);
+       new_name = get_identifier (name);
+       free (name);
+     }
+@@ -5547,8 +5548,8 @@ 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");
++				current_mode == STRUCT_LAYOUT_OPTIMIZE
++				? "slo" : "struct_reorg");
+       new_node->can_change_signature = node->can_change_signature;
+       new_node->make_local ();
+       f->newnode = new_node;
+@@ -5666,13 +5667,13 @@ ipa_struct_reorg::rewrite_expr (tree expr, tree newexpr[max_split], bool ignore_
+         newbase1 = build_fold_addr_expr (newbase1);
+       if (indirect)
+ 	{
+-	  if (current_mode == STRUCT_REORDER_FIELDS)
++	  if (current_mode == STRUCT_LAYOUT_OPTIMIZE)
+ 	    {
+ 	      /* Supports the MEM_REF offset.
+ 		 _1 = MEM[(struct arc *)ap_1 + 72B].flow;
+-		 Old rewrite: _1 = ap.reorder.0_8->flow;
++		 Old rewrite: _1 = ap.slo.0_8->flow;
+ 		 New rewrite: _1
+-		  = MEM[(struct arc.reorder.0 *)ap.reorder.0_8 + 64B].flow;
++		  = MEM[(struct arc.slo.0 *)ap.slo.0_8 + 64B].flow;
+ 	      */
+ 	      HOST_WIDE_INT offset_tmp = 0;
+ 	      HOST_WIDE_INT mem_offset = 0;
+@@ -5738,10 +5739,10 @@ ipa_struct_reorg::rewrite_assign (gassign *stmt, gimple_stmt_iterator *gsi)
+       return remove;
+     }
+ 
+-  if ((current_mode != STRUCT_REORDER_FIELDS
++  if ((current_mode != STRUCT_LAYOUT_OPTIMIZE
+        && (gimple_assign_rhs_code (stmt) == EQ_EXPR
+ 	   || gimple_assign_rhs_code (stmt) == NE_EXPR))
+-      || (current_mode == STRUCT_REORDER_FIELDS
++      || (current_mode == STRUCT_LAYOUT_OPTIMIZE
+ 	  && (TREE_CODE_CLASS (gimple_assign_rhs_code (stmt))
+ 	      == tcc_comparison)))
+     {
+@@ -5751,7 +5752,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_mode == STRUCT_LAYOUT_OPTIMIZE
+ 	  && rhs_code != EQ_EXPR && rhs_code != NE_EXPR)
+ 	{
+ 	  code = rhs_code;
+@@ -5798,8 +5799,8 @@ 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_mode != STRUCT_LAYOUT_OPTIMIZE
++	  || (current_mode == STRUCT_LAYOUT_OPTIMIZE && (num != NULL)))
+ 	{
+ 	  num = gimplify_build1 (gsi, NOP_EXPR, sizetype, num);
+ 	}
+@@ -5827,7 +5828,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_mode == STRUCT_LAYOUT_OPTIMIZE
+       && gimple_assign_rhs_code (stmt) == POINTER_DIFF_EXPR)
+     {
+       tree rhs1 = gimple_assign_rhs1 (stmt);
+@@ -6014,7 +6015,7 @@ 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_mode == STRUCT_LAYOUT_OPTIMIZE && f && f->is_safe_func)
+     {
+       tree expr = gimple_call_arg (stmt, 0);
+       tree newexpr[max_split];
+@@ -6141,9 +6142,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_mode != STRUCT_LAYOUT_OPTIMIZE
+        && (rhs_code != EQ_EXPR && rhs_code != NE_EXPR))
+-      || (current_mode == STRUCT_REORDER_FIELDS
++      || (current_mode == STRUCT_LAYOUT_OPTIMIZE
+ 	  && TREE_CODE_CLASS (rhs_code) != tcc_comparison))
+     return false;
+   tree lhs = gimple_cond_lhs (stmt);
+@@ -6171,10 +6172,10 @@ ipa_struct_reorg::rewrite_cond (gcond *stmt, gimple_stmt_iterator *gsi)
+     }
+ 
+   /*  Old rewrite: if (x_1 != 0B)
+-		-> _1 = x.reorder.0_1 != 0B; if (_1 != 1)
++		-> _1 = x.slo.0_1 != 0B; if (_1 != 1)
+ 		   The logic is incorrect.
+       New rewrite: if (x_1 != 0B)
+-		-> if (x.reorder.0_1 != 0B);*/
++		-> if (x.slo.0_1 != 0B);*/
+   for (unsigned i = 0; i < max_split && (newlhs[i] || newrhs[i]); i++)
+     {
+       if (newlhs[i])
+@@ -6203,7 +6204,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_mode == STRUCT_LAYOUT_OPTIMIZE)
+     {
+       /* Delete debug gimple now.  */
+       return true;
+@@ -6367,7 +6368,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_mode == STRUCT_LAYOUT_OPTIMIZE)
+ 	{
+ 	  for (unsigned i = 0; i < functions.length (); i++)
+ 	    {
+@@ -6386,7 +6387,7 @@ ipa_struct_reorg::rewrite_functions (void)
+       return 0;
+     }
+ 
+-  if (current_mode == STRUCT_REORDER_FIELDS && dump_file)
++  if (current_mode == STRUCT_LAYOUT_OPTIMIZE && dump_file)
+     {
+       fprintf (dump_file, "=========== all created newtypes: ===========\n\n");
+       dump_newtypes (dump_file);
+@@ -6396,13 +6397,13 @@ ipa_struct_reorg::rewrite_functions (void)
+     {
+       retval = TODO_remove_functions;
+       create_new_functions ();
+-      if (current_mode == STRUCT_REORDER_FIELDS)
++      if (current_mode == STRUCT_LAYOUT_OPTIMIZE)
+ 	{
+ 	  prune_escaped_types ();
+ 	}
+     }
+ 
+-  if (current_mode == STRUCT_REORDER_FIELDS)
++  if (current_mode == STRUCT_LAYOUT_OPTIMIZE)
+     {
+       for (unsigned i = 0; i < functions.length (); i++)
+ 	{
+@@ -6572,7 +6573,7 @@ ipa_struct_reorg::execute (enum srmode mode)
+ {
+   unsigned int ret = 0;
+ 
+-  if (mode == NORMAL || mode == STRUCT_REORDER_FIELDS)
++  if (mode == NORMAL || mode == STRUCT_LAYOUT_OPTIMIZE)
+     {
+       current_mode = mode;
+       /* If there is a top-level inline-asm,
+@@ -6660,12 +6661,12 @@ pass_ipa_struct_reorg::gate (function *)
+ 	  && (in_lto_p || flag_whole_program));
+ }
+ 
+-const pass_data pass_data_ipa_reorder_fields =
++const pass_data pass_data_ipa_struct_layout =
+ {
+   SIMPLE_IPA_PASS, // type
+-  "reorder_fields", // name
++  "struct_layout", // name
+   OPTGROUP_NONE, // optinfo_flags
+-  TV_IPA_REORDER_FIELDS, // tv_id
++  TV_IPA_STRUCT_LAYOUT, // tv_id
+   0, // properties_required
+   0, // properties_provided
+   0, // properties_destroyed
+@@ -6673,11 +6674,11 @@ const pass_data pass_data_ipa_reorder_fields =
+   0, // todo_flags_finish
+ };
+ 
+-class pass_ipa_reorder_fields : public simple_ipa_opt_pass
++class pass_ipa_struct_layout : public simple_ipa_opt_pass
+ {
+ public:
+-  pass_ipa_reorder_fields (gcc::context *ctxt)
+-    : simple_ipa_opt_pass (pass_data_ipa_reorder_fields, ctxt)
++  pass_ipa_struct_layout (gcc::context *ctxt)
++    : simple_ipa_opt_pass (pass_data_ipa_struct_layout, ctxt)
+   {}
+ 
+   /* opt_pass methods: */
+@@ -6685,17 +6686,17 @@ public:
+   virtual unsigned int execute (function *)
+   {
+     unsigned int ret = 0;
+-    ret = ipa_struct_reorg ().execute (STRUCT_REORDER_FIELDS);
++    ret = ipa_struct_reorg ().execute (STRUCT_LAYOUT_OPTIMIZE);
+     return ret;
+   }
+ 
+-}; // class pass_ipa_reorder_fields
++}; // class pass_ipa_struct_layout
+ 
+ bool
+-pass_ipa_reorder_fields::gate (function *)
++pass_ipa_struct_layout::gate (function *)
+ {
+   return (optimize >= 3
+-	  && flag_ipa_reorder_fields
++	  && flag_ipa_struct_layout
+ 	  /* Don't bother doing anything if the program has errors.  */
+ 	  && !seen_error ()
+ 	  && flag_lto_partition == LTO_PARTITION_ONE
+@@ -6715,7 +6716,7 @@ make_pass_ipa_struct_reorg (gcc::context *ctxt)
+ }
+ 
+ simple_ipa_opt_pass *
+-make_pass_ipa_reorder_fields (gcc::context *ctxt)
++make_pass_ipa_struct_layout (gcc::context *ctxt)
+ {
+-  return new pass_ipa_reorder_fields (ctxt);
++  return new pass_ipa_struct_layout (ctxt);
+ }
+diff --git a/gcc/ipa-struct-reorg/ipa-struct-reorg.h b/gcc/ipa-struct-reorg/ipa-struct-reorg.h
+index 8fb6ce9c4..54b0dc655 100644
+--- a/gcc/ipa-struct-reorg/ipa-struct-reorg.h
++++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.h
+@@ -187,7 +187,7 @@ struct srfield
+ 			  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],
++  void create_new_optimized_fields (tree newtype[max_split],
+ 				  tree newfields[max_split],
+ 				  tree newlast[max_split]);
+ };
+diff --git a/gcc/opts.c b/gcc/opts.c
+index 479d726df..c3877c24e 100644
+--- a/gcc/opts.c
++++ b/gcc/opts.c
+@@ -2695,6 +2695,18 @@ common_handle_option (struct gcc_options *opts,
+ 	}
+       break;
+ 
++    case OPT_fipa_struct_reorg_:
++      opts->x_struct_layout_optimize_level = value;
++      if (value > 1)
++	{
++	  SET_OPTION_IF_UNSET (opts, opts_set, flag_ipa_struct_layout, value);
++	}
++      /* No break here - do -fipa-struct-reorg processing.  */
++      /* FALLTHRU.  */
++    case OPT_fipa_struct_reorg:
++      opts->x_flag_ipa_struct_reorg = value;
++      break;
++
+     case OPT_fprofile_generate_:
+       opts->x_profile_data_prefix = xstrdup (arg);
+       value = true;
+diff --git a/gcc/passes.def b/gcc/passes.def
+index e9c91d26e..eea4d7808 100644
+--- a/gcc/passes.def
++++ b/gcc/passes.def
+@@ -174,7 +174,7 @@ along with GCC; see the file COPYING3.  If not see
+   INSERT_PASSES_AFTER (all_late_ipa_passes)
+   NEXT_PASS (pass_materialize_all_clones);
+   NEXT_PASS (pass_ipa_pta);
+-  NEXT_PASS (pass_ipa_reorder_fields);
++  NEXT_PASS (pass_ipa_struct_layout);
+   /* FIXME: this should 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 ddf5e3577..f62222a96 100644
+--- a/gcc/symbol-summary.h
++++ b/gcc/symbol-summary.h
+@@ -61,7 +61,7 @@ protected:
+   {
+     /* In structure optimizatons, we call new to ensure that
+        the allocated memory is initialized to 0.  */
+-    if (flag_ipa_reorder_fields || flag_ipa_struct_reorg)
++    if (flag_ipa_struct_layout || 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
+@@ -77,7 +77,7 @@ protected:
+       ggc_delete (item);
+     else
+       {
+-	if (flag_ipa_reorder_fields || flag_ipa_struct_reorg)
++	if (flag_ipa_struct_layout || flag_ipa_struct_reorg)
+ 	  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
+index b95be2dab..882a695b0 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_layout" } } */
+\ 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..20ecee545 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_layout" } } */
+\ 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 a5477dcc9..ad879fc11 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 "No structures to transform." "reorder_fields" } } */
+\ No newline at end of file
++/* { dg-final { scan-ipa-dump "No structures to transform." "struct_layout" } } */
+\ 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..f0c9d8f39 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_layout" } } */
+\ 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..fa5e6c2d0 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_layout" } } */
+\ 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..2966869e7 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_layout" } } */
+\ 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..b74b9e5e9 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_layout" } } */
+\ 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..cf85c6109 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_layout" } } */
+\ 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..61fd9f755 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_layout" } } */
+\ 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..2c115da02 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_layout" } } */
+\ 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..c7646d8b7 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_layout" } } */
+\ 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..01c000375 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_layout" } } */
+\ 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..f962163fe 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_layout" } } */
+\ 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..6558b1797 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_layout" } } */
+\ 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..6d528ed5b 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_layout" } } */
+\ 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..e95cf2e5d 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_layout" } } */
+\ 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..cb4054522 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_layout" } } */
+\ 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..38bddbae5 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_layout" } } */
+\ 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..86034f042 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_layout" } } */
+\ 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..aae7c4bc9 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_layout" } } */
+\ 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..8672e7552 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_layout" } } */
+\ 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..2d67434a0 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_layout" } } */
+\ 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..a8cf2b63c 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_layout" } } */
+\ 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..b6cba3c34 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_layout" } } */
+\ No newline at end of file
+diff --git a/gcc/testsuite/gcc.dg/struct/sr_pointer_minus.c b/gcc/testsuite/gcc.dg/struct/sr_pointer_minus.c
+index 9a82da0d6..a0614a1ba 100644
+--- a/gcc/testsuite/gcc.dg/struct/sr_pointer_minus.c
++++ b/gcc/testsuite/gcc.dg/struct/sr_pointer_minus.c
+@@ -30,4 +30,4 @@ main ()
+   return 0;
+ }
+ 
+-/* { dg-final { scan-ipa-dump "struct node has escaped: \"Type escapes via a unhandled rewrite stmt\"" "struct_reorg" } } */
++/* { dg-final { scan-ipa-dump "has escaped: \"Type escapes via a unhandled rewrite stmt\"" "struct_reorg" } } */
+diff --git a/gcc/testsuite/gcc.dg/struct/struct-reorg.exp b/gcc/testsuite/gcc.dg/struct/struct-reorg.exp
+index c8db4675f..67b3ac2d5 100644
+--- a/gcc/testsuite/gcc.dg/struct/struct-reorg.exp
++++ b/gcc/testsuite/gcc.dg/struct/struct-reorg.exp
+@@ -47,6 +47,25 @@ gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/complete_struct_relayout
+ gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/rf*.c]] \
+ 	"" "-fipa-reorder-fields -fdump-ipa-all -flto-partition=one -fwhole-program"
+ 
++# -fipa-struct-reorg=1
++gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/wo_prof_*.c]] \
++ 	"" "-fipa-struct-reorg=1 -fdump-ipa-all -flto-partition=one -fwhole-program"
++gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/w_ratio_*.c]] \
++	"" "-fipa-struct-reorg=1 -fdump-ipa-all -flto-partition=one -fwhole-program"
++gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/w_prof_*.c]] \
++	"" "-fipa-struct-reorg=1 -fdump-ipa-all -flto-partition=one -fwhole-program"
++gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/struct_reorg*.c]] \
++	"" "-fipa-struct-reorg=1 -fdump-ipa-all -flto-partition=one -fwhole-program"
++gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/sr_*.c]] \
++	"" "-fipa-struct-reorg=1 -fdump-ipa-all -flto-partition=one -fwhole-program"
++gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/csr_*.c]] \
++	"" "-fipa-struct-reorg=1 -fdump-ipa-all -flto-partition=one -fwhole-program"
++gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/complete_struct_relayout.c]] \
++	"" "-fipa-struct-reorg=1 -fdump-ipa-all -flto-partition=one -fwhole-program"
++
++# -fipa-struct-reorg=2
++gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] \
++ 	"" "-fipa-struct-reorg=2 -fdump-ipa-all -flto-partition=one -fwhole-program"
+ # All done.
+ torture-finish
+ dg-finish
+diff --git a/gcc/timevar.def b/gcc/timevar.def
+index e873747a8..b179f62bb 100644
+--- a/gcc/timevar.def
++++ b/gcc/timevar.def
+@@ -80,7 +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_LAYOUT	     , "ipa struct layout optimization")
+ DEFTIMEVAR (TV_IPA_STRUCT_REORG	     , "ipa struct reorg optimization")
+ DEFTIMEVAR (TV_IPA_EXTEND_AUTO_PROFILE, "ipa extend auto profile")
+ DEFTIMEVAR (TV_IPA_OPT		     , "ipa various optimizations")
+diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
+index be6387768..187f1a85c 100644
+--- a/gcc/tree-pass.h
++++ b/gcc/tree-pass.h
+@@ -509,7 +509,7 @@ 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_hsa (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_layout (gcc::context *ctxt);
+ extern simple_ipa_opt_pass *make_pass_ipa_struct_reorg (gcc::context *ctxt);
+ extern simple_ipa_opt_pass *make_pass_ipa_extend_auto_profile (gcc::context
+ 							       *ctxt);
+diff --git a/gcc/tree.c b/gcc/tree.c
+index 89fa469c3..c2075d735 100644
+--- a/gcc/tree.c
++++ b/gcc/tree.c
+@@ -5219,7 +5219,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_reorder_fields || flag_ipa_struct_reorg)
++  if (flag_ipa_struct_layout || flag_ipa_struct_reorg)
+     return TYPE_NAME (type);
+ 
+   if (!TYPE_NAME (type) || TREE_CODE (TYPE_NAME (type)) != TYPE_DECL)
+@@ -5463,7 +5463,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_reorder_fields || flag_ipa_struct_reorg)
++  if (flag_ipa_struct_layout || flag_ipa_struct_reorg)
+     return t;
+   if (POINTER_TYPE_P (t))
+     return fld_incomplete_type_of (t, fld);
+-- 
+2.27.0.windows.1
+
diff --git a/0038-DFE-Add-Dead-Field-Elimination-in-Struct-Reorg.patch b/0038-DFE-Add-Dead-Field-Elimination-in-Struct-Reorg.patch
new file mode 100644
index 0000000..6b913ae
--- /dev/null
+++ b/0038-DFE-Add-Dead-Field-Elimination-in-Struct-Reorg.patch
@@ -0,0 +1,902 @@
+From edd4200e2b3e94d5c124900657b91c22dfe9c557 Mon Sep 17 00:00:00 2001
+From: Mingchuan Wu 
+Date: Wed, 15 Jun 2022 16:00:25 +0800
+Subject: [PATCH 04/12] [DFE] Add Dead Field Elimination in Struct-Reorg.
+
+We can transform gimple to eliminate fields that are never read
+and remove their redundant stmts.
+Also we adapted the partial escape_cast_another_ptr for struct relayout.
+Add flag -fipa-struct-reorg=3 to enable dead field elimination.
+---
+ gcc/common.opt                                |   4 +-
+ gcc/ipa-struct-reorg/ipa-struct-reorg.c       | 209 ++++++++++++++++--
+ gcc/ipa-struct-reorg/ipa-struct-reorg.h       |   9 +-
+ gcc/testsuite/gcc.dg/struct/dfe_DTE_verify.c  |  86 +++++++
+ .../gcc.dg/struct/dfe_ele_minus_verify.c      |  60 +++++
+ .../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  |  21 +-
+ 11 files changed, 639 insertions(+), 19 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_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
+
+diff --git a/gcc/common.opt b/gcc/common.opt
+index 7fc075d35..b5ea3c7a1 100644
+--- a/gcc/common.opt
++++ b/gcc/common.opt
+@@ -1884,8 +1884,8 @@ Common Report 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, 2)
+--fipa-struct-reorg=[0,1,2] adding none, struct-reorg, reorder-fields optimizations.
++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-extend-auto-profile
+ Common Report Var(flag_ipa_extend_auto_profile)
+diff --git a/gcc/ipa-struct-reorg/ipa-struct-reorg.c b/gcc/ipa-struct-reorg/ipa-struct-reorg.c
+index 9214ee74a..2fa560239 100644
+--- a/gcc/ipa-struct-reorg/ipa-struct-reorg.c
++++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.c
+@@ -81,6 +81,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"
+@@ -238,11 +239,44 @@ enum srmode
+   STRUCT_LAYOUT_OPTIMIZE
+ };
+ 
++/* 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,
++  DEAD_FIELD_ELIMINATION
++};
++
+ static bool is_result_of_mult (tree arg, tree *num, tree struct_size);
+ bool isptrptr (tree type);
+ 
+ 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
+ 
+ namespace struct_reorg {
+@@ -318,12 +352,13 @@ srfunction::simple_dump (FILE *file)
+ /* Constructor of FIELD. */
+ 
+ srfield::srfield (tree field, srtype *base)
+-  : offset(int_byte_position (field)),
++  : offset (int_byte_position (field)),
+     fieldtype (TREE_TYPE (field)),
+     fielddecl (field),
+-    base(base),
+-    type(NULL),
+-    clusternum(0)
++    base (base),
++    type (NULL),
++    clusternum (0),
++    field_access (EMPTY_FIELD)
+ {
+   for(int i = 0;i < max_split; i++)
+     newfield[i] = NULL_TREE;
+@@ -362,6 +397,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
+@@ -833,6 +887,10 @@ srtype::create_new_type (void)
+   for (unsigned i = 0; i < fields.length (); i++)
+     {
+       srfield *f = fields[i];
++      if (current_mode == STRUCT_LAYOUT_OPTIMIZE
++	  && struct_layout_optimize_level >= DEAD_FIELD_ELIMINATION
++	  && !(f->field_access & READ_FIELD))
++	continue;
+       f->create_new_fields (newtype, newfields, newlast);
+     }
+ 
+@@ -854,6 +912,16 @@ srtype::create_new_type (void)
+ 
+   warn_padded = save_warn_padded;
+ 
++  if (current_mode == STRUCT_LAYOUT_OPTIMIZE
++      && replace_type_map.get (this->newtype[0]) == NULL)
++    replace_type_map.put (this->newtype[0], this->type);
++  if (dump_file)
++    {
++      if (current_mode == STRUCT_LAYOUT_OPTIMIZE
++	  && 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);
+@@ -1128,12 +1196,12 @@ 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.  */
++     65~127 should pad to 128 but 65~80 (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 > 80 && old_size < 128)
+     {
+       new_size = 128;
+     }
+@@ -1272,6 +1340,7 @@ public:
+   bool has_rewritten_type (srfunction*);
+   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
+@@ -3206,6 +3275,90 @@ ipa_struct_reorg::find_vars (gimple *stmt)
+     }
+ }
+ 
++/* Update field_access in srfield.  */
++
++static void
++update_field_access (tree record, tree field, unsigned access, void *data)
++{
++  srtype *this_srtype = ((ipa_struct_reorg *)data)->find_type (record);
++  if (this_srtype == NULL)
++    return;
++  srfield *this_srfield = this_srtype->find_field (int_byte_position (field));
++  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, record);
++      fprintf (dump_file, "  field:");
++      print_generic_expr (dump_file, field);
++      fprintf (dump_file, "\n");
++    }
++  return;
++}
++
++/* A callback for walk_stmt_load_store_ops to visit store.  */
++
++static bool
++find_field_p_store (gimple *, tree node, tree op, void *data)
++{
++  if (TREE_CODE (op) != COMPONENT_REF)
++    return false;
++  tree node_type = TREE_TYPE (node);
++  if (!handled_type (node_type))
++    return false;
++
++  update_field_access (node_type, TREE_OPERAND (op, 1), WRITE_FIELD, data);
++
++  return false;
++}
++
++/* A callback for walk_stmt_load_store_ops to visit load.  */
++
++static bool
++find_field_p_load (gimple *, tree node, tree op, void *data)
++{
++  if (TREE_CODE (op) != COMPONENT_REF)
++    return false;
++  tree node_type = TREE_TYPE (node);
++  if (!handled_type (node_type))
++    return false;
++
++  update_field_access (node_type, TREE_OPERAND (op, 1), 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
++      && (f->field_access & WRITE_FIELD))
++    return true;
++  return false;
++}
++
+ /* Maybe record access of statement for further analaysis. */
+ 
+ void
+@@ -3227,6 +3380,13 @@ ipa_struct_reorg::maybe_record_stmt (cgraph_node *node, gimple *stmt)
+     default:
+       break;
+     }
++  if (current_mode == STRUCT_LAYOUT_OPTIMIZE
++      && 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.  */
+@@ -3543,8 +3703,11 @@ ipa_struct_reorg::maybe_mark_or_record_other_side (tree side, tree other, gimple
+     }
+   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
+@@ -4131,8 +4294,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))
+ 	    {
+@@ -4142,7 +4306,7 @@ ipa_struct_reorg::check_type_and_push (tree newdecl, srdecl *decl,
+ 	      print_generic_expr (dump_file, TREE_TYPE (newdecl));
+ 	      fprintf (dump_file, "\n");
+ 	    }
+-          type->mark_escape (escape_cast_another_ptr, stmt);
++	  type->mark_escape (escape_cast_another_ptr, stmt);
+ 	  return;
+ 	}
+       /* At this point there should only be unkown void* ssa names. */
+@@ -4465,11 +4629,13 @@ ipa_struct_reorg::check_other_side (srdecl *decl, tree other, gimple *stmt, vec<
+ 
+       return;
+     }
++  if (!is_replace_type (t1->type, type->type))
++    {
++      if (t1)
++	t1->mark_escape (escape_cast_another_ptr, stmt);
+ 
+-  if (t1)
+-    t1->mark_escape (escape_cast_another_ptr, stmt);
+-
+-  type->mark_escape (escape_cast_another_ptr, stmt);
++      type->mark_escape (escape_cast_another_ptr, stmt);
++    }
+ }
+ 
+ 
+@@ -5722,6 +5888,19 @@ bool
+ ipa_struct_reorg::rewrite_assign (gassign *stmt, gimple_stmt_iterator *gsi)
+ {
+   bool remove = false;
++
++  if (current_mode == STRUCT_LAYOUT_OPTIMIZE
++      && 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);
++	}
++      return true;
++    }
++
+   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 54b0dc655..936c0fa6f 100644
+--- a/gcc/ipa-struct-reorg/ipa-struct-reorg.h
++++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.h
+@@ -142,6 +142,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)
+   {
+@@ -163,6 +164,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;
+@@ -174,7 +181,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/testsuite/gcc.dg/struct/dfe_DTE_verify.c b/gcc/testsuite/gcc.dg/struct/dfe_DTE_verify.c
+new file mode 100644
+index 000000000..4261d2352
+--- /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 "struct_layout" } } */
+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..42d38c63a
+--- /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 "struct_layout" } } */
+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..53583fe82
+--- /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 "struct_layout" } } */
+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..fd675ec2e
+--- /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 "struct_layout" } } */
+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..600e7908b
+--- /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 "struct_layout" } } */
+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..f411364a7
+--- /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 "struct_layout" } } */
+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..a4e723763
+--- /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 "struct_layout" } } */
+diff --git a/gcc/testsuite/gcc.dg/struct/struct-reorg.exp b/gcc/testsuite/gcc.dg/struct/struct-reorg.exp
+index 67b3ac2d5..ac5585813 100644
+--- a/gcc/testsuite/gcc.dg/struct/struct-reorg.exp
++++ b/gcc/testsuite/gcc.dg/struct/struct-reorg.exp
+@@ -64,8 +64,27 @@ gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/complete_struct_relayout
+ 	"" "-fipa-struct-reorg=1 -fdump-ipa-all -flto-partition=one -fwhole-program"
+ 
+ # -fipa-struct-reorg=2
+-gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] \
++gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/rf*.c]] \
++ 	"" "-fipa-struct-reorg=2 -fdump-ipa-all -flto-partition=one -fwhole-program"
++gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/wo_prof_*.c]] \
+  	"" "-fipa-struct-reorg=2 -fdump-ipa-all -flto-partition=one -fwhole-program"
++gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/w_ratio_*.c]] \
++	"" "-fipa-struct-reorg=2 -fdump-ipa-all -flto-partition=one -fwhole-program"
++gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/w_prof_*.c]] \
++	"" "-fipa-struct-reorg=2 -fdump-ipa-all -flto-partition=one -fwhole-program"
++gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/struct_reorg*.c]] \
++	"" "-fipa-struct-reorg=2 -fdump-ipa-all -flto-partition=one -fwhole-program"
++gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/sr_*.c]] \
++	"" "-fipa-struct-reorg=2 -fdump-ipa-all -flto-partition=one -fwhole-program"
++gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/csr_*.c]] \
++	"" "-fipa-struct-reorg=2 -fdump-ipa-all -flto-partition=one -fwhole-program"
++gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/complete_struct_relayout.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"
++
+ # All done.
+ torture-finish
+ dg-finish
+-- 
+2.27.0.windows.1
+
diff --git a/0039-Backport-ipa-sra-Fix-thinko-when-overriding-safe_to_.patch b/0039-Backport-ipa-sra-Fix-thinko-when-overriding-safe_to_.patch
new file mode 100644
index 0000000..d63a8ef
--- /dev/null
+++ b/0039-Backport-ipa-sra-Fix-thinko-when-overriding-safe_to_.patch
@@ -0,0 +1,143 @@
+From d8753de2129d230afc9a887d5804747c69824a68 Mon Sep 17 00:00:00 2001
+From: zhaowenyu <804544223@qq.com>
+Date: Mon, 20 Jun 2022 11:24:45 +0800
+Subject: [PATCH 05/12] [Backport] ipa-sra: Fix thinko when overriding
+ safe_to_import_accesses (PR 101066)
+
+Reference: https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=5aa28c8cf15cd254cc5a3a12278133b93b8b017f
+
+ipa-sra: Fix thinko when overriding safe_to_import_accesses (PR 101066)
+
+The "new" IPA-SRA has a more difficult job than the previous
+not-truly-IPA version when identifying situations in which a parameter
+passed by reference can be passed into a third function and only thee
+converted to one passed by value (and possibly "split" at the same
+time).
+
+In order to allow this, two conditions must be fulfilled.  First the
+call to the third function must happen before any modifications of
+memory, because it could change the value passed by reference.
+Second, in order to make sure we do not introduce new (invalid)
+dereferences, the call must postdominate the entry BB.
+
+The second condition is actually not necessary if the caller function
+is also certain to dereference the pointer but the first one must
+still hold.  Unfortunately, the code making this overriding decision
+also happen to trigger when the first condition is not fulfilled.
+This is fixed in the following patch.
+
+gcc/ChangeLog:
+
+2021-06-16  Martin Jambor  
+
+(cherry picked from commit 763121ccd908f52bc666f277ea2cf42110b3aad9)
+---
+ gcc/ipa-sra.c                       | 15 +++++++++++++--
+ gcc/testsuite/gcc.dg/ipa/pr101066.c | 20 ++++++++++++++++++++
+ 2 files changed, 33 insertions(+), 2 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.dg/ipa/pr101066.c
+
+diff --git a/gcc/ipa-sra.c b/gcc/ipa-sra.c
+index b706fceff..1cb30afc3 100644
+--- a/gcc/ipa-sra.c
++++ b/gcc/ipa-sra.c
+@@ -340,7 +340,7 @@ class isra_call_summary
+ public:
+   isra_call_summary ()
+     : m_arg_flow (), m_return_ignored (false), m_return_returned (false),
+-      m_bit_aligned_arg (false)
++      m_bit_aligned_arg (false), m_before_any_store (false)
+   {}
+ 
+   void init_inputs (unsigned arg_count);
+@@ -359,6 +359,10 @@ public:
+ 
+   /* Set when any of the call arguments are not byte-aligned.  */
+   unsigned m_bit_aligned_arg : 1;
++
++  /* Set to true if the call happend before any (other) store to memory in the
++     caller.  */
++  unsigned m_before_any_store : 1;
+ };
+ 
+ /* Class to manage function summaries.  */
+@@ -472,6 +476,8 @@ isra_call_summary::dump (FILE *f)
+     fprintf (f, "    return value ignored\n");
+   if (m_return_returned)
+     fprintf (f, "    return value used only to compute caller return value\n");
++  if (m_before_any_store)
++    fprintf (f, "    happens before any store to memory\n");
+   for (unsigned i = 0; i < m_arg_flow.length (); i++)
+     {
+       fprintf (f, "    Parameter %u:\n", i);
+@@ -516,6 +522,7 @@ ipa_sra_call_summaries::duplicate (cgraph_edge *, cgraph_edge *,
+   new_sum->m_return_ignored = old_sum->m_return_ignored;
+   new_sum->m_return_returned = old_sum->m_return_returned;
+   new_sum->m_bit_aligned_arg = old_sum->m_bit_aligned_arg;
++  new_sum->m_before_any_store = old_sum->m_before_any_store;
+ }
+ 
+ 
+@@ -2355,6 +2362,7 @@ process_scan_results (cgraph_node *node, struct function *fun,
+ 	unsigned count = gimple_call_num_args (call_stmt);
+ 	isra_call_summary *csum = call_sums->get_create (cs);
+ 	csum->init_inputs (count);
++	csum->m_before_any_store = uses_memory_as_obtained;
+ 	for (unsigned argidx = 0; argidx < count; argidx++)
+ 	  {
+ 	    if (!csum->m_arg_flow[argidx].pointer_pass_through)
+@@ -2601,6 +2609,7 @@ isra_write_edge_summary (output_block *ob, cgraph_edge *e)
+   bp_pack_value (&bp, csum->m_return_ignored, 1);
+   bp_pack_value (&bp, csum->m_return_returned, 1);
+   bp_pack_value (&bp, csum->m_bit_aligned_arg, 1);
++  bp_pack_value (&bp, csum->m_before_any_store, 1);
+   streamer_write_bitpack (&bp);
+ }
+ 
+@@ -2719,6 +2728,7 @@ isra_read_edge_summary (struct lto_input_block *ib, cgraph_edge *cs)
+   csum->m_return_ignored = bp_unpack_value (&bp, 1);
+   csum->m_return_returned = bp_unpack_value (&bp, 1);
+   csum->m_bit_aligned_arg = bp_unpack_value (&bp, 1);
++  csum->m_before_any_store = bp_unpack_value (&bp, 1);
+ }
+ 
+ /* Read intraprocedural analysis information about NODE and all of its outgoing
+@@ -3475,7 +3485,8 @@ param_splitting_across_edge (cgraph_edge *cs)
+ 	    }
+ 	  else if (!ipf->safe_to_import_accesses)
+ 	    {
+-	      if (!all_callee_accesses_present_p (param_desc, arg_desc))
++	      if (!csum->m_before_any_store
++		  || !all_callee_accesses_present_p (param_desc, arg_desc))
+ 		{
+ 		  if (dump_file && (dump_flags & TDF_DETAILS))
+ 		    fprintf (dump_file, "  %u->%u: cannot import accesses.\n",
+diff --git a/gcc/testsuite/gcc.dg/ipa/pr101066.c b/gcc/testsuite/gcc.dg/ipa/pr101066.c
+new file mode 100644
+index 000000000..1ceb6e431
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/ipa/pr101066.c
+@@ -0,0 +1,20 @@
++/* { dg-do run } */
++/* { dg-options "-Os -fno-ipa-cp -fno-inline" } */
++
++int a = 1, c, d, e;
++int *b = &a;
++static int g(int *h) {
++  c = *h;
++  return d;
++}
++static void f(int *h) {
++  e = *h;
++  *b = 0;
++  g(h);
++}
++int main() {
++  f(b);
++  if (c)
++    __builtin_abort();
++  return 0;
++}
+-- 
+2.27.0.windows.1
+
diff --git a/0040-Backport-ifcvt-Allow-constants-for-noce_convert_mult.patch b/0040-Backport-ifcvt-Allow-constants-for-noce_convert_mult.patch
new file mode 100644
index 0000000..23e3b89
--- /dev/null
+++ b/0040-Backport-ifcvt-Allow-constants-for-noce_convert_mult.patch
@@ -0,0 +1,59 @@
+From ea059ab02ac79eba1c05d6e05cbb2590c47d7c1f Mon Sep 17 00:00:00 2001
+From: zhaowenyu <804544223@qq.com>
+Date: Thu, 23 Jun 2022 10:16:08 +0800
+Subject: [PATCH 06/12] [Backport] ifcvt: Allow constants for
+ noce_convert_multiple.
+
+Reference: https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=9b8eaa282250ad260e01d164093b597579db00d9
+
+This lifts the restriction of not allowing constants for noce_convert_multiple.
+The code later checks if a valid sequence is produced anyway.
+gcc/ChangeLog:
+
+        * ifcvt.cc (noce_convert_multiple_sets): Allow constants.
+         (bb_ok_for_noce_convert_multiple_sets): Likewise.
+---
+ gcc/ifcvt.c | 13 ++++++++-----
+ 1 file changed, 8 insertions(+), 5 deletions(-)
+
+diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c
+index 977dd1bd4..2452f231c 100644
+--- a/gcc/ifcvt.c
++++ b/gcc/ifcvt.c
+@@ -3252,7 +3252,9 @@ noce_convert_multiple_sets (struct noce_if_info *if_info)
+ 	 we'll end up trying to emit r4:HI = cond ? (r1:SI) : (r3:HI).
+ 	 Wrap the two cmove operands into subregs if appropriate to prevent
+ 	 that.  */
+-      if (GET_MODE (new_val) != GET_MODE (temp))
++
++      if (!CONSTANT_P (new_val)
++	  && GET_MODE (new_val) != GET_MODE (temp))
+ 	{
+ 	  machine_mode src_mode = GET_MODE (new_val);
+ 	  machine_mode dst_mode = GET_MODE (temp);
+@@ -3263,7 +3265,8 @@ noce_convert_multiple_sets (struct noce_if_info *if_info)
+ 	    }
+ 	  new_val = lowpart_subreg (dst_mode, new_val, src_mode);
+ 	}
+-      if (GET_MODE (old_val) != GET_MODE (temp))
++      if (!CONSTANT_P (old_val)
++	  && GET_MODE (old_val) != GET_MODE (temp))
+ 	{
+ 	  machine_mode src_mode = GET_MODE (old_val);
+ 	  machine_mode dst_mode = GET_MODE (temp);
+@@ -3392,9 +3395,9 @@ bb_ok_for_noce_convert_multiple_sets (basic_block test_bb)
+       if (!REG_P (dest))
+ 	return false;
+ 
+-      if (!(REG_P (src)
+-	   || (GET_CODE (src) == SUBREG && REG_P (SUBREG_REG (src))
+-	       && subreg_lowpart_p (src))))
++      if (!((REG_P (src) || CONSTANT_P (src))
++	    || (GET_CODE (src) == SUBREG && REG_P (SUBREG_REG (src))
++	      && subreg_lowpart_p (src))))
+ 	return false;
+ 
+       /* Destination must be appropriate for a conditional write.  */
+-- 
+2.27.0.windows.1
+
diff --git a/0041-Backport-Register-sysroot-in-the-driver-switches-tab.patch b/0041-Backport-Register-sysroot-in-the-driver-switches-tab.patch
new file mode 100644
index 0000000..441b5c5
--- /dev/null
+++ b/0041-Backport-Register-sysroot-in-the-driver-switches-tab.patch
@@ -0,0 +1,40 @@
+From beeb0fb50c7e40ee3d79044abc6408f760d6584a Mon Sep 17 00:00:00 2001
+From: zhaowenyu <804544223@qq.com>
+Date: Thu, 23 Jun 2022 10:40:46 +0800
+Subject: [PATCH 07/12] [Backport] Register --sysroot in the driver switches
+ table
+
+Reference: https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=48e2d9b7b88dabed336cd098cd212d0e53c5125f
+
+This change adjusts the processing of --sysroot to save the option in the internal "switches"
+array, which lets self-specs test for it and provide a default value possibly dependent on
+environment variables, as in
+
+ --with-specs=%{!-sysroot*:--sysroot=%:getenv("WIND_BASE" /target)}
+
+2021-12-20  Olivier Hainque  
+
+  gcc/
+         * gcc.c (driver_handle_option): do_save --sysroot.
+---
+ gcc/gcc.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/gcc/gcc.c b/gcc/gcc.c
+index b55075b14..655beffcc 100644
+--- a/gcc/gcc.c
++++ b/gcc/gcc.c
+@@ -4190,7 +4190,9 @@ driver_handle_option (struct gcc_options *opts,
+     case OPT__sysroot_:
+       target_system_root = arg;
+       target_system_root_changed = 1;
+-      do_save = false;
++      /* Saving this option is useful to let self-specs decide to
++	 provide a default one.  */
++      do_save = true;
+       break;
+ 
+     case OPT_time_:
+-- 
+2.27.0.windows.1
+
diff --git a/0042-DFE-Fix-bugs.patch b/0042-DFE-Fix-bugs.patch
new file mode 100644
index 0000000..5801558
--- /dev/null
+++ b/0042-DFE-Fix-bugs.patch
@@ -0,0 +1,665 @@
+From f8308a2b440efe124cd6ff59924f135e85e53888 Mon Sep 17 00:00:00 2001
+From: Mingchuan Wu 
+Date: Sat, 18 Jun 2022 17:51:04 +0800
+Subject: [PATCH 08/12] [DFE] Fix bugs
+
+Fix bugs:
+1. Fixed a bug in check replace type.
+2. Use new to update field access for ref.
+3. We now replace the dead fields in stmt by creating a new ssa.
+4. The replaced type is no longer optimized in NORMAL mode.
+
+Also we added 5 dejaGNU test cases.
+---
+ gcc/ipa-struct-reorg/ipa-struct-reorg.c       |  77 ++++++---
+ 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_tcp_usrreq.c       |  58 +++++++
+ .../gcc.dg/struct/dfe_extr_ui_main.c          |  61 +++++++
+ 6 files changed, 516 insertions(+), 24 deletions(-)
+ 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_tcp_usrreq.c
+ create mode 100644 gcc/testsuite/gcc.dg/struct/dfe_extr_ui_main.c
+
+diff --git a/gcc/ipa-struct-reorg/ipa-struct-reorg.c b/gcc/ipa-struct-reorg/ipa-struct-reorg.c
+index 2fa560239..00dc4bf1d 100644
+--- a/gcc/ipa-struct-reorg/ipa-struct-reorg.c
++++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.c
+@@ -252,6 +252,7 @@ enum struct_layout_opt_level
+ 
+ static bool is_result_of_mult (tree arg, tree *num, tree struct_size);
+ bool isptrptr (tree type);
++void get_base (tree &base, tree expr);
+ 
+ srmode current_mode;
+ 
+@@ -631,7 +632,15 @@ 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;
++    {
++      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)
+@@ -3278,12 +3287,33 @@ ipa_struct_reorg::find_vars (gimple *stmt)
+ /* Update field_access in srfield.  */
+ 
+ static void
+-update_field_access (tree record, tree field, unsigned access, void *data)
++update_field_access (tree node, tree op, unsigned access, void *data)
+ {
+-  srtype *this_srtype = ((ipa_struct_reorg *)data)->find_type (record);
++  HOST_WIDE_INT offset = 0;
++  switch (TREE_CODE (op))
++    {
++      case COMPONENT_REF:
++	{
++	  offset = int_byte_position (TREE_OPERAND (op, 1));
++	  break;
++	}
++      case MEM_REF:
++	{
++	  offset = tree_to_uhwi (TREE_OPERAND (op, 1));
++	  break;
++	}
++      default:
++	return;
++    }
++  tree base = node;
++  get_base (base, node);
++  srdecl *this_srdecl = ((ipa_struct_reorg *)data)->find_decl (base);
++  if (this_srdecl == NULL)
++    return;
++  srtype *this_srtype = this_srdecl->type;
+   if (this_srtype == NULL)
+     return;
+-  srfield *this_srfield = this_srtype->find_field (int_byte_position (field));
++  srfield *this_srfield = this_srtype->find_field (offset);
+   if (this_srfield == NULL)
+     return;
+ 
+@@ -3291,9 +3321,9 @@ update_field_access (tree record, tree field, unsigned access, void *data)
+   if (dump_file && (dump_flags & TDF_DETAILS))
+     {
+       fprintf (dump_file, "record field access %d:", access);
+-      print_generic_expr (dump_file, record);
++      print_generic_expr (dump_file, this_srtype->type);
+       fprintf (dump_file, "  field:");
+-      print_generic_expr (dump_file, field);
++      print_generic_expr (dump_file, this_srfield->fielddecl);
+       fprintf (dump_file, "\n");
+     }
+   return;
+@@ -3302,15 +3332,10 @@ update_field_access (tree record, tree field, unsigned access, void *data)
+ /* A callback for walk_stmt_load_store_ops to visit store.  */
+ 
+ static bool
+-find_field_p_store (gimple *, tree node, tree op, void *data)
++find_field_p_store (gimple *stmt ATTRIBUTE_UNUSED,
++		    tree node, tree op, void *data)
+ {
+-  if (TREE_CODE (op) != COMPONENT_REF)
+-    return false;
+-  tree node_type = TREE_TYPE (node);
+-  if (!handled_type (node_type))
+-    return false;
+-
+-  update_field_access (node_type, TREE_OPERAND (op, 1), WRITE_FIELD, data);
++  update_field_access (node, op, WRITE_FIELD, data);
+ 
+   return false;
+ }
+@@ -3318,15 +3343,10 @@ find_field_p_store (gimple *, tree node, tree op, void *data)
+ /* A callback for walk_stmt_load_store_ops to visit load.  */
+ 
+ static bool
+-find_field_p_load (gimple *, tree node, tree op, void *data)
++find_field_p_load (gimple *stmt ATTRIBUTE_UNUSED,
++		   tree node, tree op, void *data)
+ {
+-  if (TREE_CODE (op) != COMPONENT_REF)
+-    return false;
+-  tree node_type = TREE_TYPE (node);
+-  if (!handled_type (node_type))
+-    return false;
+-
+-  update_field_access (node_type, TREE_OPERAND (op, 1), READ_FIELD, data);
++  update_field_access (node, op, READ_FIELD, data);
+ 
+   return false;
+ }
+@@ -4629,7 +4649,7 @@ ipa_struct_reorg::check_other_side (srdecl *decl, tree other, gimple *stmt, vec<
+ 
+       return;
+     }
+-  if (!is_replace_type (t1->type, type->type))
++  if (!is_replace_type (inner_type (t), type->type))
+     {
+       if (t1)
+ 	t1->mark_escape (escape_cast_another_ptr, stmt);
+@@ -5898,7 +5918,16 @@ ipa_struct_reorg::rewrite_assign (gassign *stmt, gimple_stmt_iterator *gsi)
+ 	  fprintf (dump_file, "\n rewriting statement (remove): \n");
+ 	  print_gimple_stmt (dump_file, stmt, 0);
+ 	}
+-      return true;
++      /* 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);
++	}
++      return false;
+     }
+ 
+   if (gimple_clobber_p (stmt))
+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..13a226ee8
+--- /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 "struct_layout" } } */
+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..1fff2cb9d
+--- /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 "struct_layout" } } */
+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..0f577667c
+--- /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 "struct_layout" } } */
+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..5570c762e
+--- /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 "struct_layout" } } */
+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..50ab9cc24
+--- /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 "struct_layout" } } */
+-- 
+2.27.0.windows.1
+
diff --git a/0045-Transposed-SLP-Enable-Transposed-SLP.patch b/0045-Transposed-SLP-Enable-Transposed-SLP.patch
new file mode 100644
index 0000000..6323e8d
--- /dev/null
+++ b/0045-Transposed-SLP-Enable-Transposed-SLP.patch
@@ -0,0 +1,3009 @@
+From 639b5248cbab1806618545fc30215ed9d1a019e7 Mon Sep 17 00:00:00 2001
+From: luohailing 
+Date: Fri, 17 Jun 2022 22:38:55 +0800
+Subject: [PATCH 11/12] [Transposed SLP] Enable Transposed SLP     Enable
+ Transposed SLP when memory is uncontinual     with
+ -ftree-slp-transpose-vectorize.
+
+---
+ 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 |   73 ++
+ 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-vect-data-refs.c               |  236 +++++
+ gcc/tree-vect-slp.c                     | 1090 ++++++++++++++++++++++-
+ gcc/tree-vect-stmts.c                   |  763 +++++++++++++++-
+ gcc/tree-vectorizer.h                   |   89 ++
+ 14 files changed, 2641 insertions(+), 4 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 24834cf60..d38401b71 100644
+--- a/gcc/common.opt
++++ b/gcc/common.opt
+@@ -3049,6 +3049,10 @@ ftree-vect-analyze-slp-group
+ Common Report Var(flag_tree_slp_group) Init(0)
+ Disable SLP vectorization for reduction chain on tree.
+ 
++ftree-slp-transpose-vectorize
++Common Report 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]	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..b01a0410e
+--- /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" } */
++/* { 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..529581c59
+--- /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" } */
++/* { 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..81a248840
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/vect/transpose-5.c
+@@ -0,0 +1,73 @@
++/* { dg-do compile { target { aarch64*-*-linux* } } } */
++/* { 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..2074d9aa8
+--- /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" } */
++/* { 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 efe17ac6f..d92e1ba5b 100644
+--- a/gcc/testsuite/gcc.dg/vect/vect.exp
++++ b/gcc/testsuite/gcc.dg/vect/vect.exp
+@@ -114,6 +114,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-vect-data-refs.c b/gcc/tree-vect-data-refs.c
+index fcc0726bd..d78b06455 100644
+--- a/gcc/tree-vect-data-refs.c
++++ b/gcc/tree-vect-data-refs.c
+@@ -2647,6 +2647,9 @@ vect_analyze_group_access_1 (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,
+@@ -2676,6 +2679,20 @@ vect_analyze_group_access_1 (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)
+@@ -5413,6 +5430,225 @@ vect_permute_store_chain (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 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 (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 (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-slp.c b/gcc/tree-vect-slp.c
+index 476b32370..d30463b96 100644
+--- a/gcc/tree-vect-slp.c
++++ b/gcc/tree-vect-slp.c
+@@ -2414,11 +2414,13 @@ vect_analyze_slp_instance (vec_info *vinfo,
+ 
+   /* For basic block SLP, try to break the group up into multiples of the
+      vector size.  */
++  bb_vec_info bb_vinfo = dyn_cast  (vinfo);
+   unsigned HOST_WIDE_INT const_nunits;
+   if (is_a  (vinfo)
+       && STMT_VINFO_GROUPED_ACCESS (stmt_info)
+       && DR_GROUP_FIRST_ELEMENT (stmt_info)
+-      && nunits.is_constant (&const_nunits))
++      && nunits.is_constant (&const_nunits)
++      && !bb_vinfo->transposed)
+     {
+       /* We consider breaking the group only on VF boundaries from the existing
+ 	 start.  */
+@@ -2455,6 +2457,898 @@ vect_analyze_slp_instance (vec_info *vinfo,
+   return false;
+ }
+ 
++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;
++}
++
++/* 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 current_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))
++	{
++	  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)
++{
++  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);
++	  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;
++    }
++  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 (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);
++      enum dr_alignment_support supportable_dr_alignment
++	= vect_supportable_dr_alignment (first_dr_info, false);
++      if (supportable_dr_alignment == dr_explicit_realign_optimized
++	  || supportable_dr_alignment == dr_explicit_realign)
++	{
++	  return false;
++	}
++    }
++  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)
++    {
++      if (STMT_VINFO_GROUPED_ACCESS (first_element))
++	{
++	  DR_GROUP_SLP_TRANSPOSE (first_element) = false;
++	}
++    }
++  FOR_EACH_VEC_ELT (bb_vinfo->grouped_loads, k, first_element)
++    {
++      if (STMT_VINFO_GROUPED_ACCESS (first_element))
++	{
++	  DR_GROUP_SLP_TRANSPOSE (first_element) = false;
++	}
++    }
++}
++
++/* 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))
++    {
++      return false;
++    }
++
++  /* 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))
++    {
++      if (dump_enabled_p ())
++	{
++	  dump_printf_loc (MSG_NOTE, vect_location,
++			   "Analysis succeeded with SLP transposed.\n");
++	}
++      return true;
++    }
++  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
+    trees of packed scalar stmts if SLP is possible.  */
+@@ -3124,7 +4018,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: \n");
+       dump_printf (MSG_NOTE, "  Vector inside of basic block cost: %d\n",
+@@ -3239,6 +4137,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;
++
+   /* Check the SLP opportunities in the basic block, analyze and build SLP
+      trees.  */
+   if (!vect_analyze_slp (bb_vinfo, n_stmts))
+@@ -3254,6 +4168,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;
++    }
++
+   vect_record_base_alignments (bb_vinfo);
+ 
+   /* Analyze and verify the alignment of data references and the
+@@ -3286,6 +4214,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 (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 ())
+@@ -3311,6 +4260,83 @@ vect_slp_analyze_bb_1 (bb_vec_info bb_vinfo, int n_stmts, bool &fatal)
+   return true;
+ }
+ 
++static bool
++may_new_transpose_bbvinfo (bb_vec_info bb_vinfo_ori, bool res_ori)
++{
++  /* 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))
++    {
++      vect_bb_vectorization_profitable_p (bb_vinfo_ori);
++    }
++  /* 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)
++{
++  /* 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))
++    {
++      vect_bb_vectorization_profitable_p (bb_vinfo_trans);
++    }
++  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;
++}
++
+ /* Subroutine of vect_slp_bb.  Try to vectorize the statements between
+    REGION_BEGIN (inclusive) and REGION_END (exclusive), returning true
+    on success.  The region has N_STMTS statements and has the datarefs
+@@ -3323,6 +4349,7 @@ vect_slp_bb_region (gimple_stmt_iterator region_begin,
+ 		    unsigned int n_stmts)
+ {
+   bb_vec_info bb_vinfo;
++  bb_vec_info bb_vinfo_trans = NULL;
+   auto_vector_modes vector_modes;
+ 
+   /* Autodetect first vector size we try.  */
+@@ -3337,6 +4364,10 @@ vect_slp_bb_region (gimple_stmt_iterator region_begin,
+     {
+       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 (region_begin, region_end, &shared);
+ 
+       bool first_time_p = shared.datarefs.is_empty ();
+@@ -3346,8 +4377,57 @@ vect_slp_bb_region (gimple_stmt_iterator region_begin,
+       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);
++      /* Analyze and new a transposed bb_vinfo.  */
++      if (may_new_transpose_bbvinfo (bb_vinfo, res_bb_vinfo_ori))
++	{
++	  bool fatal_trans = false;
++	  bb_vinfo_trans
++	    = new _bb_vec_info (region_begin, region_end, &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);
++	  if (may_choose_transpose_bbvinfo (bb_vinfo_trans,
++					   res_bb_vinfo_trans,
++					   bb_vinfo, res_bb_vinfo_ori))
++	    {
++	      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 "
++				   "using original version.\n");
++		}
++	    }
++	}
+ 
+-      if (vect_slp_analyze_bb_1 (bb_vinfo, n_stmts, fatal)
++      if ((res_bb_vinfo_ori || res_bb_vinfo_trans)
+ 	  && dbg_cnt (vect_slp))
+ 	{
+ 	  if (dump_enabled_p ())
+@@ -3400,6 +4480,10 @@ vect_slp_bb_region (gimple_stmt_iterator region_begin,
+ 	  }
+ 
+       delete bb_vinfo;
++      if (bb_vinfo_trans)
++	{
++	  bb_vinfo_trans = NULL;
++	}
+ 
+       if (mode_i < vector_modes.length ()
+ 	  && VECTOR_MODE_P (autodetected_vector_mode)
+diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
+index 6418edb52..b872cfc8d 100644
+--- a/gcc/tree-vect-stmts.c
++++ b/gcc/tree-vect-stmts.c
+@@ -7329,6 +7329,153 @@ vectorizable_scan_store (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
+   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 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 (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 (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 (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 (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 (dr_vec_info *cur_first_dr_info,
++		     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))
++    {
++      return misalign;
++    }
++  else if (DR_MISALIGNMENT (cur_first_dr_info) == -1)
++    {
++      align = dr_alignment (vect_dr_behavior (cur_first_dr_info));
++    }
++  else
++    {
++      misalign = DR_MISALIGNMENT (cur_first_dr_info);
++    }
++  return misalign;
++}
++
++static stmt_vec_info
++add_new_stmt_vect_store (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 (cur_first_dr_info, 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))
++    {
++      ;
++    }
++  else if (DR_MISALIGNMENT (cur_first_dr_info) == -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);
++  stmt_vec_info new_stmt_info
++		= vect_finish_stmt_generation (stmt_info, new_stmt, gsi);
++  return new_stmt_info;
++}
+ 
+ /* Function vectorizable_store.
+ 
+@@ -8208,6 +8355,16 @@ vectorizable_store (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
+ 	  else if (STMT_VINFO_GATHER_SCATTER_P (stmt_info))
+ 	    vect_get_gather_scatter_ops (loop, stmt_info, &gs_info,
+ 					 &dataref_ptr, &vec_offset);
++	  /* 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 (first_stmt_info, aggr_type,
+@@ -8299,6 +8456,75 @@ vectorizable_store (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
+ 	}
+       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 (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 (
++				 first_stmt_b, aggr_type,
++				 simd_lane_access_p ? loop : NULL,
++				 offset, &dummy, gsi, &ptr_incr,
++				 simd_lane_access_p, NULL_TREE, 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 (dataref_ptr, ptr_incr,
++							 gsi, first_stmt_b,
++							 bump);
++			}
++		      new_stmt_info = add_new_stmt_vect_store (
++					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_info = NULL;
+ 	  if (grouped_store)
+ 	    {
+@@ -8557,6 +8783,447 @@ 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 (dr_vec_info *cur_first_dr_info,
++		    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));
++    }
++  else if (DR_MISALIGNMENT (cur_first_dr_info) == -1)
++    {
++      align = dr_alignment (vect_dr_behavior (cur_first_dr_info));
++    }
++  else
++    {
++      misalign = DR_MISALIGNMENT (cur_first_dr_info);
++    }
++  return misalign;
++}
++
++static stmt_vec_info
++add_new_stmt_vect_load (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.  */
++  enum dr_alignment_support alignment_support_scheme
++	= vect_supportable_dr_alignment (cur_first_dr_info, false);
++  unsigned HOST_WIDE_INT align;
++  unsigned int misalign = dr_align_vect_load (cur_first_dr_info, 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 (DR_MISALIGNMENT (cur_first_dr_info) == -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);
++  stmt_vec_info new_stmt_info
++	= vect_finish_stmt_generation (stmt_info, new_stmt, gsi);
++  return new_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);
++      }
++}
++
++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 (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 (stmt_info, vec_inv, lvectype, gsi);
++  vec_info *vinfo = stmt_info->vinfo;
++  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));
++      new_stmt_info = vect_finish_stmt_generation (stmt_info, new_stmt, gsi);
++    }
++  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 (unsigned int ncopies, unsigned int nloads,
++			  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 (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 (
++			 first_stmt_info_b, vectype_info->ltype, NULL,
++			 offset_info->offset, &dummy, gsi, &ptr_incr,
++			 simd_lane_access_p, offset_info->byte_offset, bump);
++
++	  gassign *new_stmt = NULL;
++	  new_stmt_info = add_new_stmt_vect_load (
++			   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 (
++				 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 (unsigned int ncontinues, 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 (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 (
++			 first_stmt_info_b, vectype_info->ltype, NULL,
++			 offset_info->offset, &dummy, gsi, &ptr_incr,
++			 simd_lane_access_p, offset_info->byte_offset, bump);
++	    }
++	  else
++	    {
++	      dataref_ptr = bump_vector_ptr (dataref_ptr, ptr_incr,
++					  gsi, first_stmt_info_b, bump);
++	    }
++	  gassign *new_stmt = NULL;
++	  new_stmt_info = add_new_stmt_vect_load (
++			   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)
+@@ -9364,6 +10031,9 @@ vectorizable_load (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
+   tree vec_mask = NULL_TREE;
+   prev_stmt_info = NULL;
+   poly_uint64 group_elt = 0;
++  unsigned new_group_size = 0;
++  vec new_load_permutation;
++
+   for (j = 0; j < ncopies; j++)
+     {
+       stmt_vec_info new_stmt_info = NULL;
+@@ -9385,6 +10055,15 @@ vectorizable_load (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
+ 	      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
+@@ -9501,6 +10180,63 @@ vectorizable_load (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
+ 	  /* Record that VEC_ARRAY is now dead.  */
+ 	  vect_clobber_variable (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, byte_offset, 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 (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 (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++)
+@@ -9840,7 +10576,32 @@ vectorizable_load (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
+       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 (
++				     slp_node, dr_chain, gsi, vf,
++				     slp_node_instance, 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;
+           if (!vect_transform_slp_perm_load (slp_node, dr_chain, gsi, vf,
+diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
+index f7becb34a..1c4a6c421 100644
+--- a/gcc/tree-vectorizer.h
++++ b/gcc/tree-vectorizer.h
+@@ -297,6 +297,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:
+@@ -335,6 +350,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;
++
+   /* Cost data used by the target cost model.  */
+   void *target_cost_data;
+ 
+@@ -702,6 +725,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
+@@ -764,6 +789,25 @@ public:
+   basic_block bb;
+   gimple_stmt_iterator region_begin;
+   gimple_stmt_iterator region_end;
++
++  /* 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
+@@ -772,6 +816,14 @@ public:
+ #define BB_VINFO_DATAREFS(B)         (B)->shared->datarefs
+ #define BB_VINFO_DDRS(B)             (B)->shared->ddrs
+ #define BB_VINFO_TARGET_COST_DATA(B) (B)->target_cost_data
++#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
+ 
+ static inline bb_vec_info
+ vec_info_for_bb (basic_block bb)
+@@ -1012,6 +1064,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;
+@@ -1019,6 +1082,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;
+@@ -1217,6 +1283,12 @@ STMT_VINFO_BB_VINFO (stmt_vec_info stmt_vinfo)
+ #define STMT_VINFO_REDUC_VECTYPE_IN(S)  (S)->reduc_vectype_in
+ #define STMT_VINFO_SLP_VECT_ONLY(S)     (S)->slp_vect_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) \
+@@ -1227,6 +1299,8 @@ STMT_VINFO_BB_VINFO (stmt_vec_info stmt_vinfo)
+   (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)
+@@ -1624,6 +1698,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.  */
+ 
+@@ -1787,6 +1872,9 @@ extern bool vect_grouped_load_supported (tree, bool, unsigned HOST_WIDE_INT);
+ extern bool vect_load_lanes_supported (tree, unsigned HOST_WIDE_INT, bool);
+ extern void vect_permute_store_chain (vec ,unsigned int, stmt_vec_info,
+                                     gimple_stmt_iterator *, vec *);
++extern void vect_transpose_store_chain (vec, unsigned int, unsigned int,
++					stmt_vec_info, gimple_stmt_iterator *,
++					vec *);
+ extern tree vect_setup_realignment (stmt_vec_info, gimple_stmt_iterator *,
+ 				    tree *, enum dr_alignment_support, tree,
+ 	                            class loop **);
+@@ -1849,6 +1937,7 @@ extern void vect_free_slp_instance (slp_instance, bool);
+ extern bool vect_transform_slp_perm_load (slp_tree, vec ,
+ 					  gimple_stmt_iterator *, poly_uint64,
+ 					  slp_instance, bool, unsigned *);
++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 *);
+ extern opt_result vect_analyze_slp (vec_info *, unsigned);
+-- 
+2.27.0.windows.1
+
diff --git a/0046-ArrayWidenCompare-Add-a-new-optimization-for-array-c.patch b/0046-ArrayWidenCompare-Add-a-new-optimization-for-array-c.patch
new file mode 100644
index 0000000..4a3da78
--- /dev/null
+++ b/0046-ArrayWidenCompare-Add-a-new-optimization-for-array-c.patch
@@ -0,0 +1,1982 @@
+From 8072fe107c04778de78db90bf6fdb7baf474e24a Mon Sep 17 00:00:00 2001
+From: dingguangya 
+Date: Thu, 2 Jun 2022 12:48:17 +0800
+Subject: [PATCH 12/12] [ArrayWidenCompare] 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.c       | 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.c
+
+diff --git a/gcc/Makefile.in b/gcc/Makefile.in
+index 23394c64b..2b2bf474a 100644
+--- a/gcc/Makefile.in
++++ b/gcc/Makefile.in
+@@ -1591,6 +1591,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 24834cf60..2985a5791 100644
+--- a/gcc/common.opt
++++ b/gcc/common.opt
+@@ -1060,6 +1060,11 @@ fasynchronous-unwind-tables
+ Common Report Var(flag_asynchronous_unwind_tables) Optimization
+ Generate unwind tables that are exact at each instruction boundary.
+ 
++farray-widen-compare
++Common Report 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 Report 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 4b0fd2ffb..44f1f8a2e 100644
+--- a/gcc/doc/invoke.texi
++++ b/gcc/doc/invoke.texi
+@@ -459,7 +459,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
+@@ -9710,6 +9710,17 @@ This pass is always skipped on architectures that do not have
+ instructions to support this.  Enabled by default at @option{-O} 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 e9c91d26e..797b803ca 100644
+--- a/gcc/passes.def
++++ b/gcc/passes.def
+@@ -91,6 +91,7 @@ along with GCC; see the file COPYING3.  If not see
+           NEXT_PASS (pass_dse);
+ 	  NEXT_PASS (pass_cd_dce);
+ 	  NEXT_PASS (pass_phiopt, true /* early_p */);
++	  NEXT_PASS (pass_array_widen_compare);
+ 	  NEXT_PASS (pass_tail_recursion);
+ 	  NEXT_PASS (pass_convert_switch);
+ 	  NEXT_PASS (pass_cleanup_eh);
+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..27b69b0e9
+--- /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..d102364f2
+--- /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..52dd6b02b
+--- /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..d3185d326
+--- /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..9743dc623
+--- /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..2323d5bf7
+--- /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..33db62fa4
+--- /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..8c96d24a1
+--- /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 e873747a8..6d90bb6e1 100644
+--- a/gcc/timevar.def
++++ b/gcc/timevar.def
+@@ -215,6 +215,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 be6387768..aca0b83f2 100644
+--- a/gcc/tree-pass.h
++++ b/gcc/tree-pass.h
+@@ -436,6 +436,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.c b/gcc/tree-ssa-loop-array-widen-compare.c
+new file mode 100644
+index 000000000..ba51d785d
+--- /dev/null
++++ b/gcc/tree-ssa-loop-array-widen-compare.c
+@@ -0,0 +1,1555 @@
++/* Array widen compare.
++   Copyright (C) 2022-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
++.  */
++
++#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_EACH_LOOP (loop, 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);
++}
+\ No newline at end of file
+-- 
+2.27.0.windows.1
+
diff --git a/0047-DFE-Fix-the-bug-caused-by-inconsistent-types.patch b/0047-DFE-Fix-the-bug-caused-by-inconsistent-types.patch
new file mode 100644
index 0000000..4e6cc86
--- /dev/null
+++ b/0047-DFE-Fix-the-bug-caused-by-inconsistent-types.patch
@@ -0,0 +1,379 @@
+From 8f51c8c83355cb1b69553e582fb512c6e37b71f5 Mon Sep 17 00:00:00 2001
+From: Mingchuan Wu 
+Date: Thu, 18 Aug 2022 17:15:08 +0800
+Subject: [PATCH] [DFE] Fix the bug caused by inconsistent types: 1. Update
+ some functions to fix the bug caused by inconsistent base and node types.
+
+Also we added 3 dejaGNU test cases.
+---
+ gcc/ipa-struct-reorg/ipa-struct-reorg.c       | 57 ++++++++-----
+ .../gcc.dg/struct/dfe_extr_board_init.c       | 77 +++++++++++++++++
+ gcc/testsuite/gcc.dg/struct/dfe_extr_claw.c   | 77 +++++++++++++++++
+ .../gcc.dg/struct/dfe_extr_mv_udc_core.c      | 82 +++++++++++++++++++
+ 4 files changed, 273 insertions(+), 20 deletions(-)
+ 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_mv_udc_core.c
+
+diff --git a/gcc/ipa-struct-reorg/ipa-struct-reorg.c b/gcc/ipa-struct-reorg/ipa-struct-reorg.c
+index 00dc4bf1d..8d3da3540 100644
+--- a/gcc/ipa-struct-reorg/ipa-struct-reorg.c
++++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.c
+@@ -3284,33 +3284,31 @@ ipa_struct_reorg::find_vars (gimple *stmt)
+     }
+ }
+ 
+-/* Update field_access in srfield.  */
+-
+-static void
+-update_field_access (tree node, tree op, unsigned access, void *data)
++static HOST_WIDE_INT
++get_offset (tree op, HOST_WIDE_INT offset)
+ {
+-  HOST_WIDE_INT offset = 0;
+   switch (TREE_CODE (op))
+     {
+       case COMPONENT_REF:
+ 	{
+-	  offset = int_byte_position (TREE_OPERAND (op, 1));
+-	  break;
++	  return int_byte_position (TREE_OPERAND (op, 1));
+ 	}
+       case MEM_REF:
+ 	{
+-	  offset = tree_to_uhwi (TREE_OPERAND (op, 1));
+-	  break;
++	  return tree_to_uhwi (TREE_OPERAND (op, 1));
+ 	}
+       default:
+-	return;
++	return offset;
+     }
+-  tree base = node;
+-  get_base (base, node);
+-  srdecl *this_srdecl = ((ipa_struct_reorg *)data)->find_decl (base);
+-  if (this_srdecl == NULL)
+-    return;
+-  srtype *this_srtype = this_srdecl->type;
++  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);
+@@ -3321,12 +3319,33 @@ update_field_access (tree node, tree op, unsigned access, void *data)
+   if (dump_file && (dump_flags & TDF_DETAILS))
+     {
+       fprintf (dump_file, "record field access %d:", access);
+-      print_generic_expr (dump_file, this_srtype->type);
++      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.  */
+@@ -3373,8 +3392,7 @@ ipa_struct_reorg::remove_dead_field_stmt (tree lhs)
+     return false;
+   if (f == NULL)
+     return false;
+-  if (f->newfield[0] == NULL
+-      && (f->field_access & WRITE_FIELD))
++  if (f->newfield[0] == NULL)
+     return true;
+   return false;
+ }
+@@ -5927,7 +5945,6 @@ ipa_struct_reorg::rewrite_assign (gassign *stmt, gimple_stmt_iterator *gsi)
+ 	  fprintf (dump_file, "To: \n");
+ 	  print_gimple_stmt (dump_file, stmt, 0);
+ 	}
+-      return false;
+     }
+ 
+   if (gimple_clobber_p (stmt))
+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..4e52564b6
+--- /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 "struct_layout" } } */
+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..894e9f460
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/struct/dfe_extr_claw.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_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__((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 "struct_layout" } } */
+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..9801f87f1
+--- /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 "struct_layout" } } */
+-- 
+2.33.0
+
diff --git a/0048-Struct-Reorg-Type-simplify-limitation-when-in-struct.patch b/0048-Struct-Reorg-Type-simplify-limitation-when-in-struct.patch
new file mode 100644
index 0000000..e44de6e
--- /dev/null
+++ b/0048-Struct-Reorg-Type-simplify-limitation-when-in-struct.patch
@@ -0,0 +1,146 @@
+From b66a843505f32685f428c502f1a88e0f681b4acd Mon Sep 17 00:00:00 2001
+From: eastb233 
+Date: Thu, 15 Sep 2022 17:57:00 +0800
+Subject: [PATCH] [Struct Reorg] Type simplify limitation when in structure
+ optimizaiton
+
+When enable structure optimization, we should not simplify
+TYPE NODE. But now we unconditionally skip the simplification
+under structure optimization regardless of whether it takes
+effect. So add the same limitation as the optimization has.
+---
+ gcc/ipa-struct-reorg/ipa-struct-reorg.c | 72 ++++++++++++-------------
+ gcc/tree.c                              | 13 ++++-
+ 2 files changed, 47 insertions(+), 38 deletions(-)
+
+diff --git a/gcc/ipa-struct-reorg/ipa-struct-reorg.c b/gcc/ipa-struct-reorg/ipa-struct-reorg.c
+index 8d3da35400d..54c20ca3f33 100644
+--- a/gcc/ipa-struct-reorg/ipa-struct-reorg.c
++++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.c
+@@ -104,6 +104,42 @@ along with GCC; see the file COPYING3.  If not see
+ 
+ #define VOID_POINTER_P(type) (POINTER_TYPE_P (type) && VOID_TYPE_P (TREE_TYPE (type)))
+ 
++/* 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;
+@@ -163,42 +199,6 @@ handled_type (tree type)
+   return false;
+ }
+ 
+-/* 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;
+-}
+-
+ /* Get the number of pointer layers.  */
+ 
+ int
+diff --git a/gcc/tree.c b/gcc/tree.c
+index c2075d73586..84a440b3576 100644
+--- a/gcc/tree.c
++++ b/gcc/tree.c
+@@ -128,6 +128,9 @@ const char *const tree_code_class_strings[] =
+ /* obstack.[ch] explicitly declined to prototype this.  */
+ extern int _obstack_allocated_p (struct obstack *h, void *obj);
+ 
++/* Check whether in C language or LTO with only C language.  */
++extern bool lang_c_p (void);
++
+ /* Statistics-gathering stuff.  */
+ 
+ static uint64_t tree_code_counts[MAX_TREE_CODES];
+@@ -5219,7 +5222,10 @@ 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_layout || flag_ipa_struct_reorg)
++  if ((flag_ipa_struct_layout || flag_ipa_struct_reorg)
++      && lang_c_p ()
++      && flag_lto_partition == LTO_PARTITION_ONE
++      && (in_lto_p || flag_whole_program))
+     return TYPE_NAME (type);
+ 
+   if (!TYPE_NAME (type) || TREE_CODE (TYPE_NAME (type)) != TYPE_DECL)
+@@ -5463,7 +5469,10 @@ 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_layout || flag_ipa_struct_reorg)
++  if ((flag_ipa_struct_layout || flag_ipa_struct_reorg)
++      && lang_c_p ()
++      && flag_lto_partition == LTO_PARTITION_ONE
++      && (in_lto_p || flag_whole_program))
+     return t;
+   if (POINTER_TYPE_P (t))
+     return fld_incomplete_type_of (t, fld);
+-- 
+2.21.0.windows.1
+
diff --git a/0049-build-Add-some-file-right-to-executable.patch b/0049-build-Add-some-file-right-to-executable.patch
new file mode 100644
index 0000000..b9aa9b9
--- /dev/null
+++ b/0049-build-Add-some-file-right-to-executable.patch
@@ -0,0 +1,21 @@
+From 7dffda64fcbbd522616d7dc9c70530d146f4fed6 Mon Sep 17 00:00:00 2001
+From: zhongyunde 
+Date: Tue, 1 Nov 2022 16:38:38 +0800
+Subject: [PATCH 01/35] [build] Add some file right to executable
+
+---
+ libgcc/mkheader.sh | 0
+ move-if-change     | 0
+ 2 files changed, 0 insertions(+), 0 deletions(-)
+ mode change 100644 => 100755 libgcc/mkheader.sh
+ mode change 100644 => 100755 move-if-change
+
+diff --git a/libgcc/mkheader.sh b/libgcc/mkheader.sh
+old mode 100644
+new mode 100755
+diff --git a/move-if-change b/move-if-change
+old mode 100644
+new mode 100755
+-- 
+2.27.0.windows.1
+
diff --git a/0050-Backport-phiopt-Optimize-x-1024-0-to-int-x-10-PR9769.patch b/0050-Backport-phiopt-Optimize-x-1024-0-to-int-x-10-PR9769.patch
new file mode 100644
index 0000000..d3acf4c
--- /dev/null
+++ b/0050-Backport-phiopt-Optimize-x-1024-0-to-int-x-10-PR9769.patch
@@ -0,0 +1,186 @@
+From c690da762e873d0f5c66ea084e420ba4842354a6 Mon Sep 17 00:00:00 2001
+From: Jakub Jelinek 
+Date: Wed, 4 Nov 2020 11:55:29 +0100
+Subject: [PATCH 02/35] [Backport] phiopt: Optimize x ? 1024 : 0 to (int) x <<
+ 10 [PR97690]
+
+Reference: https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=3e190757fa332d327bee27495f37beb01155cfab
+
+The following patch generalizes the x ? 1 : 0 -> (int) x optimization
+to handle also left shifts by constant.
+
+During x86_64-linux and i686-linux bootstraps + regtests it triggered
+in 1514 unique non-LTO -m64 cases (sort -u on log mentioning
+filename, function name and shift count) and 1866 -m32 cases.
+
+Unfortunately, the patch regresses (before the tests have been adjusted):
++FAIL: gcc.dg/tree-ssa/ssa-ccp-11.c scan-tree-dump-times optimized "if " 0
++FAIL: gcc.dg/vect/bb-slp-pattern-2.c -flto -ffat-lto-objects  scan-tree-dump-times slp1 "optimized: basic block" 1
++FAIL: gcc.dg/vect/bb-slp-pattern-2.c scan-tree-dump-times slp1 "optimized: basic block" 1
+and in both cases it actually results in worse code.
+
+> > We'd need some optimization that would go through all PHI edges and
+> > compute if some use of the phi results don't actually compute a constant
+> > across all the PHI edges - 1 & 0 and 0 & 1 is always 0.
+
+> PRE should do this, IMHO only optimizing it at -O2 is fine.
+
+> > Similarly, in the slp vectorization test there is:
+> >      a[0] = b[0] ? 1 : 7;
+
+> note this, carefully avoiding the already "optimized" b[0] ? 1 : 0 ...
+
+> So the option is to put : 7 in the 2, 4 an 8 case as well.  The testcase
+> wasn't added for any real-world case but is artificial I guess for
+> COND_EXPR handling of invariants.
+
+> But yeah, for things like SLP it means we eventually have to
+> implement reverse transforms for all of this to make the lanes
+> matching.  But that's true anyway for things like x + 1 vs. x + 0
+> or x / 3 vs. x / 2 or other simplifications we do.
+
+2020-11-04  Jakub Jelinek  
+
+	PR tree-optimization/97690
+	* tree-ssa-phiopt.c (conditional_replacement): Also optimize
+	cond ? pow2p_cst : 0 as ((type) cond) << cst.
+
+	* gcc.dg/tree-ssa/phi-opt-22.c: New test.
+	* gcc.dg/tree-ssa/ssa-ccp-11.c: Use -O2 instead of -O1.
+	* gcc.dg/vect/bb-slp-pattern-2.c (foo): Use ? 2 : 7, ? 4 : 7 and
+	? 8 : 7 instead of ? 2 : 0, ? 4 : 0, ? 8 : 0.
+---
+ gcc/testsuite/gcc.dg/tree-ssa/phi-opt-22.c   | 11 ++++++
+ gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-11.c   |  2 +-
+ gcc/testsuite/gcc.dg/vect/bb-slp-pattern-2.c |  6 ++--
+ gcc/tree-ssa-phiopt.c                        | 38 ++++++++++++++------
+ 4 files changed, 43 insertions(+), 14 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/phi-opt-22.c
+
+diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-22.c b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-22.c
+new file mode 100644
+index 000000000..fd3706666
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-22.c
+@@ -0,0 +1,11 @@
++/* PR tree-optimization/97690 */
++/* { dg-do compile } */
++/* { dg-options "-O2 -fdump-tree-phiopt2" } */
++
++int foo (_Bool d) { return d ? 2 : 0; }
++int bar (_Bool d) { return d ? 1 : 0; }
++int baz (_Bool d) { return d ? -__INT_MAX__ - 1 : 0; }
++int qux (_Bool d) { return d ? 1024 : 0; }
++
++/* { dg-final { scan-tree-dump-not "if" "phiopt2" } } */
++/* { dg-final { scan-tree-dump-times " << " 3 "phiopt2" } } */
+diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-11.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-11.c
+index 36b8e7fc8..d70ea5a01 100644
+--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-11.c
++++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-11.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */ 
+-/* { dg-options "-O1 -fdump-tree-optimized" } */
++/* { dg-options "-O2 -fdump-tree-optimized" } */
+ 
+ /* Test for CPROP across a DAG. */
+ 
+diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-pattern-2.c b/gcc/testsuite/gcc.dg/vect/bb-slp-pattern-2.c
+index d32cb7585..e64f0115a 100644
+--- a/gcc/testsuite/gcc.dg/vect/bb-slp-pattern-2.c
++++ b/gcc/testsuite/gcc.dg/vect/bb-slp-pattern-2.c
+@@ -13,13 +13,13 @@ foo (short * __restrict__ a, int * __restrict__ b, int stride)
+   for (i = 0; i < N/stride; i++, a += stride, b += stride)
+    {
+      a[0] = b[0] ? 1 : 7;
+-     a[1] = b[1] ? 2 : 0;
++     a[1] = b[1] ? 2 : 7;
+      a[2] = b[2] ? 3 : 0;
+-     a[3] = b[3] ? 4 : 0;
++     a[3] = b[3] ? 4 : 7;
+      a[4] = b[4] ? 5 : 0;
+      a[5] = b[5] ? 6 : 0;
+      a[6] = b[6] ? 7 : 0;
+-     a[7] = b[7] ? 8 : 0;
++     a[7] = b[7] ? 8 : 7;
+    }
+ }
+ 
+diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c
+index 591b6435f..85587e8d1 100644
+--- a/gcc/tree-ssa-phiopt.c
++++ b/gcc/tree-ssa-phiopt.c
+@@ -753,7 +753,9 @@ conditional_replacement (basic_block cond_bb, basic_block middle_bb,
+   gimple_stmt_iterator gsi;
+   edge true_edge, false_edge;
+   tree new_var, new_var2;
+-  bool neg;
++  bool neg = false;
++  int shift = 0;
++  tree nonzero_arg;
+ 
+   /* FIXME: Gimplification of complex type is too hard for now.  */
+   /* We aren't prepared to handle vectors either (and it is a question
+@@ -764,14 +766,22 @@ conditional_replacement (basic_block cond_bb, basic_block middle_bb,
+ 	   || POINTER_TYPE_P (TREE_TYPE (arg1))))
+     return false;
+ 
+-  /* The PHI arguments have the constants 0 and 1, or 0 and -1, then
+-     convert it to the conditional.  */
+-  if ((integer_zerop (arg0) && integer_onep (arg1))
+-      || (integer_zerop (arg1) && integer_onep (arg0)))
+-    neg = false;
+-  else if ((integer_zerop (arg0) && integer_all_onesp (arg1))
+-	   || (integer_zerop (arg1) && integer_all_onesp (arg0)))
++  /* The PHI arguments have the constants 0 and 1, or 0 and -1 or
++     0 and (1 << cst), then convert it to the conditional.  */
++  if (integer_zerop (arg0))
++    nonzero_arg = arg1;
++  else if (integer_zerop (arg1))
++    nonzero_arg = arg0;
++  else
++    return false;
++  if (integer_all_onesp (nonzero_arg))
+     neg = true;
++  else if (integer_pow2p (nonzero_arg))
++    {
++      shift = tree_log2 (nonzero_arg);
++      if (shift && POINTER_TYPE_P (TREE_TYPE (nonzero_arg)))
++	return false;
++    }
+   else
+     return false;
+ 
+@@ -783,12 +793,12 @@ conditional_replacement (basic_block cond_bb, basic_block middle_bb,
+      falls through into BB.
+ 
+      There is a single PHI node at the join point (BB) and its arguments
+-     are constants (0, 1) or (0, -1).
++     are constants (0, 1) or (0, -1) or (0, (1 << shift)).
+ 
+      So, given the condition COND, and the two PHI arguments, we can
+      rewrite this PHI into non-branching code:
+ 
+-       dest = (COND) or dest = COND'
++       dest = (COND) or dest = COND' or dest = (COND) << shift
+ 
+      We use the condition as-is if the argument associated with the
+      true edge has the value one or the argument associated with the
+@@ -823,6 +833,14 @@ conditional_replacement (basic_block cond_bb, basic_block middle_bb,
+       cond = fold_build1_loc (gimple_location (stmt),
+                               NEGATE_EXPR, TREE_TYPE (cond), cond);
+     }
++  else if (shift)
++    {
++      cond = fold_convert_loc (gimple_location (stmt),
++			       TREE_TYPE (result), cond);
++      cond = fold_build2_loc (gimple_location (stmt),
++			      LSHIFT_EXPR, TREE_TYPE (cond), cond,
++			      build_int_cst (integer_type_node, shift));
++    }
+ 
+   /* Insert our new statements at the end of conditional block before the
+      COND_STMT.  */
+-- 
+2.27.0.windows.1
+
diff --git a/0051-Backport-phiopt-Fix-up-conditional_replacement-PR993.patch b/0051-Backport-phiopt-Fix-up-conditional_replacement-PR993.patch
new file mode 100644
index 0000000..3d47670
--- /dev/null
+++ b/0051-Backport-phiopt-Fix-up-conditional_replacement-PR993.patch
@@ -0,0 +1,92 @@
+From 79a974bc7bb67cf425a7839f3c1f5689e41c7ee8 Mon Sep 17 00:00:00 2001
+From: Jakub Jelinek 
+Date: Tue, 9 Mar 2021 19:13:11 +0100
+Subject: [PATCH 03/35] [Backport] phiopt: Fix up conditional_replacement
+ [PR99305]
+
+Reference: https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=b610c30453d8e4cc88693d85a5a100d089640be5
+
+Before my PR97690 changes, conditional_replacement would not set neg
+when the nonzero arg was boolean true.
+I've simplified the testing, so that it first finds the zero argument
+and then checks the other argument for all the handled cases
+(1, -1 and 1 << X, where the last case is what the patch added support for).
+But, unfortunately I've placed the integer_all_onesp test first.
+For unsigned precision 1 types such as bool integer_all_onesp, integer_onep
+and integer_pow2p can all be true and the code set neg to true in that case,
+which is undesirable.
+
+The following patch tests integer_pow2p first (which is trivially true
+for integer_onep too and tree_log2 in that case gives shift == 0)
+and only if that isn't the case, integer_all_onesp.
+
+2021-03-09  Jakub Jelinek  
+
+	PR tree-optimization/99305
+	* tree-ssa-phiopt.c (conditional_replacement): Test integer_pow2p
+	before integer_all_onesp instead of vice versa.
+
+	* g++.dg/opt/pr99305.C: New test.
+---
+ gcc/testsuite/g++.dg/opt/pr99305.C | 26 ++++++++++++++++++++++++++
+ gcc/tree-ssa-phiopt.c              |  6 +++---
+ 2 files changed, 29 insertions(+), 3 deletions(-)
+ create mode 100644 gcc/testsuite/g++.dg/opt/pr99305.C
+
+diff --git a/gcc/testsuite/g++.dg/opt/pr99305.C b/gcc/testsuite/g++.dg/opt/pr99305.C
+new file mode 100644
+index 000000000..8a91277e7
+--- /dev/null
++++ b/gcc/testsuite/g++.dg/opt/pr99305.C
+@@ -0,0 +1,26 @@
++// PR tree-optimization/99305
++// { dg-do compile }
++// { dg-options "-O3 -fno-ipa-icf -fdump-tree-optimized" }
++// { dg-final { scan-tree-dump-times " = \\\(unsigned char\\\) c_\[0-9]*\\\(D\\\);" 3 "optimized" } }
++// { dg-final { scan-tree-dump-times " = \[^\n\r]* \\+ \[0-9]*;" 3 "optimized" } }
++// { dg-final { scan-tree-dump-times " = \[^\n\r]* <= 9;" 3 "optimized" } }
++// { dg-final { scan-tree-dump-not "if \\\(c_\[0-9]*\\\(D\\\) \[!=]= 0\\\)" "optimized" } }
++// { dg-final { scan-tree-dump-not " = PHI <" "optimized" } }
++
++bool
++foo (char c)
++{
++  return c >= 48 && c <= 57;
++}
++
++bool
++bar (char c)
++{
++  return c != 0 && foo (c);
++}
++
++bool
++baz (char c)
++{
++  return c != 0 && c >= 48 && c <= 57;
++}
+diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c
+index 85587e8d1..b9be28474 100644
+--- a/gcc/tree-ssa-phiopt.c
++++ b/gcc/tree-ssa-phiopt.c
+@@ -774,14 +774,14 @@ conditional_replacement (basic_block cond_bb, basic_block middle_bb,
+     nonzero_arg = arg0;
+   else
+     return false;
+-  if (integer_all_onesp (nonzero_arg))
+-    neg = true;
+-  else if (integer_pow2p (nonzero_arg))
++  if (integer_pow2p (nonzero_arg))
+     {
+       shift = tree_log2 (nonzero_arg);
+       if (shift && POINTER_TYPE_P (TREE_TYPE (nonzero_arg)))
+ 	return false;
+     }
++  else if (integer_all_onesp (nonzero_arg))
++    neg = true;
+   else
+     return false;
+ 
+-- 
+2.27.0.windows.1
+
diff --git a/0052-Backport-phiopt-Handle-bool-in-two_value_replacement.patch b/0052-Backport-phiopt-Handle-bool-in-two_value_replacement.patch
new file mode 100644
index 0000000..9ea9a42
--- /dev/null
+++ b/0052-Backport-phiopt-Handle-bool-in-two_value_replacement.patch
@@ -0,0 +1,122 @@
+From 09263d5ed4d81a008ca8ffcc2883dc766e7874d5 Mon Sep 17 00:00:00 2001
+From: Jakub Jelinek 
+Date: Sun, 6 Dec 2020 10:58:10 +0100
+Subject: [PATCH 04/35] [Backport] phiopt: Handle bool in two_value_replacement
+ [PR796232]
+
+Reference: https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=8c23434fdadcf4caa1f0e966294c5f67ccf4bcf9
+
+The following patch improves code generation on the included testcase by
+enabling two_value_replacement on booleans.  It does that only for arg0/arg1
+values that conditional_replacement doesn't handle.  Additionally
+it limits two_value_replacement optimization to the late phiopt like
+conditional_replacement.
+
+2020-12-06  Jakub Jelinek  
+
+	PR tree-optimization/96232
+	* tree-ssa-phiopt.c (two_value_replacement): Optimize even boolean lhs
+	cases as long as arg0 has wider precision and conditional_replacement
+	doesn't handle that case.
+	(tree_ssa_phiopt_worker): Don't call two_value_replacement during
+	early phiopt.
+
+	* gcc.dg/tree-ssa/pr96232-2.c: New test.
+	* gcc.dg/tree-ssa/pr88676-2.c: Check phiopt2 dump rather than phiopt1.
+---
+ gcc/testsuite/gcc.dg/tree-ssa/pr88676-2.c |  4 ++--
+ gcc/testsuite/gcc.dg/tree-ssa/pr96232-2.c | 18 ++++++++++++++++++
+ gcc/tree-ssa-phiopt.c                     | 23 +++++++++++++++++++----
+ 3 files changed, 39 insertions(+), 6 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr96232-2.c
+
+diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr88676-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr88676-2.c
+index 0e616365b..ea88407b6 100644
+--- a/gcc/testsuite/gcc.dg/tree-ssa/pr88676-2.c
++++ b/gcc/testsuite/gcc.dg/tree-ssa/pr88676-2.c
+@@ -1,7 +1,7 @@
+ /* PR tree-optimization/88676 */
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -fdump-tree-phiopt1" } */
+-/* { dg-final { scan-tree-dump-not " = PHI <" "phiopt1" { target le } } } */
++/* { dg-options "-O2 -fdump-tree-phiopt2" } */
++/* { dg-final { scan-tree-dump-not " = PHI <" "phiopt2" { target le } } } */
+ 
+ struct foo1 {
+   int i:1;
+diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr96232-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr96232-2.c
+new file mode 100644
+index 000000000..9f51820ed
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/tree-ssa/pr96232-2.c
+@@ -0,0 +1,18 @@
++/* PR tree-optimization/96232 */
++/* { dg-do compile } */
++/* { dg-options "-O2 -fdump-tree-optimized" } */
++/* { dg-final { scan-tree-dump " 38 - " "optimized" } } */
++/* { dg-final { scan-tree-dump " \\+ 97;" "optimized" } } */
++/* { dg-final { scan-tree-dump-not "PHI <" "optimized" } } */
++
++int
++foo (_Bool x)
++{
++  return x ? 37 : 38;
++}
++
++int
++bar (_Bool x)
++{
++  return x ? 98 : 97;
++}
+diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c
+index b9be28474..0623d740d 100644
+--- a/gcc/tree-ssa-phiopt.c
++++ b/gcc/tree-ssa-phiopt.c
+@@ -339,7 +339,7 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads, bool early_p)
+ 	    }
+ 
+ 	  /* Do the replacement of conditional if it can be done.  */
+-	  if (two_value_replacement (bb, bb1, e2, phi, arg0, arg1))
++	  if (!early_p && two_value_replacement (bb, bb1, e2, phi, arg0, arg1))
+ 	    cfgchanged = true;
+ 	  else if (!early_p
+ 		   && conditional_replacement (bb, bb1, e1, e2, phi,
+@@ -636,7 +636,6 @@ two_value_replacement (basic_block cond_bb, basic_block middle_bb,
+ 
+   if (TREE_CODE (lhs) != SSA_NAME
+       || !INTEGRAL_TYPE_P (TREE_TYPE (lhs))
+-      || TREE_CODE (TREE_TYPE (lhs)) == BOOLEAN_TYPE
+       || TREE_CODE (rhs) != INTEGER_CST)
+     return false;
+ 
+@@ -649,9 +648,25 @@ two_value_replacement (basic_block cond_bb, basic_block middle_bb,
+       return false;
+     }
+ 
++  /* Defer boolean x ? 0 : {1,-1} or x ? {1,-1} : 0 to
++     conditional_replacement.  */
++  if (TREE_CODE (TREE_TYPE (lhs)) == BOOLEAN_TYPE
++      && (integer_zerop (arg0)
++	  || integer_zerop (arg1)
++	  || TREE_CODE (TREE_TYPE (arg0)) == BOOLEAN_TYPE
++	  || (TYPE_PRECISION (TREE_TYPE (arg0))
++	      <= TYPE_PRECISION (TREE_TYPE (lhs)))))
++    return false;
++
+   wide_int min, max;
+-  if (get_range_info (lhs, &min, &max) != VR_RANGE
+-      || min + 1 != max
++  if (TREE_CODE (TREE_TYPE (lhs)) == BOOLEAN_TYPE)
++    {
++      min = wi::to_wide (boolean_false_node);
++      max = wi::to_wide (boolean_true_node);
++    }
++  else if (get_range_info (lhs, &min, &max) != VR_RANGE)
++    return false;
++  if (min + 1 != max
+       || (wi::to_wide (rhs) != min
+ 	  && wi::to_wide (rhs) != max))
+     return false;
+-- 
+2.27.0.windows.1
+
diff --git a/0053-Backport-phiopt-Optimize-x-__builtin_clz-x-32-in-GIM.patch b/0053-Backport-phiopt-Optimize-x-__builtin_clz-x-32-in-GIM.patch
new file mode 100644
index 0000000..15c260e
--- /dev/null
+++ b/0053-Backport-phiopt-Optimize-x-__builtin_clz-x-32-in-GIM.patch
@@ -0,0 +1,256 @@
+From a92cf465f10585350f7cd5739457c3f2852cfc86 Mon Sep 17 00:00:00 2001
+From: Jakub Jelinek 
+Date: Wed, 21 Oct 2020 10:51:33 +0200
+Subject: [PATCH 05/35] [Backport] phiopt: Optimize x ? __builtin_clz (x) : 32
+ in GIMPLE [PR97503]
+
+Reference: https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=5244b4af5e47bc98a2a9cf36f048981583a1b163
+
+While we have at the RTL level noce_try_ifelse_collapse combined with
+simplify_cond_clz_ctz, that optimization doesn't always trigger because
+e.g. on powerpc there is an define_insn to compare a reg against zero and
+copy that register to another one and so we end up with a different pseudo
+in the simplify_cond_clz_ctz test and punt.
+
+For targets that define C?Z_DEFINED_VALUE_AT_ZERO to 2 for certain modes,
+we can optimize it already in phiopt though, just need to ensure that
+we transform the __builtin_c?z* calls into .C?Z ifns because my recent
+VRP changes codified that the builtin calls are always undefined at zero,
+while ifns honor C?Z_DEFINED_VALUE_AT_ZERO equal to 2.
+And, in phiopt we already have popcount handling that does pretty much the
+same thing, except for always using a zero value rather than the one set
+by C?Z_DEFINED_VALUE_AT_ZERO.
+
+So, this patch extends that function to handle not just popcount, but also
+clz and ctz.
+
+2020-10-21  Jakub Jelinek  
+
+	PR tree-optimization/97503
+	* tree-ssa-phiopt.c: Include internal-fn.h.
+	(cond_removal_in_popcount_pattern): Rename to ...
+	(cond_removal_in_popcount_clz_ctz_pattern): ... this.  Handle not just
+	popcount, but also clz and ctz if it has C?Z_DEFINED_VALUE_AT_ZERO 2.
+
+	* gcc.dg/tree-ssa/pr97503.c: New test.
+---
+ gcc/testsuite/gcc.dg/tree-ssa/pr97503.c |  19 +++++
+ gcc/tree-ssa-phiopt.c                   | 100 ++++++++++++++++++------
+ 2 files changed, 95 insertions(+), 24 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr97503.c
+
+diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr97503.c b/gcc/testsuite/gcc.dg/tree-ssa/pr97503.c
+new file mode 100644
+index 000000000..3a3dae6c7
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/tree-ssa/pr97503.c
+@@ -0,0 +1,19 @@
++/* PR tree-optimization/97503 */
++/* { dg-do compile } */
++/* { dg-options "-O2 -fdump-tree-optimized" } */
++/* { dg-additional-options "-mbmi -mlzcnt" { target i?86-*-* x86_64-*-* } } */
++/* { dg-final { scan-tree-dump-times "\.CLZ" 2 "optimized" { target { { i?86-*-* x86_64-*-* aarch64-*-* powerpc*-*-* } && lp64 } } } } */
++/* { dg-final { scan-tree-dump-not "__builtin_clz" "optimized" { target { { i?86-*-* x86_64-*-* aarch64-*-* powerpc*-*-*} && lp64 } } } } */
++/* { dg-final { scan-tree-dump-not "PHI <" "optimized" { target { { i?86-*-* x86_64-*-* aarch64-*-* powerpc*-*-*} && lp64 } } } } */
++
++int
++foo (int x)
++{
++  return x ? __builtin_clz (x) : 32;
++}
++
++int
++bar (unsigned long long x)
++{
++  return x ? __builtin_clzll (x) : 64;
++}
+diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c
+index 0623d740d..c1e11916e 100644
+--- a/gcc/tree-ssa-phiopt.c
++++ b/gcc/tree-ssa-phiopt.c
+@@ -46,6 +46,7 @@ along with GCC; see the file COPYING3.  If not see
+ #include "tree-inline.h"
+ #include "case-cfn-macros.h"
+ #include "tree-eh.h"
++#include "internal-fn.h"
+ 
+ static unsigned int tree_ssa_phiopt_worker (bool, bool, bool);
+ static bool two_value_replacement (basic_block, basic_block, edge, gphi *,
+@@ -60,8 +61,9 @@ static bool minmax_replacement (basic_block, basic_block,
+ 				edge, edge, gimple *, tree, tree);
+ static bool abs_replacement (basic_block, basic_block,
+ 			     edge, edge, gimple *, tree, tree);
+-static bool cond_removal_in_popcount_pattern (basic_block, basic_block,
+-					      edge, edge, gimple *, tree, tree);
++static bool cond_removal_in_popcount_clz_ctz_pattern (basic_block, basic_block,
++						      edge, edge, gimple *,
++						      tree, tree);
+ static bool cond_store_replacement (basic_block, basic_block, edge, edge,
+ 				    hash_set *);
+ static bool cond_if_else_store_replacement (basic_block, basic_block, basic_block);
+@@ -348,8 +350,9 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads, bool early_p)
+ 	  else if (abs_replacement (bb, bb1, e1, e2, phi, arg0, arg1))
+ 	    cfgchanged = true;
+ 	  else if (!early_p
+-		   && cond_removal_in_popcount_pattern (bb, bb1, e1, e2,
+-							phi, arg0, arg1))
++		   && cond_removal_in_popcount_clz_ctz_pattern (bb, bb1, e1,
++								e2, phi, arg0,
++								arg1))
+ 	    cfgchanged = true;
+ 	  else if (minmax_replacement (bb, bb1, e1, e2, phi, arg0, arg1))
+ 	    cfgchanged = true;
+@@ -1771,16 +1774,20 @@ minmax_replacement (basic_block cond_bb, basic_block middle_bb,
+ 
+    
+    c_12 = PHI <_9(2)>
+-*/
++
++   Similarly for __builtin_clz or __builtin_ctz if
++   C?Z_DEFINED_VALUE_AT_ZERO is 2, optab is present and
++   instead of 0 above it uses the value from that macro.  */
+ 
+ static bool
+-cond_removal_in_popcount_pattern (basic_block cond_bb, basic_block middle_bb,
+-				  edge e1, edge e2,
+-				  gimple *phi, tree arg0, tree arg1)
++cond_removal_in_popcount_clz_ctz_pattern (basic_block cond_bb,
++					  basic_block middle_bb,
++					  edge e1, edge e2, gimple *phi,
++					  tree arg0, tree arg1)
+ {
+   gimple *cond;
+   gimple_stmt_iterator gsi, gsi_from;
+-  gimple *popcount;
++  gimple *call;
+   gimple *cast = NULL;
+   tree lhs, arg;
+ 
+@@ -1798,35 +1805,67 @@ cond_removal_in_popcount_pattern (basic_block cond_bb, basic_block middle_bb,
+   gsi_next_nondebug (&gsi);
+   if (!gsi_end_p (gsi))
+     {
+-      popcount = gsi_stmt (gsi);
++      call = gsi_stmt (gsi);
+       gsi_next_nondebug (&gsi);
+       if (!gsi_end_p (gsi))
+ 	return false;
+     }
+   else
+     {
+-      popcount = cast;
++      call = cast;
+       cast = NULL;
+     }
+ 
+-  /* Check that we have a popcount builtin.  */
+-  if (!is_gimple_call (popcount))
++  /* Check that we have a popcount/clz/ctz builtin.  */
++  if (!is_gimple_call (call) || gimple_call_num_args (call) != 1)
++    return false;
++
++  arg = gimple_call_arg (call, 0);
++  lhs = gimple_get_lhs (call);
++
++  if (lhs == NULL_TREE)
+     return false;
+-  combined_fn cfn = gimple_call_combined_fn (popcount);
++
++  combined_fn cfn = gimple_call_combined_fn (call);
++  internal_fn ifn = IFN_LAST;
++  int val = 0;
+   switch (cfn)
+     {
+     CASE_CFN_POPCOUNT:
+       break;
++    CASE_CFN_CLZ:
++      if (INTEGRAL_TYPE_P (TREE_TYPE (arg)))
++	{
++	  scalar_int_mode mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg));
++	  if (direct_internal_fn_supported_p (IFN_CLZ, TREE_TYPE (arg),
++					      OPTIMIZE_FOR_BOTH)
++	      && CLZ_DEFINED_VALUE_AT_ZERO (mode, val) == 2)
++	    {
++	      ifn = IFN_CLZ;
++	      break;
++	    }
++	}
++      return false;
++    CASE_CFN_CTZ:
++      if (INTEGRAL_TYPE_P (TREE_TYPE (arg)))
++	{
++	  scalar_int_mode mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg));
++	  if (direct_internal_fn_supported_p (IFN_CTZ, TREE_TYPE (arg),
++					      OPTIMIZE_FOR_BOTH)
++	      && CTZ_DEFINED_VALUE_AT_ZERO (mode, val) == 2)
++	    {
++	      ifn = IFN_CTZ;
++	      break;
++	    }
++	}
++      return false;
+     default:
+       return false;
+     }
+ 
+-  arg = gimple_call_arg (popcount, 0);
+-  lhs = gimple_get_lhs (popcount);
+-
+   if (cast)
+     {
+-      /* We have a cast stmt feeding popcount builtin.  */
++      /* We have a cast stmt feeding popcount/clz/ctz builtin.  */
+       /* Check that we have a cast prior to that.  */
+       if (gimple_code (cast) != GIMPLE_ASSIGN
+ 	  || !CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (cast)))
+@@ -1839,7 +1878,7 @@ cond_removal_in_popcount_pattern (basic_block cond_bb, basic_block middle_bb,
+ 
+   cond = last_stmt (cond_bb);
+ 
+-  /* Cond_bb has a check for b_4 [!=|==] 0 before calling the popcount
++  /* Cond_bb has a check for b_4 [!=|==] 0 before calling the popcount/clz/ctz
+      builtin.  */
+   if (gimple_code (cond) != GIMPLE_COND
+       || (gimple_cond_code (cond) != NE_EXPR
+@@ -1859,10 +1898,13 @@ cond_removal_in_popcount_pattern (basic_block cond_bb, basic_block middle_bb,
+     }
+ 
+   /* Check PHI arguments.  */
+-  if (lhs != arg0 || !integer_zerop (arg1))
++  if (lhs != arg0
++      || TREE_CODE (arg1) != INTEGER_CST
++      || wi::to_wide (arg1) != val)
+     return false;
+ 
+-  /* And insert the popcount builtin and cast stmt before the cond_bb.  */
++  /* And insert the popcount/clz/ctz builtin and cast stmt before the
++     cond_bb.  */
+   gsi = gsi_last_bb (cond_bb);
+   if (cast)
+     {
+@@ -1870,9 +1912,19 @@ cond_removal_in_popcount_pattern (basic_block cond_bb, basic_block middle_bb,
+       gsi_move_before (&gsi_from, &gsi);
+       reset_flow_sensitive_info (gimple_get_lhs (cast));
+     }
+-  gsi_from = gsi_for_stmt (popcount);
+-  gsi_move_before (&gsi_from, &gsi);
+-  reset_flow_sensitive_info (gimple_get_lhs (popcount));
++  gsi_from = gsi_for_stmt (call);
++  if (ifn == IFN_LAST || gimple_call_internal_p (call))
++    gsi_move_before (&gsi_from, &gsi);
++  else
++    {
++      /* For __builtin_c[lt]z* force .C[LT]Z ifn, because only
++	 the latter is well defined at zero.  */
++      call = gimple_build_call_internal (ifn, 1, gimple_call_arg (call, 0));
++      gimple_call_set_lhs (call, lhs);
++      gsi_insert_before (&gsi, call, GSI_SAME_STMT);
++      gsi_remove (&gsi_from, true);
++    }
++  reset_flow_sensitive_info (lhs);
+ 
+   /* Now update the PHI and remove unneeded bbs.  */
+   replace_phi_edge_with_variable (cond_bb, e2, phi, lhs);
+-- 
+2.27.0.windows.1
+
diff --git a/0054-Backport-phiopt-Optimize-x-__builtin_clz-x-32-in-GIM.patch b/0054-Backport-phiopt-Optimize-x-__builtin_clz-x-32-in-GIM.patch
new file mode 100644
index 0000000..160afc0
--- /dev/null
+++ b/0054-Backport-phiopt-Optimize-x-__builtin_clz-x-32-in-GIM.patch
@@ -0,0 +1,69 @@
+From 7d5d2ab082ce9986db4f3313013b44faa46bc412 Mon Sep 17 00:00:00 2001
+From: Jakub Jelinek 
+Date: Thu, 22 Oct 2020 09:34:28 +0200
+Subject: [PATCH 06/35] [Backport] phiopt: Optimize x ? __builtin_clz (x) : 32
+ in GIMPLE fallout [PR97503]
+
+Reference: https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=ef2d3ec325b1b720df5da20784eba46249af2294
+
+> this broke sparc-sun-solaris2.11 bootstrap
+>
+> /vol/gcc/src/hg/master/local/gcc/tree-ssa-phiopt.c: In function 'bool cond_removal_in_popcount_clz_ctz_pattern(basic_block, basic_block, edge, edge, gimple*, tree, tree)':
+> /vol/gcc/src/hg/master/local/gcc/tree-ssa-phiopt.c:1858:27: error: variable 'mode' set but not used [-Werror=unused-but-set-variable]
+>  1858 |           scalar_int_mode mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg));
+>       |                           ^~~~
+>
+>
+> and doubtlessly several other targets that use the defaults.h definition of
+>
+> #define CTZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE)  0
+
+Ugh, seems many of those macros do not evaluate the first argument.
+This got broken by the change to direct_internal_fn_supported_p, previously
+it used mode also in the optab test.
+
+2020-10-22  Jakub Jelinek  
+
+	* tree-ssa-phiopt.c (cond_removal_in_popcount_clz_ctz_pattern):
+	For CLZ and CTZ tests, use type temporary instead of mode.
+---
+ gcc/tree-ssa-phiopt.c | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c
+index c1e11916e..707a5882e 100644
+--- a/gcc/tree-ssa-phiopt.c
++++ b/gcc/tree-ssa-phiopt.c
+@@ -1836,10 +1836,10 @@ cond_removal_in_popcount_clz_ctz_pattern (basic_block cond_bb,
+     CASE_CFN_CLZ:
+       if (INTEGRAL_TYPE_P (TREE_TYPE (arg)))
+ 	{
+-	  scalar_int_mode mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg));
+-	  if (direct_internal_fn_supported_p (IFN_CLZ, TREE_TYPE (arg),
+-					      OPTIMIZE_FOR_BOTH)
+-	      && CLZ_DEFINED_VALUE_AT_ZERO (mode, val) == 2)
++	  tree type = TREE_TYPE (arg);
++	  if (direct_internal_fn_supported_p (IFN_CLZ, type, OPTIMIZE_FOR_BOTH)
++	      && CLZ_DEFINED_VALUE_AT_ZERO (SCALAR_INT_TYPE_MODE (type),
++					    val) == 2)
+ 	    {
+ 	      ifn = IFN_CLZ;
+ 	      break;
+@@ -1849,10 +1849,10 @@ cond_removal_in_popcount_clz_ctz_pattern (basic_block cond_bb,
+     CASE_CFN_CTZ:
+       if (INTEGRAL_TYPE_P (TREE_TYPE (arg)))
+ 	{
+-	  scalar_int_mode mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg));
+-	  if (direct_internal_fn_supported_p (IFN_CTZ, TREE_TYPE (arg),
+-					      OPTIMIZE_FOR_BOTH)
+-	      && CTZ_DEFINED_VALUE_AT_ZERO (mode, val) == 2)
++	  tree type = TREE_TYPE (arg);
++	  if (direct_internal_fn_supported_p (IFN_CTZ, type, OPTIMIZE_FOR_BOTH)
++	      && CTZ_DEFINED_VALUE_AT_ZERO (SCALAR_INT_TYPE_MODE (type),
++					    val) == 2)
+ 	    {
+ 	      ifn = IFN_CTZ;
+ 	      break;
+-- 
+2.27.0.windows.1
+
diff --git a/0055-Backport-phiopt-Optimize-x-0-y-y-to-x-31-y-PR96928.patch b/0055-Backport-phiopt-Optimize-x-0-y-y-to-x-31-y-PR96928.patch
new file mode 100644
index 0000000..35b773e
--- /dev/null
+++ b/0055-Backport-phiopt-Optimize-x-0-y-y-to-x-31-y-PR96928.patch
@@ -0,0 +1,218 @@
+From 018523df11698dd0e2d42326c57bdf724a7a1aa5 Mon Sep 17 00:00:00 2001
+From: Jakub Jelinek 
+Date: Tue, 5 Jan 2021 16:35:22 +0100
+Subject: [PATCH 07/35] [Backport] phiopt: Optimize x < 0 ? ~y : y to (x >> 31)
+ ^ y [PR96928]
+
+Reference: https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=576714b309b330df0e80e34114bcdf0bba35e146
+
+As requested in the PR, the one's complement abs can be done more
+efficiently without cmov or branching.
+
+Had to change the ifcvt-onecmpl-abs-1.c testcase, we no longer optimize
+it in ifcvt, on x86_64 with -m32 we generate in the end the exact same
+code, but with -m64:
+        movl    %edi, %eax
+-       notl    %eax
+-       cmpl    %edi, %eax
+-       cmovl   %edi, %eax
++       sarl    $31, %eax
++       xorl    %edi, %eax
+        ret
+
+2021-01-05  Jakub Jelinek  
+
+	PR tree-optimization/96928
+	* tree-ssa-phiopt.c (xor_replacement): New function.
+	(tree_ssa_phiopt_worker): Call it.
+
+	* gcc.dg/tree-ssa/pr96928.c: New test.
+	* gcc.target/i386/ifcvt-onecmpl-abs-1.c: Remove -fdump-rtl-ce1,
+	instead of scanning rtl dump for ifcvt message check assembly
+	for xor instruction.
+---
+ gcc/testsuite/gcc.dg/tree-ssa/pr96928.c |  38 +++++++++
+ gcc/tree-ssa-phiopt.c                   | 108 ++++++++++++++++++++++++
+ 2 files changed, 146 insertions(+)
+ create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr96928.c
+
+diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr96928.c b/gcc/testsuite/gcc.dg/tree-ssa/pr96928.c
+new file mode 100644
+index 000000000..209135726
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/tree-ssa/pr96928.c
+@@ -0,0 +1,38 @@
++/* PR tree-optimization/96928 */
++/* { dg-do compile } */
++/* { dg-options "-O2 -fdump-tree-phiopt2" } */
++/* { dg-final { scan-tree-dump-times " = a_\[0-9]*\\\(D\\\) >> " 5 "phiopt2" } } */
++/* { dg-final { scan-tree-dump-times " = ~c_\[0-9]*\\\(D\\\);" 1 "phiopt2" } } */
++/* { dg-final { scan-tree-dump-times " = ~" 1 "phiopt2" } } */
++/* { dg-final { scan-tree-dump-times " = \[abc_0-9\\\(\\\)D]* \\\^ " 5 "phiopt2" } } */
++/* { dg-final { scan-tree-dump-not "a < 0" "phiopt2" } } */
++
++int
++foo (int a)
++{
++  return a < 0 ? ~a : a;
++}
++
++int
++bar (int a, int b)
++{
++  return a < 0 ? ~b : b;
++}
++
++unsigned
++baz (int a, unsigned int b)
++{
++  return a < 0 ? ~b : b;
++}
++
++unsigned
++qux (int a, unsigned int c)
++{
++  return a >= 0 ? ~c : c;
++}
++
++int
++corge (int a, int b)
++{
++  return a >= 0 ? b : ~b;
++}
+diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c
+index 707a5882e..b9cd07a60 100644
+--- a/gcc/tree-ssa-phiopt.c
++++ b/gcc/tree-ssa-phiopt.c
+@@ -61,6 +61,8 @@ static bool minmax_replacement (basic_block, basic_block,
+ 				edge, edge, gimple *, tree, tree);
+ static bool abs_replacement (basic_block, basic_block,
+ 			     edge, edge, gimple *, tree, tree);
++static bool xor_replacement (basic_block, basic_block,
++			     edge, edge, gimple *, tree, tree);
+ static bool cond_removal_in_popcount_clz_ctz_pattern (basic_block, basic_block,
+ 						      edge, edge, gimple *,
+ 						      tree, tree);
+@@ -349,6 +351,9 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads, bool early_p)
+ 	    cfgchanged = true;
+ 	  else if (abs_replacement (bb, bb1, e1, e2, phi, arg0, arg1))
+ 	    cfgchanged = true;
++	  else if (!early_p
++		   && xor_replacement (bb, bb1, e1, e2, phi, arg0, arg1))
++	    cfgchanged = true;
+ 	  else if (!early_p
+ 		   && cond_removal_in_popcount_clz_ctz_pattern (bb, bb1, e1,
+ 								e2, phi, arg0,
+@@ -2059,6 +2064,109 @@ abs_replacement (basic_block cond_bb, basic_block middle_bb,
+   return true;
+ }
+ 
++/* Optimize x < 0 ? ~y : y into (x >> (prec-1)) ^ y.  */
++
++static bool
++xor_replacement (basic_block cond_bb, basic_block middle_bb,
++		 edge e0 ATTRIBUTE_UNUSED, edge e1,
++		 gimple *phi, tree arg0, tree arg1)
++{
++  if (!INTEGRAL_TYPE_P (TREE_TYPE (arg1)))
++    return false;
++
++  /* OTHER_BLOCK must have only one executable statement which must have the
++     form arg0 = ~arg1 or arg1 = ~arg0.  */
++
++  gimple *assign = last_and_only_stmt (middle_bb);
++  /* If we did not find the proper one's complement assignment, then we cannot
++     optimize.  */
++  if (assign == NULL)
++    return false;
++
++  /* If we got here, then we have found the only executable statement
++     in OTHER_BLOCK.  If it is anything other than arg = ~arg1 or
++     arg1 = ~arg0, then we cannot optimize.  */
++  if (!is_gimple_assign (assign))
++    return false;
++
++  if (gimple_assign_rhs_code (assign) != BIT_NOT_EXPR)
++    return false;
++
++  tree lhs = gimple_assign_lhs (assign);
++  tree rhs = gimple_assign_rhs1 (assign);
++
++  /* The assignment has to be arg0 = -arg1 or arg1 = -arg0.  */
++  if (!(lhs == arg0 && rhs == arg1) && !(lhs == arg1 && rhs == arg0))
++    return false;
++
++  gimple *cond = last_stmt (cond_bb);
++  tree result = PHI_RESULT (phi);
++
++  /* Only relationals comparing arg[01] against zero are interesting.  */
++  enum tree_code cond_code = gimple_cond_code (cond);
++  if (cond_code != LT_EXPR && cond_code != GE_EXPR)
++    return false;
++
++  /* Make sure the conditional is x OP 0.  */
++  tree clhs = gimple_cond_lhs (cond);
++  if (TREE_CODE (clhs) != SSA_NAME
++      || !INTEGRAL_TYPE_P (TREE_TYPE (clhs))
++      || TYPE_UNSIGNED (TREE_TYPE (clhs))
++      || TYPE_PRECISION (TREE_TYPE (clhs)) != TYPE_PRECISION (TREE_TYPE (arg1))
++      || !integer_zerop (gimple_cond_rhs (cond)))
++    return false;
++
++  /* We need to know which is the true edge and which is the false
++     edge so that we know if have xor or inverted xor.  */
++  edge true_edge, false_edge;
++  extract_true_false_edges_from_block (cond_bb, &true_edge, &false_edge);
++
++  /* For GE_EXPR, if the true edge goes to OTHER_BLOCK, then we
++     will need to invert the result.  Similarly for LT_EXPR if
++     the false edge goes to OTHER_BLOCK.  */
++  edge e;
++  if (cond_code == GE_EXPR)
++    e = true_edge;
++  else
++    e = false_edge;
++
++  bool invert = e->dest == middle_bb;
++
++  result = duplicate_ssa_name (result, NULL);
++
++  gimple_stmt_iterator gsi = gsi_last_bb (cond_bb);
++
++  int prec = TYPE_PRECISION (TREE_TYPE (clhs));
++  gimple *new_stmt
++    = gimple_build_assign (make_ssa_name (TREE_TYPE (clhs)), RSHIFT_EXPR, clhs,
++			   build_int_cst (integer_type_node, prec - 1));
++  gsi_insert_before (&gsi, new_stmt, GSI_SAME_STMT);
++
++  if (!useless_type_conversion_p (TREE_TYPE (result), TREE_TYPE (clhs)))
++    {
++      new_stmt = gimple_build_assign (make_ssa_name (TREE_TYPE (result)),
++				      NOP_EXPR, gimple_assign_lhs (new_stmt));
++      gsi_insert_before (&gsi, new_stmt, GSI_SAME_STMT);
++    }
++  lhs = gimple_assign_lhs (new_stmt);
++
++  if (invert)
++    {
++      new_stmt = gimple_build_assign (make_ssa_name (TREE_TYPE (result)),
++				      BIT_NOT_EXPR, rhs);
++      gsi_insert_before (&gsi, new_stmt, GSI_SAME_STMT);
++      rhs = gimple_assign_lhs (new_stmt);
++    }
++
++  new_stmt = gimple_build_assign (result, BIT_XOR_EXPR, lhs, rhs);
++  gsi_insert_before (&gsi, new_stmt, GSI_NEW_STMT);
++
++  replace_phi_edge_with_variable (cond_bb, e1, phi, result);
++
++  /* Note that we optimized this PHI.  */
++  return true;
++}
++
+ /* Auxiliary functions to determine the set of memory accesses which
+    can't trap because they are preceded by accesses to the same memory
+    portion.  We do that for MEM_REFs, so we only need to track
+-- 
+2.27.0.windows.1
+
diff --git a/0056-Backport-phiopt-Optimize-x-y-cmp-z-PR94589.patch b/0056-Backport-phiopt-Optimize-x-y-cmp-z-PR94589.patch
new file mode 100644
index 0000000..473dee8
--- /dev/null
+++ b/0056-Backport-phiopt-Optimize-x-y-cmp-z-PR94589.patch
@@ -0,0 +1,1067 @@
+From 02313ab8cf7eb4defc1482ece48c07c2d8c77be9 Mon Sep 17 00:00:00 2001
+From: Jakub Jelinek 
+Date: Thu, 6 May 2021 10:15:40 +0200
+Subject: [PATCH 08/35] [Backport] phiopt: Optimize (x <=> y) cmp z [PR94589]
+
+Reference: https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=ad96c867e173c1ebcfc201b201adac5095683a08
+
+genericize_spaceship genericizes i <=> j to approximately
+({ int c; if (i == j) c = 0; else if (i < j) c = -1; else c = 1; c; })
+for strong ordering and
+({ int c; if (i == j) c = 0; else if (i < j) c = -1; else if (i > j) c = 1; else c = 2; c; })
+for partial ordering.
+The C++ standard supports then == or != comparisons of that against
+strong/partial ordering enums, or />= comparisons of <=> result
+against literal 0.
+
+In some cases we already optimize that but in many cases we keep performing
+all the 2 or 3 comparisons, compute the spaceship value and then compare
+that.
+
+The following patch recognizes those patterns if the <=> operands are
+integral types or floating point (the latter only for -ffast-math) and
+optimizes it to the single comparison that is needed (plus adds debug stmts
+if needed for the spaceship result).
+
+There is one thing I'd like to address in a follow-up: the pr94589-2.C
+testcase should be matching just 12 times each, but runs
+into operator>=(partial_ordering, unspecified) being defined as
+(_M_value&1)==_M_value
+rather than _M_value>=0.  When not honoring NaNs, the 2 case should be
+unreachable and so (_M_value&1)==_M_value is then equivalent to _M_value>=0,
+but is not a single use but two uses.  I'll need to pattern match that case
+specially.
+
+2021-05-06  Jakub Jelinek  
+
+	PR tree-optimization/94589
+	* tree-ssa-phiopt.c (tree_ssa_phiopt_worker): Call
+	spaceship_replacement.
+	(cond_only_block_p, spaceship_replacement): New functions.
+
+	* gcc.dg/pr94589-1.c: New test.
+	* gcc.dg/pr94589-2.c: New test.
+	* gcc.dg/pr94589-3.c: New test.
+	* gcc.dg/pr94589-4.c: New test.
+	* g++.dg/opt/pr94589-1.C: New test.
+	* g++.dg/opt/pr94589-2.C: New test.
+	* g++.dg/opt/pr94589-3.C: New test.
+	* g++.dg/opt/pr94589-4.C: New test.
+---
+ gcc/testsuite/g++.dg/opt/pr94589-1.C |  33 +++
+ gcc/testsuite/g++.dg/opt/pr94589-2.C |  33 +++
+ gcc/testsuite/g++.dg/opt/pr94589-3.C |  84 ++++++
+ gcc/testsuite/g++.dg/opt/pr94589-4.C |  84 ++++++
+ gcc/testsuite/gcc.dg/pr94589-1.c     |  35 +++
+ gcc/testsuite/gcc.dg/pr94589-2.c     |  35 +++
+ gcc/testsuite/gcc.dg/pr94589-3.c     |  97 ++++++
+ gcc/testsuite/gcc.dg/pr94589-4.c     |  97 ++++++
+ gcc/tree-ssa-phiopt.c                | 424 +++++++++++++++++++++++++++
+ 9 files changed, 922 insertions(+)
+ create mode 100644 gcc/testsuite/g++.dg/opt/pr94589-1.C
+ create mode 100644 gcc/testsuite/g++.dg/opt/pr94589-2.C
+ create mode 100644 gcc/testsuite/g++.dg/opt/pr94589-3.C
+ create mode 100644 gcc/testsuite/g++.dg/opt/pr94589-4.C
+ create mode 100644 gcc/testsuite/gcc.dg/pr94589-1.c
+ create mode 100644 gcc/testsuite/gcc.dg/pr94589-2.c
+ create mode 100644 gcc/testsuite/gcc.dg/pr94589-3.c
+ create mode 100644 gcc/testsuite/gcc.dg/pr94589-4.c
+
+diff --git a/gcc/testsuite/g++.dg/opt/pr94589-1.C b/gcc/testsuite/g++.dg/opt/pr94589-1.C
+new file mode 100644
+index 000000000..d1cc5050c
+--- /dev/null
++++ b/gcc/testsuite/g++.dg/opt/pr94589-1.C
+@@ -0,0 +1,33 @@
++// PR tree-optimization/94589
++// { dg-do compile { target c++20 } }
++// { dg-options "-O2 -g0 -fdump-tree-optimized" }
++// { dg-final { scan-tree-dump-times "\[ij]_\[0-9]+\\(D\\) (?:<|<=|==|!=|>|>=) \[ij]_\[0-9]+\\(D\\)" 12 "optimized" } }
++// { dg-final { scan-tree-dump-times "i_\[0-9]+\\(D\\) (?:<|<=|==|!=|>|>=) \[45]" 12 "optimized" } }
++
++#include 
++
++#define A __attribute__((noipa))
++A bool f1 (int i, int j) { auto c = i <=> j; return c == 0; }
++A bool f2 (int i, int j) { auto c = i <=> j; return c != 0; }
++A bool f3 (int i, int j) { auto c = i <=> j; return c > 0; }
++A bool f4 (int i, int j) { auto c = i <=> j; return c < 0; }
++A bool f5 (int i, int j) { auto c = i <=> j; return c >= 0; }
++A bool f6 (int i, int j) { auto c = i <=> j; return c <= 0; }
++A bool f7 (int i, int j) { auto c = i <=> j; return c == std::strong_ordering::less; }
++A bool f8 (int i, int j) { auto c = i <=> j; return c != std::strong_ordering::less; }
++A bool f9 (int i, int j) { auto c = i <=> j; return c == std::strong_ordering::equal; }
++A bool f10 (int i, int j) { auto c = i <=> j; return c != std::strong_ordering::equal; }
++A bool f11 (int i, int j) { auto c = i <=> j; return c == std::strong_ordering::greater; }
++A bool f12 (int i, int j) { auto c = i <=> j; return c != std::strong_ordering::greater; }
++A bool f13 (int i) { auto c = i <=> 5; return c == 0; }
++A bool f14 (int i) { auto c = i <=> 5; return c != 0; }
++A bool f15 (int i) { auto c = i <=> 5; return c > 0; }
++A bool f16 (int i) { auto c = i <=> 5; return c < 0; }
++A bool f17 (int i) { auto c = i <=> 5; return c >= 0; }
++A bool f18 (int i) { auto c = i <=> 5; return c <= 0; }
++A bool f19 (int i) { auto c = i <=> 5; return c == std::strong_ordering::less; }
++A bool f20 (int i) { auto c = i <=> 5; return c != std::strong_ordering::less; }
++A bool f21 (int i) { auto c = i <=> 5; return c == std::strong_ordering::equal; }
++A bool f22 (int i) { auto c = i <=> 5; return c != std::strong_ordering::equal; }
++A bool f23 (int i) { auto c = i <=> 5; return c == std::strong_ordering::greater; }
++A bool f24 (int i) { auto c = i <=> 5; return c != std::strong_ordering::greater; }
+diff --git a/gcc/testsuite/g++.dg/opt/pr94589-2.C b/gcc/testsuite/g++.dg/opt/pr94589-2.C
+new file mode 100644
+index 000000000..dda947e22
+--- /dev/null
++++ b/gcc/testsuite/g++.dg/opt/pr94589-2.C
+@@ -0,0 +1,33 @@
++// PR tree-optimization/94589
++// { dg-do compile { target c++20 } }
++// { dg-options "-O2 -g0 -ffast-math -fdump-tree-optimized" }
++// { dg-final { scan-tree-dump-times "\[ij]_\[0-9]+\\(D\\) (?:<|<=|==|!=|>|>=) \[ij]_\[0-9]+\\(D\\)" 14 "optimized" } }
++// { dg-final { scan-tree-dump-times "i_\[0-9]+\\(D\\) (?:<|<=|==|!=|>|>=) 5\\.0" 14 "optimized" } }
++
++#include 
++
++#define A __attribute__((noipa))
++A bool f1 (double i, double j) { auto c = i <=> j; return c == 0; }
++A bool f2 (double i, double j) { auto c = i <=> j; return c != 0; }
++A bool f3 (double i, double j) { auto c = i <=> j; return c > 0; }
++A bool f4 (double i, double j) { auto c = i <=> j; return c < 0; }
++A bool f5 (double i, double j) { auto c = i <=> j; return c >= 0; }
++A bool f6 (double i, double j) { auto c = i <=> j; return c <= 0; }
++A bool f7 (double i, double j) { auto c = i <=> j; return c == std::partial_ordering::less; }
++A bool f8 (double i, double j) { auto c = i <=> j; return c != std::partial_ordering::less; }
++A bool f9 (double i, double j) { auto c = i <=> j; return c == std::partial_ordering::equivalent; }
++A bool f10 (double i, double j) { auto c = i <=> j; return c != std::partial_ordering::equivalent; }
++A bool f11 (double i, double j) { auto c = i <=> j; return c == std::partial_ordering::greater; }
++A bool f12 (double i, double j) { auto c = i <=> j; return c != std::partial_ordering::greater; }
++A bool f13 (double i) { auto c = i <=> 5.0; return c == 0; }
++A bool f14 (double i) { auto c = i <=> 5.0; return c != 0; }
++A bool f15 (double i) { auto c = i <=> 5.0; return c > 0; }
++A bool f16 (double i) { auto c = i <=> 5.0; return c < 0; }
++A bool f17 (double i) { auto c = i <=> 5.0; return c >= 0; }
++A bool f18 (double i) { auto c = i <=> 5.0; return c <= 0; }
++A bool f19 (double i) { auto c = i <=> 5.0; return c == std::partial_ordering::less; }
++A bool f20 (double i) { auto c = i <=> 5.0; return c != std::partial_ordering::less; }
++A bool f21 (double i) { auto c = i <=> 5.0; return c == std::partial_ordering::equivalent; }
++A bool f22 (double i) { auto c = i <=> 5.0; return c != std::partial_ordering::equivalent; }
++A bool f23 (double i) { auto c = i <=> 5.0; return c == std::partial_ordering::greater; }
++A bool f24 (double i) { auto c = i <=> 5.0; return c != std::partial_ordering::greater; }
+diff --git a/gcc/testsuite/g++.dg/opt/pr94589-3.C b/gcc/testsuite/g++.dg/opt/pr94589-3.C
+new file mode 100644
+index 000000000..725b81f56
+--- /dev/null
++++ b/gcc/testsuite/g++.dg/opt/pr94589-3.C
+@@ -0,0 +1,84 @@
++// { dg-do run { target c++20 } }
++// { dg-options "-O2 -g" }
++
++#include "pr94589-1.C"
++
++#define C(fn, i, j, r) if (fn (i, j) != r) __builtin_abort ()
++#define D(fn, i, r) if (fn (i) != r) __builtin_abort ()
++
++int
++main ()
++{
++  C (f1, 7, 8, false);
++  C (f1, 8, 8, true);
++  C (f1, 9, 8, false);
++  C (f2, 7, 8, true);
++  C (f2, 8, 8, false);
++  C (f2, 9, 8, true);
++  C (f3, 7, 8, false);
++  C (f3, 8, 8, false);
++  C (f3, 9, 8, true);
++  C (f4, 7, 8, true);
++  C (f4, 8, 8, false);
++  C (f4, 9, 8, false);
++  C (f5, 7, 8, false);
++  C (f5, 8, 8, true);
++  C (f5, 9, 8, true);
++  C (f6, 7, 8, true);
++  C (f6, 8, 8, true);
++  C (f6, 9, 8, false);
++  C (f7, 7, 8, true);
++  C (f7, 8, 8, false);
++  C (f7, 9, 8, false);
++  C (f8, 7, 8, false);
++  C (f8, 8, 8, true);
++  C (f8, 9, 8, true);
++  C (f9, 7, 8, false);
++  C (f9, 8, 8, true);
++  C (f9, 9, 8, false);
++  C (f10, 7, 8, true);
++  C (f10, 8, 8, false);
++  C (f10, 9, 8, true);
++  C (f11, 7, 8, false);
++  C (f11, 8, 8, false);
++  C (f11, 9, 8, true);
++  C (f12, 7, 8, true);
++  C (f12, 8, 8, true);
++  C (f12, 9, 8, false);
++  D (f13, 4, false);
++  D (f13, 5, true);
++  D (f13, 6, false);
++  D (f14, 4, true);
++  D (f14, 5, false);
++  D (f14, 6, true);
++  D (f15, 4, false);
++  D (f15, 5, false);
++  D (f15, 6, true);
++  D (f16, 4, true);
++  D (f16, 5, false);
++  D (f16, 6, false);
++  D (f17, 4, false);
++  D (f17, 5, true);
++  D (f17, 6, true);
++  D (f18, 4, true);
++  D (f18, 5, true);
++  D (f18, 6, false);
++  D (f19, 4, true);
++  D (f19, 5, false);
++  D (f19, 6, false);
++  D (f20, 4, false);
++  D (f20, 5, true);
++  D (f20, 6, true);
++  D (f21, 4, false);
++  D (f21, 5, true);
++  D (f21, 6, false);
++  D (f22, 4, true);
++  D (f22, 5, false);
++  D (f22, 6, true);
++  D (f23, 4, false);
++  D (f23, 5, false);
++  D (f23, 6, true);
++  D (f24, 4, true);
++  D (f24, 5, true);
++  D (f24, 6, false);
++}
+diff --git a/gcc/testsuite/g++.dg/opt/pr94589-4.C b/gcc/testsuite/g++.dg/opt/pr94589-4.C
+new file mode 100644
+index 000000000..256a45580
+--- /dev/null
++++ b/gcc/testsuite/g++.dg/opt/pr94589-4.C
+@@ -0,0 +1,84 @@
++// { dg-do run { target c++20 } }
++// { dg-options "-O2 -g -ffast-math" }
++
++#include "pr94589-2.C"
++
++#define C(fn, i, j, r) if (fn (i, j) != r) __builtin_abort ()
++#define D(fn, i, r) if (fn (i) != r) __builtin_abort ()
++
++int
++main ()
++{
++  C (f1, 7.0, 8.0, false);
++  C (f1, 8.0, 8.0, true);
++  C (f1, 9.0, 8.0, false);
++  C (f2, 7.0, 8.0, true);
++  C (f2, 8.0, 8.0, false);
++  C (f2, 9.0, 8.0, true);
++  C (f3, 7.0, 8.0, false);
++  C (f3, 8.0, 8.0, false);
++  C (f3, 9.0, 8.0, true);
++  C (f4, 7.0, 8.0, true);
++  C (f4, 8.0, 8.0, false);
++  C (f4, 9.0, 8.0, false);
++  C (f5, 7.0, 8.0, false);
++  C (f5, 8.0, 8.0, true);
++  C (f5, 9.0, 8.0, true);
++  C (f6, 7.0, 8.0, true);
++  C (f6, 8.0, 8.0, true);
++  C (f6, 9.0, 8.0, false);
++  C (f7, 7.0, 8.0, true);
++  C (f7, 8.0, 8.0, false);
++  C (f7, 9.0, 8.0, false);
++  C (f8, 7.0, 8.0, false);
++  C (f8, 8.0, 8.0, true);
++  C (f8, 9.0, 8.0, true);
++  C (f9, 7.0, 8.0, false);
++  C (f9, 8.0, 8.0, true);
++  C (f9, 9.0, 8.0, false);
++  C (f10, 7.0, 8.0, true);
++  C (f10, 8.0, 8.0, false);
++  C (f10, 9.0, 8.0, true);
++  C (f11, 7.0, 8.0, false);
++  C (f11, 8.0, 8.0, false);
++  C (f11, 9.0, 8.0, true);
++  C (f12, 7.0, 8.0, true);
++  C (f12, 8.0, 8.0, true);
++  C (f12, 9.0, 8.0, false);
++  D (f13, 4.0, false);
++  D (f13, 5.0, true);
++  D (f13, 6.0, false);
++  D (f14, 4.0, true);
++  D (f14, 5.0, false);
++  D (f14, 6.0, true);
++  D (f15, 4.0, false);
++  D (f15, 5.0, false);
++  D (f15, 6.0, true);
++  D (f16, 4.0, true);
++  D (f16, 5.0, false);
++  D (f16, 6.0, false);
++  D (f17, 4.0, false);
++  D (f17, 5.0, true);
++  D (f17, 6.0, true);
++  D (f18, 4.0, true);
++  D (f18, 5.0, true);
++  D (f18, 6.0, false);
++  D (f19, 4.0, true);
++  D (f19, 5.0, false);
++  D (f19, 6.0, false);
++  D (f20, 4.0, false);
++  D (f20, 5.0, true);
++  D (f20, 6.0, true);
++  D (f21, 4.0, false);
++  D (f21, 5.0, true);
++  D (f21, 6.0, false);
++  D (f22, 4.0, true);
++  D (f22, 5.0, false);
++  D (f22, 6.0, true);
++  D (f23, 4.0, false);
++  D (f23, 5.0, false);
++  D (f23, 6.0, true);
++  D (f24, 4.0, true);
++  D (f24, 5.0, true);
++  D (f24, 6.0, false);
++}
+diff --git a/gcc/testsuite/gcc.dg/pr94589-1.c b/gcc/testsuite/gcc.dg/pr94589-1.c
+new file mode 100644
+index 000000000..de404ea82
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/pr94589-1.c
+@@ -0,0 +1,35 @@
++/* PR tree-optimization/94589 */
++/* { dg-do compile } */
++/* { dg-options "-O2 -g0 -fdump-tree-optimized" } */
++/* { dg-final { scan-tree-dump-times "\[ij]_\[0-9]+\\(D\\) (?:<|<=|==|!=|>|>=) \[ij]_\[0-9]+\\(D\\)" 14 "optimized" } } */
++/* { dg-final { scan-tree-dump-times "i_\[0-9]+\\(D\\) (?:<|<=|==|!=|>|>=) \[45]" 14 "optimized" } } */
++
++#define A __attribute__((noipa))
++A int f1 (int i, int j) { int c = i == j ? 0 : i < j ? -1 : 1; return c == 0; }
++A int f2 (int i, int j) { int c = i == j ? 0 : i < j ? -1 : 1; return c != 0; }
++A int f3 (int i, int j) { int c = i == j ? 0 : i < j ? -1 : 1; return c > 0; }
++A int f4 (int i, int j) { int c = i == j ? 0 : i < j ? -1 : 1; return c < 0; }
++A int f5 (int i, int j) { int c = i == j ? 0 : i < j ? -1 : 1; return c >= 0; }
++A int f6 (int i, int j) { int c = i == j ? 0 : i < j ? -1 : 1; return c <= 0; }
++A int f7 (int i, int j) { int c = i == j ? 0 : i < j ? -1 : 1; return c == -1; }
++A int f8 (int i, int j) { int c = i == j ? 0 : i < j ? -1 : 1; return c != -1; }
++A int f9 (int i, int j) { int c = i == j ? 0 : i < j ? -1 : 1; return c > -1; }
++A int f10 (int i, int j) { int c = i == j ? 0 : i < j ? -1 : 1; return c <= -1; }
++A int f11 (int i, int j) { int c = i == j ? 0 : i < j ? -1 : 1; return c == 1; }
++A int f12 (int i, int j) { int c = i == j ? 0 : i < j ? -1 : 1; return c != 1; }
++A int f13 (int i, int j) { int c = i == j ? 0 : i < j ? -1 : 1; return c < 1; }
++A int f14 (int i, int j) { int c = i == j ? 0 : i < j ? -1 : 1; return c >= 1; }
++A int f15 (int i) { int c = i == 5 ? 0 : i < 5 ? -1 : 1; return c == 0; }
++A int f16 (int i) { int c = i == 5 ? 0 : i < 5 ? -1 : 1; return c != 0; }
++A int f17 (int i) { int c = i == 5 ? 0 : i < 5 ? -1 : 1; return c > 0; }
++A int f18 (int i) { int c = i == 5 ? 0 : i < 5 ? -1 : 1; return c < 0; }
++A int f19 (int i) { int c = i == 5 ? 0 : i < 5 ? -1 : 1; return c >= 0; }
++A int f20 (int i) { int c = i == 5 ? 0 : i < 5 ? -1 : 1; return c <= 0; }
++A int f21 (int i) { int c = i == 5 ? 0 : i < 5 ? -1 : 1; return c == -1; }
++A int f22 (int i) { int c = i == 5 ? 0 : i < 5 ? -1 : 1; return c != -1; }
++A int f23 (int i) { int c = i == 5 ? 0 : i < 5 ? -1 : 1; return c > -1; }
++A int f24 (int i) { int c = i == 5 ? 0 : i < 5 ? -1 : 1; return c <= -1; }
++A int f25 (int i) { int c = i == 5 ? 0 : i < 5 ? -1 : 1; return c == 1; }
++A int f26 (int i) { int c = i == 5 ? 0 : i < 5 ? -1 : 1; return c != 1; }
++A int f27 (int i) { int c = i == 5 ? 0 : i < 5 ? -1 : 1; return c < 1; }
++A int f28 (int i) { int c = i == 5 ? 0 : i < 5 ? -1 : 1; return c >= 1; }
+diff --git a/gcc/testsuite/gcc.dg/pr94589-2.c b/gcc/testsuite/gcc.dg/pr94589-2.c
+new file mode 100644
+index 000000000..9481b764d
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/pr94589-2.c
+@@ -0,0 +1,35 @@
++/* PR tree-optimization/94589 */
++/* { dg-do compile } */
++/* { dg-options "-O2 -g0 -ffast-math -fdump-tree-optimized" } */
++/* { dg-final { scan-tree-dump-times "\[ij]_\[0-9]+\\(D\\) (?:<|<=|==|!=|>|>=) \[ij]_\[0-9]+\\(D\\)" 14 "optimized" } } */
++/* { dg-final { scan-tree-dump-times "i_\[0-9]+\\(D\\) (?:<|<=|==|!=|>|>=) 5\\.0" 14 "optimized" } } */
++
++#define A __attribute__((noipa))
++A int f1 (double i, double j) { int c; if (i == j) c = 0; else if (i < j) c = -1; else if (i > j) c = 1; else c = 2; return c == 0; }
++A int f2 (double i, double j) { int c; if (i == j) c = 0; else if (i < j) c = -1; else if (i > j) c = 1; else c = 2; return c != 0; }
++A int f3 (double i, double j) { int c; if (i == j) c = 0; else if (i < j) c = -1; else if (i > j) c = 1; else c = 2; return c > 0; }
++A int f4 (double i, double j) { int c; if (i == j) c = 0; else if (i < j) c = -1; else if (i > j) c = 1; else c = 2; return c < 0; }
++A int f5 (double i, double j) { int c; if (i == j) c = 0; else if (i < j) c = -1; else if (i > j) c = 1; else c = 2; return c >= 0; }
++A int f6 (double i, double j) { int c; if (i == j) c = 0; else if (i < j) c = -1; else if (i > j) c = 1; else c = 2; return c <= 0; }
++A int f7 (double i, double j) { int c; if (i == j) c = 0; else if (i < j) c = -1; else if (i > j) c = 1; else c = 2; return c == -1; }
++A int f8 (double i, double j) { int c; if (i == j) c = 0; else if (i < j) c = -1; else if (i > j) c = 1; else c = 2; return c != -1; }
++A int f9 (double i, double j) { int c; if (i == j) c = 0; else if (i < j) c = -1; else if (i > j) c = 1; else c = 2; return c > -1; }
++A int f10 (double i, double j) { int c; if (i == j) c = 0; else if (i < j) c = -1; else if (i > j) c = 1; else c = 2; return c <= -1; }
++A int f11 (double i, double j) { int c; if (i == j) c = 0; else if (i < j) c = -1; else if (i > j) c = 1; else c = 2; return c == 1; }
++A int f12 (double i, double j) { int c; if (i == j) c = 0; else if (i < j) c = -1; else if (i > j) c = 1; else c = 2; return c != 1; }
++A int f13 (double i, double j) { int c; if (i == j) c = 0; else if (i < j) c = -1; else if (i > j) c = 1; else c = 2; return c < 1; }
++A int f14 (double i, double j) { int c; if (i == j) c = 0; else if (i < j) c = -1; else if (i > j) c = 1; else c = 2; return c >= 1; }
++A int f15 (double i) { int c; if (i == 5.0) c = 0; else if (i < 5.0) c = -1; else if (i > 5.0) c = 1; else c = 2; return c == 0; }
++A int f16 (double i) { int c; if (i == 5.0) c = 0; else if (i < 5.0) c = -1; else if (i > 5.0) c = 1; else c = 2; return c != 0; }
++A int f17 (double i) { int c; if (i == 5.0) c = 0; else if (i < 5.0) c = -1; else if (i > 5.0) c = 1; else c = 2; return c > 0; }
++A int f18 (double i) { int c; if (i == 5.0) c = 0; else if (i < 5.0) c = -1; else if (i > 5.0) c = 1; else c = 2; return c < 0; }
++A int f19 (double i) { int c; if (i == 5.0) c = 0; else if (i < 5.0) c = -1; else if (i > 5.0) c = 1; else c = 2; return c >= 0; }
++A int f20 (double i) { int c; if (i == 5.0) c = 0; else if (i < 5.0) c = -1; else if (i > 5.0) c = 1; else c = 2; return c <= 0; }
++A int f21 (double i) { int c; if (i == 5.0) c = 0; else if (i < 5.0) c = -1; else if (i > 5.0) c = 1; else c = 2; return c == -1; }
++A int f22 (double i) { int c; if (i == 5.0) c = 0; else if (i < 5.0) c = -1; else if (i > 5.0) c = 1; else c = 2; return c != -1; }
++A int f23 (double i) { int c; if (i == 5.0) c = 0; else if (i < 5.0) c = -1; else if (i > 5.0) c = 1; else c = 2; return c > -1; }
++A int f24 (double i) { int c; if (i == 5.0) c = 0; else if (i < 5.0) c = -1; else if (i > 5.0) c = 1; else c = 2; return c <= -1; }
++A int f25 (double i) { int c; if (i == 5.0) c = 0; else if (i < 5.0) c = -1; else if (i > 5.0) c = 1; else c = 2; return c == 1; }
++A int f26 (double i) { int c; if (i == 5.0) c = 0; else if (i < 5.0) c = -1; else if (i > 5.0) c = 1; else c = 2; return c != 1; }
++A int f27 (double i) { int c; if (i == 5.0) c = 0; else if (i < 5.0) c = -1; else if (i > 5.0) c = 1; else c = 2; return c < 1; }
++A int f28 (double i) { int c; if (i == 5.0) c = 0; else if (i < 5.0) c = -1; else if (i > 5.0) c = 1; else c = 2; return c >= 1; }
+diff --git a/gcc/testsuite/gcc.dg/pr94589-3.c b/gcc/testsuite/gcc.dg/pr94589-3.c
+new file mode 100644
+index 000000000..df82fab73
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/pr94589-3.c
+@@ -0,0 +1,97 @@
++/* { dg-do run } */
++/* { dg-options "-O2 -g" } */
++
++#include "pr94589-1.c"
++
++#define C(fn, i, j, r) if (fn (i, j) != r) __builtin_abort ()
++#define D(fn, i, r) if (fn (i) != r) __builtin_abort ()
++
++int
++main ()
++{
++  C (f1, 7, 8, 0);
++  C (f1, 8, 8, 1);
++  C (f1, 9, 8, 0);
++  C (f2, 7, 8, 1);
++  C (f2, 8, 8, 0);
++  C (f2, 9, 8, 1);
++  C (f3, 7, 8, 0);
++  C (f3, 8, 8, 0);
++  C (f3, 9, 8, 1);
++  C (f4, 7, 8, 1);
++  C (f4, 8, 8, 0);
++  C (f4, 9, 8, 0);
++  C (f5, 7, 8, 0);
++  C (f5, 8, 8, 1);
++  C (f5, 9, 8, 1);
++  C (f6, 7, 8, 1);
++  C (f6, 8, 8, 1);
++  C (f6, 9, 8, 0);
++  C (f7, 7, 8, 1);
++  C (f7, 8, 8, 0);
++  C (f7, 9, 8, 0);
++  C (f8, 7, 8, 0);
++  C (f8, 8, 8, 1);
++  C (f8, 9, 8, 1);
++  C (f9, 7, 8, 0);
++  C (f9, 8, 8, 1);
++  C (f9, 9, 8, 1);
++  C (f10, 7, 8, 1);
++  C (f10, 8, 8, 0);
++  C (f10, 9, 8, 0);
++  C (f11, 7, 8, 0);
++  C (f11, 8, 8, 0);
++  C (f11, 9, 8, 1);
++  C (f12, 7, 8, 1);
++  C (f12, 8, 8, 1);
++  C (f12, 9, 8, 0);
++  C (f13, 7, 8, 1);
++  C (f13, 8, 8, 1);
++  C (f13, 9, 8, 0);
++  C (f14, 7, 8, 0);
++  C (f14, 8, 8, 0);
++  C (f14, 9, 8, 1);
++  D (f15, 4, 0);
++  D (f15, 5, 1);
++  D (f15, 6, 0);
++  D (f16, 4, 1);
++  D (f16, 5, 0);
++  D (f16, 6, 1);
++  D (f17, 4, 0);
++  D (f17, 5, 0);
++  D (f17, 6, 1);
++  D (f18, 4, 1);
++  D (f18, 5, 0);
++  D (f18, 6, 0);
++  D (f19, 4, 0);
++  D (f19, 5, 1);
++  D (f19, 6, 1);
++  D (f20, 4, 1);
++  D (f20, 5, 1);
++  D (f20, 6, 0);
++  D (f21, 4, 1);
++  D (f21, 5, 0);
++  D (f21, 6, 0);
++  D (f22, 4, 0);
++  D (f22, 5, 1);
++  D (f22, 6, 1);
++  D (f23, 4, 0);
++  D (f23, 5, 1);
++  D (f23, 6, 1);
++  D (f24, 4, 1);
++  D (f24, 5, 0);
++  D (f24, 6, 0);
++  D (f25, 4, 0);
++  D (f25, 5, 0);
++  D (f25, 6, 1);
++  D (f26, 4, 1);
++  D (f26, 5, 1);
++  D (f26, 6, 0);
++  D (f27, 4, 1);
++  D (f27, 5, 1);
++  D (f27, 6, 0);
++  D (f28, 4, 0);
++  D (f28, 5, 0);
++  D (f28, 6, 1);
++  return 0;
++}
+diff --git a/gcc/testsuite/gcc.dg/pr94589-4.c b/gcc/testsuite/gcc.dg/pr94589-4.c
+new file mode 100644
+index 000000000..b2557fb07
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/pr94589-4.c
+@@ -0,0 +1,97 @@
++/* { dg-do run } */
++/* { dg-options "-O2 -g -ffast-math" } */
++
++#include "pr94589-2.c"
++
++#define C(fn, i, j, r) if (fn (i, j) != r) __builtin_abort ()
++#define D(fn, i, r) if (fn (i) != r) __builtin_abort ()
++
++int
++main ()
++{
++  C (f1, 7.0, 8.0, 0);
++  C (f1, 8.0, 8.0, 1);
++  C (f1, 9.0, 8.0, 0);
++  C (f2, 7.0, 8.0, 1);
++  C (f2, 8.0, 8.0, 0);
++  C (f2, 9.0, 8.0, 1);
++  C (f3, 7.0, 8.0, 0);
++  C (f3, 8.0, 8.0, 0);
++  C (f3, 9.0, 8.0, 1);
++  C (f4, 7.0, 8.0, 1);
++  C (f4, 8.0, 8.0, 0);
++  C (f4, 9.0, 8.0, 0);
++  C (f5, 7.0, 8.0, 0);
++  C (f5, 8.0, 8.0, 1);
++  C (f5, 9.0, 8.0, 1);
++  C (f6, 7.0, 8.0, 1);
++  C (f6, 8.0, 8.0, 1);
++  C (f6, 9.0, 8.0, 0);
++  C (f7, 7.0, 8.0, 1);
++  C (f7, 8.0, 8.0, 0);
++  C (f7, 9.0, 8.0, 0);
++  C (f8, 7.0, 8.0, 0);
++  C (f8, 8.0, 8.0, 1);
++  C (f8, 9.0, 8.0, 1);
++  C (f9, 7.0, 8.0, 0);
++  C (f9, 8.0, 8.0, 1);
++  C (f9, 9.0, 8.0, 1);
++  C (f10, 7.0, 8.0, 1);
++  C (f10, 8.0, 8.0, 0);
++  C (f10, 9.0, 8.0, 0);
++  C (f11, 7.0, 8.0, 0);
++  C (f11, 8.0, 8.0, 0);
++  C (f11, 9.0, 8.0, 1);
++  C (f12, 7.0, 8.0, 1);
++  C (f12, 8.0, 8.0, 1);
++  C (f12, 9.0, 8.0, 0);
++  C (f13, 7.0, 8.0, 1);
++  C (f13, 8.0, 8.0, 1);
++  C (f13, 9.0, 8.0, 0);
++  C (f14, 7.0, 8.0, 0);
++  C (f14, 8.0, 8.0, 0);
++  C (f14, 9.0, 8.0, 1);
++  D (f15, 4.0, 0);
++  D (f15, 5.0, 1);
++  D (f15, 6.0, 0);
++  D (f16, 4.0, 1);
++  D (f16, 5.0, 0);
++  D (f16, 6.0, 1);
++  D (f17, 4.0, 0);
++  D (f17, 5.0, 0);
++  D (f17, 6.0, 1);
++  D (f18, 4.0, 1);
++  D (f18, 5.0, 0);
++  D (f18, 6.0, 0);
++  D (f19, 4.0, 0);
++  D (f19, 5.0, 1);
++  D (f19, 6.0, 1);
++  D (f20, 4.0, 1);
++  D (f20, 5.0, 1);
++  D (f20, 6.0, 0);
++  D (f21, 4.0, 1);
++  D (f21, 5.0, 0);
++  D (f21, 6.0, 0);
++  D (f22, 4.0, 0);
++  D (f22, 5.0, 1);
++  D (f22, 6.0, 1);
++  D (f23, 4.0, 0);
++  D (f23, 5.0, 1);
++  D (f23, 6.0, 1);
++  D (f24, 4.0, 1);
++  D (f24, 5.0, 0);
++  D (f24, 6.0, 0);
++  D (f25, 4.0, 0);
++  D (f25, 5.0, 0);
++  D (f25, 6.0, 1);
++  D (f26, 4.0, 1);
++  D (f26, 5.0, 1);
++  D (f26, 6.0, 0);
++  D (f27, 4.0, 1);
++  D (f27, 5.0, 1);
++  D (f27, 6.0, 0);
++  D (f28, 4.0, 0);
++  D (f28, 5.0, 0);
++  D (f28, 6.0, 1);
++  return 0;
++}
+diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c
+index b9cd07a60..fca32222f 100644
+--- a/gcc/tree-ssa-phiopt.c
++++ b/gcc/tree-ssa-phiopt.c
+@@ -63,6 +63,8 @@ static bool abs_replacement (basic_block, basic_block,
+ 			     edge, edge, gimple *, tree, tree);
+ static bool xor_replacement (basic_block, basic_block,
+ 			     edge, edge, gimple *, tree, tree);
++static bool spaceship_replacement (basic_block, basic_block,
++				   edge, edge, gphi *, tree, tree);
+ static bool cond_removal_in_popcount_clz_ctz_pattern (basic_block, basic_block,
+ 						      edge, edge, gimple *,
+ 						      tree, tree);
+@@ -361,6 +363,8 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads, bool early_p)
+ 	    cfgchanged = true;
+ 	  else if (minmax_replacement (bb, bb1, e1, e2, phi, arg0, arg1))
+ 	    cfgchanged = true;
++	  else if (spaceship_replacement (bb, bb1, e1, e2, phi, arg0, arg1))
++	    cfgchanged = true;
+ 	}
+     }
+ 
+@@ -1753,6 +1757,426 @@ minmax_replacement (basic_block cond_bb, basic_block middle_bb,
+   return true;
+ }
+ 
++/* Return true if the only executable statement in BB is a GIMPLE_COND.  */
++
++static bool
++cond_only_block_p (basic_block bb)
++{
++  /* BB must have no executable statements.  */
++  gimple_stmt_iterator gsi = gsi_after_labels (bb);
++  if (phi_nodes (bb))
++    return false;
++  while (!gsi_end_p (gsi))
++    {
++      gimple *stmt = gsi_stmt (gsi);
++      if (is_gimple_debug (stmt))
++	;
++      else if (gimple_code (stmt) == GIMPLE_NOP
++	       || gimple_code (stmt) == GIMPLE_PREDICT
++	       || gimple_code (stmt) == GIMPLE_COND)
++	;
++      else
++	return false;
++      gsi_next (&gsi);
++    }
++  return true;
++}
++
++/* Attempt to optimize (x <=> y) cmp 0 and similar comparisons.
++   For strong ordering <=> try to match something like:
++     :  // cond3_bb (== cond2_bb)
++    if (x_4(D) != y_5(D))
++      goto ; [INV]
++    else
++      goto ; [INV]
++
++     :  // cond_bb
++    if (x_4(D) < y_5(D))
++      goto ; [INV]
++    else
++      goto ; [INV]
++
++     :  // middle_bb
++
++     :  // phi_bb
++    # iftmp.0_2 = PHI <1(4), 0(2), -1(3)>
++    _1 = iftmp.0_2 == 0;
++
++   and for partial ordering <=> something like:
++
++     :  // cond3_bb
++    if (a_3(D) == b_5(D))
++      goto ; [50.00%]
++    else
++      goto ; [50.00%]
++
++     [local count: 536870913]:  // cond2_bb
++    if (a_3(D) < b_5(D))
++      goto ; [50.00%]
++    else
++      goto ; [50.00%]
++
++     [local count: 268435456]:  // cond_bb
++    if (a_3(D) > b_5(D))
++      goto ; [50.00%]
++    else
++      goto ; [50.00%]
++
++     [local count: 134217728]:  // middle_bb
++
++     [local count: 1073741824]:  // phi_bb
++    # SR.27_4 = PHI <0(2), -1(3), 1(4), 2(5)>
++    _2 = SR.27_4 > 0;  */
++
++static bool
++spaceship_replacement (basic_block cond_bb, basic_block middle_bb,
++		       edge e0, edge e1, gphi *phi,
++		       tree arg0, tree arg1)
++{
++  if (!INTEGRAL_TYPE_P (TREE_TYPE (PHI_RESULT (phi)))
++      || TYPE_UNSIGNED (TREE_TYPE (PHI_RESULT (phi)))
++      || !tree_fits_shwi_p (arg0)
++      || !tree_fits_shwi_p (arg1)
++      || !IN_RANGE (tree_to_shwi (arg0), -1, 2)
++      || !IN_RANGE (tree_to_shwi (arg1), -1, 2))
++    return false;
++
++  basic_block phi_bb = gimple_bb (phi);
++  gcc_assert (phi_bb == e0->dest && phi_bb == e1->dest);
++  if (!IN_RANGE (EDGE_COUNT (phi_bb->preds), 3, 4))
++    return false;
++
++  use_operand_p use_p;
++  gimple *use_stmt;
++  if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (PHI_RESULT (phi)))
++    return false;
++  if (!single_imm_use (PHI_RESULT (phi), &use_p, &use_stmt))
++    return false;
++  enum tree_code cmp;
++  tree lhs, rhs;
++  if (gimple_code (use_stmt) == GIMPLE_COND)
++    {
++      cmp = gimple_cond_code (use_stmt);
++      lhs = gimple_cond_lhs (use_stmt);
++      rhs = gimple_cond_rhs (use_stmt);
++    }
++  else if (is_gimple_assign (use_stmt))
++    {
++      if (gimple_assign_rhs_class (use_stmt) == GIMPLE_BINARY_RHS)
++	{
++	  cmp = gimple_assign_rhs_code (use_stmt);
++	  lhs = gimple_assign_rhs1 (use_stmt);
++	  rhs = gimple_assign_rhs2 (use_stmt);
++	}
++      else if (gimple_assign_rhs_code (use_stmt) == COND_EXPR)
++	{
++	  tree cond = gimple_assign_rhs1 (use_stmt);
++	  if (!COMPARISON_CLASS_P (cond))
++	    return false;
++	  cmp = TREE_CODE (cond);
++	  lhs = TREE_OPERAND (cond, 0);
++	  rhs = TREE_OPERAND (cond, 1);
++	}
++      else
++	return false;
++    }
++  else
++    return false;
++  switch (cmp)
++    {
++    case EQ_EXPR:
++    case NE_EXPR:
++    case LT_EXPR:
++    case GT_EXPR:
++    case LE_EXPR:
++    case GE_EXPR:
++      break;
++    default:
++      return false;
++    }
++  if (lhs != PHI_RESULT (phi)
++      || !tree_fits_shwi_p (rhs)
++      || !IN_RANGE (tree_to_shwi (rhs), -1, 1))
++    return false;
++
++  if (!empty_block_p (middle_bb))
++    return false;
++
++  gcond *cond1 = as_a  (last_stmt (cond_bb));
++  enum tree_code cmp1 = gimple_cond_code (cond1);
++  if (cmp1 != LT_EXPR && cmp1 != GT_EXPR)
++    return false;
++  tree lhs1 = gimple_cond_lhs (cond1);
++  tree rhs1 = gimple_cond_rhs (cond1);
++  /* The optimization may be unsafe due to NaNs.  */
++  if (HONOR_NANS (TREE_TYPE (lhs1)))
++    return false;
++  if (TREE_CODE (lhs1) == SSA_NAME && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs1))
++    return false;
++  if (TREE_CODE (rhs1) == SSA_NAME && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs1))
++    return false;
++
++  if (!single_pred_p (cond_bb) || !cond_only_block_p (cond_bb))
++    return false;
++
++  basic_block cond2_bb = single_pred (cond_bb);
++  if (EDGE_COUNT (cond2_bb->succs) != 2)
++    return false;
++  edge cond2_phi_edge;
++  if (EDGE_SUCC (cond2_bb, 0)->dest == cond_bb)
++    {
++      if (EDGE_SUCC (cond2_bb, 1)->dest != phi_bb)
++	return false;
++      cond2_phi_edge = EDGE_SUCC (cond2_bb, 1);
++    }
++  else if (EDGE_SUCC (cond2_bb, 0)->dest != phi_bb)
++    return false;
++  else
++    cond2_phi_edge = EDGE_SUCC (cond2_bb, 0);
++  tree arg2 = gimple_phi_arg_def (phi, cond2_phi_edge->dest_idx);
++  if (!tree_fits_shwi_p (arg2))
++    return false;
++  gimple *cond2 = last_stmt (cond2_bb);
++  if (cond2 == NULL || gimple_code (cond2) != GIMPLE_COND)
++    return false;
++  enum tree_code cmp2 = gimple_cond_code (cond2);
++  tree lhs2 = gimple_cond_lhs (cond2);
++  tree rhs2 = gimple_cond_rhs (cond2);
++  if (lhs2 == lhs1)
++    {
++      if (!operand_equal_p (rhs2, rhs1, 0))
++	return false;
++    }
++  else if (lhs2 == rhs1)
++    {
++      if (rhs2 != lhs1)
++	return false;
++    }
++  else
++    return false;
++
++  tree arg3 = arg2;
++  basic_block cond3_bb = cond2_bb;
++  edge cond3_phi_edge = cond2_phi_edge;
++  gimple *cond3 = cond2;
++  enum tree_code cmp3 = cmp2;
++  tree lhs3 = lhs2;
++  tree rhs3 = rhs2;
++  if (EDGE_COUNT (phi_bb->preds) == 4)
++    {
++      if (absu_hwi (tree_to_shwi (arg2)) != 1)
++	return false;
++      if (e1->flags & EDGE_TRUE_VALUE)
++	{
++	  if (tree_to_shwi (arg0) != 2
++	      || absu_hwi (tree_to_shwi (arg1)) != 1
++	      || wi::to_widest (arg1) == wi::to_widest (arg2))
++	    return false;
++	}
++      else if (tree_to_shwi (arg1) != 2
++	       || absu_hwi (tree_to_shwi (arg0)) != 1
++	       || wi::to_widest (arg0) == wi::to_widest (arg1))
++	return false;
++      if (cmp2 != LT_EXPR && cmp2 != GT_EXPR)
++	return false;
++      /* if (x < y) goto phi_bb; else fallthru;
++	 if (x > y) goto phi_bb; else fallthru;
++	 bbx:;
++	 phi_bb:;
++	 is ok, but if x and y are swapped in one of the comparisons,
++	 or the comparisons are the same and operands not swapped,
++	 or second goto phi_bb is not the true edge, it is not.  */
++      if ((lhs2 == lhs1)
++	  ^ (cmp2 == cmp1)
++	  ^ ((e1->flags & EDGE_TRUE_VALUE) != 0))
++	return false;
++      if ((cond2_phi_edge->flags & EDGE_TRUE_VALUE) == 0)
++	return false;
++      if (!single_pred_p (cond2_bb) || !cond_only_block_p (cond2_bb))
++	return false;
++      cond3_bb = single_pred (cond2_bb);
++      if (EDGE_COUNT (cond2_bb->succs) != 2)
++	return false;
++      if (EDGE_SUCC (cond3_bb, 0)->dest == cond2_bb)
++	{
++	  if (EDGE_SUCC (cond3_bb, 1)->dest != phi_bb)
++	    return false;
++	  cond3_phi_edge = EDGE_SUCC (cond3_bb, 1);
++	}
++      else if (EDGE_SUCC (cond3_bb, 0)->dest != phi_bb)
++	return false;
++      else
++	cond3_phi_edge = EDGE_SUCC (cond3_bb, 0);
++      arg3 = gimple_phi_arg_def (phi, cond3_phi_edge->dest_idx);
++      cond3 = last_stmt (cond3_bb);
++      if (cond3 == NULL || gimple_code (cond3) != GIMPLE_COND)
++	return false;
++      cmp3 = gimple_cond_code (cond3);
++      lhs3 = gimple_cond_lhs (cond3);
++      rhs3 = gimple_cond_rhs (cond3);
++      if (lhs3 == lhs1)
++	{
++	  if (!operand_equal_p (rhs3, rhs1, 0))
++	    return false;
++	}
++      else if (lhs3 == rhs1)
++	{
++	  if (rhs3 != lhs1)
++	    return false;
++	}
++      else
++	return false;
++    }
++  else if (absu_hwi (tree_to_shwi (arg0)) != 1
++	   || absu_hwi (tree_to_shwi (arg1)) != 1
++	   || wi::to_widest (arg0) == wi::to_widest (arg1))
++    return false;
++
++  if (!integer_zerop (arg3) || (cmp3 != EQ_EXPR && cmp3 != NE_EXPR))
++    return false;
++  if ((cond3_phi_edge->flags & (cmp3 == EQ_EXPR
++				? EDGE_TRUE_VALUE : EDGE_FALSE_VALUE)) == 0)
++    return false;
++
++  /* lhs1 one_cmp rhs1 results in PHI_RESULT (phi) of 1.  */
++  enum tree_code one_cmp;
++  if ((cmp1 == LT_EXPR)
++      ^ (!integer_onep ((e1->flags & EDGE_TRUE_VALUE) ? arg1 : arg0)))
++    one_cmp = LT_EXPR;
++  else
++    one_cmp = GT_EXPR;
++
++  enum tree_code res_cmp;
++  switch (cmp)
++    {
++    case EQ_EXPR:
++      if (integer_zerop (rhs))
++	res_cmp = EQ_EXPR;
++      else if (integer_minus_onep (rhs))
++	res_cmp = one_cmp == LT_EXPR ? GT_EXPR : LT_EXPR;
++      else if (integer_onep (rhs))
++	res_cmp = one_cmp;
++      else
++	return false;
++      break;
++    case NE_EXPR:
++      if (integer_zerop (rhs))
++	res_cmp = NE_EXPR;
++      else if (integer_minus_onep (rhs))
++	res_cmp = one_cmp == LT_EXPR ? LE_EXPR : GE_EXPR;
++      else if (integer_onep (rhs))
++	res_cmp = one_cmp == LT_EXPR ? GE_EXPR : LE_EXPR;
++      else
++	return false;
++      break;
++    case LT_EXPR:
++      if (integer_onep (rhs))
++	res_cmp = one_cmp == LT_EXPR ? GE_EXPR : LE_EXPR;
++      else if (integer_zerop (rhs))
++	res_cmp = one_cmp == LT_EXPR ? GT_EXPR : LT_EXPR;
++      else
++	return false;
++      break;
++    case LE_EXPR:
++      if (integer_zerop (rhs))
++	res_cmp = one_cmp == LT_EXPR ? GE_EXPR : LE_EXPR;
++      else if (integer_minus_onep (rhs))
++	res_cmp = one_cmp == LT_EXPR ? GT_EXPR : LT_EXPR;
++      else
++	return false;
++      break;
++    case GT_EXPR:
++      if (integer_minus_onep (rhs))
++	res_cmp = one_cmp == LT_EXPR ? LE_EXPR : GE_EXPR;
++      else if (integer_zerop (rhs))
++	res_cmp = one_cmp;
++      else
++	return false;
++      break;
++    case GE_EXPR:
++      if (integer_zerop (rhs))
++	res_cmp = one_cmp == LT_EXPR ? LE_EXPR : GE_EXPR;
++      else if (integer_onep (rhs))
++	res_cmp = one_cmp;
++      else
++	return false;
++      break;
++    default:
++      gcc_unreachable ();
++    }
++
++  if (gimple_code (use_stmt) == GIMPLE_COND)
++    {
++      gcond *use_cond = as_a  (use_stmt);
++      gimple_cond_set_code (use_cond, res_cmp);
++      gimple_cond_set_lhs (use_cond, lhs1);
++      gimple_cond_set_rhs (use_cond, rhs1);
++    }
++  else if (gimple_assign_rhs_class (use_stmt) == GIMPLE_BINARY_RHS)
++    {
++      gimple_assign_set_rhs_code (use_stmt, res_cmp);
++      gimple_assign_set_rhs1 (use_stmt, lhs1);
++      gimple_assign_set_rhs2 (use_stmt, rhs1);
++    }
++  else
++    {
++      tree cond = build2 (res_cmp, TREE_TYPE (gimple_assign_rhs1 (use_stmt)),
++			  lhs1, rhs1);
++      gimple_assign_set_rhs1 (use_stmt, cond);
++    }
++  update_stmt (use_stmt);
++
++  if (MAY_HAVE_DEBUG_BIND_STMTS)
++    {
++      use_operand_p use_p;
++      imm_use_iterator iter;
++      bool has_debug_uses = false;
++      FOR_EACH_IMM_USE_FAST (use_p, iter, PHI_RESULT (phi))
++	{
++	  gimple *use_stmt = USE_STMT (use_p);
++	  gcc_assert (is_gimple_debug (use_stmt));
++	  has_debug_uses = true;
++	  break;
++	}
++
++      if (has_debug_uses)
++	{
++	  /* If there are debug uses, emit something like:
++	     # DEBUG D#1 => i_2(D) > j_3(D) ? 1 : -1
++	     # DEBUG D#2 => i_2(D) == j_3(D) ? 0 : D#1
++	     where > stands for the comparison that yielded 1
++	     and replace debug uses of phi result with that D#2.
++	     Ignore the value of 2, because if NaNs aren't expected,
++	     all floating point numbers should be comparable.  */
++	  gimple_stmt_iterator gsi = gsi_after_labels (gimple_bb (phi));
++	  tree type = TREE_TYPE (PHI_RESULT (phi));
++	  tree temp1 = make_node (DEBUG_EXPR_DECL);
++	  DECL_ARTIFICIAL (temp1) = 1;
++	  TREE_TYPE (temp1) = type;
++	  SET_DECL_MODE (temp1, TYPE_MODE (type));
++	  tree t = build2 (one_cmp, boolean_type_node, lhs1, rhs2);
++	  t = build3 (COND_EXPR, type, t, build_one_cst (type),
++		      build_int_cst (type, -1));
++	  gimple *g = gimple_build_debug_bind (temp1, t, phi);
++	  gsi_insert_before (&gsi, g, GSI_SAME_STMT);
++	  tree temp2 = make_node (DEBUG_EXPR_DECL);
++	  DECL_ARTIFICIAL (temp2) = 1;
++	  TREE_TYPE (temp2) = type;
++	  SET_DECL_MODE (temp2, TYPE_MODE (type));
++	  t = build2 (EQ_EXPR, boolean_type_node, lhs1, rhs2);
++	  t = build3 (COND_EXPR, type, t, build_zero_cst (type), temp1);
++	  g = gimple_build_debug_bind (temp2, t, phi);
++	  gsi_insert_before (&gsi, g, GSI_SAME_STMT);
++	  replace_uses_by (PHI_RESULT (phi), temp2);
++	}
++    }
++
++  gimple_stmt_iterator psi = gsi_for_stmt (phi);
++  remove_phi_node (&psi, true);
++
++  return true;
++}
++
+ /* Convert
+ 
+    
+-- 
+2.27.0.windows.1
+
diff --git a/0057-Backport-Add-support-for-__builtin_bswap128.patch b/0057-Backport-Add-support-for-__builtin_bswap128.patch
new file mode 100644
index 0000000..5f00306
--- /dev/null
+++ b/0057-Backport-Add-support-for-__builtin_bswap128.patch
@@ -0,0 +1,253 @@
+From 96afd5b761a74e9eef40a2e843810c503c669de8 Mon Sep 17 00:00:00 2001
+From: Eric Botcazou 
+Date: Thu, 28 May 2020 00:31:15 +0200
+Subject: [PATCH 09/35] [Backport] Add support for __builtin_bswap128
+
+Reference: https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=fe7ebef7fe4f9acb79658ed9db0749b07efc3105
+
+This patch introduces a new builtin named __builtin_bswap128 on targets
+where TImode is supported, i.e. 64-bit targets only in practice.  The
+implementation simply reuses the existing double word path in optab, so
+no routine is added to libgcc (which means that you get two calls to
+_bswapdi2 in the worst case).
+
+gcc/ChangeLog:
+
+	* builtin-types.def (BT_UINT128): New primitive type.
+	(BT_FN_UINT128_UINT128): New function type.
+	* builtins.def (BUILT_IN_BSWAP128): New GCC builtin.
+	* doc/extend.texi (__builtin_bswap128): Document it.
+	* builtins.c (expand_builtin): Deal with BUILT_IN_BSWAP128.
+	(is_inexpensive_builtin): Likewise.
+	* fold-const-call.c (fold_const_call_ss): Likewise.
+	* fold-const.c (tree_call_nonnegative_warnv_p): Likewise.
+	* tree-ssa-ccp.c (evaluate_stmt): Likewise.
+	* tree-vect-stmts.c (vect_get_data_ptr_increment): Likewise.
+	(vectorizable_call): Likewise.
+	* optabs.c (expand_unop): Always use the double word path for it.
+	* tree-core.h (enum tree_index): Add TI_UINT128_TYPE.
+	* tree.h (uint128_type_node): New global type.
+	* tree.c (build_common_tree_nodes): Build it if TImode is supported.
+
+gcc/testsuite/ChangeLog:
+
+	* gcc.dg/builtin-bswap-10.c: New test.
+	* gcc.dg/builtin-bswap-11.c: Likewise.
+	* gcc.dg/builtin-bswap-12.c: Likewise.
+	* gcc.target/i386/builtin-bswap-5.c: Likewise.
+---
+ gcc/builtin-types.def |  4 ++++
+ gcc/builtins.c        |  2 ++
+ gcc/builtins.def      |  2 ++
+ gcc/doc/extend.texi   | 10 ++++++++--
+ gcc/fold-const-call.c |  1 +
+ gcc/fold-const.c      |  2 ++
+ gcc/optabs.c          |  5 ++++-
+ gcc/tree-core.h       |  1 +
+ gcc/tree-ssa-ccp.c    |  1 +
+ gcc/tree-vect-stmts.c |  5 +++--
+ gcc/tree.c            |  2 ++
+ gcc/tree.h            |  1 +
+ 12 files changed, 31 insertions(+), 5 deletions(-)
+
+diff --git a/gcc/builtin-types.def b/gcc/builtin-types.def
+index c7aa691b2..c46b1bc5c 100644
+--- a/gcc/builtin-types.def
++++ b/gcc/builtin-types.def
+@@ -73,6 +73,9 @@ DEF_PRIMITIVE_TYPE (BT_UINT8, unsigned_char_type_node)
+ DEF_PRIMITIVE_TYPE (BT_UINT16, uint16_type_node)
+ DEF_PRIMITIVE_TYPE (BT_UINT32, uint32_type_node)
+ DEF_PRIMITIVE_TYPE (BT_UINT64, uint64_type_node)
++DEF_PRIMITIVE_TYPE (BT_UINT128, uint128_type_node
++				? uint128_type_node
++				: error_mark_node)
+ DEF_PRIMITIVE_TYPE (BT_WORD, (*lang_hooks.types.type_for_mode) (word_mode, 1))
+ DEF_PRIMITIVE_TYPE (BT_UNWINDWORD, (*lang_hooks.types.type_for_mode)
+ 				    (targetm.unwind_word_mode (), 1))
+@@ -300,6 +303,7 @@ DEF_FUNCTION_TYPE_1 (BT_FN_UINT8_FLOAT, BT_UINT8, BT_FLOAT)
+ DEF_FUNCTION_TYPE_1 (BT_FN_UINT16_UINT16, BT_UINT16, BT_UINT16)
+ DEF_FUNCTION_TYPE_1 (BT_FN_UINT32_UINT32, BT_UINT32, BT_UINT32)
+ DEF_FUNCTION_TYPE_1 (BT_FN_UINT64_UINT64, BT_UINT64, BT_UINT64)
++DEF_FUNCTION_TYPE_1 (BT_FN_UINT128_UINT128, BT_UINT128, BT_UINT128)
+ DEF_FUNCTION_TYPE_1 (BT_FN_UINT64_FLOAT, BT_UINT64, BT_FLOAT)
+ DEF_FUNCTION_TYPE_1 (BT_FN_BOOL_INT, BT_BOOL, BT_INT)
+ DEF_FUNCTION_TYPE_1 (BT_FN_BOOL_PTR, BT_BOOL, BT_PTR)
+diff --git a/gcc/builtins.c b/gcc/builtins.c
+index 10b6fd3bb..1b1c75cc1 100644
+--- a/gcc/builtins.c
++++ b/gcc/builtins.c
+@@ -8015,6 +8015,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode,
+     case BUILT_IN_BSWAP16:
+     case BUILT_IN_BSWAP32:
+     case BUILT_IN_BSWAP64:
++    case BUILT_IN_BSWAP128:
+       target = expand_builtin_bswap (target_mode, exp, target, subtarget);
+       if (target)
+ 	return target;
+@@ -11732,6 +11733,7 @@ is_inexpensive_builtin (tree decl)
+       case BUILT_IN_BSWAP16:
+       case BUILT_IN_BSWAP32:
+       case BUILT_IN_BSWAP64:
++      case BUILT_IN_BSWAP128:
+       case BUILT_IN_CLZ:
+       case BUILT_IN_CLZIMAX:
+       case BUILT_IN_CLZL:
+diff --git a/gcc/builtins.def b/gcc/builtins.def
+index fa8b0641a..ee67ac15d 100644
+--- a/gcc/builtins.def
++++ b/gcc/builtins.def
+@@ -834,6 +834,8 @@ DEF_GCC_BUILTIN        (BUILT_IN_APPLY_ARGS, "apply_args", BT_FN_PTR_VAR, ATTR_L
+ DEF_GCC_BUILTIN        (BUILT_IN_BSWAP16, "bswap16", BT_FN_UINT16_UINT16, ATTR_CONST_NOTHROW_LEAF_LIST)
+ DEF_GCC_BUILTIN        (BUILT_IN_BSWAP32, "bswap32", BT_FN_UINT32_UINT32, ATTR_CONST_NOTHROW_LEAF_LIST)
+ DEF_GCC_BUILTIN        (BUILT_IN_BSWAP64, "bswap64", BT_FN_UINT64_UINT64, ATTR_CONST_NOTHROW_LEAF_LIST)
++DEF_GCC_BUILTIN        (BUILT_IN_BSWAP128, "bswap128", BT_FN_UINT128_UINT128, ATTR_CONST_NOTHROW_LEAF_LIST)
++
+ DEF_EXT_LIB_BUILTIN    (BUILT_IN_CLEAR_CACHE, "__clear_cache", BT_FN_VOID_PTR_PTR, ATTR_NOTHROW_LEAF_LIST)
+ /* [trans-mem]: Adjust BUILT_IN_TM_CALLOC if BUILT_IN_CALLOC is changed.  */
+ DEF_LIB_BUILTIN        (BUILT_IN_CALLOC, "calloc", BT_FN_PTR_SIZE_SIZE, ATTR_MALLOC_WARN_UNUSED_RESULT_SIZE_1_2_NOTHROW_LEAF_LIST)
+diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
+index 9c7345959..a7bd772de 100644
+--- a/gcc/doc/extend.texi
++++ b/gcc/doc/extend.texi
+@@ -13727,14 +13727,20 @@ exactly 8 bits.
+ 
+ @deftypefn {Built-in Function} uint32_t __builtin_bswap32 (uint32_t x)
+ Similar to @code{__builtin_bswap16}, except the argument and return types
+-are 32 bit.
++are 32-bit.
+ @end deftypefn
+ 
+ @deftypefn {Built-in Function} uint64_t __builtin_bswap64 (uint64_t x)
+ Similar to @code{__builtin_bswap32}, except the argument and return types
+-are 64 bit.
++are 64-bit.
+ @end deftypefn
+ 
++@deftypefn {Built-in Function} uint128_t __builtin_bswap128 (uint128_t x)
++Similar to @code{__builtin_bswap64}, except the argument and return types
++are 128-bit.  Only supported on targets when 128-bit types are supported.
++@end deftypefn
++
++
+ @deftypefn {Built-in Function} Pmode __builtin_extend_pointer (void * x)
+ On targets where the user visible pointer size is smaller than the size
+ of an actual hardware address this function returns the extended user
+diff --git a/gcc/fold-const-call.c b/gcc/fold-const-call.c
+index 6150d7ada..da01759d9 100644
+--- a/gcc/fold-const-call.c
++++ b/gcc/fold-const-call.c
+@@ -1032,6 +1032,7 @@ fold_const_call_ss (wide_int *result, combined_fn fn, const wide_int_ref &arg,
+     case CFN_BUILT_IN_BSWAP16:
+     case CFN_BUILT_IN_BSWAP32:
+     case CFN_BUILT_IN_BSWAP64:
++    case CFN_BUILT_IN_BSWAP128:
+       *result = wide_int::from (arg, precision, TYPE_SIGN (arg_type)).bswap ();
+       return true;
+ 
+diff --git a/gcc/fold-const.c b/gcc/fold-const.c
+index 6e635382f..78227a83d 100644
+--- a/gcc/fold-const.c
++++ b/gcc/fold-const.c
+@@ -13889,8 +13889,10 @@ tree_call_nonnegative_warnv_p (tree type, combined_fn fn, tree arg0, tree arg1,
+     CASE_CFN_POPCOUNT:
+     CASE_CFN_CLZ:
+     CASE_CFN_CLRSB:
++    case CFN_BUILT_IN_BSWAP16:
+     case CFN_BUILT_IN_BSWAP32:
+     case CFN_BUILT_IN_BSWAP64:
++    case CFN_BUILT_IN_BSWAP128:
+       /* Always true.  */
+       return true;
+ 
+diff --git a/gcc/optabs.c b/gcc/optabs.c
+index 049a18ceb..c3751fdf7 100644
+--- a/gcc/optabs.c
++++ b/gcc/optabs.c
+@@ -2896,8 +2896,11 @@ expand_unop (machine_mode mode, optab unoptab, rtx op0, rtx target,
+ 	  if (temp)
+ 	    return temp;
+ 
++	  /* We do not provide a 128-bit bswap in libgcc so force the use of
++	     a double bswap for 64-bit targets.  */
+ 	  if (GET_MODE_SIZE (int_mode) == 2 * UNITS_PER_WORD
+-	      && optab_handler (unoptab, word_mode) != CODE_FOR_nothing)
++	      && (UNITS_PER_WORD == 64
++		  || optab_handler (unoptab, word_mode) != CODE_FOR_nothing))
+ 	    {
+ 	      temp = expand_doubleword_bswap (mode, op0, target);
+ 	      if (temp)
+diff --git a/gcc/tree-core.h b/gcc/tree-core.h
+index eb01c2434..058e046aa 100644
+--- a/gcc/tree-core.h
++++ b/gcc/tree-core.h
+@@ -600,6 +600,7 @@ enum tree_index {
+   TI_UINT16_TYPE,
+   TI_UINT32_TYPE,
+   TI_UINT64_TYPE,
++  TI_UINT128_TYPE,
+ 
+   TI_VOID,
+ 
+diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c
+index 952fd9cd4..dcdf10369 100644
+--- a/gcc/tree-ssa-ccp.c
++++ b/gcc/tree-ssa-ccp.c
+@@ -2005,6 +2005,7 @@ evaluate_stmt (gimple *stmt)
+ 	    case BUILT_IN_BSWAP16:
+ 	    case BUILT_IN_BSWAP32:
+ 	    case BUILT_IN_BSWAP64:
++	    case BUILT_IN_BSWAP128:
+ 	      val = get_value_for_expr (gimple_call_arg (stmt, 0), true);
+ 	      if (val.lattice_val == UNDEFINED)
+ 		break;
+diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
+index b872cfc8d..4636b7ba2 100644
+--- a/gcc/tree-vect-stmts.c
++++ b/gcc/tree-vect-stmts.c
+@@ -3085,7 +3085,7 @@ vect_get_data_ptr_increment (dr_vec_info *dr_info, tree aggr_type,
+   return iv_step;
+ }
+ 
+-/* Check and perform vectorization of BUILT_IN_BSWAP{16,32,64}.  */
++/* Check and perform vectorization of BUILT_IN_BSWAP{16,32,64,128}.  */
+ 
+ static bool
+ vectorizable_bswap (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
+@@ -3454,7 +3454,8 @@ vectorizable_call (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
+       else if (modifier == NONE
+ 	       && (gimple_call_builtin_p (stmt, BUILT_IN_BSWAP16)
+ 		   || gimple_call_builtin_p (stmt, BUILT_IN_BSWAP32)
+-		   || gimple_call_builtin_p (stmt, BUILT_IN_BSWAP64)))
++		   || gimple_call_builtin_p (stmt, BUILT_IN_BSWAP64)
++		   || gimple_call_builtin_p (stmt, BUILT_IN_BSWAP128)))
+ 	return vectorizable_bswap (stmt_info, gsi, vec_stmt, slp_node,
+ 				   vectype_in, cost_vec);
+       else
+diff --git a/gcc/tree.c b/gcc/tree.c
+index 84a440b35..3e6647ae0 100644
+--- a/gcc/tree.c
++++ b/gcc/tree.c
+@@ -10394,6 +10394,8 @@ build_common_tree_nodes (bool signed_char)
+   uint16_type_node = make_or_reuse_type (16, 1);
+   uint32_type_node = make_or_reuse_type (32, 1);
+   uint64_type_node = make_or_reuse_type (64, 1);
++  if (targetm.scalar_mode_supported_p (TImode))
++    uint128_type_node = make_or_reuse_type (128, 1);
+ 
+   /* Decimal float types. */
+   if (targetm.decimal_float_supported_p ())
+diff --git a/gcc/tree.h b/gcc/tree.h
+index 328a2d5d2..bddc6e528 100644
+--- a/gcc/tree.h
++++ b/gcc/tree.h
+@@ -4035,6 +4035,7 @@ tree_strip_any_location_wrapper (tree exp)
+ #define uint16_type_node		global_trees[TI_UINT16_TYPE]
+ #define uint32_type_node		global_trees[TI_UINT32_TYPE]
+ #define uint64_type_node		global_trees[TI_UINT64_TYPE]
++#define uint128_type_node		global_trees[TI_UINT128_TYPE]
+ 
+ #define void_node			global_trees[TI_VOID]
+ 
+-- 
+2.27.0.windows.1
+
diff --git a/0058-Backport-tree-optimization-95393-fold-MIN-MAX_EXPR-g.patch b/0058-Backport-tree-optimization-95393-fold-MIN-MAX_EXPR-g.patch
new file mode 100644
index 0000000..0edbcb0
--- /dev/null
+++ b/0058-Backport-tree-optimization-95393-fold-MIN-MAX_EXPR-g.patch
@@ -0,0 +1,113 @@
+From b9ac0cc69aab3c8d662d5b0a9ed43d971c13ac70 Mon Sep 17 00:00:00 2001
+From: Richard Biener 
+Date: Fri, 29 May 2020 09:25:53 +0200
+Subject: [PATCH 10/35] [Backport] tree-optimization/95393 - fold MIN/MAX_EXPR
+ generated by phiopt
+
+Reference: https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=07852a81f58532c63a57631d7c3757fc6bcea17d
+
+This makes sure to fold generated stmts so they do not survive
+until RTL expansion and cause awkward code generation.
+
+2020-05-29  Richard Biener 
+
+	PR tree-optimization/95393
+	* tree-ssa-phiopt.c (minmax_replacement): Use gimple_build
+	to build the min/max expression so we simplify cases like
+	MAX(0, s) immediately.
+
+	* gcc.dg/tree-ssa/phi-opt-21.c: New testcase.
+	* g++.dg/vect/slp-pr87105.cc: Adjust.
+---
+ gcc/testsuite/g++.dg/vect/slp-pr87105.cc   |  2 +-
+ gcc/testsuite/gcc.dg/tree-ssa/phi-opt-21.c | 15 +++++++++++++
+ gcc/tree-ssa-phiopt.c                      | 25 +++++++++++-----------
+ 3 files changed, 29 insertions(+), 13 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/phi-opt-21.c
+
+diff --git a/gcc/testsuite/g++.dg/vect/slp-pr87105.cc b/gcc/testsuite/g++.dg/vect/slp-pr87105.cc
+index 5518f319b..d07b1cd46 100644
+--- a/gcc/testsuite/g++.dg/vect/slp-pr87105.cc
++++ b/gcc/testsuite/g++.dg/vect/slp-pr87105.cc
+@@ -102,4 +102,4 @@ void quadBoundingBoxA(const Point bez[3], Box& bBox) noexcept {
+ // { dg-final { scan-tree-dump-times "basic block part vectorized" 1 "slp2" { xfail { { ! vect_element_align } && { ! vect_hw_misalign } } } } }
+ // It's a bit awkward to detect that all stores were vectorized but the
+ // following more or less does the trick
+-// { dg-final { scan-tree-dump "vect_iftmp\[^\r\m\]* = MIN" "slp2" { xfail { { ! vect_element_align } && { ! vect_hw_misalign } } } } }
++// { dg-final { scan-tree-dump "vect_\[^\r\m\]* = MIN" "slp2" { xfail { { ! vect_element_align } && { ! vect_hw_misalign } } } } }
+diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-21.c b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-21.c
+new file mode 100644
+index 000000000..9f3d56957
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-21.c
+@@ -0,0 +1,15 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -fdump-tree-phiopt4-details" } */
++
++int f(unsigned s)
++{
++  int i;
++  for (i = 0; i < s; ++i)
++    ;
++
++  return i;
++}
++
++/* { dg-final { scan-tree-dump "converted to straightline code" "phiopt4" } } */
++/* Make sure we fold the detected MAX.  */
++/* { dg-final { scan-tree-dump-not "MAX" "phiopt4" } } */
+diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c
+index fca32222f..269eda21c 100644
+--- a/gcc/tree-ssa-phiopt.c
++++ b/gcc/tree-ssa-phiopt.c
+@@ -46,6 +46,7 @@ along with GCC; see the file COPYING3.  If not see
+ #include "tree-inline.h"
+ #include "case-cfn-macros.h"
+ #include "tree-eh.h"
++#include "gimple-fold.h"
+ #include "internal-fn.h"
+ 
+ static unsigned int tree_ssa_phiopt_worker (bool, bool, bool);
+@@ -1414,7 +1415,6 @@ minmax_replacement (basic_block cond_bb, basic_block middle_bb,
+ {
+   tree result, type, rhs;
+   gcond *cond;
+-  gassign *new_stmt;
+   edge true_edge, false_edge;
+   enum tree_code cmp, minmax, ass_code;
+   tree smaller, alt_smaller, larger, alt_larger, arg_true, arg_false;
+@@ -1738,19 +1738,20 @@ minmax_replacement (basic_block cond_bb, basic_block middle_bb,
+       gsi_move_before (&gsi_from, &gsi);
+     }
+ 
+-  /* Create an SSA var to hold the min/max result.  If we're the only
+-     things setting the target PHI, then we  can clone the PHI
+-     variable.  Otherwise we must create a new one.  */
+-  result = PHI_RESULT (phi);
+-  if (EDGE_COUNT (gimple_bb (phi)->preds) == 2)
+-    result = duplicate_ssa_name (result, NULL);
+-  else
+-    result = make_ssa_name (TREE_TYPE (result));
+-
+   /* Emit the statement to compute min/max.  */
+-  new_stmt = gimple_build_assign (result, minmax, arg0, arg1);
++  gimple_seq stmts = NULL;
++  tree phi_result = PHI_RESULT (phi);
++  result = gimple_build (&stmts, minmax, TREE_TYPE (phi_result), arg0, arg1);
++  /* Duplicate range info if we're the only things setting the target PHI.  */
++  if (!gimple_seq_empty_p (stmts)
++      && EDGE_COUNT (gimple_bb (phi)->preds) == 2
++      && !POINTER_TYPE_P (TREE_TYPE (phi_result))
++      && SSA_NAME_RANGE_INFO (phi_result))
++    duplicate_ssa_name_range_info (result, SSA_NAME_RANGE_TYPE (phi_result),
++				   SSA_NAME_RANGE_INFO (phi_result));
++
+   gsi = gsi_last_bb (cond_bb);
+-  gsi_insert_before (&gsi, new_stmt, GSI_NEW_STMT);
++  gsi_insert_seq_before (&gsi, stmts, GSI_NEW_STMT);
+ 
+   replace_phi_edge_with_variable (cond_bb, e1, phi, result);
+ 
+-- 
+2.27.0.windows.1
+
diff --git a/0059-Backport-Add-a-couple-of-A-CST1-CST2-match-and-simpl.patch b/0059-Backport-Add-a-couple-of-A-CST1-CST2-match-and-simpl.patch
new file mode 100644
index 0000000..a16b336
--- /dev/null
+++ b/0059-Backport-Add-a-couple-of-A-CST1-CST2-match-and-simpl.patch
@@ -0,0 +1,91 @@
+From 9f3a8c600abe16f172b36d8113862e8f7aea940c Mon Sep 17 00:00:00 2001
+From: Andrew Pinski 
+Date: Sun, 16 May 2021 13:07:06 -0700
+Subject: [PATCH 11/35] [Backport] Add a couple of A?CST1:CST2 match and
+ simplify optimizations
+
+Reference: https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=b6bdd7a4cb41ee057f2d064fffcb00f23ce6b497
+
+Instead of some of the more manual optimizations inside phi-opt,
+it would be good idea to do a lot of the heavy lifting inside match
+and simplify instead. In the process, this moves the three simple
+A?CST1:CST2 (where CST1 or CST2 is zero) simplifications.
+
+OK? Boostrapped and tested on x86_64-linux-gnu with no regressions.
+
+Differences from V1:
+* Use bit_xor 1 instead of bit_not to fix the problem with boolean types
+which are not 1 bit precision.
+
+Thanks,
+Andrew Pinski
+
+gcc:
+	* match.pd (A?CST1:CST2): Add simplifcations for A?0:+-1, A?+-1:0,
+	A?POW2:0 and A?0:POW2.
+---
+ gcc/match.pd | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 48 insertions(+)
+
+diff --git a/gcc/match.pd b/gcc/match.pd
+index 660d5c268..032830b0d 100644
+--- a/gcc/match.pd
++++ b/gcc/match.pd
+@@ -3334,6 +3334,54 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
+    (if (cst1 && cst2)
+     (vec_cond @0 { cst1; } { cst2; })))))
+ 
++/* A few simplifications of "a ? CST1 : CST2". */
++/* NOTE: Only do this on gimple as the if-chain-to-switch
++   optimization depends on the gimple to have if statements in it. */
++#if GIMPLE
++(simplify
++ (cond @0 INTEGER_CST@1 INTEGER_CST@2)
++ (switch
++  (if (integer_zerop (@2))
++   (switch
++    /* a ? 1 : 0 -> a if 0 and 1 are integral types. */
++    (if (integer_onep (@1))
++     (convert (convert:boolean_type_node @0)))
++    /* a ? powerof2cst : 0 -> a << (log2(powerof2cst)) */
++    (if (INTEGRAL_TYPE_P (type) && integer_pow2p (@1))
++     (with {
++       tree shift = build_int_cst (integer_type_node, tree_log2 (@1));
++      }
++      (lshift (convert (convert:boolean_type_node @0)) { shift; })))
++    /* a ? -1 : 0 -> -a.  No need to check the TYPE_PRECISION not being 1
++       here as the powerof2cst case above will handle that case correctly.  */
++    (if (INTEGRAL_TYPE_P (type) && integer_all_onesp (@1))
++     (negate (convert (convert:boolean_type_node @0))))))
++  (if (integer_zerop (@1))
++   (with {
++      tree booltrue = constant_boolean_node (true, boolean_type_node);
++    }
++    (switch
++     /* a ? 0 : 1 -> !a. */
++     (if (integer_onep (@2))
++      (convert (bit_xor (convert:boolean_type_node @0) { booltrue; } )))
++     /* a ? powerof2cst : 0 -> (!a) << (log2(powerof2cst)) */
++     (if (INTEGRAL_TYPE_P (type) &&  integer_pow2p (@2))
++      (with {
++	tree shift = build_int_cst (integer_type_node, tree_log2 (@2));
++       }
++       (lshift (convert (bit_xor (convert:boolean_type_node @0) { booltrue; } ))
++        { shift; })))
++     /* a ? -1 : 0 -> -(!a).  No need to check the TYPE_PRECISION not being 1
++       here as the powerof2cst case above will handle that case correctly.  */
++     (if (INTEGRAL_TYPE_P (type) && integer_all_onesp (@2))
++      (negate (convert (bit_xor (convert:boolean_type_node @0) { booltrue; } ))))
++    )
++   )
++  )
++ )
++)
++#endif
++
+ /* Simplification moved from fold_cond_expr_with_comparison.  It may also
+    be extended.  */
+ /* This pattern implements two kinds simplification:
+-- 
+2.27.0.windows.1
+
diff --git a/0060-Backport-Optimize-x-0-y-y-to-x-31-y-in-match.pd.patch b/0060-Backport-Optimize-x-0-y-y-to-x-31-y-in-match.pd.patch
new file mode 100644
index 0000000..80d602a
--- /dev/null
+++ b/0060-Backport-Optimize-x-0-y-y-to-x-31-y-in-match.pd.patch
@@ -0,0 +1,155 @@
+From 4352b952ba24c413697fcfc191d06165a8a31ced Mon Sep 17 00:00:00 2001
+From: Andrew Pinski 
+Date: Sat, 22 May 2021 19:49:50 +0000
+Subject: [PATCH 12/35] [Backport] Optimize x < 0 ? ~y : y to (x >> 31) ^ y in
+ match.pd
+
+Reference: https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=1fd76b24306ed4df4cf9e797d900699ed59ce7f7
+
+This copies the optimization that is done in phiopt for
+"x < 0 ? ~y : y to (x >> 31) ^ y" into match.pd. The code
+for phiopt is kept around until phiopt uses match.pd (which
+I am working towards).
+
+Note the original testcase is now optimized early on and I added a
+new testcase to optimize during phiopt.
+
+OK?  Bootstrapped and tested on x86_64-linux-gnu with no regressions.
+
+Thanks,
+Andrew Pinski
+
+Differences from v1:
+V2: Add check for integeral type to make sure vector types are not done.
+
+gcc:
+	* match.pd (x < 0 ? ~y : y): New patterns.
+
+gcc/testsuite:
+	* gcc.dg/tree-ssa/pr96928.c: Update test for slightly different IR.
+	* gcc.dg/tree-ssa/pr96928-1.c: New testcase.
+---
+ gcc/match.pd                              | 32 +++++++++++++++
+ gcc/testsuite/gcc.dg/tree-ssa/pr96928-1.c | 48 +++++++++++++++++++++++
+ gcc/testsuite/gcc.dg/tree-ssa/pr96928.c   |  7 +++-
+ 3 files changed, 85 insertions(+), 2 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr96928-1.c
+
+diff --git a/gcc/match.pd b/gcc/match.pd
+index 032830b0d..5899eea95 100644
+--- a/gcc/match.pd
++++ b/gcc/match.pd
+@@ -4390,6 +4390,38 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
+   (cmp (bit_and@2 @0 integer_pow2p@1) @1)
+   (icmp @2 { build_zero_cst (TREE_TYPE (@0)); })))
+ 
++(for cmp (ge lt)
++/* x < 0 ? ~y : y into (x >> (prec-1)) ^ y. */
++/* x >= 0 ? ~y : y into ~((x >> (prec-1)) ^ y). */
++ (simplify
++  (cond (cmp @0 integer_zerop) (bit_not @1) @1)
++   (if (INTEGRAL_TYPE_P (type)
++	&& INTEGRAL_TYPE_P (TREE_TYPE (@0))
++        && !TYPE_UNSIGNED (TREE_TYPE (@0))
++        && TYPE_PRECISION (TREE_TYPE (@0)) == TYPE_PRECISION (type))
++    (with
++     {
++       tree shifter = build_int_cst (integer_type_node, TYPE_PRECISION (type) - 1);
++     }
++    (if (cmp == LT_EXPR)
++     (bit_xor (convert (rshift @0 {shifter;})) @1)
++     (bit_not (bit_xor (convert (rshift @0 {shifter;})) @1))))))
++/* x < 0 ? y : ~y into ~((x >> (prec-1)) ^ y). */
++/* x >= 0 ? y : ~y into (x >> (prec-1)) ^ y. */
++ (simplify
++  (cond (cmp @0 integer_zerop) @1 (bit_not @1))
++   (if (INTEGRAL_TYPE_P (type)
++	&& INTEGRAL_TYPE_P (TREE_TYPE (@0))
++        && !TYPE_UNSIGNED (TREE_TYPE (@0))
++        && TYPE_PRECISION (TREE_TYPE (@0)) == TYPE_PRECISION (type))
++    (with
++     {
++       tree shifter = build_int_cst (integer_type_node, TYPE_PRECISION (type) - 1);
++     }
++    (if (cmp == GE_EXPR)
++     (bit_xor (convert (rshift @0 {shifter;})) @1)
++     (bit_not (bit_xor (convert (rshift @0 {shifter;})) @1)))))))
++
+ /* If we have (A & C) != 0 ? D : 0 where C and D are powers of 2,
+    convert this into a shift followed by ANDing with D.  */
+ (simplify
+diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr96928-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr96928-1.c
+new file mode 100644
+index 000000000..a2770e5e8
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/tree-ssa/pr96928-1.c
+@@ -0,0 +1,48 @@
++/* PR tree-optimization/96928 */
++/* { dg-do compile } */
++/* { dg-options "-O2 -fdump-tree-phiopt2" } */
++/* { dg-final { scan-tree-dump-times " = a_\[0-9]*\\\(D\\\) >> " 5 "phiopt2" } } */
++/* { dg-final { scan-tree-dump-times " = ~c_\[0-9]*\\\(D\\\);" 1 "phiopt2" } } */
++/* { dg-final { scan-tree-dump-times " = ~" 1 "phiopt2" } } */
++/* { dg-final { scan-tree-dump-times " = \[abc_0-9\\\(\\\)D]* \\\^ " 5 "phiopt2" } } */
++/* { dg-final { scan-tree-dump-not "a < 0" "phiopt2" } } */
++
++int
++foo (int a)
++{
++  if (a < 0)
++    return ~a;
++  return a;
++}
++
++int
++bar (int a, int b)
++{
++  if (a < 0)
++    return ~b;
++  return b;
++}
++
++unsigned
++baz (int a, unsigned int b)
++{
++  if (a < 0)
++    return ~b;
++  return b;
++}
++
++unsigned
++qux (int a, unsigned int c)
++{
++  if (a >= 0)
++    return ~c;
++  return c;
++}
++
++int
++corge (int a, int b)
++{
++  if (a >= 0)
++    return b;
++  return ~b;
++}
+diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr96928.c b/gcc/testsuite/gcc.dg/tree-ssa/pr96928.c
+index 209135726..e8fd82fc2 100644
+--- a/gcc/testsuite/gcc.dg/tree-ssa/pr96928.c
++++ b/gcc/testsuite/gcc.dg/tree-ssa/pr96928.c
+@@ -1,8 +1,11 @@
+ /* PR tree-optimization/96928 */
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -fdump-tree-phiopt2" } */
++/* { dg-options "-O2 -fdump-tree-phiopt2 -fdump-tree-optimized" } */
+ /* { dg-final { scan-tree-dump-times " = a_\[0-9]*\\\(D\\\) >> " 5 "phiopt2" } } */
+-/* { dg-final { scan-tree-dump-times " = ~c_\[0-9]*\\\(D\\\);" 1 "phiopt2" } } */
++/* The following check is done at optimized because a ^ (~b) is rewritten as ~(a^b)
++   and in the case of match.pd optimizing these ?:, the ~ is moved out already
++   by the time we get to phiopt2. */
++/* { dg-final { scan-tree-dump-times "\\\^ c_\[0-9]*\\\(D\\\);" 1 "optimized" } } */
+ /* { dg-final { scan-tree-dump-times " = ~" 1 "phiopt2" } } */
+ /* { dg-final { scan-tree-dump-times " = \[abc_0-9\\\(\\\)D]* \\\^ " 5 "phiopt2" } } */
+ /* { dg-final { scan-tree-dump-not "a < 0" "phiopt2" } } */
+-- 
+2.27.0.windows.1
+
diff --git a/0061-Backport-Replace-conditional_replacement-with-match-.patch b/0061-Backport-Replace-conditional_replacement-with-match-.patch
new file mode 100644
index 0000000..12808be
--- /dev/null
+++ b/0061-Backport-Replace-conditional_replacement-with-match-.patch
@@ -0,0 +1,249 @@
+From 406071e8c1838c824f06c35ef3cf9419aa543e6e Mon Sep 17 00:00:00 2001
+From: Andrew Pinski 
+Date: Tue, 1 Jun 2021 01:05:09 +0000
+Subject: [PATCH 13/35] [Backport] Replace conditional_replacement with match
+ and simplify
+
+Reference: https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=9f55df63154a39d67ef5b24def7044bf87300831
+
+This is the first of series of patches to simplify phi-opt
+to use match and simplify in many cases.  This simplification
+will more things to optimize.
+
+This is what Richard requested in
+https://gcc.gnu.org/pipermail/gcc-patches/2021-May/571197.html
+and I think it is the right thing to do too.
+
+OK? Bootstrapped and tested on x86_64-linux-gnu with no regressions.
+
+gcc/ChangeLog:
+
+	PR tree-optimization/25290
+	* tree-ssa-phiopt.c (match_simplify_replacement):
+	New function.
+	(tree_ssa_phiopt_worker): Use match_simplify_replacement.
+	(two_value_replacement): Change the comment about
+	conditional_replacement.
+	(conditional_replacement): Delete.
+---
+ gcc/tree-ssa-phiopt.c | 144 ++++++++++++------------------------------
+ 1 file changed, 39 insertions(+), 105 deletions(-)
+
+diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c
+index 269eda21c..9fa6363b6 100644
+--- a/gcc/tree-ssa-phiopt.c
++++ b/gcc/tree-ssa-phiopt.c
+@@ -52,8 +52,8 @@ along with GCC; see the file COPYING3.  If not see
+ static unsigned int tree_ssa_phiopt_worker (bool, bool, bool);
+ static bool two_value_replacement (basic_block, basic_block, edge, gphi *,
+ 				   tree, tree);
+-static bool conditional_replacement (basic_block, basic_block,
+-				     edge, edge, gphi *, tree, tree);
++static bool match_simplify_replacement (basic_block, basic_block,
++					edge, edge, gphi *, tree, tree);
+ static gphi *factor_out_conditional_conversion (edge, edge, gphi *, tree, tree,
+ 						gimple *);
+ static int value_replacement (basic_block, basic_block,
+@@ -349,8 +349,8 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads, bool early_p)
+ 	  if (!early_p && two_value_replacement (bb, bb1, e2, phi, arg0, arg1))
+ 	    cfgchanged = true;
+ 	  else if (!early_p
+-		   && conditional_replacement (bb, bb1, e1, e2, phi,
+-					       arg0, arg1))
++		   && match_simplify_replacement (bb, bb1, e1, e2, phi,
++						  arg0, arg1))
+ 	    cfgchanged = true;
+ 	  else if (abs_replacement (bb, bb1, e1, e2, phi, arg0, arg1))
+ 	    cfgchanged = true;
+@@ -662,7 +662,7 @@ two_value_replacement (basic_block cond_bb, basic_block middle_bb,
+     }
+ 
+   /* Defer boolean x ? 0 : {1,-1} or x ? {1,-1} : 0 to
+-     conditional_replacement.  */
++     match_simplify_replacement.  */
+   if (TREE_CODE (TREE_TYPE (lhs)) == BOOLEAN_TYPE
+       && (integer_zerop (arg0)
+ 	  || integer_zerop (arg1)
+@@ -763,137 +763,71 @@ two_value_replacement (basic_block cond_bb, basic_block middle_bb,
+   return true;
+ }
+ 
+-/*  The function conditional_replacement does the main work of doing the
+-    conditional replacement.  Return true if the replacement is done.
++/*  The function match_simplify_replacement does the main work of doing the
++    replacement using match and simplify.  Return true if the replacement is done.
+     Otherwise return false.
+     BB is the basic block where the replacement is going to be done on.  ARG0
+     is argument 0 from PHI.  Likewise for ARG1.  */
+ 
+ static bool
+-conditional_replacement (basic_block cond_bb, basic_block middle_bb,
+-			 edge e0, edge e1, gphi *phi,
+-			 tree arg0, tree arg1)
++match_simplify_replacement (basic_block cond_bb, basic_block middle_bb,
++			    edge e0, edge e1, gphi *phi,
++			    tree arg0, tree arg1)
+ {
+-  tree result;
+   gimple *stmt;
+-  gassign *new_stmt;
+   tree cond;
+   gimple_stmt_iterator gsi;
+   edge true_edge, false_edge;
+-  tree new_var, new_var2;
+-  bool neg = false;
+-  int shift = 0;
+-  tree nonzero_arg;
+-
+-  /* FIXME: Gimplification of complex type is too hard for now.  */
+-  /* We aren't prepared to handle vectors either (and it is a question
+-     if it would be worthwhile anyway).  */
+-  if (!(INTEGRAL_TYPE_P (TREE_TYPE (arg0))
+-	|| POINTER_TYPE_P (TREE_TYPE (arg0)))
+-      || !(INTEGRAL_TYPE_P (TREE_TYPE (arg1))
+-	   || POINTER_TYPE_P (TREE_TYPE (arg1))))
+-    return false;
++  gimple_seq seq = NULL;
++  tree result;
+ 
+-  /* The PHI arguments have the constants 0 and 1, or 0 and -1 or
+-     0 and (1 << cst), then convert it to the conditional.  */
+-  if (integer_zerop (arg0))
+-    nonzero_arg = arg1;
+-  else if (integer_zerop (arg1))
+-    nonzero_arg = arg0;
+-  else
+-    return false;
+-  if (integer_pow2p (nonzero_arg))
+-    {
+-      shift = tree_log2 (nonzero_arg);
+-      if (shift && POINTER_TYPE_P (TREE_TYPE (nonzero_arg)))
+-	return false;
+-    }
+-  else if (integer_all_onesp (nonzero_arg))
+-    neg = true;
+-  else
++  if (!empty_block_p (middle_bb))
+     return false;
+ 
+-  if (!empty_block_p (middle_bb))
++  /* Special case A ? B : B as this will always simplify to B. */
++  if (operand_equal_for_phi_arg_p (arg0, arg1))
+     return false;
+ 
+-  /* At this point we know we have a GIMPLE_COND with two successors.
++    /* At this point we know we have a GIMPLE_COND with two successors.
+      One successor is BB, the other successor is an empty block which
+      falls through into BB.
+ 
+-     There is a single PHI node at the join point (BB) and its arguments
+-     are constants (0, 1) or (0, -1) or (0, (1 << shift)).
+-
+-     So, given the condition COND, and the two PHI arguments, we can
+-     rewrite this PHI into non-branching code:
++     There is a single PHI node at the join point (BB).
+ 
+-       dest = (COND) or dest = COND' or dest = (COND) << shift
+-
+-     We use the condition as-is if the argument associated with the
+-     true edge has the value one or the argument associated with the
+-     false edge as the value zero.  Note that those conditions are not
+-     the same since only one of the outgoing edges from the GIMPLE_COND
+-     will directly reach BB and thus be associated with an argument.  */
++     So, given the condition COND, and the two PHI arguments, match and simplify
++     can happen on (COND) ? arg0 : arg1. */
+ 
+   stmt = last_stmt (cond_bb);
+-  result = PHI_RESULT (phi);
+ 
+   /* To handle special cases like floating point comparison, it is easier and
+      less error-prone to build a tree and gimplify it on the fly though it is
+-     less efficient.  */
+-  cond = fold_build2_loc (gimple_location (stmt),
+-			  gimple_cond_code (stmt), boolean_type_node,
+-			  gimple_cond_lhs (stmt), gimple_cond_rhs (stmt));
++     less efficient.
++     Don't use fold_build2 here as that might create (bool)a instead of just
++     "a != 0".  */
++  cond = build2_loc (gimple_location (stmt),
++		     gimple_cond_code (stmt), boolean_type_node,
++		     gimple_cond_lhs (stmt), gimple_cond_rhs (stmt));
+ 
+   /* We need to know which is the true edge and which is the false
+      edge so that we know when to invert the condition below.  */
+   extract_true_false_edges_from_block (cond_bb, &true_edge, &false_edge);
+-  if ((e0 == true_edge && integer_zerop (arg0))
+-      || (e0 == false_edge && !integer_zerop (arg0))
+-      || (e1 == true_edge && integer_zerop (arg1))
+-      || (e1 == false_edge && !integer_zerop (arg1)))
+-    cond = fold_build1_loc (gimple_location (stmt),
+-                            TRUTH_NOT_EXPR, TREE_TYPE (cond), cond);
+-
+-  if (neg)
+-    {
+-      cond = fold_convert_loc (gimple_location (stmt),
+-                               TREE_TYPE (result), cond);
+-      cond = fold_build1_loc (gimple_location (stmt),
+-                              NEGATE_EXPR, TREE_TYPE (cond), cond);
+-    }
+-  else if (shift)
+-    {
+-      cond = fold_convert_loc (gimple_location (stmt),
+-			       TREE_TYPE (result), cond);
+-      cond = fold_build2_loc (gimple_location (stmt),
+-			      LSHIFT_EXPR, TREE_TYPE (cond), cond,
+-			      build_int_cst (integer_type_node, shift));
+-    }
++  if (e1 == true_edge || e0 == false_edge)
++    std::swap (arg0, arg1);
+ 
+-  /* Insert our new statements at the end of conditional block before the
+-     COND_STMT.  */
+-  gsi = gsi_for_stmt (stmt);
+-  new_var = force_gimple_operand_gsi (&gsi, cond, true, NULL, true,
+-				      GSI_SAME_STMT);
++  tree type = TREE_TYPE (gimple_phi_result (phi));
++  result = gimple_simplify (COND_EXPR, type,
++			    cond,
++			    arg0, arg1,
++			    &seq, NULL);
++  if (!result)
++    return false;
+ 
+-  if (!useless_type_conversion_p (TREE_TYPE (result), TREE_TYPE (new_var)))
+-    {
+-      location_t locus_0, locus_1;
++  gsi = gsi_last_bb (cond_bb);
+ 
+-      new_var2 = make_ssa_name (TREE_TYPE (result));
+-      new_stmt = gimple_build_assign (new_var2, CONVERT_EXPR, new_var);
+-      gsi_insert_before (&gsi, new_stmt, GSI_SAME_STMT);
+-      new_var = new_var2;
+-
+-      /* Set the locus to the first argument, unless is doesn't have one.  */
+-      locus_0 = gimple_phi_arg_location (phi, 0);
+-      locus_1 = gimple_phi_arg_location (phi, 1);
+-      if (locus_0 == UNKNOWN_LOCATION)
+-        locus_0 = locus_1;
+-      gimple_set_location (new_stmt, locus_0);
+-    }
++  if (seq)
++    gsi_insert_seq_before (&gsi, seq, GSI_SAME_STMT);
+ 
+-  replace_phi_edge_with_variable (cond_bb, e1, phi, new_var);
++  replace_phi_edge_with_variable (cond_bb, e1, phi, result);
+ 
+   /* Note that we optimized this PHI.  */
+   return true;
+@@ -3905,7 +3839,7 @@ gate_hoist_loads (void)
+    Conditional Replacement
+    -----------------------
+ 
+-   This transformation, implemented in conditional_replacement,
++   This transformation, implemented in match_simplify_replacement,
+    replaces
+ 
+      bb0:
+-- 
+2.27.0.windows.1
+
diff --git a/0062-Backport-Allow-match-and-simplified-phiopt-to-run-in.patch b/0062-Backport-Allow-match-and-simplified-phiopt-to-run-in.patch
new file mode 100644
index 0000000..bf1b0cd
--- /dev/null
+++ b/0062-Backport-Allow-match-and-simplified-phiopt-to-run-in.patch
@@ -0,0 +1,174 @@
+From fabbe6ccc798d3cb097c6371b4d53cd6dfde6c7c Mon Sep 17 00:00:00 2001
+From: Andrew Pinski 
+Date: Fri, 11 Jun 2021 13:21:34 -0700
+Subject: [PATCH 14/35] [Backport] Allow match-and-simplified phiopt to run in
+ early phiopt
+
+Reference: https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=cd48e550d1dc58307ab1c0ab490745673f748ccc
+
+To move a few things more to match-and-simplify from phiopt,
+we need to allow match_simplify_replacement to run in early
+phiopt. To do this we add a replacement for gimple_simplify
+that is explictly for phiopt.
+
+OK? Bootstrapped and tested on x86_64-linux-gnu with no
+regressions.
+
+gcc/ChangeLog:
+
+	* tree-ssa-phiopt.c (match_simplify_replacement):
+	Add early_p argument. Call gimple_simplify_phiopt
+	instead of gimple_simplify.
+	(tree_ssa_phiopt_worker): Update call to
+	match_simplify_replacement and allow unconditionally.
+	(phiopt_early_allow): New function.
+	(gimple_simplify_phiopt): New function.
+---
+ gcc/tree-ssa-phiopt.c | 89 ++++++++++++++++++++++++++++++++++---------
+ 1 file changed, 70 insertions(+), 19 deletions(-)
+
+diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c
+index 9fa6363b6..92aeb8415 100644
+--- a/gcc/tree-ssa-phiopt.c
++++ b/gcc/tree-ssa-phiopt.c
+@@ -48,12 +48,13 @@ along with GCC; see the file COPYING3.  If not see
+ #include "tree-eh.h"
+ #include "gimple-fold.h"
+ #include "internal-fn.h"
++#include "gimple-match.h"
+ 
+ static unsigned int tree_ssa_phiopt_worker (bool, bool, bool);
+ static bool two_value_replacement (basic_block, basic_block, edge, gphi *,
+ 				   tree, tree);
+ static bool match_simplify_replacement (basic_block, basic_block,
+-					edge, edge, gphi *, tree, tree);
++					edge, edge, gphi *, tree, tree, bool);
+ static gphi *factor_out_conditional_conversion (edge, edge, gphi *, tree, tree,
+ 						gimple *);
+ static int value_replacement (basic_block, basic_block,
+@@ -348,9 +349,9 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads, bool early_p)
+ 	  /* Do the replacement of conditional if it can be done.  */
+ 	  if (!early_p && two_value_replacement (bb, bb1, e2, phi, arg0, arg1))
+ 	    cfgchanged = true;
+-	  else if (!early_p
+-		   && match_simplify_replacement (bb, bb1, e1, e2, phi,
+-						  arg0, arg1))
++	  else if (match_simplify_replacement (bb, bb1, e1, e2, phi,
++					       arg0, arg1,
++					       early_p))
+ 	    cfgchanged = true;
+ 	  else if (abs_replacement (bb, bb1, e1, e2, phi, arg0, arg1))
+ 	    cfgchanged = true;
+@@ -763,6 +764,67 @@ two_value_replacement (basic_block cond_bb, basic_block middle_bb,
+   return true;
+ }
+ 
++/* Return TRUE if CODE should be allowed during early phiopt.
++   Currently this is to allow MIN/MAX and ABS/NEGATE.  */
++static bool
++phiopt_early_allow (enum tree_code code)
++{
++  switch (code)
++    {
++      case MIN_EXPR:
++      case MAX_EXPR:
++      case ABS_EXPR:
++      case ABSU_EXPR:
++      case NEGATE_EXPR:
++      case SSA_NAME:
++	return true;
++      default:
++	return false;
++    }
++}
++
++/* gimple_simplify_phiopt is like gimple_simplify but designed for PHIOPT.
++   Return NULL if nothing can be simplified or the resulting simplified value
++   with parts pushed if EARLY_P was true. Also rejects non allowed tree code
++   if EARLY_P is set.
++   Takes the comparison from COMP_STMT and two args, ARG0 and ARG1 and tries
++   to simplify CMP ? ARG0 : ARG1.  */
++static tree
++gimple_simplify_phiopt (bool early_p, tree type, gimple *comp_stmt,
++			tree arg0, tree arg1,
++			gimple_seq *seq)
++{
++  tree result;
++  enum tree_code comp_code = gimple_cond_code (comp_stmt);
++  location_t loc = gimple_location (comp_stmt);
++  tree cmp0 = gimple_cond_lhs (comp_stmt);
++  tree cmp1 = gimple_cond_rhs (comp_stmt);
++  /* To handle special cases like floating point comparison, it is easier and
++     less error-prone to build a tree and gimplify it on the fly though it is
++     less efficient.
++     Don't use fold_build2 here as that might create (bool)a instead of just
++     "a != 0".  */
++  tree cond = build2_loc (loc, comp_code, boolean_type_node,
++			  cmp0, cmp1);
++  gimple_match_op op (gimple_match_cond::UNCOND,
++		      COND_EXPR, type, cond, arg0, arg1);
++
++  if (op.resimplify (early_p ? NULL : seq, follow_all_ssa_edges))
++    {
++      /* Early we want only to allow some generated tree codes. */
++      if (!early_p
++	  || op.code.is_tree_code ()
++	  || phiopt_early_allow ((tree_code)op.code))
++	{
++	  result = maybe_push_res_to_seq (&op, seq);
++	  if (result)
++	    return result;
++	}
++    }
++
++  return NULL;
++}
++
+ /*  The function match_simplify_replacement does the main work of doing the
+     replacement using match and simplify.  Return true if the replacement is done.
+     Otherwise return false.
+@@ -772,10 +834,9 @@ two_value_replacement (basic_block cond_bb, basic_block middle_bb,
+ static bool
+ match_simplify_replacement (basic_block cond_bb, basic_block middle_bb,
+ 			    edge e0, edge e1, gphi *phi,
+-			    tree arg0, tree arg1)
++			    tree arg0, tree arg1, bool early_p)
+ {
+   gimple *stmt;
+-  tree cond;
+   gimple_stmt_iterator gsi;
+   edge true_edge, false_edge;
+   gimple_seq seq = NULL;
+@@ -799,15 +860,6 @@ match_simplify_replacement (basic_block cond_bb, basic_block middle_bb,
+ 
+   stmt = last_stmt (cond_bb);
+ 
+-  /* To handle special cases like floating point comparison, it is easier and
+-     less error-prone to build a tree and gimplify it on the fly though it is
+-     less efficient.
+-     Don't use fold_build2 here as that might create (bool)a instead of just
+-     "a != 0".  */
+-  cond = build2_loc (gimple_location (stmt),
+-		     gimple_cond_code (stmt), boolean_type_node,
+-		     gimple_cond_lhs (stmt), gimple_cond_rhs (stmt));
+-
+   /* We need to know which is the true edge and which is the false
+      edge so that we know when to invert the condition below.  */
+   extract_true_false_edges_from_block (cond_bb, &true_edge, &false_edge);
+@@ -815,10 +867,9 @@ match_simplify_replacement (basic_block cond_bb, basic_block middle_bb,
+     std::swap (arg0, arg1);
+ 
+   tree type = TREE_TYPE (gimple_phi_result (phi));
+-  result = gimple_simplify (COND_EXPR, type,
+-			    cond,
+-			    arg0, arg1,
+-			    &seq, NULL);
++  result = gimple_simplify_phiopt (early_p, type, stmt,
++				   arg0, arg1,
++				   &seq);
+   if (!result)
+     return false;
+ 
+-- 
+2.27.0.windows.1
+
diff --git a/0063-Backport-Improve-match_simplify_replacement-in-phi-o.patch b/0063-Backport-Improve-match_simplify_replacement-in-phi-o.patch
new file mode 100644
index 0000000..8440622
--- /dev/null
+++ b/0063-Backport-Improve-match_simplify_replacement-in-phi-o.patch
@@ -0,0 +1,259 @@
+From d212d216be0752370dbe7bc63bd75b3a9249e0b5 Mon Sep 17 00:00:00 2001
+From: Andrew Pinski 
+Date: Tue, 1 Jun 2021 06:48:05 +0000
+Subject: [PATCH 15/35] [Backport] Improve match_simplify_replacement in
+ phi-opt
+
+Reference: https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=c4574d23cb07340918793a5a98ae7bb2988b3791
+
+This improves match_simplify_replace in phi-opt to handle the
+case where there is one cheap (non-call) preparation statement in the
+middle basic block similar to xor_replacement and others.
+This allows to remove xor_replacement which it does too.
+
+OK?  Bootstrapped and tested on x86_64-linux-gnu with no regressions.
+
+Thanks,
+Andrew Pinski
+
+Changes since v1:
+v3 - Just minor changes to using gimple_assign_lhs
+instead of gimple_lhs and fixing a comment.
+v2 - change the check on the preparation statement to
+allow only assignments and no calls and only assignments
+that feed into the phi.
+
+gcc/ChangeLog:
+
+	PR tree-optimization/25290
+	* tree-ssa-phiopt.c (xor_replacement): Delete.
+	(tree_ssa_phiopt_worker): Delete use of xor_replacement.
+	(match_simplify_replacement): Allow one cheap preparation
+	statement that can be moved to before the if.
+
+gcc/testsuite/ChangeLog:
+
+	* gcc.dg/tree-ssa/pr96928-1.c: Fix testcase for now that ~
+	happens on the outside of the bit_xor.
+---
+ gcc/tree-ssa-phiopt.c | 164 ++++++++++++++----------------------------
+ 1 file changed, 52 insertions(+), 112 deletions(-)
+
+diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c
+index 92aeb8415..51a2d3684 100644
+--- a/gcc/tree-ssa-phiopt.c
++++ b/gcc/tree-ssa-phiopt.c
+@@ -28,6 +28,7 @@ along with GCC; see the file COPYING3.  If not see
+ #include "cfghooks.h"
+ #include "tree-pass.h"
+ #include "ssa.h"
++#include "tree-ssa.h"
+ #include "optabs-tree.h"
+ #include "insn-config.h"
+ #include "gimple-pretty-print.h"
+@@ -63,8 +64,6 @@ static bool minmax_replacement (basic_block, basic_block,
+ 				edge, edge, gimple *, tree, tree);
+ static bool abs_replacement (basic_block, basic_block,
+ 			     edge, edge, gimple *, tree, tree);
+-static bool xor_replacement (basic_block, basic_block,
+-			     edge, edge, gimple *, tree, tree);
+ static bool spaceship_replacement (basic_block, basic_block,
+ 				   edge, edge, gphi *, tree, tree);
+ static bool cond_removal_in_popcount_clz_ctz_pattern (basic_block, basic_block,
+@@ -355,9 +354,6 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads, bool early_p)
+ 	    cfgchanged = true;
+ 	  else if (abs_replacement (bb, bb1, e1, e2, phi, arg0, arg1))
+ 	    cfgchanged = true;
+-	  else if (!early_p
+-		   && xor_replacement (bb, bb1, e1, e2, phi, arg0, arg1))
+-	    cfgchanged = true;
+ 	  else if (!early_p
+ 		   && cond_removal_in_popcount_clz_ctz_pattern (bb, bb1, e1,
+ 								e2, phi, arg0,
+@@ -841,14 +837,51 @@ match_simplify_replacement (basic_block cond_bb, basic_block middle_bb,
+   edge true_edge, false_edge;
+   gimple_seq seq = NULL;
+   tree result;
+-
+-  if (!empty_block_p (middle_bb))
+-    return false;
++  gimple *stmt_to_move = NULL;
+ 
+   /* Special case A ? B : B as this will always simplify to B. */
+   if (operand_equal_for_phi_arg_p (arg0, arg1))
+     return false;
+ 
++  /* If the basic block only has a cheap preparation statement,
++     allow it and move it once the transformation is done. */
++  if (!empty_block_p (middle_bb))
++    {
++      stmt_to_move = last_and_only_stmt (middle_bb);
++      if (!stmt_to_move)
++	return false;
++
++      if (gimple_vuse (stmt_to_move))
++	return false;
++
++      if (gimple_could_trap_p (stmt_to_move)
++	  || gimple_has_side_effects (stmt_to_move))
++	return false;
++
++      if (gimple_uses_undefined_value_p (stmt_to_move))
++	return false;
++
++      /* Allow assignments and not no calls.
++	 As const calls don't match any of the above, yet they could
++	 still have some side-effects - they could contain
++	 gimple_could_trap_p statements, like floating point
++	 exceptions or integer division by zero.  See PR70586.
++	 FIXME: perhaps gimple_has_side_effects or gimple_could_trap_p
++	 should handle this.  */
++      if (!is_gimple_assign (stmt_to_move))
++	return false;
++
++      tree lhs = gimple_assign_lhs  (stmt_to_move);
++      gimple *use_stmt;
++      use_operand_p use_p;
++
++      /* Allow only a statement which feeds into the phi.  */
++      if (!lhs || TREE_CODE (lhs) != SSA_NAME
++	  || !single_imm_use (lhs, &use_p, &use_stmt)
++	  || use_stmt != phi)
++	return false;
++    }
++
+     /* At this point we know we have a GIMPLE_COND with two successors.
+      One successor is BB, the other successor is an empty block which
+      falls through into BB.
+@@ -874,7 +907,17 @@ match_simplify_replacement (basic_block cond_bb, basic_block middle_bb,
+     return false;
+ 
+   gsi = gsi_last_bb (cond_bb);
+-
++  if (stmt_to_move)
++    {
++      if (dump_file && (dump_flags & TDF_DETAILS))
++	{
++	  fprintf (dump_file, "statement un-sinked:\n");
++	  print_gimple_stmt (dump_file, stmt_to_move, 0,
++			   TDF_VOPS|TDF_MEMSYMS);
++	}
++      gimple_stmt_iterator gsi1 = gsi_for_stmt (stmt_to_move);
++      gsi_move_before (&gsi1, &gsi);
++    }
+   if (seq)
+     gsi_insert_seq_before (&gsi, seq, GSI_SAME_STMT);
+ 
+@@ -2474,109 +2517,6 @@ abs_replacement (basic_block cond_bb, basic_block middle_bb,
+   return true;
+ }
+ 
+-/* Optimize x < 0 ? ~y : y into (x >> (prec-1)) ^ y.  */
+-
+-static bool
+-xor_replacement (basic_block cond_bb, basic_block middle_bb,
+-		 edge e0 ATTRIBUTE_UNUSED, edge e1,
+-		 gimple *phi, tree arg0, tree arg1)
+-{
+-  if (!INTEGRAL_TYPE_P (TREE_TYPE (arg1)))
+-    return false;
+-
+-  /* OTHER_BLOCK must have only one executable statement which must have the
+-     form arg0 = ~arg1 or arg1 = ~arg0.  */
+-
+-  gimple *assign = last_and_only_stmt (middle_bb);
+-  /* If we did not find the proper one's complement assignment, then we cannot
+-     optimize.  */
+-  if (assign == NULL)
+-    return false;
+-
+-  /* If we got here, then we have found the only executable statement
+-     in OTHER_BLOCK.  If it is anything other than arg = ~arg1 or
+-     arg1 = ~arg0, then we cannot optimize.  */
+-  if (!is_gimple_assign (assign))
+-    return false;
+-
+-  if (gimple_assign_rhs_code (assign) != BIT_NOT_EXPR)
+-    return false;
+-
+-  tree lhs = gimple_assign_lhs (assign);
+-  tree rhs = gimple_assign_rhs1 (assign);
+-
+-  /* The assignment has to be arg0 = -arg1 or arg1 = -arg0.  */
+-  if (!(lhs == arg0 && rhs == arg1) && !(lhs == arg1 && rhs == arg0))
+-    return false;
+-
+-  gimple *cond = last_stmt (cond_bb);
+-  tree result = PHI_RESULT (phi);
+-
+-  /* Only relationals comparing arg[01] against zero are interesting.  */
+-  enum tree_code cond_code = gimple_cond_code (cond);
+-  if (cond_code != LT_EXPR && cond_code != GE_EXPR)
+-    return false;
+-
+-  /* Make sure the conditional is x OP 0.  */
+-  tree clhs = gimple_cond_lhs (cond);
+-  if (TREE_CODE (clhs) != SSA_NAME
+-      || !INTEGRAL_TYPE_P (TREE_TYPE (clhs))
+-      || TYPE_UNSIGNED (TREE_TYPE (clhs))
+-      || TYPE_PRECISION (TREE_TYPE (clhs)) != TYPE_PRECISION (TREE_TYPE (arg1))
+-      || !integer_zerop (gimple_cond_rhs (cond)))
+-    return false;
+-
+-  /* We need to know which is the true edge and which is the false
+-     edge so that we know if have xor or inverted xor.  */
+-  edge true_edge, false_edge;
+-  extract_true_false_edges_from_block (cond_bb, &true_edge, &false_edge);
+-
+-  /* For GE_EXPR, if the true edge goes to OTHER_BLOCK, then we
+-     will need to invert the result.  Similarly for LT_EXPR if
+-     the false edge goes to OTHER_BLOCK.  */
+-  edge e;
+-  if (cond_code == GE_EXPR)
+-    e = true_edge;
+-  else
+-    e = false_edge;
+-
+-  bool invert = e->dest == middle_bb;
+-
+-  result = duplicate_ssa_name (result, NULL);
+-
+-  gimple_stmt_iterator gsi = gsi_last_bb (cond_bb);
+-
+-  int prec = TYPE_PRECISION (TREE_TYPE (clhs));
+-  gimple *new_stmt
+-    = gimple_build_assign (make_ssa_name (TREE_TYPE (clhs)), RSHIFT_EXPR, clhs,
+-			   build_int_cst (integer_type_node, prec - 1));
+-  gsi_insert_before (&gsi, new_stmt, GSI_SAME_STMT);
+-
+-  if (!useless_type_conversion_p (TREE_TYPE (result), TREE_TYPE (clhs)))
+-    {
+-      new_stmt = gimple_build_assign (make_ssa_name (TREE_TYPE (result)),
+-				      NOP_EXPR, gimple_assign_lhs (new_stmt));
+-      gsi_insert_before (&gsi, new_stmt, GSI_SAME_STMT);
+-    }
+-  lhs = gimple_assign_lhs (new_stmt);
+-
+-  if (invert)
+-    {
+-      new_stmt = gimple_build_assign (make_ssa_name (TREE_TYPE (result)),
+-				      BIT_NOT_EXPR, rhs);
+-      gsi_insert_before (&gsi, new_stmt, GSI_SAME_STMT);
+-      rhs = gimple_assign_lhs (new_stmt);
+-    }
+-
+-  new_stmt = gimple_build_assign (result, BIT_XOR_EXPR, lhs, rhs);
+-  gsi_insert_before (&gsi, new_stmt, GSI_NEW_STMT);
+-
+-  replace_phi_edge_with_variable (cond_bb, e1, phi, result);
+-
+-  /* Note that we optimized this PHI.  */
+-  return true;
+-}
+-
+ /* Auxiliary functions to determine the set of memory accesses which
+    can't trap because they are preceded by accesses to the same memory
+    portion.  We do that for MEM_REFs, so we only need to track
+-- 
+2.27.0.windows.1
+
diff --git a/0064-Backport-phiopt-Use-gphi-phi-instead-of-gimple-phi-s.patch b/0064-Backport-phiopt-Use-gphi-phi-instead-of-gimple-phi-s.patch
new file mode 100644
index 0000000..de21109
--- /dev/null
+++ b/0064-Backport-phiopt-Use-gphi-phi-instead-of-gimple-phi-s.patch
@@ -0,0 +1,103 @@
+From 0d55d24aa4e47c40f74e0281d023089cfaafcf74 Mon Sep 17 00:00:00 2001
+From: Jakub Jelinek 
+Date: Thu, 6 May 2021 14:05:06 +0200
+Subject: [PATCH 16/35] [Backport] phiopt: Use gphi *phi instead of gimple *phi
+ some more
+
+Reference: https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=cfd65e8d5299a7cf7d2ecd92b0e24ea4cfb697d9
+
+Various functions in phiopt are also called with a gphi * but use
+gimple * argument for it.
+
+2021-05-06  Jakub Jelinek  
+
+	* tree-ssa-phiopt.c (value_replacement, minmax_replacement,
+	abs_replacement, xor_replacement,
+	cond_removal_in_popcount_clz_ctz_pattern,
+	replace_phi_edge_with_variable): Change type of phi argument from
+	gimple * to gphi *.
+---
+ gcc/tree-ssa-phiopt.c | 22 ++++++++++------------
+ 1 file changed, 10 insertions(+), 12 deletions(-)
+
+diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c
+index 51a2d3684..045a7b1b8 100644
+--- a/gcc/tree-ssa-phiopt.c
++++ b/gcc/tree-ssa-phiopt.c
+@@ -59,21 +59,21 @@ static bool match_simplify_replacement (basic_block, basic_block,
+ static gphi *factor_out_conditional_conversion (edge, edge, gphi *, tree, tree,
+ 						gimple *);
+ static int value_replacement (basic_block, basic_block,
+-			      edge, edge, gimple *, tree, tree);
++			      edge, edge, gphi *, tree, tree);
+ static bool minmax_replacement (basic_block, basic_block,
+-				edge, edge, gimple *, tree, tree);
++				edge, edge, gphi *, tree, tree);
+ static bool abs_replacement (basic_block, basic_block,
+-			     edge, edge, gimple *, tree, tree);
++			     edge, edge, gphi *, tree, tree);
+ static bool spaceship_replacement (basic_block, basic_block,
+ 				   edge, edge, gphi *, tree, tree);
+ static bool cond_removal_in_popcount_clz_ctz_pattern (basic_block, basic_block,
+-						      edge, edge, gimple *,
++						      edge, edge, gphi *,
+ 						      tree, tree);
+ static bool cond_store_replacement (basic_block, basic_block, edge, edge,
+ 				    hash_set *);
+ static bool cond_if_else_store_replacement (basic_block, basic_block, basic_block);
+ static hash_set * get_non_trapping ();
+-static void replace_phi_edge_with_variable (basic_block, edge, gimple *, tree);
++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);
+@@ -389,7 +389,7 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads, bool early_p)
+ 
+ static void
+ replace_phi_edge_with_variable (basic_block cond_block,
+-				edge e, gimple *phi, tree new_tree)
++				edge e, gphi *phi, tree new_tree)
+ {
+   basic_block bb = gimple_bb (phi);
+   basic_block block_to_remove;
+@@ -1129,8 +1129,7 @@ absorbing_element_p (tree_code code, tree arg, bool right, tree rval)
+ 
+ static int
+ value_replacement (basic_block cond_bb, basic_block middle_bb,
+-		   edge e0, edge e1, gimple *phi,
+-		   tree arg0, tree arg1)
++		   edge e0, edge e1, gphi *phi, tree arg0, tree arg1)
+ {
+   gimple_stmt_iterator gsi;
+   gimple *cond;
+@@ -1438,8 +1437,7 @@ value_replacement (basic_block cond_bb, basic_block middle_bb,
+ 
+ static bool
+ minmax_replacement (basic_block cond_bb, basic_block middle_bb,
+-		    edge e0, edge e1, gimple *phi,
+-		    tree arg0, tree arg1)
++		    edge e0, edge e1, gphi *phi, tree arg0, tree arg1)
+ {
+   tree result, type, rhs;
+   gcond *cond;
+@@ -2240,7 +2238,7 @@ spaceship_replacement (basic_block cond_bb, basic_block middle_bb,
+ static bool
+ cond_removal_in_popcount_clz_ctz_pattern (basic_block cond_bb,
+ 					  basic_block middle_bb,
+-					  edge e1, edge e2, gimple *phi,
++					  edge e1, edge e2, gphi *phi,
+ 					  tree arg0, tree arg1)
+ {
+   gimple *cond;
+@@ -2398,7 +2396,7 @@ cond_removal_in_popcount_clz_ctz_pattern (basic_block cond_bb,
+ static bool
+ abs_replacement (basic_block cond_bb, basic_block middle_bb,
+ 		 edge e0 ATTRIBUTE_UNUSED, edge e1,
+-		 gimple *phi, tree arg0, tree arg1)
++		 gphi *phi, tree arg0, tree arg1)
+ {
+   tree result;
+   gassign *new_stmt;
+-- 
+2.27.0.windows.1
+
diff --git a/0065-Backport-Optimize-x-bswap-x-0-in-tree-ssa-phiopt.patch b/0065-Backport-Optimize-x-bswap-x-0-in-tree-ssa-phiopt.patch
new file mode 100644
index 0000000..db7b4b2
--- /dev/null
+++ b/0065-Backport-Optimize-x-bswap-x-0-in-tree-ssa-phiopt.patch
@@ -0,0 +1,212 @@
+From 33dc778a34d7b93978efe922bb1b4583d8e6c4bb Mon Sep 17 00:00:00 2001
+From: Roger Sayle 
+Date: Mon, 2 Aug 2021 13:27:53 +0100
+Subject: [PATCH 17/35] [Backport] Optimize x ? bswap(x) : 0 in tree-ssa-phiopt
+
+Reference: https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=f9fcf754825a1e01033336f84c18690aaa971a6f
+
+Many thanks again to Jakub Jelinek for a speedy fix for PR 101642.
+Interestingly, that test case "bswap16(x) ? : x" also reveals a
+missed optimization opportunity.  The resulting "x ? bswap(x) : 0"
+can be further simplified to just bswap(x).
+
+Conveniently, tree-ssa-phiopt.c already recognizes/optimizes the
+related "x ? popcount(x) : 0", so this patch simply makes that
+transformation make general, additionally handling bswap, parity,
+ffs and clrsb.  All of the required infrastructure is already
+present thanks to Jakub previously adding support for clz/ctz.
+To reflect this generalization, the name of the function is changed
+from cond_removal_in_popcount_clz_ctz_pattern to the hopefully
+equally descriptive cond_removal_in_builtin_zero_pattern.
+
+2021-08-02  Roger Sayle  
+
+gcc/ChangeLog
+	* tree-ssa-phiopt.c (cond_removal_in_builtin_zero_pattern):
+	Renamed from cond_removal_in_popcount_clz_ctz_pattern.
+	Add support for BSWAP, FFS, PARITY and CLRSB builtins.
+	(tree_ssa_phiop_worker): Update call to function above.
+
+gcc/testsuite/ChangeLog
+	* gcc.dg/tree-ssa/phi-opt-25.c: New test case.
+---
+ gcc/testsuite/gcc.dg/tree-ssa/phi-opt-25.c | 83 ++++++++++++++++++++++
+ gcc/tree-ssa-phiopt.c                      | 37 +++++++---
+ 2 files changed, 109 insertions(+), 11 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/phi-opt-25.c
+
+diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-25.c b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-25.c
+new file mode 100644
+index 000000000..c52c92e1d
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-25.c
+@@ -0,0 +1,83 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -fdump-tree-optimized" } */
++
++unsigned short test_bswap16(unsigned short x)
++{
++  return x ? __builtin_bswap16(x) : 0;
++}
++
++unsigned int test_bswap32(unsigned int x)
++{
++  return x ? __builtin_bswap32(x) : 0;
++}
++
++unsigned long long test_bswap64(unsigned long long x)
++{
++  return x ? __builtin_bswap64(x) : 0;
++}
++
++int test_clrsb(int x)
++{
++  return x ? __builtin_clrsb(x) : (__SIZEOF_INT__*8-1);
++}
++
++int test_clrsbl(long x)
++{
++  return x ? __builtin_clrsbl(x) : (__SIZEOF_LONG__*8-1);
++}
++
++int test_clrsbll(long long x)
++{
++  return x ? __builtin_clrsbll(x) : (__SIZEOF_LONG_LONG__*8-1);
++}
++
++#if 0
++/* BUILT_IN_FFS is transformed by match.pd */
++int test_ffs(unsigned int x)
++{
++  return x ? __builtin_ffs(x) : 0;
++}
++
++int test_ffsl(unsigned long x)
++{
++  return x ? __builtin_ffsl(x) : 0;
++}
++
++int test_ffsll(unsigned long long x)
++{
++  return x ? __builtin_ffsll(x) : 0;
++}
++#endif
++
++int test_parity(int x)
++{
++  return x ? __builtin_parity(x) : 0;
++}
++
++int test_parityl(long x)
++{
++  return x ? __builtin_parityl(x) : 0;
++}
++
++int test_parityll(long long x)
++{
++  return x ? __builtin_parityll(x) : 0;
++}
++
++int test_popcount(int x)
++{
++  return x ? __builtin_popcount(x) : 0;
++}
++
++int test_popcountl(long x)
++{
++  return x ? __builtin_popcountl(x) : 0;
++}
++
++int test_popcountll(long long x)
++{
++  return x ? __builtin_popcountll(x) : 0;
++}
++
++/* { dg-final { scan-tree-dump-not "goto" "optimized" } } */
++
+diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c
+index 045a7b1b8..21ac08145 100644
+--- a/gcc/tree-ssa-phiopt.c
++++ b/gcc/tree-ssa-phiopt.c
+@@ -66,9 +66,9 @@ static bool abs_replacement (basic_block, basic_block,
+ 			     edge, edge, gphi *, tree, tree);
+ static bool spaceship_replacement (basic_block, basic_block,
+ 				   edge, edge, gphi *, tree, tree);
+-static bool cond_removal_in_popcount_clz_ctz_pattern (basic_block, basic_block,
+-						      edge, edge, gphi *,
+-						      tree, tree);
++static bool cond_removal_in_builtin_zero_pattern (basic_block, basic_block,
++						  edge, edge, gphi *,
++						  tree, tree);
+ static bool cond_store_replacement (basic_block, basic_block, edge, edge,
+ 				    hash_set *);
+ static bool cond_if_else_store_replacement (basic_block, basic_block, basic_block);
+@@ -355,9 +355,8 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads, bool early_p)
+ 	  else if (abs_replacement (bb, bb1, e1, e2, phi, arg0, arg1))
+ 	    cfgchanged = true;
+ 	  else if (!early_p
+-		   && cond_removal_in_popcount_clz_ctz_pattern (bb, bb1, e1,
+-								e2, phi, arg0,
+-								arg1))
++		   && cond_removal_in_builtin_zero_pattern (bb, bb1, e1, e2,
++							    phi, arg0, arg1))
+ 	    cfgchanged = true;
+ 	  else if (minmax_replacement (bb, bb1, e1, e2, phi, arg0, arg1))
+ 	    cfgchanged = true;
+@@ -2204,7 +2203,8 @@ spaceship_replacement (basic_block cond_bb, basic_block middle_bb,
+   return true;
+ }
+ 
+-/* Convert
++/* Optimize x ? __builtin_fun (x) : C, where C is __builtin_fun (0).
++   Convert
+ 
+    
+    if (b_4(D) != 0)
+@@ -2236,10 +2236,10 @@ spaceship_replacement (basic_block cond_bb, basic_block middle_bb,
+    instead of 0 above it uses the value from that macro.  */
+ 
+ static bool
+-cond_removal_in_popcount_clz_ctz_pattern (basic_block cond_bb,
+-					  basic_block middle_bb,
+-					  edge e1, edge e2, gphi *phi,
+-					  tree arg0, tree arg1)
++cond_removal_in_builtin_zero_pattern (basic_block cond_bb,
++				      basic_block middle_bb,
++				      edge e1, edge e2, gphi *phi,
++				      tree arg0, tree arg1)
+ {
+   gimple *cond;
+   gimple_stmt_iterator gsi, gsi_from;
+@@ -2287,6 +2287,12 @@ cond_removal_in_popcount_clz_ctz_pattern (basic_block cond_bb,
+   int val = 0;
+   switch (cfn)
+     {
++    case CFN_BUILT_IN_BSWAP16:
++    case CFN_BUILT_IN_BSWAP32:
++    case CFN_BUILT_IN_BSWAP64:
++    case CFN_BUILT_IN_BSWAP128:
++    CASE_CFN_FFS:
++    CASE_CFN_PARITY:
+     CASE_CFN_POPCOUNT:
+       break;
+     CASE_CFN_CLZ:
+@@ -2315,6 +2321,15 @@ cond_removal_in_popcount_clz_ctz_pattern (basic_block cond_bb,
+ 	    }
+ 	}
+       return false;
++    case BUILT_IN_CLRSB:
++      val = TYPE_PRECISION (integer_type_node) - 1;
++      break;
++    case BUILT_IN_CLRSBL:
++      val = TYPE_PRECISION (long_integer_type_node) - 1;
++      break;
++    case BUILT_IN_CLRSBLL:
++      val = TYPE_PRECISION (long_long_integer_type_node) - 1;
++      break;
+     default:
+       return false;
+     }
+-- 
+2.27.0.windows.1
+
diff --git a/0066-Backport-tree-optimization-102880-make-PHI-OPT-recog.patch b/0066-Backport-tree-optimization-102880-make-PHI-OPT-recog.patch
new file mode 100644
index 0000000..df34234
--- /dev/null
+++ b/0066-Backport-tree-optimization-102880-make-PHI-OPT-recog.patch
@@ -0,0 +1,251 @@
+From 77398954ce517aa011b7a254c7aa2858521b2093 Mon Sep 17 00:00:00 2001
+From: Richard Biener 
+Date: Mon, 15 Nov 2021 15:19:36 +0100
+Subject: [PATCH 18/35] [Backport] tree-optimization/102880 - make PHI-OPT
+ recognize more CFGs
+
+Reference: https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=f98f373dd822b35c52356b753d528924e9f89678
+
+This allows extra edges into the middle BB for the PHI-OPT
+transforms using replace_phi_edge_with_variable that do not
+end up moving stmts from that middle BB.  This avoids regressing
+gcc.dg/tree-ssa/ssa-hoist-4.c with the actual fix for PR102880
+where CFG cleanup has the choice to remove two forwarders and
+picks "the wrong" leading to
+
+   if (a > b) /
+       /\    /
+      /  
+     /    |
+  # PHI 
+
+rather than
+
+   if (a > b)  |
+       /\      |
+     \     |
+     /    \    |
+  # PHI 
+
+but it's relatively straight-forward to support extra edges
+into the middle-BB in paths ending in replace_phi_edge_with_variable
+and that do not require moving stmts.  That's because we really
+only want to remove the edge from the condition to the middle BB.
+Of course actually doing that means updating dominators in non-trival
+ways which is why I kept the original code for the single edge
+case and simply defer to CFG cleanup by adjusting the condition for
+the complicated case.
+
+The testcase needs to be a GIMPLE one since it's quite unreliable
+to produce the desired CFG.
+
+2021-11-15  Richard Biener  
+
+	PR tree-optimization/102880
+	* tree-ssa-phiopt.c (tree_ssa_phiopt_worker): Push
+	single_pred (bb1) condition to places that really need it.
+	(match_simplify_replacement): Likewise.
+	(value_replacement): Likewise.
+	(replace_phi_edge_with_variable): Deal with extra edges
+	into the middle BB.
+
+	* gcc.dg/tree-ssa/phi-opt-26.c: New testcase.
+---
+ gcc/testsuite/gcc.dg/tree-ssa/phi-opt-26.c | 31 +++++++++
+ gcc/tree-ssa-phiopt.c                      | 73 +++++++++++++---------
+ 2 files changed, 75 insertions(+), 29 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/phi-opt-26.c
+
+diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-26.c b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-26.c
+new file mode 100644
+index 000000000..21aa66e38
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-26.c
+@@ -0,0 +1,31 @@
++/* { dg-do compile } */
++/* { dg-options "-O -fgimple -fdump-tree-phiopt1" } */
++
++int __GIMPLE (ssa,startwith("phiopt"))
++foo (int a, int b, int flag)
++{
++  int res;
++
++  __BB(2):
++  if (flag_2(D) != 0)
++    goto __BB6;
++  else
++    goto __BB4;
++
++  __BB(4):
++  if (a_3(D) > b_4(D))
++    goto __BB7;
++  else
++    goto __BB6;
++
++  __BB(6):
++  goto __BB7;
++
++  __BB(7):
++  res_1 = __PHI (__BB4: a_3(D), __BB6: b_4(D));
++  return res_1;
++}
++
++/* We should be able to detect MAX despite the extra edge into
++   the middle BB.  */
++/* { dg-final { scan-tree-dump "MAX" "phiopt1" } } */
+diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c
+index 21ac08145..079d29e74 100644
+--- a/gcc/tree-ssa-phiopt.c
++++ b/gcc/tree-ssa-phiopt.c
+@@ -219,7 +219,6 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads, bool early_p)
+ 
+       /* If either bb1's succ or bb2 or bb2's succ is non NULL.  */
+       if (EDGE_COUNT (bb1->succs) == 0
+-          || bb2 == NULL
+ 	  || EDGE_COUNT (bb2->succs) == 0)
+         continue;
+ 
+@@ -279,14 +278,14 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads, bool early_p)
+ 	  || (e1->flags & EDGE_FALLTHRU) == 0)
+         continue;
+ 
+-      /* Also make sure that bb1 only have one predecessor and that it
+-	 is bb.  */
+-      if (!single_pred_p (bb1)
+-          || single_pred (bb1) != bb)
+-	continue;
+-
+       if (do_store_elim)
+ 	{
++	  /* Also make sure that bb1 only have one predecessor and that it
++	     is bb.  */
++	  if (!single_pred_p (bb1)
++	      || single_pred (bb1) != bb)
++	    continue;
++
+ 	  /* bb1 is the middle block, bb2 the join block, bb the split block,
+ 	     e1 the fallthrough edge from bb1 to bb2.  We can't do the
+ 	     optimization if the join block has more than two predecessors.  */
+@@ -331,10 +330,11 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads, bool early_p)
+ 	     node.  */
+ 	  gcc_assert (arg0 != NULL_TREE && arg1 != NULL_TREE);
+ 
+-	  gphi *newphi = factor_out_conditional_conversion (e1, e2, phi,
+-							    arg0, arg1,
+-							    cond_stmt);
+-	  if (newphi != NULL)
++	  gphi *newphi;
++	  if (single_pred_p (bb1)
++	      && (newphi = factor_out_conditional_conversion (e1, e2, phi,
++							      arg0, arg1,
++							      cond_stmt)))
+ 	    {
+ 	      phi = newphi;
+ 	      /* factor_out_conditional_conversion may create a new PHI in
+@@ -355,12 +355,14 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads, bool early_p)
+ 	  else if (abs_replacement (bb, bb1, e1, e2, phi, arg0, arg1))
+ 	    cfgchanged = true;
+ 	  else if (!early_p
++		   && single_pred_p (bb1)
+ 		   && cond_removal_in_builtin_zero_pattern (bb, bb1, e1, e2,
+ 							    phi, arg0, arg1))
+ 	    cfgchanged = true;
+ 	  else if (minmax_replacement (bb, bb1, e1, e2, phi, arg0, arg1))
+ 	    cfgchanged = true;
+-	  else if (spaceship_replacement (bb, bb1, e1, e2, phi, arg0, arg1))
++	  else if (single_pred_p (bb1)
++		   && spaceship_replacement (bb, bb1, e1, e2, phi, arg0, arg1))
+ 	    cfgchanged = true;
+ 	}
+     }
+@@ -391,35 +393,41 @@ replace_phi_edge_with_variable (basic_block cond_block,
+ 				edge e, gphi *phi, tree new_tree)
+ {
+   basic_block bb = gimple_bb (phi);
+-  basic_block block_to_remove;
+   gimple_stmt_iterator gsi;
+ 
+   /* Change the PHI argument to new.  */
+   SET_USE (PHI_ARG_DEF_PTR (phi, e->dest_idx), new_tree);
+ 
+   /* Remove the empty basic block.  */
++  edge edge_to_remove;
+   if (EDGE_SUCC (cond_block, 0)->dest == bb)
++    edge_to_remove = EDGE_SUCC (cond_block, 1);
++  else
++    edge_to_remove = EDGE_SUCC (cond_block, 0);
++  if (EDGE_COUNT (edge_to_remove->dest->preds) == 1)
+     {
+-      EDGE_SUCC (cond_block, 0)->flags |= EDGE_FALLTHRU;
+-      EDGE_SUCC (cond_block, 0)->flags &= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE);
+-      EDGE_SUCC (cond_block, 0)->probability = profile_probability::always ();
+-
+-      block_to_remove = EDGE_SUCC (cond_block, 1)->dest;
++      e->flags |= EDGE_FALLTHRU;
++      e->flags &= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE);
++      e->probability = profile_probability::always ();
++      delete_basic_block (edge_to_remove->dest);
++
++      /* Eliminate the COND_EXPR at the end of COND_BLOCK.  */
++      gsi = gsi_last_bb (cond_block);
++      gsi_remove (&gsi, true);
+     }
+   else
+     {
+-      EDGE_SUCC (cond_block, 1)->flags |= EDGE_FALLTHRU;
+-      EDGE_SUCC (cond_block, 1)->flags
+-	&= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE);
+-      EDGE_SUCC (cond_block, 1)->probability = profile_probability::always ();
+-
+-      block_to_remove = EDGE_SUCC (cond_block, 0)->dest;
++      /* If there are other edges into the middle block make
++	 CFG cleanup deal with the edge removal to avoid
++	 updating dominators here in a non-trivial way.  */
++      gcond *cond = as_a  (last_stmt (cond_block));
++      if (edge_to_remove->flags & EDGE_TRUE_VALUE)
++	gimple_cond_make_false (cond);
++      else
++	gimple_cond_make_true (cond);
+     }
+-  delete_basic_block (block_to_remove);
+ 
+-  /* Eliminate the COND_EXPR at the end of COND_BLOCK.  */
+-  gsi = gsi_last_bb (cond_block);
+-  gsi_remove (&gsi, true);
++  statistics_counter_event (cfun, "Replace PHI with variable", 1);
+ 
+   if (dump_file && (dump_flags & TDF_DETAILS))
+     fprintf (dump_file,
+@@ -846,6 +854,9 @@ match_simplify_replacement (basic_block cond_bb, basic_block middle_bb,
+      allow it and move it once the transformation is done. */
+   if (!empty_block_p (middle_bb))
+     {
++      if (!single_pred_p (middle_bb))
++	return false;
++
+       stmt_to_move = last_and_only_stmt (middle_bb);
+       if (!stmt_to_move)
+ 	return false;
+@@ -1225,6 +1236,11 @@ value_replacement (basic_block cond_bb, basic_block middle_bb,
+ 	}
+       else
+ 	{
++	  if (!single_pred_p (middle_bb))
++	    return 0;
++	  statistics_counter_event (cfun, "Replace PHI with "
++				    "variable/value_replacement", 1);
++
+ 	  /* Replace the PHI arguments with arg. */
+ 	  SET_PHI_ARG_DEF (phi, e0->dest_idx, arg);
+ 	  SET_PHI_ARG_DEF (phi, e1->dest_idx, arg);
+@@ -1239,7 +1255,6 @@ value_replacement (basic_block cond_bb, basic_block middle_bb,
+             }
+           return 1;
+ 	}
+-
+     }
+ 
+   /* Now optimize (x != 0) ? x + y : y to just x + y.  */
+-- 
+2.27.0.windows.1
+
diff --git a/0067-Backport-tree-Add-vector_element_bits-_tree-PR94980-.patch b/0067-Backport-tree-Add-vector_element_bits-_tree-PR94980-.patch
new file mode 100644
index 0000000..06217a8
--- /dev/null
+++ b/0067-Backport-tree-Add-vector_element_bits-_tree-PR94980-.patch
@@ -0,0 +1,250 @@
+From a2f5e6f38fe7b5b32a252643b00dd2d7ab0e3fac Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 12 May 2020 09:01:10 +0100
+Subject: [PATCH 19/35] [Backport] tree: Add vector_element_bits(_tree)
+ [PR94980 1/3]
+
+Reference: https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=d17a896da1e898928d337596d029f0ece0039d55
+
+A lot of code that wants to know the number of bits in a vector
+element gets that information from the element's TYPE_SIZE,
+which is always equal to TYPE_SIZE_UNIT * BITS_PER_UNIT.
+This doesn't work for SVE and AVX512-style packed boolean vectors,
+where several elements can occupy a single byte.
+
+This patch introduces a new pair of helpers for getting the true
+(possibly sub-byte) size.  I made a token attempt to convert obvious
+element size calculations, but I'm sure I missed some.
+
+2020-05-12  Richard Sandiford  
+
+gcc/
+	PR tree-optimization/94980
+	* tree.h (vector_element_bits, vector_element_bits_tree): Declare.
+	* tree.c (vector_element_bits, vector_element_bits_tree): New.
+	* match.pd: Use the new functions instead of determining the
+	vector element size directly from TYPE_SIZE(_UNIT).
+	* tree-vect-data-refs.c (vect_gather_scatter_fn_p): Likewise.
+	* tree-vect-patterns.c (vect_recog_mask_conversion_pattern): Likewise.
+	* tree-vect-stmts.c (vect_is_simple_cond): Likewise.
+	* tree-vect-generic.c (expand_vector_piecewise): Likewise.
+	(expand_vector_conversion): Likewise.
+	(expand_vector_addition): Likewise for a TYPE_SIZE_UNIT used as
+	a divisor.  Convert the dividend to bits to compensate.
+	* tree-vect-loop.c (vectorizable_live_operation): Call
+	vector_element_bits instead of open-coding it.
+---
+ gcc/ChangeLog             | 17 +++++++++++++++++
+ gcc/match.pd              |  2 +-
+ gcc/tree-vect-data-refs.c |  2 +-
+ gcc/tree-vect-generic.c   | 19 +++++++------------
+ gcc/tree-vect-loop.c      |  4 +---
+ gcc/tree-vect-patterns.c  |  3 +--
+ gcc/tree-vect-stmts.c     |  3 +--
+ gcc/tree.c                | 24 ++++++++++++++++++++++++
+ gcc/tree.h                |  2 ++
+ 9 files changed, 55 insertions(+), 21 deletions(-)
+
+diff --git a/gcc/ChangeLog b/gcc/ChangeLog
+index 3b1384e70..07aea9b86 100644
+--- a/gcc/ChangeLog
++++ b/gcc/ChangeLog
+@@ -1,3 +1,20 @@
++2020-05-12  Richard Sandiford  
++
++	PR tree-optimization/94980
++	* tree.h (vector_element_bits, vector_element_bits_tree): Declare.
++	* tree.c (vector_element_bits, vector_element_bits_tree): New.
++	* match.pd: Use the new functions instead of determining the
++	vector element size directly from TYPE_SIZE(_UNIT).
++	* tree-vect-data-refs.c (vect_gather_scatter_fn_p): Likewise.
++	* tree-vect-patterns.c (vect_recog_mask_conversion_pattern): Likewise.
++	* tree-vect-stmts.c (vect_is_simple_cond): Likewise.
++	* tree-vect-generic.c (expand_vector_piecewise): Likewise.
++	(expand_vector_conversion): Likewise.
++	(expand_vector_addition): Likewise for a TYPE_SIZE_UNIT used as
++	a divisor.  Convert the dividend to bits to compensate.
++	* tree-vect-loop.c (vectorizable_live_operation): Call
++	vector_element_bits instead of open-coding it.
++
+ 2021-04-08  Release Manager
+ 
+ 	* GCC 10.3.0 released.
+diff --git a/gcc/match.pd b/gcc/match.pd
+index 5899eea95..79a0228d2 100644
+--- a/gcc/match.pd
++++ b/gcc/match.pd
+@@ -6236,7 +6236,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
+       }
+       (if (ins)
+        (bit_insert { op0; } { ins; }
+-         { bitsize_int (at * tree_to_uhwi (TYPE_SIZE (TREE_TYPE (type)))); })
++         { bitsize_int (at * vector_element_bits (type)); })
+        (if (changed)
+         (vec_perm { op0; } { op1; } { op2; }))))))))))
+ 
+diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c
+index d78b06455..e4466a4f3 100644
+--- a/gcc/tree-vect-data-refs.c
++++ b/gcc/tree-vect-data-refs.c
+@@ -3709,7 +3709,7 @@ vect_gather_scatter_fn_p (vec_info *vinfo, bool read_p, bool masked_p,
+ 			  tree *offset_vectype_out)
+ {
+   unsigned int memory_bits = tree_to_uhwi (TYPE_SIZE (memory_type));
+-  unsigned int element_bits = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (vectype)));
++  unsigned int element_bits = vector_element_bits (vectype);
+   if (element_bits != memory_bits)
+     /* For now the vector elements must be the same width as the
+        memory elements.  */
+diff --git a/gcc/tree-vect-generic.c b/gcc/tree-vect-generic.c
+index c10492034..37c3956a4 100644
+--- a/gcc/tree-vect-generic.c
++++ b/gcc/tree-vect-generic.c
+@@ -276,8 +276,7 @@ expand_vector_piecewise (gimple_stmt_iterator *gsi, elem_op_func f,
+   tree part_width = TYPE_SIZE (inner_type);
+   tree index = bitsize_int (0);
+   int nunits = nunits_for_known_piecewise_op (type);
+-  int delta = tree_to_uhwi (part_width)
+-	      / tree_to_uhwi (TYPE_SIZE (TREE_TYPE (type)));
++  int delta = tree_to_uhwi (part_width) / vector_element_bits (type);
+   int i;
+   location_t loc = gimple_location (gsi_stmt (*gsi));
+ 
+@@ -357,8 +356,7 @@ expand_vector_addition (gimple_stmt_iterator *gsi,
+ 			elem_op_func f, elem_op_func f_parallel,
+ 			tree type, tree a, tree b, enum tree_code code)
+ {
+-  int parts_per_word = UNITS_PER_WORD
+-	  	       / tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (type)));
++  int parts_per_word = BITS_PER_WORD / vector_element_bits (type);
+ 
+   if (INTEGRAL_TYPE_P (TREE_TYPE (type))
+       && parts_per_word >= 4
+@@ -1733,19 +1731,17 @@ expand_vector_conversion (gimple_stmt_iterator *gsi)
+   optab optab1 = unknown_optab;
+ 
+   gcc_checking_assert (VECTOR_TYPE_P (ret_type) && VECTOR_TYPE_P (arg_type));
+-  gcc_checking_assert (tree_fits_uhwi_p (TYPE_SIZE (TREE_TYPE (ret_type))));
+-  gcc_checking_assert (tree_fits_uhwi_p (TYPE_SIZE (TREE_TYPE (arg_type))));
+   if (INTEGRAL_TYPE_P (TREE_TYPE (ret_type))
+       && SCALAR_FLOAT_TYPE_P (TREE_TYPE (arg_type)))
+     code = FIX_TRUNC_EXPR;
+   else if (INTEGRAL_TYPE_P (TREE_TYPE (arg_type))
+ 	   && SCALAR_FLOAT_TYPE_P (TREE_TYPE (ret_type)))
+     code = FLOAT_EXPR;
+-  if (tree_to_uhwi (TYPE_SIZE (TREE_TYPE (ret_type)))
+-      < tree_to_uhwi (TYPE_SIZE (TREE_TYPE (arg_type))))
++  unsigned int ret_elt_bits = vector_element_bits (ret_type);
++  unsigned int arg_elt_bits = vector_element_bits (arg_type);
++  if (ret_elt_bits < arg_elt_bits)
+     modifier = NARROW;
+-  else if (tree_to_uhwi (TYPE_SIZE (TREE_TYPE (ret_type)))
+-	   > tree_to_uhwi (TYPE_SIZE (TREE_TYPE (arg_type))))
++  else if (ret_elt_bits > arg_elt_bits)
+     modifier = WIDEN;
+ 
+   if (modifier == NONE && (code == FIX_TRUNC_EXPR || code == FLOAT_EXPR))
+@@ -1908,8 +1904,7 @@ expand_vector_conversion (gimple_stmt_iterator *gsi)
+ 	      tree part_width = TYPE_SIZE (compute_type);
+ 	      tree index = bitsize_int (0);
+ 	      int nunits = nunits_for_known_piecewise_op (arg_type);
+-	      int delta = tree_to_uhwi (part_width)
+-			  / tree_to_uhwi (TYPE_SIZE (TREE_TYPE (arg_type)));
++	      int delta = tree_to_uhwi (part_width) / arg_elt_bits;
+ 	      int i;
+ 	      location_t loc = gimple_location (gsi_stmt (*gsi));
+ 
+diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c
+index 899b56087..7990e31de 100644
+--- a/gcc/tree-vect-loop.c
++++ b/gcc/tree-vect-loop.c
+@@ -8059,9 +8059,7 @@ vectorizable_live_operation (stmt_vec_info stmt_info,
+ 	: gimple_get_lhs (stmt);
+   lhs_type = TREE_TYPE (lhs);
+ 
+-  bitsize = (VECTOR_BOOLEAN_TYPE_P (vectype)
+-	     ? bitsize_int (TYPE_PRECISION (TREE_TYPE (vectype)))
+-	     : TYPE_SIZE (TREE_TYPE (vectype)));
++  bitsize = vector_element_bits_tree (vectype);
+   vec_bitsize = TYPE_SIZE (vectype);
+ 
+   /* Get the vectorized lhs of STMT and the lane to use (counted in bits).  */
+diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c
+index 84d7ddb17..b076740ef 100644
+--- a/gcc/tree-vect-patterns.c
++++ b/gcc/tree-vect-patterns.c
+@@ -4406,8 +4406,7 @@ vect_recog_mask_conversion_pattern (stmt_vec_info stmt_vinfo, tree *type_out)
+ 		  || dt == vect_constant_def))
+ 	    {
+ 	      tree wide_scalar_type = build_nonstandard_integer_type
+-		(tree_to_uhwi (TYPE_SIZE (TREE_TYPE (vectype1))),
+-		 TYPE_UNSIGNED (rhs1_type));
++		(vector_element_bits (vectype1), TYPE_UNSIGNED (rhs1_type));
+ 	      tree vectype3 = get_vectype_for_scalar_type (vinfo,
+ 							   wide_scalar_type);
+ 	      if (expand_vec_cond_expr_p (vectype1, vectype3, TREE_CODE (rhs1)))
+diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
+index 4636b7ba2..0bdf9a547 100644
+--- a/gcc/tree-vect-stmts.c
++++ b/gcc/tree-vect-stmts.c
+@@ -10717,8 +10717,7 @@ vect_is_simple_cond (tree cond, vec_info *vinfo, slp_tree slp_node,
+ 	      && tree_int_cst_lt (TYPE_SIZE (scalar_type),
+ 				  TYPE_SIZE (TREE_TYPE (vectype))))
+ 	    scalar_type = build_nonstandard_integer_type
+-	      (tree_to_uhwi (TYPE_SIZE (TREE_TYPE (vectype))),
+-	       TYPE_UNSIGNED (scalar_type));
++	      (vector_element_bits (vectype), TYPE_UNSIGNED (scalar_type));
+ 	  *comp_vectype = get_vectype_for_scalar_type (vinfo, scalar_type,
+ 						       slp_node);
+ 	}
+diff --git a/gcc/tree.c b/gcc/tree.c
+index 3e6647ae0..9a0cedf10 100644
+--- a/gcc/tree.c
++++ b/gcc/tree.c
+@@ -13892,6 +13892,30 @@ vector_type_mode (const_tree t)
+   return mode;
+ }
+ 
++/* Return the size in bits of each element of vector type TYPE.  */
++
++unsigned int
++vector_element_bits (const_tree type)
++{
++  gcc_checking_assert (VECTOR_TYPE_P (type));
++  if (VECTOR_BOOLEAN_TYPE_P (type))
++    return vector_element_size (tree_to_poly_uint64 (TYPE_SIZE (type)),
++				TYPE_VECTOR_SUBPARTS (type));
++  return tree_to_uhwi (TYPE_SIZE (TREE_TYPE (type)));
++}
++
++/* Calculate the size in bits of each element of vector type TYPE
++   and return the result as a tree of type bitsizetype.  */
++
++tree
++vector_element_bits_tree (const_tree type)
++{
++  gcc_checking_assert (VECTOR_TYPE_P (type));
++  if (VECTOR_BOOLEAN_TYPE_P (type))
++    return bitsize_int (vector_element_bits (type));
++  return TYPE_SIZE (TREE_TYPE (type));
++}
++
+ /* Verify that basic properties of T match TV and thus T can be a variant of
+    TV.  TV should be the more specified variant (i.e. the main variant).  */
+ 
+diff --git a/gcc/tree.h b/gcc/tree.h
+index bddc6e528..c66207fa0 100644
+--- a/gcc/tree.h
++++ b/gcc/tree.h
+@@ -1996,6 +1996,8 @@ class auto_suppress_location_wrappers
+ 
+ extern machine_mode element_mode (const_tree);
+ extern machine_mode vector_type_mode (const_tree);
++extern unsigned int vector_element_bits (const_tree);
++extern tree vector_element_bits_tree (const_tree);
+ 
+ /* The "canonical" type for this type node, which is used by frontends to
+    compare the type for equality with another type.  If two types are
+-- 
+2.27.0.windows.1
+
diff --git a/0068-Backport-Lower-VEC_COND_EXPR-into-internal-functions.patch b/0068-Backport-Lower-VEC_COND_EXPR-into-internal-functions.patch
new file mode 100644
index 0000000..6bbb8ad
--- /dev/null
+++ b/0068-Backport-Lower-VEC_COND_EXPR-into-internal-functions.patch
@@ -0,0 +1,1063 @@
+From 3a45b2fc131e4639b05f62d6064bd964d129c19b Mon Sep 17 00:00:00 2001
+From: Martin Liska 
+Date: Mon, 9 Mar 2020 13:23:03 +0100
+Subject: [PATCH 20/35] [Backport] Lower VEC_COND_EXPR into internal functions.
+
+Reference: https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=502d63b6d6141597bb18fd23c87736a1b384cf8f
+
+gcc/ChangeLog:
+
+	* Makefile.in: Add new file.
+	* expr.c (expand_expr_real_2): Add gcc_unreachable as we should
+	not meet this condition.
+	(do_store_flag): Likewise.
+	* gimplify.c (gimplify_expr): Gimplify first argument of
+	VEC_COND_EXPR to be a SSA name.
+	* internal-fn.c (vec_cond_mask_direct): New.
+	(vec_cond_direct): Likewise.
+	(vec_condu_direct): Likewise.
+	(vec_condeq_direct): Likewise.
+	(expand_vect_cond_optab_fn):  New.
+	(expand_vec_cond_optab_fn): Likewise.
+	(expand_vec_condu_optab_fn): Likewise.
+	(expand_vec_condeq_optab_fn): Likewise.
+	(expand_vect_cond_mask_optab_fn): Likewise.
+	(expand_vec_cond_mask_optab_fn): Likewise.
+	(direct_vec_cond_mask_optab_supported_p): Likewise.
+	(direct_vec_cond_optab_supported_p): Likewise.
+	(direct_vec_condu_optab_supported_p): Likewise.
+	(direct_vec_condeq_optab_supported_p): Likewise.
+	* internal-fn.def (VCOND): New OPTAB.
+	(VCONDU): Likewise.
+	(VCONDEQ): Likewise.
+	(VCOND_MASK): Likewise.
+	* optabs.c (get_rtx_code): Make it global.
+	(expand_vec_cond_mask_expr): Removed.
+	(expand_vec_cond_expr): Removed.
+	* optabs.h (expand_vec_cond_expr): Likewise.
+	(vector_compare_rtx): Make it global.
+	* passes.def: Add new pass_gimple_isel pass.
+	* tree-cfg.c (verify_gimple_assign_ternary): Add check
+	for VEC_COND_EXPR about first argument.
+	* tree-pass.h (make_pass_gimple_isel): New.
+	* tree-ssa-forwprop.c (pass_forwprop::execute): Prevent
+	propagation of the first argument of a VEC_COND_EXPR.
+	* tree-ssa-reassoc.c (ovce_extract_ops): Support SSA_NAME as
+	first argument of a VEC_COND_EXPR.
+	(optimize_vec_cond_expr): Likewise.
+	* tree-vect-generic.c (expand_vector_divmod): Make SSA_NAME
+	for a first argument of created VEC_COND_EXPR.
+	(expand_vector_condition): Fix coding style.
+	* tree-vect-stmts.c (vectorizable_condition): Gimplify
+	first argument.
+	* gimple-isel.cc: New file.
+
+gcc/testsuite/ChangeLog:
+
+	* g++.dg/vect/vec-cond-expr-eh.C: New test.
+---
+ gcc/Makefile.in                              |   2 +
+ gcc/expr.c                                   |  25 +-
+ gcc/gimple-isel.cc                           | 244 +++++++++++++++++++
+ gcc/gimplify.c                               |  15 +-
+ gcc/internal-fn.c                            |  89 +++++++
+ gcc/internal-fn.def                          |   5 +
+ gcc/optabs.c                                 | 124 +---------
+ gcc/optabs.h                                 |   7 +-
+ gcc/passes.def                               |   1 +
+ gcc/testsuite/g++.dg/vect/vec-cond-expr-eh.C |  17 ++
+ gcc/tree-cfg.c                               |   2 +-
+ gcc/tree-pass.h                              |   1 +
+ gcc/tree-ssa-forwprop.c                      |   3 +-
+ gcc/tree-ssa-reassoc.c                       |  64 +++--
+ gcc/tree-vect-generic.c                      |  45 ++--
+ gcc/tree-vect-stmts.c                        |   8 +-
+ 16 files changed, 441 insertions(+), 211 deletions(-)
+ create mode 100644 gcc/gimple-isel.cc
+ create mode 100644 gcc/testsuite/g++.dg/vect/vec-cond-expr-eh.C
+
+diff --git a/gcc/Makefile.in b/gcc/Makefile.in
+index 2b2bf474a..3f06b8907 100644
+--- a/gcc/Makefile.in
++++ b/gcc/Makefile.in
+@@ -1623,6 +1623,7 @@ OBJS = \
+ 	tree-streamer-out.o \
+ 	tree-tailcall.o \
+ 	tree-vect-generic.o \
++	gimple-isel.o \
+ 	tree-vect-patterns.o \
+ 	tree-vect-data-refs.o \
+ 	tree-vect-stmts.o \
+@@ -2591,6 +2592,7 @@ GTFILES = $(CPPLIB_H) $(srcdir)/input.h $(srcdir)/coretypes.h \
+   $(srcdir)/dwarf2cfi.c \
+   $(srcdir)/dwarf2out.c \
+   $(srcdir)/tree-vect-generic.c \
++  $(srcdir)/gimple-isel.cc \
+   $(srcdir)/dojump.c $(srcdir)/emit-rtl.h \
+   $(srcdir)/emit-rtl.c $(srcdir)/except.h $(srcdir)/explow.c $(srcdir)/expr.c \
+   $(srcdir)/expr.h \
+diff --git a/gcc/expr.c b/gcc/expr.c
+index d66fdd4e9..c468b5eb9 100644
+--- a/gcc/expr.c
++++ b/gcc/expr.c
+@@ -9286,17 +9286,8 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
+       if (temp != 0)
+ 	return temp;
+ 
+-      /* For vector MIN , expand it a VEC_COND_EXPR 
+-	 and similarly for MAX .  */
+       if (VECTOR_TYPE_P (type))
+-	{
+-	  tree t0 = make_tree (type, op0);
+-	  tree t1 = make_tree (type, op1);
+-	  tree comparison = build2 (code == MIN_EXPR ? LE_EXPR : GE_EXPR,
+-				    type, t0, t1);
+-	  return expand_vec_cond_expr (type, comparison, t0, t1,
+-				       original_target);
+-	}
++	gcc_unreachable ();
+ 
+       /* At this point, a MEM target is no longer useful; we will get better
+ 	 code without it.  */
+@@ -9885,10 +9876,6 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
+ 	return temp;
+       }
+ 
+-    case VEC_COND_EXPR:
+-      target = expand_vec_cond_expr (type, treeop0, treeop1, treeop2, target);
+-      return target;
+-
+     case VEC_DUPLICATE_EXPR:
+       op0 = expand_expr (treeop0, NULL_RTX, VOIDmode, modifier);
+       target = expand_vector_broadcast (mode, op0);
+@@ -12222,8 +12209,7 @@ do_store_flag (sepops ops, rtx target, machine_mode mode)
+   STRIP_NOPS (arg1);
+ 
+   /* For vector typed comparisons emit code to generate the desired
+-     all-ones or all-zeros mask.  Conveniently use the VEC_COND_EXPR
+-     expander for this.  */
++     all-ones or all-zeros mask.  */
+   if (TREE_CODE (ops->type) == VECTOR_TYPE)
+     {
+       tree ifexp = build2 (ops->code, ops->type, arg0, arg1);
+@@ -12231,12 +12217,7 @@ do_store_flag (sepops ops, rtx target, machine_mode mode)
+ 	  && expand_vec_cmp_expr_p (TREE_TYPE (arg0), ops->type, ops->code))
+ 	return expand_vec_cmp_expr (ops->type, ifexp, target);
+       else
+-	{
+-	  tree if_true = constant_boolean_node (true, ops->type);
+-	  tree if_false = constant_boolean_node (false, ops->type);
+-	  return expand_vec_cond_expr (ops->type, ifexp, if_true,
+-				       if_false, target);
+-	}
++	gcc_unreachable ();
+     }
+ 
+   /* Optimize (x % C1) == C2 or (x % C1) != C2 if it is beneficial
+diff --git a/gcc/gimple-isel.cc b/gcc/gimple-isel.cc
+new file mode 100644
+index 000000000..97f920805
+--- /dev/null
++++ b/gcc/gimple-isel.cc
+@@ -0,0 +1,244 @@
++/* Schedule GIMPLE vector statements.
++   Copyright (C) 2020 Free Software Foundation, Inc.
++
++This file is part of GCC.
++
++GCC is free software; you can redistribute it and/or modify it
++under the terms of the GNU General Public License as published by the
++Free Software Foundation; either version 3, or (at your option) any
++later version.
++
++GCC is distributed in the hope that it will be useful, but WITHOUT
++ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++for more details.
++
++You should have received a copy of the GNU General Public License
++along with GCC; see the file COPYING3.  If not see
++.  */
++
++#include "config.h"
++#include "system.h"
++#include "coretypes.h"
++#include "backend.h"
++#include "rtl.h"
++#include "tree.h"
++#include "gimple.h"
++#include "tree-pass.h"
++#include "ssa.h"
++#include "expmed.h"
++#include "optabs-tree.h"
++#include "tree-eh.h"
++#include "gimple-iterator.h"
++#include "gimplify-me.h"
++#include "gimplify.h"
++#include "tree-cfg.h"
++
++/* Expand all VEC_COND_EXPR gimple assignments into calls to internal
++   function based on type of selected expansion.  */
++
++static gimple *
++gimple_expand_vec_cond_expr (gimple_stmt_iterator *gsi,
++			     hash_map *vec_cond_ssa_name_uses)
++{
++  tree lhs, op0a = NULL_TREE, op0b = NULL_TREE;
++  enum tree_code code;
++  enum tree_code tcode;
++  machine_mode cmp_op_mode;
++  bool unsignedp;
++  enum insn_code icode;
++  imm_use_iterator imm_iter;
++
++  /* Only consider code == GIMPLE_ASSIGN.  */
++  gassign *stmt = dyn_cast (gsi_stmt (*gsi));
++  if (!stmt)
++    return NULL;
++
++  code = gimple_assign_rhs_code (stmt);
++  if (code != VEC_COND_EXPR)
++    return NULL;
++
++  tree op0 = gimple_assign_rhs1 (stmt);
++  tree op1 = gimple_assign_rhs2 (stmt);
++  tree op2 = gimple_assign_rhs3 (stmt);
++  lhs = gimple_assign_lhs (stmt);
++  machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
++
++  gcc_assert (!COMPARISON_CLASS_P (op0));
++  if (TREE_CODE (op0) == SSA_NAME)
++    {
++      unsigned int used_vec_cond_exprs = 0;
++      unsigned int *slot = vec_cond_ssa_name_uses->get (op0);
++      if (slot)
++	used_vec_cond_exprs = *slot;
++      else
++	{
++	  gimple *use_stmt;
++	  FOR_EACH_IMM_USE_STMT (use_stmt, imm_iter, op0)
++	    {
++	      gassign *assign = dyn_cast (use_stmt);
++	      if (assign != NULL
++		  && gimple_assign_rhs_code (assign) == VEC_COND_EXPR
++		  && gimple_assign_rhs1 (assign) == op0)
++		used_vec_cond_exprs++;
++	    }
++	  vec_cond_ssa_name_uses->put (op0, used_vec_cond_exprs);
++	}
++
++      gassign *def_stmt = dyn_cast (SSA_NAME_DEF_STMT (op0));
++      if (def_stmt)
++	{
++	  tcode = gimple_assign_rhs_code (def_stmt);
++	  op0a = gimple_assign_rhs1 (def_stmt);
++	  op0b = gimple_assign_rhs2 (def_stmt);
++
++	  tree op0a_type = TREE_TYPE (op0a);
++	  if (used_vec_cond_exprs >= 2
++	      && (get_vcond_mask_icode (mode, TYPE_MODE (op0a_type))
++		  != CODE_FOR_nothing)
++	      && expand_vec_cmp_expr_p (op0a_type, TREE_TYPE (lhs), tcode))
++	    {
++	      /* Keep the SSA name and use vcond_mask.  */
++	      tcode = TREE_CODE (op0);
++	    }
++	}
++      else
++	tcode = TREE_CODE (op0);
++    }
++  else
++    tcode = TREE_CODE (op0);
++
++  if (TREE_CODE_CLASS (tcode) != tcc_comparison)
++    {
++      gcc_assert (VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (op0)));
++      if (get_vcond_mask_icode (mode, TYPE_MODE (TREE_TYPE (op0)))
++	  != CODE_FOR_nothing)
++	return gimple_build_call_internal (IFN_VCOND_MASK, 3, op0, op1, op2);
++      /* Fake op0 < 0.  */
++      else
++	{
++	  gcc_assert (GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (op0)))
++		      == MODE_VECTOR_INT);
++	  op0a = op0;
++	  op0b = build_zero_cst (TREE_TYPE (op0));
++	  tcode = LT_EXPR;
++	}
++    }
++  cmp_op_mode = TYPE_MODE (TREE_TYPE (op0a));
++  unsignedp = TYPE_UNSIGNED (TREE_TYPE (op0a));
++
++
++  gcc_assert (known_eq (GET_MODE_SIZE (mode), GET_MODE_SIZE (cmp_op_mode))
++	      && known_eq (GET_MODE_NUNITS (mode),
++			   GET_MODE_NUNITS (cmp_op_mode)));
++
++  icode = get_vcond_icode (mode, cmp_op_mode, unsignedp);
++  if (icode == CODE_FOR_nothing)
++    {
++      if (tcode == LT_EXPR
++	  && op0a == op0
++	  && TREE_CODE (op0) == VECTOR_CST)
++	{
++	  /* A VEC_COND_EXPR condition could be folded from EQ_EXPR/NE_EXPR
++	     into a constant when only get_vcond_eq_icode is supported.
++	     Verify < 0 and != 0 behave the same and change it to NE_EXPR.  */
++	  unsigned HOST_WIDE_INT nelts;
++	  if (!VECTOR_CST_NELTS (op0).is_constant (&nelts))
++	    {
++	      if (VECTOR_CST_STEPPED_P (op0))
++		gcc_unreachable ();
++	      nelts = vector_cst_encoded_nelts (op0);
++	    }
++	  for (unsigned int i = 0; i < nelts; ++i)
++	    if (tree_int_cst_sgn (vector_cst_elt (op0, i)) == 1)
++	      gcc_unreachable ();
++	  tcode = NE_EXPR;
++	}
++      if (tcode == EQ_EXPR || tcode == NE_EXPR)
++	{
++	  tree tcode_tree = build_int_cst (integer_type_node, tcode);
++	  return gimple_build_call_internal (IFN_VCONDEQ, 5, op0a, op0b, op1,
++					     op2, tcode_tree);
++	}
++    }
++
++  gcc_assert (icode != CODE_FOR_nothing);
++  tree tcode_tree = build_int_cst (integer_type_node, tcode);
++  return gimple_build_call_internal (unsignedp ? IFN_VCONDU : IFN_VCOND,
++				     5, op0a, op0b, op1, op2, tcode_tree);
++}
++
++
++
++/* Iterate all gimple statements and try to expand
++   VEC_COND_EXPR assignments.  */
++
++static unsigned int
++gimple_expand_vec_cond_exprs (void)
++{
++  gimple_stmt_iterator gsi;
++  basic_block bb;
++  bool cfg_changed = false;
++  hash_map vec_cond_ssa_name_uses;
++
++  FOR_EACH_BB_FN (bb, cfun)
++    {
++      for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
++	{
++	  gimple *g = gimple_expand_vec_cond_expr (&gsi,
++						   &vec_cond_ssa_name_uses);
++	  if (g != NULL)
++	    {
++	      tree lhs = gimple_assign_lhs (gsi_stmt (gsi));
++	      gimple_set_lhs (g, lhs);
++	      gsi_replace (&gsi, g, false);
++	    }
++	}
++    }
++
++  return cfg_changed ? TODO_cleanup_cfg : 0;
++}
++
++namespace {
++
++const pass_data pass_data_gimple_isel =
++{
++  GIMPLE_PASS, /* type */
++  "isel", /* name */
++  OPTGROUP_VEC, /* optinfo_flags */
++  TV_NONE, /* tv_id */
++  PROP_cfg, /* properties_required */
++  0, /* properties_provided */
++  0, /* properties_destroyed */
++  0, /* todo_flags_start */
++  TODO_update_ssa, /* todo_flags_finish */
++};
++
++class pass_gimple_isel : public gimple_opt_pass
++{
++public:
++  pass_gimple_isel (gcc::context *ctxt)
++    : gimple_opt_pass (pass_data_gimple_isel, ctxt)
++  {}
++
++  /* opt_pass methods: */
++  virtual bool gate (function *)
++    {
++      return true;
++    }
++
++  virtual unsigned int execute (function *)
++    {
++      return gimple_expand_vec_cond_exprs ();
++    }
++
++}; // class pass_gimple_isel
++
++} // anon namespace
++
++gimple_opt_pass *
++make_pass_gimple_isel (gcc::context *ctxt)
++{
++  return new pass_gimple_isel (ctxt);
++}
++
+diff --git a/gcc/gimplify.c b/gcc/gimplify.c
+index 89a4ae087..16b2f4328 100644
+--- a/gcc/gimplify.c
++++ b/gcc/gimplify.c
+@@ -14272,20 +14272,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
+ 	  }
+ 
+ 	case VEC_COND_EXPR:
+-	  {
+-	    enum gimplify_status r0, r1, r2;
+-
+-	    r0 = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
+-				post_p, is_gimple_condexpr, fb_rvalue);
+-	    r1 = gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p,
+-				post_p, is_gimple_val, fb_rvalue);
+-	    r2 = gimplify_expr (&TREE_OPERAND (*expr_p, 2), pre_p,
+-				post_p, is_gimple_val, fb_rvalue);
+-
+-	    ret = MIN (MIN (r0, r1), r2);
+-	    recalculate_side_effects (*expr_p);
+-	  }
+-	  break;
++	  goto expr_3;
+ 
+ 	case VEC_PERM_EXPR:
+ 	  /* Classified as tcc_expression.  */
+diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c
+index 5e9aa6072..644f234e0 100644
+--- a/gcc/internal-fn.c
++++ b/gcc/internal-fn.c
+@@ -49,6 +49,7 @@ along with GCC; see the file COPYING3.  If not see
+ #include "gimple-ssa.h"
+ #include "tree-phinodes.h"
+ #include "ssa-iterators.h"
++#include "explow.h"
+ 
+ /* The names of each internal function, indexed by function number.  */
+ const char *const internal_fn_name_array[] = {
+@@ -107,6 +108,10 @@ init_internal_fns ()
+ #define mask_store_direct { 3, 2, false }
+ #define store_lanes_direct { 0, 0, false }
+ #define mask_store_lanes_direct { 0, 0, false }
++#define vec_cond_mask_direct { 0, 0, false }
++#define vec_cond_direct { 0, 0, false }
++#define vec_condu_direct { 0, 0, false }
++#define vec_condeq_direct { 0, 0, false }
+ #define scatter_store_direct { 3, 1, false }
+ #define unary_direct { 0, 0, true }
+ #define binary_direct { 0, 0, true }
+@@ -2548,6 +2553,86 @@ expand_mask_store_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
+ 
+ #define expand_mask_store_lanes_optab_fn expand_mask_store_optab_fn
+ 
++/* Expand VCOND, VCONDU and VCONDEQ optab internal functions.
++   The expansion of STMT happens based on OPTAB table associated.  */
++
++static void
++expand_vect_cond_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
++{
++  class expand_operand ops[6];
++  insn_code icode;
++  tree lhs = gimple_call_lhs (stmt);
++  tree op0a = gimple_call_arg (stmt, 0);
++  tree op0b = gimple_call_arg (stmt, 1);
++  tree op1 = gimple_call_arg (stmt, 2);
++  tree op2 = gimple_call_arg (stmt, 3);
++  enum tree_code tcode = (tree_code) int_cst_value (gimple_call_arg (stmt, 4));
++
++  tree vec_cond_type = TREE_TYPE (lhs);
++  tree op_mode = TREE_TYPE (op0a);
++  bool unsignedp = TYPE_UNSIGNED (op_mode);
++
++  machine_mode mode = TYPE_MODE (vec_cond_type);
++  machine_mode cmp_op_mode = TYPE_MODE (op_mode);
++
++  icode = convert_optab_handler (optab, mode, cmp_op_mode);
++  rtx comparison
++    = vector_compare_rtx (VOIDmode, tcode, op0a, op0b, unsignedp, icode, 4);
++  rtx rtx_op1 = expand_normal (op1);
++  rtx rtx_op2 = expand_normal (op2);
++
++  rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
++  create_output_operand (&ops[0], target, mode);
++  create_input_operand (&ops[1], rtx_op1, mode);
++  create_input_operand (&ops[2], rtx_op2, mode);
++  create_fixed_operand (&ops[3], comparison);
++  create_fixed_operand (&ops[4], XEXP (comparison, 0));
++  create_fixed_operand (&ops[5], XEXP (comparison, 1));
++  expand_insn (icode, 6, ops);
++}
++
++#define expand_vec_cond_optab_fn expand_vect_cond_optab_fn
++#define expand_vec_condu_optab_fn expand_vect_cond_optab_fn
++#define expand_vec_condeq_optab_fn expand_vect_cond_optab_fn
++
++/* Expand VCOND_MASK optab internal function.
++   The expansion of STMT happens based on OPTAB table associated.  */
++
++static void
++expand_vect_cond_mask_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
++{
++  class expand_operand ops[4];
++
++  tree lhs = gimple_call_lhs (stmt);
++  tree op0 = gimple_call_arg (stmt, 0);
++  tree op1 = gimple_call_arg (stmt, 1);
++  tree op2 = gimple_call_arg (stmt, 2);
++  tree vec_cond_type = TREE_TYPE (lhs);
++
++  machine_mode mode = TYPE_MODE (vec_cond_type);
++  machine_mode mask_mode = TYPE_MODE (TREE_TYPE (op0));
++  enum insn_code icode = convert_optab_handler (optab, mode, mask_mode);
++  rtx mask, rtx_op1, rtx_op2;
++
++  gcc_assert (icode != CODE_FOR_nothing);
++
++  mask = expand_normal (op0);
++  rtx_op1 = expand_normal (op1);
++  rtx_op2 = expand_normal (op2);
++
++  mask = force_reg (mask_mode, mask);
++  rtx_op1 = force_reg (GET_MODE (rtx_op1), rtx_op1);
++
++  rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
++  create_output_operand (&ops[0], target, mode);
++  create_input_operand (&ops[1], rtx_op1, mode);
++  create_input_operand (&ops[2], rtx_op2, mode);
++  create_input_operand (&ops[3], mask, mask_mode);
++  expand_insn (icode, 4, ops);
++}
++
++#define expand_vec_cond_mask_optab_fn expand_vect_cond_mask_optab_fn
++
+ static void
+ expand_ABNORMAL_DISPATCHER (internal_fn, gcall *)
+ {
+@@ -3131,6 +3216,10 @@ multi_vector_optab_supported_p (convert_optab optab, tree_pair types,
+ #define direct_mask_store_optab_supported_p direct_optab_supported_p
+ #define direct_store_lanes_optab_supported_p multi_vector_optab_supported_p
+ #define direct_mask_store_lanes_optab_supported_p multi_vector_optab_supported_p
++#define direct_vec_cond_mask_optab_supported_p multi_vector_optab_supported_p
++#define direct_vec_cond_optab_supported_p multi_vector_optab_supported_p
++#define direct_vec_condu_optab_supported_p multi_vector_optab_supported_p
++#define direct_vec_condeq_optab_supported_p multi_vector_optab_supported_p
+ #define direct_scatter_store_optab_supported_p convert_optab_supported_p
+ #define direct_while_optab_supported_p convert_optab_supported_p
+ #define direct_fold_extract_optab_supported_p direct_optab_supported_p
+diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def
+index 1d190d492..0c6fc3711 100644
+--- a/gcc/internal-fn.def
++++ b/gcc/internal-fn.def
+@@ -136,6 +136,11 @@ DEF_INTERNAL_OPTAB_FN (STORE_LANES, ECF_CONST, vec_store_lanes, store_lanes)
+ DEF_INTERNAL_OPTAB_FN (MASK_STORE_LANES, 0,
+ 		       vec_mask_store_lanes, mask_store_lanes)
+ 
++DEF_INTERNAL_OPTAB_FN (VCOND, 0, vcond, vec_cond)
++DEF_INTERNAL_OPTAB_FN (VCONDU, 0, vcondu, vec_condu)
++DEF_INTERNAL_OPTAB_FN (VCONDEQ, 0, vcondeq, vec_condeq)
++DEF_INTERNAL_OPTAB_FN (VCOND_MASK, 0, vcond_mask, vec_cond_mask)
++
+ DEF_INTERNAL_OPTAB_FN (WHILE_ULT, ECF_CONST | ECF_NOTHROW, while_ult, while)
+ DEF_INTERNAL_OPTAB_FN (CHECK_RAW_PTRS, ECF_CONST | ECF_NOTHROW,
+ 		       check_raw_ptrs, check_ptrs)
+diff --git a/gcc/optabs.c b/gcc/optabs.c
+index c3751fdf7..64a1a1768 100644
+--- a/gcc/optabs.c
++++ b/gcc/optabs.c
+@@ -5454,7 +5454,7 @@ get_rtx_code (enum tree_code tcode, bool unsignedp)
+    first comparison operand for insn ICODE.  Do not generate the
+    compare instruction itself.  */
+ 
+-static rtx
++rtx
+ vector_compare_rtx (machine_mode cmp_mode, enum tree_code tcode,
+ 		    tree t_op0, tree t_op1, bool unsignedp,
+ 		    enum insn_code icode, unsigned int opno)
+@@ -5821,128 +5821,6 @@ expand_vec_perm_var (machine_mode mode, rtx v0, rtx v1, rtx sel, rtx target)
+   return tmp;
+ }
+ 
+-/* Generate insns for a VEC_COND_EXPR with mask, given its TYPE and its
+-   three operands.  */
+-
+-rtx
+-expand_vec_cond_mask_expr (tree vec_cond_type, tree op0, tree op1, tree op2,
+-			   rtx target)
+-{
+-  class expand_operand ops[4];
+-  machine_mode mode = TYPE_MODE (vec_cond_type);
+-  machine_mode mask_mode = TYPE_MODE (TREE_TYPE (op0));
+-  enum insn_code icode = get_vcond_mask_icode (mode, mask_mode);
+-  rtx mask, rtx_op1, rtx_op2;
+-
+-  if (icode == CODE_FOR_nothing)
+-    return 0;
+-
+-  mask = expand_normal (op0);
+-  rtx_op1 = expand_normal (op1);
+-  rtx_op2 = expand_normal (op2);
+-
+-  mask = force_reg (mask_mode, mask);
+-  rtx_op1 = force_reg (GET_MODE (rtx_op1), rtx_op1);
+-
+-  create_output_operand (&ops[0], target, mode);
+-  create_input_operand (&ops[1], rtx_op1, mode);
+-  create_input_operand (&ops[2], rtx_op2, mode);
+-  create_input_operand (&ops[3], mask, mask_mode);
+-  expand_insn (icode, 4, ops);
+-
+-  return ops[0].value;
+-}
+-
+-/* Generate insns for a VEC_COND_EXPR, given its TYPE and its
+-   three operands.  */
+-
+-rtx
+-expand_vec_cond_expr (tree vec_cond_type, tree op0, tree op1, tree op2,
+-		      rtx target)
+-{
+-  class expand_operand ops[6];
+-  enum insn_code icode;
+-  rtx comparison, rtx_op1, rtx_op2;
+-  machine_mode mode = TYPE_MODE (vec_cond_type);
+-  machine_mode cmp_op_mode;
+-  bool unsignedp;
+-  tree op0a, op0b;
+-  enum tree_code tcode;
+-
+-  if (COMPARISON_CLASS_P (op0))
+-    {
+-      op0a = TREE_OPERAND (op0, 0);
+-      op0b = TREE_OPERAND (op0, 1);
+-      tcode = TREE_CODE (op0);
+-    }
+-  else
+-    {
+-      gcc_assert (VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (op0)));
+-      if (get_vcond_mask_icode (mode, TYPE_MODE (TREE_TYPE (op0)))
+-	  != CODE_FOR_nothing)
+-	return expand_vec_cond_mask_expr (vec_cond_type, op0, op1,
+-					  op2, target);
+-      /* Fake op0 < 0.  */
+-      else
+-	{
+-	  gcc_assert (GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (op0)))
+-		      == MODE_VECTOR_INT);
+-	  op0a = op0;
+-	  op0b = build_zero_cst (TREE_TYPE (op0));
+-	  tcode = LT_EXPR;
+-	}
+-    }
+-  cmp_op_mode = TYPE_MODE (TREE_TYPE (op0a));
+-  unsignedp = TYPE_UNSIGNED (TREE_TYPE (op0a));
+-
+-
+-  gcc_assert (known_eq (GET_MODE_SIZE (mode), GET_MODE_SIZE (cmp_op_mode))
+-	      && known_eq (GET_MODE_NUNITS (mode),
+-			   GET_MODE_NUNITS (cmp_op_mode)));
+-
+-  icode = get_vcond_icode (mode, cmp_op_mode, unsignedp);
+-  if (icode == CODE_FOR_nothing)
+-    {
+-      if (tcode == LT_EXPR
+-	  && op0a == op0
+-	  && TREE_CODE (op0) == VECTOR_CST)
+-	{
+-	  /* A VEC_COND_EXPR condition could be folded from EQ_EXPR/NE_EXPR
+-	     into a constant when only get_vcond_eq_icode is supported.
+-	     Verify < 0 and != 0 behave the same and change it to NE_EXPR.  */
+-	  unsigned HOST_WIDE_INT nelts;
+-	  if (!VECTOR_CST_NELTS (op0).is_constant (&nelts))
+-	    {
+-	      if (VECTOR_CST_STEPPED_P (op0))
+-		return 0;
+-	      nelts = vector_cst_encoded_nelts (op0);
+-	    }
+-	  for (unsigned int i = 0; i < nelts; ++i)
+-	    if (tree_int_cst_sgn (vector_cst_elt (op0, i)) == 1)
+-	      return 0;
+-	  tcode = NE_EXPR;
+-	}
+-      if (tcode == EQ_EXPR || tcode == NE_EXPR)
+-	icode = get_vcond_eq_icode (mode, cmp_op_mode);
+-      if (icode == CODE_FOR_nothing)
+-	return 0;
+-    }
+-
+-  comparison = vector_compare_rtx (VOIDmode, tcode, op0a, op0b, unsignedp,
+-				   icode, 4);
+-  rtx_op1 = expand_normal (op1);
+-  rtx_op2 = expand_normal (op2);
+-
+-  create_output_operand (&ops[0], target, mode);
+-  create_input_operand (&ops[1], rtx_op1, mode);
+-  create_input_operand (&ops[2], rtx_op2, mode);
+-  create_fixed_operand (&ops[3], comparison);
+-  create_fixed_operand (&ops[4], XEXP (comparison, 0));
+-  create_fixed_operand (&ops[5], XEXP (comparison, 1));
+-  expand_insn (icode, 6, ops);
+-  return ops[0].value;
+-}
+-
+ /* Generate VEC_SERIES_EXPR , returning a value of mode VMODE.
+    Use TARGET for the result if nonnull and convenient.  */
+ 
+diff --git a/gcc/optabs.h b/gcc/optabs.h
+index 5bd19503a..7c2ec257c 100644
+--- a/gcc/optabs.h
++++ b/gcc/optabs.h
+@@ -321,9 +321,6 @@ extern rtx expand_vec_perm_const (machine_mode, rtx, rtx,
+ /* Generate code for vector comparison.  */
+ extern rtx expand_vec_cmp_expr (tree, tree, rtx);
+ 
+-/* Generate code for VEC_COND_EXPR.  */
+-extern rtx expand_vec_cond_expr (tree, tree, tree, tree, rtx);
+-
+ /* Generate code for VEC_SERIES_EXPR.  */
+ extern rtx expand_vec_series_expr (machine_mode, rtx, rtx, rtx);
+ 
+@@ -364,5 +361,9 @@ extern void expand_jump_insn (enum insn_code icode, unsigned int nops,
+ 			      class expand_operand *ops);
+ 
+ extern enum rtx_code get_rtx_code (enum tree_code tcode, bool unsignedp);
++extern rtx vector_compare_rtx (machine_mode cmp_mode, enum tree_code tcode,
++			       tree t_op0, tree t_op1, bool unsignedp,
++			       enum insn_code icode, unsigned int opno);
++
+ 
+ #endif /* GCC_OPTABS_H */
+diff --git a/gcc/passes.def b/gcc/passes.def
+index 94554cc1d..5a62819cc 100644
+--- a/gcc/passes.def
++++ b/gcc/passes.def
+@@ -403,6 +403,7 @@ along with GCC; see the file COPYING3.  If not see
+   NEXT_PASS (pass_cleanup_eh);
+   NEXT_PASS (pass_lower_resx);
+   NEXT_PASS (pass_nrv);
++  NEXT_PASS (pass_gimple_isel);
+   NEXT_PASS (pass_cleanup_cfg_post_optimizing);
+   NEXT_PASS (pass_warn_function_noreturn);
+   NEXT_PASS (pass_gen_hsail);
+diff --git a/gcc/testsuite/g++.dg/vect/vec-cond-expr-eh.C b/gcc/testsuite/g++.dg/vect/vec-cond-expr-eh.C
+new file mode 100644
+index 000000000..00fe24224
+--- /dev/null
++++ b/gcc/testsuite/g++.dg/vect/vec-cond-expr-eh.C
+@@ -0,0 +1,17 @@
++/* { dg-do compile } */
++/* { dg-additional-options "-fnon-call-exceptions" } */
++
++typedef double v2df __attribute__((vector_size(16)));
++
++v2df foo (v2df a, v2df b, v2df c, v2df d)
++{
++  try
++  {
++    v2df res = a < b ? c : d;
++    return res;
++    }
++    catch (...)
++    {
++    return (v2df){};
++    }
++}
+diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
+index 1af59fc6f..d82fe23d8 100644
+--- a/gcc/tree-cfg.c
++++ b/gcc/tree-cfg.c
+@@ -4196,7 +4196,7 @@ verify_gimple_assign_ternary (gassign *stmt)
+       return true;
+     }
+ 
+-  if (((rhs_code == VEC_COND_EXPR || rhs_code == COND_EXPR)
++  if ((rhs_code == COND_EXPR
+        ? !is_gimple_condexpr (rhs1) : !is_gimple_val (rhs1))
+       || !is_gimple_val (rhs2)
+       || !is_gimple_val (rhs3))
+diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
+index 09dd9b289..1c620b28e 100644
+--- a/gcc/tree-pass.h
++++ b/gcc/tree-pass.h
+@@ -631,6 +631,7 @@ extern gimple_opt_pass *make_pass_local_fn_summary (gcc::context *ctxt);
+ extern gimple_opt_pass *make_pass_update_address_taken (gcc::context *ctxt);
+ extern gimple_opt_pass *make_pass_convert_switch (gcc::context *ctxt);
+ extern gimple_opt_pass *make_pass_lower_vaarg (gcc::context *ctxt);
++extern gimple_opt_pass *make_pass_gimple_isel (gcc::context *ctxt);
+ 
+ /* Current optimization pass.  */
+ extern opt_pass *current_pass;
+diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c
+index 3161d2e39..ba0b55f4a 100644
+--- a/gcc/tree-ssa-forwprop.c
++++ b/gcc/tree-ssa-forwprop.c
+@@ -3131,8 +3131,7 @@ pass_forwprop::execute (function *fun)
+ 		    tree rhs1 = gimple_assign_rhs1 (stmt);
+ 		    enum tree_code code = gimple_assign_rhs_code (stmt);
+ 
+-		    if (code == COND_EXPR
+-			|| code == VEC_COND_EXPR)
++		    if (code == COND_EXPR)
+ 		      {
+ 			/* In this case the entire COND_EXPR is in rhs1. */
+ 			if (forward_propagate_into_cond (&gsi))
+diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c
+index af8df8563..5f978ac78 100644
+--- a/gcc/tree-ssa-reassoc.c
++++ b/gcc/tree-ssa-reassoc.c
+@@ -3830,7 +3830,8 @@ optimize_range_tests (enum tree_code opcode,
+    to type of comparison.  */
+ 
+ static tree_code
+-ovce_extract_ops (tree var, gassign **rets, bool *reti, tree *type)
++ovce_extract_ops (tree var, gassign **rets, bool *reti, tree *type,
++		  tree *lhs, tree *rhs, gassign **vcond)
+ {
+   if (TREE_CODE (var) != SSA_NAME)
+     return ERROR_MARK;
+@@ -3838,6 +3839,8 @@ ovce_extract_ops (tree var, gassign **rets, bool *reti, tree *type)
+   gassign *stmt = dyn_cast  (SSA_NAME_DEF_STMT (var));
+   if (stmt == NULL)
+     return ERROR_MARK;
++  if (*vcond)
++    *vcond = stmt;
+ 
+   /* ??? If we start creating more COND_EXPR, we could perform
+      this same optimization with them.	For now, simplify.  */
+@@ -3846,9 +3849,20 @@ ovce_extract_ops (tree var, gassign **rets, bool *reti, tree *type)
+ 
+   tree cond = gimple_assign_rhs1 (stmt);
+   tree_code cmp = TREE_CODE (cond);
+-  if (TREE_CODE_CLASS (cmp) != tcc_comparison)
++  if (cmp != SSA_NAME)
+     return ERROR_MARK;
+ 
++  gassign *assign = dyn_cast (SSA_NAME_DEF_STMT (cond));
++  if (stmt == NULL
++      || TREE_CODE_CLASS (gimple_assign_rhs_code (assign)) != tcc_comparison)
++    return ERROR_MARK;
++
++  cmp = gimple_assign_rhs_code (assign);
++  if (lhs)
++    *lhs = gimple_assign_rhs1 (assign);
++  if (rhs)
++    *rhs = gimple_assign_rhs2 (assign);
++
+   /* ??? For now, allow only canonical true and false result vectors.
+      We could expand this to other constants should the need arise,
+      but at the moment we don't create them.  */
+@@ -3869,7 +3883,7 @@ ovce_extract_ops (tree var, gassign **rets, bool *reti, tree *type)
+ 
+   /* Success!  */
+   if (rets)
+-    *rets = stmt;
++    *rets = assign;
+   if (reti)
+     *reti = inv;
+   if (type)
+@@ -3893,10 +3907,11 @@ optimize_vec_cond_expr (tree_code opcode, vec *ops)
+     {
+       tree elt0 = (*ops)[i]->op;
+ 
+-      gassign *stmt0;
++      gassign *stmt0, *vcond0;
+       bool invert;
+-      tree type;
+-      tree_code cmp0 = ovce_extract_ops (elt0, &stmt0, &invert, &type);
++      tree type, lhs0, rhs0;
++      tree_code cmp0 = ovce_extract_ops (elt0, &stmt0, &invert, &type, &lhs0,
++					 &rhs0, &vcond0);
+       if (cmp0 == ERROR_MARK)
+ 	continue;
+ 
+@@ -3904,26 +3919,20 @@ optimize_vec_cond_expr (tree_code opcode, vec *ops)
+ 	{
+ 	  tree &elt1 = (*ops)[j]->op;
+ 
+-	  gassign *stmt1;
+-	  tree_code cmp1 = ovce_extract_ops (elt1, &stmt1, NULL, NULL);
++	  gassign *stmt1, *vcond1;
++	  tree lhs1, rhs1;
++	  tree_code cmp1 = ovce_extract_ops (elt1, &stmt1, NULL, NULL, &lhs1,
++					     &rhs1, &vcond1);
+ 	  if (cmp1 == ERROR_MARK)
+ 	    continue;
+ 
+-	  tree cond0 = gimple_assign_rhs1 (stmt0);
+-	  tree x0 = TREE_OPERAND (cond0, 0);
+-	  tree y0 = TREE_OPERAND (cond0, 1);
+-
+-	  tree cond1 = gimple_assign_rhs1 (stmt1);
+-	  tree x1 = TREE_OPERAND (cond1, 0);
+-	  tree y1 = TREE_OPERAND (cond1, 1);
+-
+ 	  tree comb;
+ 	  if (opcode == BIT_AND_EXPR)
+-	    comb = maybe_fold_and_comparisons (type, cmp0, x0, y0, cmp1, x1,
+-					       y1);
++	    comb = maybe_fold_and_comparisons (type, cmp0, lhs0, rhs0,
++					       cmp1, lhs1, rhs1);
+ 	  else if (opcode == BIT_IOR_EXPR)
+-	    comb = maybe_fold_or_comparisons (type, cmp0, x0, y0, cmp1, x1,
+-					      y1);
++	    comb = maybe_fold_or_comparisons (type, cmp0, lhs0, rhs0,
++					      cmp1, lhs1, rhs1);
+ 	  else
+ 	    gcc_unreachable ();
+ 	  if (comb == NULL)
+@@ -3933,19 +3942,22 @@ optimize_vec_cond_expr (tree_code opcode, vec *ops)
+ 	  if (dump_file && (dump_flags & TDF_DETAILS))
+ 	    {
+ 	      fprintf (dump_file, "Transforming ");
+-	      print_generic_expr (dump_file, cond0);
++	      print_generic_expr (dump_file, gimple_assign_lhs (stmt0));
+ 	      fprintf (dump_file, " %c ", opcode == BIT_AND_EXPR ? '&' : '|');
+-	      print_generic_expr (dump_file, cond1);
++	      print_generic_expr (dump_file, gimple_assign_lhs (stmt1));
+ 	      fprintf (dump_file, " into ");
+ 	      print_generic_expr (dump_file, comb);
+ 	      fputc ('\n', dump_file);
+ 	    }
+ 
+-	  gimple_assign_set_rhs1 (stmt0, comb);
++	  gimple_stmt_iterator gsi = gsi_for_stmt (vcond0);
++	  tree exp = force_gimple_operand_gsi (&gsi, comb, true, NULL_TREE,
++					       true, GSI_SAME_STMT);
+ 	  if (invert)
+-	    std::swap (*gimple_assign_rhs2_ptr (stmt0),
+-		       *gimple_assign_rhs3_ptr (stmt0));
+-	  update_stmt (stmt0);
++	    swap_ssa_operands (vcond0, gimple_assign_rhs2_ptr (vcond0),
++			       gimple_assign_rhs3_ptr (vcond0));
++	  gimple_assign_set_rhs1 (vcond0, exp);
++	  update_stmt (vcond0);
+ 
+ 	  elt1 = error_mark_node;
+ 	  any_changes = true;
+diff --git a/gcc/tree-vect-generic.c b/gcc/tree-vect-generic.c
+index 37c3956a4..0ec4412bc 100644
+--- a/gcc/tree-vect-generic.c
++++ b/gcc/tree-vect-generic.c
+@@ -693,12 +693,14 @@ expand_vector_divmod (gimple_stmt_iterator *gsi, tree type, tree op0,
+ 	  if (addend == NULL_TREE
+ 	      && expand_vec_cond_expr_p (type, type, LT_EXPR))
+ 	    {
+-	      tree zero, cst, cond, mask_type;
+-	      gimple *stmt;
++	      tree zero, cst, mask_type, mask;
++	      gimple *stmt, *cond;
+ 
+ 	      mask_type = truth_type_for (type);
+ 	      zero = build_zero_cst (type);
+-	      cond = build2 (LT_EXPR, mask_type, op0, zero);
++	      mask = make_ssa_name (mask_type);
++	      cond = gimple_build_assign (mask, LT_EXPR, op0, zero);
++	      gsi_insert_before (gsi, cond, GSI_SAME_STMT);
+ 	      tree_vector_builder vec (type, nunits, 1);
+ 	      for (i = 0; i < nunits; i++)
+ 		vec.quick_push (build_int_cst (TREE_TYPE (type),
+@@ -706,8 +708,8 @@ expand_vector_divmod (gimple_stmt_iterator *gsi, tree type, tree op0,
+ 						<< shifts[i]) - 1));
+ 	      cst = vec.build ();
+ 	      addend = make_ssa_name (type);
+-	      stmt = gimple_build_assign (addend, VEC_COND_EXPR, cond,
+-					  cst, zero);
++	      stmt
++		= gimple_build_assign (addend, VEC_COND_EXPR, mask, cst, zero);
+ 	      gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
+ 	    }
+ 	}
+@@ -949,21 +951,28 @@ expand_vector_condition (gimple_stmt_iterator *gsi)
+   tree index = bitsize_int (0);
+   tree comp_width = width;
+   tree comp_index = index;
+-  int i;
+   location_t loc = gimple_location (gsi_stmt (*gsi));
++  tree_code code = TREE_CODE (a);
+ 
+-  if (!is_gimple_val (a))
++  if (code == SSA_NAME)
+     {
+-      gcc_assert (COMPARISON_CLASS_P (a));
+-      a_is_comparison = true;
+-      a1 = TREE_OPERAND (a, 0);
+-      a2 = TREE_OPERAND (a, 1);
+-      comp_inner_type = TREE_TYPE (TREE_TYPE (a1));
+-      comp_width = TYPE_SIZE (comp_inner_type);
++      gimple *assign = SSA_NAME_DEF_STMT (a);
++      if (TREE_CODE_CLASS (gimple_assign_rhs_code (assign)) == tcc_comparison)
++	{
++	  a_is_comparison = true;
++	  a1 = gimple_assign_rhs1 (assign);
++	  a2 = gimple_assign_rhs2 (assign);
++	  code = gimple_assign_rhs_code (assign);
++	  comp_inner_type = TREE_TYPE (TREE_TYPE (a1));
++	  comp_width = vector_element_bits_tree (TREE_TYPE (a1));
++	}
+     }
+ 
+-  if (expand_vec_cond_expr_p (type, TREE_TYPE (a1), TREE_CODE (a)))
+-    return;
++  if (expand_vec_cond_expr_p (type, TREE_TYPE (a1), code))
++    {
++      gcc_assert (TREE_CODE (a) == SSA_NAME || TREE_CODE (a) == VECTOR_CST);
++      return;
++    }
+ 
+   /* Handle vector boolean types with bitmasks.  If there is a comparison
+      and we can expand the comparison into the vector boolean bitmask,
+@@ -986,7 +995,7 @@ expand_vector_condition (gimple_stmt_iterator *gsi)
+ 	  : expand_vec_cmp_expr_p (TREE_TYPE (a1), type, TREE_CODE (a))))
+     {
+       if (a_is_comparison)
+-	a = gimplify_build2 (gsi, TREE_CODE (a), type, a1, a2);
++	a = gimplify_build2 (gsi, code, type, a1, a2);
+       a1 = gimplify_build2 (gsi, BIT_AND_EXPR, type, a, b);
+       a2 = gimplify_build1 (gsi, BIT_NOT_EXPR, type, a);
+       a2 = gimplify_build2 (gsi, BIT_AND_EXPR, type, a2, c);
+@@ -1017,7 +1026,7 @@ expand_vector_condition (gimple_stmt_iterator *gsi)
+ 
+   int nunits = nunits_for_known_piecewise_op (type);
+   vec_alloc (v, nunits);
+-  for (i = 0; i < nunits; i++)
++  for (int i = 0; i < nunits; i++)
+     {
+       tree aa, result;
+       tree bb = tree_vec_extract (gsi, inner_type, b, width, index);
+@@ -1028,7 +1037,7 @@ expand_vector_condition (gimple_stmt_iterator *gsi)
+ 				       comp_width, comp_index);
+ 	  tree aa2 = tree_vec_extract (gsi, comp_inner_type, a2,
+ 				       comp_width, comp_index);
+-	  aa = fold_build2 (TREE_CODE (a), cond_type, aa1, aa2);
++	  aa = fold_build2 (code, cond_type, aa1, aa2);
+ 	}
+       else if (a_is_scalar_bitmask)
+ 	{
+diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
+index 0bdf9a547..2c2197022 100644
+--- a/gcc/tree-vect-stmts.c
++++ b/gcc/tree-vect-stmts.c
+@@ -11100,8 +11100,12 @@ vectorizable_condition (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
+ 	    {
+ 	      vec_cond_rhs = vec_oprnds1[i];
+ 	      if (bitop1 == NOP_EXPR)
+-		vec_compare = build2 (cond_code, vec_cmp_type,
+-				      vec_cond_lhs, vec_cond_rhs);
++	    {
++	      gimple_seq stmts = NULL;
++	      vec_compare = gimple_build (&stmts, cond_code, vec_cmp_type,
++					   vec_cond_lhs, vec_cond_rhs);
++	      gsi_insert_before (gsi, stmts, GSI_SAME_STMT);
++	    }
+ 	      else
+ 		{
+ 		  new_temp = make_ssa_name (vec_cmp_type);
+-- 
+2.27.0.windows.1
+
diff --git a/0069-Backport-gimple-match-Add-a-gimple_extract_op-functi.patch b/0069-Backport-gimple-match-Add-a-gimple_extract_op-functi.patch
new file mode 100644
index 0000000..7ef1e00
--- /dev/null
+++ b/0069-Backport-gimple-match-Add-a-gimple_extract_op-functi.patch
@@ -0,0 +1,379 @@
+From 21d265af074726b166e08301a2f847c474fcb680 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 30 Nov 2021 09:52:24 +0000
+Subject: [PATCH 21/35] [Backport] gimple-match: Add a gimple_extract_op
+ function
+
+Reference: https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=33973fa754de1f95d459bfca66c0d80deec36537
+
+code_helper and gimple_match_op seem like generally useful ways
+of summing up a gimple_assign or gimple_call (or gimple_cond).
+This patch adds a gimple_extract_op function that can be used
+for that.
+
+gcc/
+	* gimple-match.h (code_helper): Add functions for querying whether
+	the code represents an internal_fn or a built_in_function.
+	Provide explicit conversion operators for both cases.
+	(gimple_extract_op): Declare.
+	* gimple-match-head.c (gimple_extract): New function, extracted from...
+	(gimple_simplify): ...here.
+	(gimple_extract_op): New function.
+---
+ gcc/gimple-match-head.c | 219 ++++++++++++++++++++--------------------
+ gcc/gimple-match.h      |  27 +++++
+ 2 files changed, 135 insertions(+), 111 deletions(-)
+
+diff --git a/gcc/gimple-match-head.c b/gcc/gimple-match-head.c
+index 9b3e7298d..c1dea1734 100644
+--- a/gcc/gimple-match-head.c
++++ b/gcc/gimple-match-head.c
+@@ -884,12 +884,20 @@ try_conditional_simplification (internal_fn ifn, gimple_match_op *res_op,
+   return true;
+ }
+ 
+-/* The main STMT based simplification entry.  It is used by the fold_stmt
+-   and the fold_stmt_to_constant APIs.  */
++/* Common subroutine of gimple_extract_op and gimple_simplify.  Try to
++   describe STMT in RES_OP, returning true on success.  Before recording
++   an operand, call:
+ 
+-bool
+-gimple_simplify (gimple *stmt, gimple_match_op *res_op, gimple_seq *seq,
+-		 tree (*valueize)(tree), tree (*top_valueize)(tree))
++   - VALUEIZE_CONDITION for a COND_EXPR condition
++   - VALUEIZE_OP for every other top-level operand
++
++   Both routines take a tree argument and returns a tree.  */
++
++template
++inline bool
++gimple_extract (gimple *stmt, gimple_match_op *res_op,
++		ValueizeOp valueize_op,
++		ValueizeCondition valueize_condition)
+ {
+   switch (gimple_code (stmt))
+     {
+@@ -905,101 +913,50 @@ gimple_simplify (gimple *stmt, gimple_match_op *res_op, gimple_seq *seq,
+ 		|| code == VIEW_CONVERT_EXPR)
+ 	      {
+ 		tree op0 = TREE_OPERAND (gimple_assign_rhs1 (stmt), 0);
+-		bool valueized = false;
+-		op0 = do_valueize (op0, top_valueize, valueized);
+-		res_op->set_op (code, type, op0);
+-		return (gimple_resimplify1 (seq, res_op, valueize)
+-			|| valueized);
++		res_op->set_op (code, type, valueize_op (op0));
++		return true;
+ 	      }
+ 	    else if (code == BIT_FIELD_REF)
+ 	      {
+ 		tree rhs1 = gimple_assign_rhs1 (stmt);
+-		tree op0 = TREE_OPERAND (rhs1, 0);
+-		bool valueized = false;
+-		op0 = do_valueize (op0, top_valueize, valueized);
++		tree op0 = valueize_op (TREE_OPERAND (rhs1, 0));
+ 		res_op->set_op (code, type, op0,
+ 				TREE_OPERAND (rhs1, 1),
+ 				TREE_OPERAND (rhs1, 2),
+ 				REF_REVERSE_STORAGE_ORDER (rhs1));
+-		if (res_op->reverse)
+-		  return valueized;
+-		return (gimple_resimplify3 (seq, res_op, valueize)
+-			|| valueized);
++		return true;
+ 	      }
+-	    else if (code == SSA_NAME
+-		     && top_valueize)
++	    else if (code == SSA_NAME)
+ 	      {
+ 		tree op0 = gimple_assign_rhs1 (stmt);
+-		tree valueized = top_valueize (op0);
+-		if (!valueized || op0 == valueized)
+-		  return false;
+-		res_op->set_op (TREE_CODE (op0), type, valueized);
++		res_op->set_op (TREE_CODE (op0), type, valueize_op (op0));
+ 		return true;
+ 	      }
+ 	    break;
+ 	  case GIMPLE_UNARY_RHS:
+ 	    {
+ 	      tree rhs1 = gimple_assign_rhs1 (stmt);
+-	      bool valueized = false;
+-	      rhs1 = do_valueize (rhs1, top_valueize, valueized);
+-	      res_op->set_op (code, type, rhs1);
+-	      return (gimple_resimplify1 (seq, res_op, valueize)
+-		      || valueized);
++	      res_op->set_op (code, type, valueize_op (rhs1));
++	      return true;
+ 	    }
+ 	  case GIMPLE_BINARY_RHS:
+ 	    {
+-	      tree rhs1 = gimple_assign_rhs1 (stmt);
+-	      tree rhs2 = gimple_assign_rhs2 (stmt);
+-	      bool valueized = false;
+-	      rhs1 = do_valueize (rhs1, top_valueize, valueized);
+-	      rhs2 = do_valueize (rhs2, top_valueize, valueized);
++	      tree rhs1 = valueize_op (gimple_assign_rhs1 (stmt));
++	      tree rhs2 = valueize_op (gimple_assign_rhs2 (stmt));
+ 	      res_op->set_op (code, type, rhs1, rhs2);
+-	      return (gimple_resimplify2 (seq, res_op, valueize)
+-		      || valueized);
++	      return true;
+ 	    }
+ 	  case GIMPLE_TERNARY_RHS:
+ 	    {
+-	      bool valueized = false;
+ 	      tree rhs1 = gimple_assign_rhs1 (stmt);
+-	      /* If this is a [VEC_]COND_EXPR first try to simplify an
+-		 embedded GENERIC condition.  */
+-	      if (code == COND_EXPR
+-		  || code == VEC_COND_EXPR)
+-		{
+-		  if (COMPARISON_CLASS_P (rhs1))
+-		    {
+-		      tree lhs = TREE_OPERAND (rhs1, 0);
+-		      tree rhs = TREE_OPERAND (rhs1, 1);
+-		      lhs = do_valueize (lhs, top_valueize, valueized);
+-		      rhs = do_valueize (rhs, top_valueize, valueized);
+-		      gimple_match_op res_op2 (res_op->cond, TREE_CODE (rhs1),
+-					       TREE_TYPE (rhs1), lhs, rhs);
+-		      if ((gimple_resimplify2 (seq, &res_op2, valueize)
+-			   || valueized)
+-			  && res_op2.code.is_tree_code ())
+-			{
+-			  valueized = true;
+-			  if (TREE_CODE_CLASS ((enum tree_code) res_op2.code)
+-			      == tcc_comparison)
+-			    rhs1 = build2 (res_op2.code, TREE_TYPE (rhs1),
+-					   res_op2.ops[0], res_op2.ops[1]);
+-			  else if (res_op2.code == SSA_NAME
+-				   || res_op2.code == INTEGER_CST
+-				   || res_op2.code == VECTOR_CST)
+-			    rhs1 = res_op2.ops[0];
+-			  else
+-			    valueized = false;
+-			}
+-		    }
+-		}
+-	      tree rhs2 = gimple_assign_rhs2 (stmt);
+-	      tree rhs3 = gimple_assign_rhs3 (stmt);
+-	      rhs1 = do_valueize (rhs1, top_valueize, valueized);
+-	      rhs2 = do_valueize (rhs2, top_valueize, valueized);
+-	      rhs3 = do_valueize (rhs3, top_valueize, valueized);
++	      if (code == COND_EXPR && COMPARISON_CLASS_P (rhs1))
++		rhs1 = valueize_condition (rhs1);
++	      else
++		rhs1 = valueize_op (rhs1);
++	      tree rhs2 = valueize_op (gimple_assign_rhs2 (stmt));
++	      tree rhs3 = valueize_op (gimple_assign_rhs3 (stmt));
+ 	      res_op->set_op (code, type, rhs1, rhs2, rhs3);
+-	      return (gimple_resimplify3 (seq, res_op, valueize)
+-		      || valueized);
++	      return true;
+ 	    }
+ 	  default:
+ 	    gcc_unreachable ();
+@@ -1013,7 +970,6 @@ gimple_simplify (gimple *stmt, gimple_match_op *res_op, gimple_seq *seq,
+ 	  && gimple_call_num_args (stmt) >= 1
+ 	  && gimple_call_num_args (stmt) <= 5)
+ 	{
+-	  bool valueized = false;
+ 	  combined_fn cfn;
+ 	  if (gimple_call_internal_p (stmt))
+ 	    cfn = as_combined_fn (gimple_call_internal_fn (stmt));
+@@ -1023,7 +979,7 @@ gimple_simplify (gimple *stmt, gimple_match_op *res_op, gimple_seq *seq,
+ 	      if (!fn)
+ 		return false;
+ 
+-	      fn = do_valueize (fn, top_valueize, valueized);
++	      fn = valueize_op (fn);
+ 	      if (TREE_CODE (fn) != ADDR_EXPR
+ 		  || TREE_CODE (TREE_OPERAND (fn, 0)) != FUNCTION_DECL)
+ 		return false;
+@@ -1039,47 +995,17 @@ gimple_simplify (gimple *stmt, gimple_match_op *res_op, gimple_seq *seq,
+ 	  unsigned int num_args = gimple_call_num_args (stmt);
+ 	  res_op->set_op (cfn, TREE_TYPE (gimple_call_lhs (stmt)), num_args);
+ 	  for (unsigned i = 0; i < num_args; ++i)
+-	    {
+-	      tree arg = gimple_call_arg (stmt, i);
+-	      res_op->ops[i] = do_valueize (arg, top_valueize, valueized);
+-	    }
+-	  if (internal_fn_p (cfn)
+-	      && try_conditional_simplification (as_internal_fn (cfn),
+-						 res_op, seq, valueize))
+-	    return true;
+-	  switch (num_args)
+-	    {
+-	    case 1:
+-	      return (gimple_resimplify1 (seq, res_op, valueize)
+-		      || valueized);
+-	    case 2:
+-	      return (gimple_resimplify2 (seq, res_op, valueize)
+-		      || valueized);
+-	    case 3:
+-	      return (gimple_resimplify3 (seq, res_op, valueize)
+-		      || valueized);
+-	    case 4:
+-	      return (gimple_resimplify4 (seq, res_op, valueize)
+-		      || valueized);
+-	    case 5:
+-	      return (gimple_resimplify5 (seq, res_op, valueize)
+-		      || valueized);
+-	    default:
+-	     gcc_unreachable ();
+-	    }
++	    res_op->ops[i] = valueize_op (gimple_call_arg (stmt, i));
++	  return true;
+ 	}
+       break;
+ 
+     case GIMPLE_COND:
+       {
+-	tree lhs = gimple_cond_lhs (stmt);
+-	tree rhs = gimple_cond_rhs (stmt);
+-	bool valueized = false;
+-	lhs = do_valueize (lhs, top_valueize, valueized);
+-	rhs = do_valueize (rhs, top_valueize, valueized);
++	tree lhs = valueize_op (gimple_cond_lhs (stmt));
++	tree rhs = valueize_op (gimple_cond_rhs (stmt));
+ 	res_op->set_op (gimple_cond_code (stmt), boolean_type_node, lhs, rhs);
+-	return (gimple_resimplify2 (seq, res_op, valueize)
+-		|| valueized);
++	return true;
+       }
+ 
+     default:
+@@ -1089,6 +1015,77 @@ gimple_simplify (gimple *stmt, gimple_match_op *res_op, gimple_seq *seq,
+   return false;
+ }
+ 
++/* Try to describe STMT in RES_OP, returning true on success.
++   For GIMPLE_CONDs, describe the condition that is being tested.
++   For GIMPLE_ASSIGNs, describe the rhs of the assignment.
++   For GIMPLE_CALLs, describe the call.  */
++
++bool
++gimple_extract_op (gimple *stmt, gimple_match_op *res_op)
++{
++  auto nop = [](tree op) { return op; };
++  return gimple_extract (stmt, res_op, nop, nop);
++}
++
++/* The main STMT based simplification entry.  It is used by the fold_stmt
++   and the fold_stmt_to_constant APIs.  */
++
++bool
++gimple_simplify (gimple *stmt, gimple_match_op *res_op, gimple_seq *seq,
++		 tree (*valueize)(tree), tree (*top_valueize)(tree))
++{
++  bool valueized = false;
++  auto valueize_op = [&](tree op)
++    {
++      return do_valueize (op, top_valueize, valueized);
++    };
++  auto valueize_condition = [&](tree op) -> tree
++    {
++      bool cond_valueized = false;
++      tree lhs = do_valueize (TREE_OPERAND (op, 0), top_valueize,
++			      cond_valueized);
++      tree rhs = do_valueize (TREE_OPERAND (op, 1), top_valueize,
++			      cond_valueized);
++      gimple_match_op res_op2 (res_op->cond, TREE_CODE (op),
++			       TREE_TYPE (op), lhs, rhs);
++      if ((gimple_resimplify2 (seq, &res_op2, valueize)
++	   || cond_valueized)
++	  && res_op2.code.is_tree_code ())
++	{
++	  if (TREE_CODE_CLASS ((tree_code) res_op2.code) == tcc_comparison)
++	    {
++	      valueized = true;
++	      return build2 (res_op2.code, TREE_TYPE (op),
++			     res_op2.ops[0], res_op2.ops[1]);
++	    }
++	  else if (res_op2.code == SSA_NAME
++		   || res_op2.code == INTEGER_CST
++		   || res_op2.code == VECTOR_CST)
++	    {
++	      valueized = true;
++	      return res_op2.ops[0];
++	    }
++	}
++      return valueize_op (op);
++    };
++
++  if (!gimple_extract (stmt, res_op, valueize_op, valueize_condition))
++    return false;
++
++  if (res_op->code.is_internal_fn ())
++    {
++      internal_fn ifn = internal_fn (res_op->code);
++      if (try_conditional_simplification (ifn, res_op, seq, valueize))
++	return true;
++    }
++
++  if (!res_op->reverse
++      && res_op->num_ops
++      && res_op->resimplify (seq, valueize))
++    return true;
++
++  return valueized;
++}
+ 
+ /* Helper for the autogenerated code, valueize OP.  */
+ 
+diff --git a/gcc/gimple-match.h b/gcc/gimple-match.h
+index 097898aed..39858c45f 100644
+--- a/gcc/gimple-match.h
++++ b/gcc/gimple-match.h
+@@ -33,13 +33,39 @@ public:
+   code_helper (combined_fn fn) : rep (-(int) fn) {}
+   operator tree_code () const { return (tree_code) rep; }
+   operator combined_fn () const { return (combined_fn) -rep; }
++  explicit operator internal_fn () const;
++  explicit operator built_in_function () const;
+   bool is_tree_code () const { return rep > 0; }
+   bool is_fn_code () const { return rep < 0; }
++  bool is_internal_fn () const;
++  bool is_builtin_fn () const;
+   int get_rep () const { return rep; }
+ private:
+   int rep;
+ };
+ 
++inline code_helper::operator internal_fn () const
++{
++  return as_internal_fn (combined_fn (*this));
++}
++
++inline code_helper::operator built_in_function () const
++{
++  return as_builtin_fn (combined_fn (*this));
++}
++
++inline bool
++code_helper::is_internal_fn () const
++{
++  return is_fn_code () && internal_fn_p (combined_fn (*this));
++}
++
++inline bool
++code_helper::is_builtin_fn () const
++{
++  return is_fn_code () && builtin_fn_p (combined_fn (*this));
++}
++
+ /* Represents the condition under which an operation should happen,
+    and the value to use otherwise.  The condition applies elementwise
+    (as for VEC_COND_EXPR) if the values are vectors.  */
+@@ -333,6 +359,7 @@ gimple_simplified_result_is_gimple_val (const gimple_match_op *op)
+ 
+ extern tree (*mprts_hook) (gimple_match_op *);
+ 
++bool gimple_extract_op (gimple *, gimple_match_op *);
+ bool gimple_simplify (gimple *, gimple_match_op *, gimple_seq *,
+ 		      tree (*)(tree), tree (*)(tree));
+ tree maybe_push_res_to_seq (gimple_match_op *, gimple_seq *,
+-- 
+2.27.0.windows.1
+
diff --git a/0070-Backport-aarch64-Fix-subs_compare_2.c-regression-PR1.patch b/0070-Backport-aarch64-Fix-subs_compare_2.c-regression-PR1.patch
new file mode 100644
index 0000000..ab9ac6e
--- /dev/null
+++ b/0070-Backport-aarch64-Fix-subs_compare_2.c-regression-PR1.patch
@@ -0,0 +1,1004 @@
+From f6b6948de1d836b594ad388388b7121dd7a702cb Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 15 Feb 2022 18:09:35 +0000
+Subject: [PATCH 22/35] [Backport] aarch64: Fix subs_compare_2.c regression
+ [PR100874]
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reference: https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=8e84b2b37a541b27feea69769fc314d534464ebd
+
+subs_compare_2.c tests that we can use a SUBS+CSEL sequence for:
+
+unsigned int
+foo (unsigned int a, unsigned int b)
+{
+  unsigned int x = a - 4;
+  if (a < 4)
+    return x;
+  else
+    return 0;
+}
+
+As Andrew notes in the PR, this is effectively MIN (x, 4) - 4,
+and it is now recognised as such by phiopt.  Previously it was
+if-converted in RTL instead.
+
+I tried to look for ways to generalise this to other situations
+and to other ?:-style operations, not just max and min.  However,
+for general ?: we tend to push an outer “- CST” into the arms of
+the ?: -- at least if one of them simplifies -- so I didn't find
+any useful abstraction.
+
+This patch therefore adds a pattern specifically for
+max/min(a,cst)-cst.  I'm not thrilled at having to do this,
+but it seems like the least worst fix in the circumstances.
+Also, max(a,cst)-cst for unsigned a is a useful saturating
+subtraction idiom and so is arguably worth its own code
+for that reason.
+
+gcc/
+	PR target/100874
+	* config/aarch64/aarch64-protos.h (aarch64_maxmin_plus_const):
+	Declare.
+	* config/aarch64/aarch64.cc (aarch64_maxmin_plus_const): New function.
+	* config/aarch64/aarch64.md (*aarch64_minmax_plus): New pattern.
+
+gcc/testsuite/
+	* gcc.target/aarch64/max_plus_1.c: New test.
+	* gcc.target/aarch64/max_plus_2.c: Likewise.
+	* gcc.target/aarch64/max_plus_3.c: Likewise.
+	* gcc.target/aarch64/max_plus_4.c: Likewise.
+	* gcc.target/aarch64/max_plus_5.c: Likewise.
+	* gcc.target/aarch64/max_plus_6.c: Likewise.
+	* gcc.target/aarch64/max_plus_7.c: Likewise.
+	* gcc.target/aarch64/min_plus_1.c: Likewise.
+	* gcc.target/aarch64/min_plus_2.c: Likewise.
+	* gcc.target/aarch64/min_plus_3.c: Likewise.
+	* gcc.target/aarch64/min_plus_4.c: Likewise.
+	* gcc.target/aarch64/min_plus_5.c: Likewise.
+	* gcc.target/aarch64/min_plus_6.c: Likewise.
+	* gcc.target/aarch64/min_plus_7.c: Likewise.
+---
+ gcc/config/aarch64/aarch64-protos.h           |   1 +
+ gcc/config/aarch64/aarch64.c                  | 104 ++++++++++++
+ gcc/config/aarch64/aarch64.md                 |  27 ++++
+ gcc/testsuite/gcc.target/aarch64/max_plus_1.c | 149 ++++++++++++++++++
+ gcc/testsuite/gcc.target/aarch64/max_plus_2.c |  35 ++++
+ gcc/testsuite/gcc.target/aarch64/max_plus_3.c |  35 ++++
+ gcc/testsuite/gcc.target/aarch64/max_plus_4.c |  30 ++++
+ gcc/testsuite/gcc.target/aarch64/max_plus_5.c |  35 ++++
+ gcc/testsuite/gcc.target/aarch64/max_plus_6.c |   9 ++
+ gcc/testsuite/gcc.target/aarch64/max_plus_7.c |  35 ++++
+ gcc/testsuite/gcc.target/aarch64/min_plus_1.c | 149 ++++++++++++++++++
+ gcc/testsuite/gcc.target/aarch64/min_plus_2.c |  35 ++++
+ gcc/testsuite/gcc.target/aarch64/min_plus_3.c |  35 ++++
+ gcc/testsuite/gcc.target/aarch64/min_plus_4.c |  30 ++++
+ gcc/testsuite/gcc.target/aarch64/min_plus_5.c |  35 ++++
+ gcc/testsuite/gcc.target/aarch64/min_plus_6.c |   9 ++
+ gcc/testsuite/gcc.target/aarch64/min_plus_7.c |  35 ++++
+ 17 files changed, 788 insertions(+)
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/max_plus_1.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/max_plus_2.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/max_plus_3.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/max_plus_4.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/max_plus_5.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/max_plus_6.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/max_plus_7.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/min_plus_1.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/min_plus_2.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/min_plus_3.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/min_plus_4.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/min_plus_5.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/min_plus_6.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/min_plus_7.c
+
+diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
+index 226f3a8ff..9b6d309a7 100644
+--- a/gcc/config/aarch64/aarch64-protos.h
++++ b/gcc/config/aarch64/aarch64-protos.h
+@@ -696,6 +696,7 @@ bool aarch64_legitimate_address_p (machine_mode, rtx, bool,
+ 				   aarch64_addr_query_type = ADDR_QUERY_M);
+ machine_mode aarch64_select_cc_mode (RTX_CODE, rtx, rtx);
+ rtx aarch64_gen_compare_reg (RTX_CODE, rtx, rtx);
++bool aarch64_maxmin_plus_const (rtx_code, rtx *, bool);
+ rtx aarch64_load_tp (rtx);
+ 
+ void aarch64_expand_compare_and_swap (rtx op[]);
+diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
+index f78942b04..85dbd3898 100644
+--- a/gcc/config/aarch64/aarch64.c
++++ b/gcc/config/aarch64/aarch64.c
+@@ -3038,6 +3038,110 @@ aarch64_gen_compare_reg_maybe_ze (RTX_CODE code, rtx x, rtx y,
+   return aarch64_gen_compare_reg (code, x, y);
+ }
+ 
++/* Consider the operation:
++
++     OPERANDS[0] = CODE (OPERANDS[1], OPERANDS[2]) + OPERANDS[3]
++
++   where:
++
++   - CODE is [SU]MAX or [SU]MIN
++   - OPERANDS[2] and OPERANDS[3] are constant integers
++   - OPERANDS[3] is a positive or negative shifted 12-bit immediate
++   - all operands have mode MODE
++
++   Decide whether it is possible to implement the operation using:
++
++     SUBS , OPERANDS[1], -OPERANDS[3]
++     or
++     ADDS , OPERANDS[1], OPERANDS[3]
++
++   followed by:
++
++      OPERANDS[0], , [wx]zr, 
++
++   where  is one of CSEL, CSINV or CSINC.  Return true if so.
++   If GENERATE_P is true, also update OPERANDS as follows:
++
++     OPERANDS[4] = -OPERANDS[3]
++     OPERANDS[5] = the rtl condition representing 
++     OPERANDS[6] = 
++     OPERANDS[7] = 0 for CSEL, -1 for CSINV or 1 for CSINC.  */
++bool
++aarch64_maxmin_plus_const (rtx_code code, rtx *operands, bool generate_p)
++{
++  signop sgn = (code == UMAX || code == UMIN ? UNSIGNED : SIGNED);
++  rtx dst = operands[0];
++  rtx maxmin_op = operands[2];
++  rtx add_op = operands[3];
++  machine_mode mode = GET_MODE (dst);
++
++  /* max (x, y) - z == (x >= y + 1 ? x : y) - z
++		    == (x >= y ? x : y) - z
++		    == (x > y ? x : y) - z
++		    == (x > y - 1 ? x : y) - z
++
++     min (x, y) - z == (x <= y - 1 ? x : y) - z
++		    == (x <= y ? x : y) - z
++		    == (x < y ? x : y) - z
++		    == (x < y + 1 ? x : y) - z
++
++     Check whether z is in { y - 1, y, y + 1 } and pick the form(s) for
++     which x is compared with z.  Set DIFF to y - z.  Thus the supported
++     combinations are as follows, with DIFF being the value after the ":":
++
++     max (x, y) - z == x >= y + 1 ? x - (y + 1) : -1   [z == y + 1]
++		    == x >= y ? x - y : 0              [z == y]
++		    == x > y ? x - y : 0               [z == y]
++		    == x > y - 1 ? x - (y - 1) : 1     [z == y - 1]
++
++     min (x, y) - z == x <= y - 1 ? x - (y - 1) : 1    [z == y - 1]
++		    == x <= y ? x - y : 0              [z == y]
++		    == x < y ? x - y : 0               [z == y]
++		    == x < y + 1 ? x - (y + 1) : -1    [z == y + 1].  */
++  auto maxmin_val = rtx_mode_t (maxmin_op, mode);
++  auto add_val = rtx_mode_t (add_op, mode);
++  auto sub_val = wi::neg (add_val);
++  auto diff = wi::sub (maxmin_val, sub_val);
++  if (!(diff == 0
++	|| (diff == 1 && wi::gt_p (maxmin_val, sub_val, sgn))
++	|| (diff == -1 && wi::lt_p (maxmin_val, sub_val, sgn))))
++    return false;
++
++  if (!generate_p)
++    return true;
++
++  rtx_code cmp;
++  switch (code)
++    {
++    case SMAX:
++      cmp = diff == 1 ? GT : GE;
++      break;
++    case UMAX:
++      cmp = diff == 1 ? GTU : GEU;
++      break;
++    case SMIN:
++      cmp = diff == -1 ? LT : LE;
++      break;
++    case UMIN:
++      cmp = diff == -1 ? LTU : LEU;
++      break;
++    default:
++      gcc_unreachable ();
++    }
++  rtx cc = gen_rtx_REG (CCmode, CC_REGNUM);
++
++  operands[4] = immed_wide_int_const (sub_val, mode);
++  operands[5] = gen_rtx_fmt_ee (cmp, VOIDmode, cc, const0_rtx);
++  if (can_create_pseudo_p ())
++    operands[6] = gen_reg_rtx (mode);
++  else
++    operands[6] = dst;
++  operands[7] = immed_wide_int_const (diff, mode);
++
++  return true;
++}
++
++
+ /* Build the SYMBOL_REF for __tls_get_addr.  */
+ 
+ static GTY(()) rtx tls_get_addr_libfunc;
+diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
+index ee80261f1..7c2562f49 100644
+--- a/gcc/config/aarch64/aarch64.md
++++ b/gcc/config/aarch64/aarch64.md
+@@ -4499,6 +4499,33 @@
+   }
+ )
+ 
++;; Implement MAX/MIN (A, B) - C using SUBS/ADDS followed by CSEL/CSINV/CSINC.
++;; See aarch64_maxmin_plus_const for details about the supported cases.
++(define_insn_and_split "*aarch64_minmax_plus"
++  [(set (match_operand:GPI 0 "register_operand" "=r")
++	(plus:GPI
++	  (MAXMIN:GPI
++	    (match_operand:GPI 1 "register_operand" "r")
++	    (match_operand:GPI 2 "const_int_operand"))
++	  (match_operand:GPI 3 "aarch64_plus_immediate")))
++   (clobber (reg:CC CC_REGNUM))]
++  "aarch64_maxmin_plus_const (, operands, false)"
++  "#"
++  "&& 1"
++  [(parallel
++     [(set (reg:CC CC_REGNUM)
++	   (compare:CC (match_dup 1) (match_dup 4)))
++      (set (match_dup 6)
++	   (plus:GPI (match_dup 1) (match_dup 3)))])
++   (set (match_dup 0)
++	(if_then_else:GPI (match_dup 5) (match_dup 6) (match_dup 7)))]
++  {
++    if (!aarch64_maxmin_plus_const (, operands, true))
++      gcc_unreachable ();
++  }
++  [(set_attr "length" "8")]
++)
++
+ ;; -------------------------------------------------------------------
+ ;; Logical operations
+ ;; -------------------------------------------------------------------
+diff --git a/gcc/testsuite/gcc.target/aarch64/max_plus_1.c b/gcc/testsuite/gcc.target/aarch64/max_plus_1.c
+new file mode 100644
+index 000000000..ef336aeec
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/max_plus_1.c
+@@ -0,0 +1,149 @@
++/* { dg-do run } */
++/* { dg-options "-O2 --save-temps" } */
++/* { dg-final { check-function-bodies "**" "" "" } } */
++
++/*
++** f1:
++**	adds	(w[0-9]+), w0, #4
++**	csel	w0, \1, wzr, g[te]
++**	ret
++*/
++/*
++** f2:
++**	adds	(w[0-9]+), w0, #4
++**	csel	w0, \1, wzr, g[te]
++**	ret
++*/
++/*
++** f3:
++**	adds	(w[0-9]+), w0, #5
++**	csinc	w0, \1, wzr, gt
++**	ret
++*/
++/*
++** f4:
++**	adds	(w[0-9]+), w0, #3
++**	csinv	w0, \1, wzr, ge
++**	ret
++*/
++
++#ifndef TYPE
++#define TYPE int32_t
++#define TYPE_MIN INT32_MIN
++#define TYPE_MAX INT32_MAX
++#define VALUE -4
++#endif
++
++#include 
++
++TYPE __attribute__((noipa))
++f1 (TYPE x)
++{
++  return (x > VALUE ? x - VALUE : 0);
++}
++
++TYPE __attribute__((noipa))
++f2 (TYPE x)
++{
++  return (x > VALUE ? x : VALUE) - VALUE;
++}
++
++TYPE __attribute__((noipa))
++f3 (TYPE x)
++{
++  return (x > VALUE ? x : VALUE) - (VALUE - 1);
++}
++
++TYPE __attribute__((noipa))
++f4 (TYPE x)
++{
++  return (x > VALUE ? x : VALUE) - (VALUE + 1);
++}
++
++TYPE __attribute__((noipa))
++f5 (TYPE x)
++{
++  return (x > VALUE ? x : VALUE) - (VALUE + 2);
++}
++
++TYPE __attribute__((noipa))
++f6 (TYPE x)
++{
++  return (x > VALUE ? x : VALUE) - (VALUE - 2);
++}
++
++int
++main (void)
++{
++  TYPE max_test = TYPE_MAX;
++  if (TYPE_MIN < 0 && VALUE < 0)
++    max_test += VALUE;
++
++  if (f1 (TYPE_MIN) != 0)
++    __builtin_abort ();
++  if (f1 (VALUE - 1) != 0)
++    __builtin_abort ();
++  if (f1 (VALUE) != 0)
++    __builtin_abort ();
++  if (f1 (VALUE + 1) != 1)
++    __builtin_abort ();
++  if (f1 (max_test) != max_test - VALUE)
++    __builtin_abort ();
++
++  if (f2 (TYPE_MIN) != 0)
++    __builtin_abort ();
++  if (f2 (VALUE - 1) != 0)
++    __builtin_abort ();
++  if (f2 (VALUE) != 0)
++    __builtin_abort ();
++  if (f2 (VALUE + 1) != 1)
++    __builtin_abort ();
++  if (f2 (max_test) != max_test - VALUE)
++    __builtin_abort ();
++
++  if (f3 (TYPE_MIN) != 1)
++    __builtin_abort ();
++  if (f3 (VALUE - 1) != 1)
++    __builtin_abort ();
++  if (f3 (VALUE) != 1)
++    __builtin_abort ();
++  if (f3 (VALUE + 1) != 2)
++    __builtin_abort ();
++  if (f3 (max_test - 1) != max_test - VALUE)
++    __builtin_abort ();
++
++  if (f4 (TYPE_MIN) != -1)
++    __builtin_abort ();
++  if (f4 (VALUE - 1) != -1)
++    __builtin_abort ();
++  if (f4 (VALUE) != -1)
++    __builtin_abort ();
++  if (f4 (VALUE + 1) != 0)
++    __builtin_abort ();
++  if (f4 (max_test) != max_test - VALUE - 1)
++    __builtin_abort ();
++
++  if (f5 (TYPE_MIN) != -2)
++    __builtin_abort ();
++  if (f5 (VALUE - 1) != -2)
++    __builtin_abort ();
++  if (f5 (VALUE) != -2)
++    __builtin_abort ();
++  if (f5 (VALUE + 1) != -1)
++    __builtin_abort ();
++  if (f5 (max_test) != max_test - VALUE - 2)
++    __builtin_abort ();
++
++  if (f6 (TYPE_MIN) != 2)
++    __builtin_abort ();
++  if (f6 (VALUE - 1) != 2)
++    __builtin_abort ();
++  if (f6 (VALUE) != 2)
++    __builtin_abort ();
++  if (f6 (VALUE + 1) != 3)
++    __builtin_abort ();
++  if (VALUE <= max_test - 2 && f6 (max_test - 2) != max_test - VALUE)
++    __builtin_abort ();
++
++  return 0;
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/max_plus_2.c b/gcc/testsuite/gcc.target/aarch64/max_plus_2.c
+new file mode 100644
+index 000000000..a2a1295d9
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/max_plus_2.c
+@@ -0,0 +1,35 @@
++/* { dg-do run } */
++/* { dg-options "-O2 --save-temps" } */
++/* { dg-final { check-function-bodies "**" "" "" } } */
++
++/*
++** f1:
++**	adds	(x[0-9]+), x0, #4094
++**	csel	x0, \1, xzr, g[te]
++**	ret
++*/
++/*
++** f2:
++**	adds	(x[0-9]+), x0, #4094
++**	csel	x0, \1, xzr, g[te]
++**	ret
++*/
++/*
++** f3:
++**	adds	(x[0-9]+), x0, #4095
++**	csinc	x0, \1, xzr, gt
++**	ret
++*/
++/*
++** f4:
++**	adds	(x[0-9]+), x0, #4093
++**	csinv	x0, \1, xzr, ge
++**	ret
++*/
++
++#define TYPE int64_t
++#define TYPE_MIN INT64_MIN
++#define TYPE_MAX INT64_MAX
++#define VALUE -4094
++
++#include "max_plus_1.c"
+diff --git a/gcc/testsuite/gcc.target/aarch64/max_plus_3.c b/gcc/testsuite/gcc.target/aarch64/max_plus_3.c
+new file mode 100644
+index 000000000..a9792ecc9
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/max_plus_3.c
+@@ -0,0 +1,35 @@
++/* { dg-do run } */
++/* { dg-options "-O2 --save-temps" } */
++/* { dg-final { check-function-bodies "**" "" "" } } */
++
++/*
++** f1:
++**	adds	(w[0-9]+), w0, #4095
++**	csel	w0, \1, wzr, g[te]
++**	ret
++*/
++/*
++** f2:
++**	adds	(w[0-9]+), w0, #4095
++**	csel	w0, \1, wzr, g[te]
++**	ret
++*/
++/*
++** f3:
++**	adds	(w[0-9]+), w0, #4096
++**	csinc	w0, \1, wzr, gt
++**	ret
++*/
++/*
++** f4:
++**	adds	(w[0-9]+), w0, #4094
++**	csinv	w0, \1, wzr, ge
++**	ret
++*/
++
++#define TYPE int32_t
++#define TYPE_MIN INT32_MIN
++#define TYPE_MAX INT32_MAX
++#define VALUE -4095
++
++#include "max_plus_1.c"
+diff --git a/gcc/testsuite/gcc.target/aarch64/max_plus_4.c b/gcc/testsuite/gcc.target/aarch64/max_plus_4.c
+new file mode 100644
+index 000000000..5090fa101
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/max_plus_4.c
+@@ -0,0 +1,30 @@
++/* { dg-do run } */
++/* { dg-options "-O2 --save-temps" } */
++/* { dg-final { check-function-bodies "**" "" "" } } */
++
++/*
++** f1:
++**	adds	(x[0-9]+), x0, #4096
++**	csel	x0, \1, xzr, g[te]
++**	ret
++*/
++/*
++** f2:
++**	adds	(x[0-9]+), x0, #4096
++**	csel	x0, \1, xzr, g[te]
++**	ret
++*/
++/* f3 out of range */
++/*
++** f4:
++**	adds	(x[0-9]+), x0, #4095
++**	csinv	x0, \1, xzr, ge
++**	ret
++*/
++
++#define TYPE int64_t
++#define TYPE_MIN INT64_MIN
++#define TYPE_MAX INT64_MAX
++#define VALUE -4096
++
++#include "max_plus_1.c"
+diff --git a/gcc/testsuite/gcc.target/aarch64/max_plus_5.c b/gcc/testsuite/gcc.target/aarch64/max_plus_5.c
+new file mode 100644
+index 000000000..63f3b3442
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/max_plus_5.c
+@@ -0,0 +1,35 @@
++/* { dg-do run } */
++/* { dg-options "-O2 --save-temps" } */
++/* { dg-final { check-function-bodies "**" "" "" } } */
++
++/*
++** f1:
++**	adds	(w[0-9]+), w0, #4095
++**	csel	w0, \1, wzr, (cs|hi)
++**	ret
++*/
++/*
++** f2:
++**	adds	(w[0-9]+), w0, #4095
++**	csel	w0, \1, wzr, (cs|hi)
++**	ret
++*/
++/*
++** f3:
++**	adds	(w[0-9]+), w0, #4096
++**	csinc	w0, \1, wzr, hi
++**	ret
++*/
++/*
++** f4:
++**	adds	(w[0-9]+), w0, #4094
++**	csinv	w0, \1, wzr, cs
++**	ret
++*/
++
++#define TYPE uint32_t
++#define TYPE_MIN 0
++#define TYPE_MAX UINT32_MAX
++#define VALUE (uint32_t)-4095
++
++#include "max_plus_1.c"
+diff --git a/gcc/testsuite/gcc.target/aarch64/max_plus_6.c b/gcc/testsuite/gcc.target/aarch64/max_plus_6.c
+new file mode 100644
+index 000000000..ad592c690
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/max_plus_6.c
+@@ -0,0 +1,9 @@
++/* { dg-do run } */
++/* { dg-options "-O2 --save-temps" } */
++
++#define TYPE uint64_t
++#define TYPE_MIN 0
++#define TYPE_MAX UINT64_MAX
++#define VALUE (uint64_t)-2
++
++#include "max_plus_1.c"
+diff --git a/gcc/testsuite/gcc.target/aarch64/max_plus_7.c b/gcc/testsuite/gcc.target/aarch64/max_plus_7.c
+new file mode 100644
+index 000000000..ac9f27dec
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/max_plus_7.c
+@@ -0,0 +1,35 @@
++/* { dg-do run } */
++/* { dg-options "-O2 --save-temps" } */
++/* { dg-final { check-function-bodies "**" "" "" } } */
++
++/*
++** f1:
++**	adds	(x[0-9]+), x0, #3
++**	csel	x0, \1, xzr, (cs|hi)
++**	ret
++*/
++/*
++** f2:
++**	adds	(x[0-9]+), x0, #3
++**	csel	x0, \1, xzr, (cs|hi)
++**	ret
++*/
++/*
++** f3:
++**	adds	(x[0-9]+), x0, #4
++**	csinc	x0, \1, xzr, hi
++**	ret
++*/
++/*
++** f4:
++**	adds	(x[0-9]+), x0, #2
++**	csinv	x0, \1, xzr, cs
++**	ret
++*/
++
++#define TYPE uint64_t
++#define TYPE_MIN 0
++#define TYPE_MAX UINT64_MAX
++#define VALUE (uint64_t)-3
++
++#include "max_plus_1.c"
+diff --git a/gcc/testsuite/gcc.target/aarch64/min_plus_1.c b/gcc/testsuite/gcc.target/aarch64/min_plus_1.c
+new file mode 100644
+index 000000000..f4c9106df
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/min_plus_1.c
+@@ -0,0 +1,149 @@
++/* { dg-do run } */
++/* { dg-options "-O2 --save-temps" } */
++/* { dg-final { check-function-bodies "**" "" "" } } */
++
++/*
++** f1:
++**	subs	(w[0-9]+), w0, #?4
++**	csel	w0, \1, wzr, l[te]
++**	ret
++*/
++/*
++** f2:
++**	subs	(w[0-9]+), w0, #?4
++**	csel	w0, \1, wzr, l[te]
++**	ret
++*/
++/*
++** f3:
++**	subs	(w[0-9]+), w0, #?3
++**	csinc	w0, \1, wzr, le
++**	ret
++*/
++/*
++** f4:
++**	subs	(w[0-9]+), w0, #?5
++**	csinv	w0, \1, wzr, lt
++**	ret
++*/
++
++#ifndef TYPE
++#define TYPE int32_t
++#define TYPE_MIN INT32_MIN
++#define TYPE_MAX INT32_MAX
++#define VALUE 4
++#endif
++
++#include 
++
++TYPE __attribute__((noipa))
++f1 (TYPE x)
++{
++  return (x < VALUE ? x - VALUE : 0);
++}
++
++TYPE __attribute__((noipa))
++f2 (TYPE x)
++{
++  return (x < VALUE ? x : VALUE) - VALUE;
++}
++
++TYPE __attribute__((noipa))
++f3 (TYPE x)
++{
++  return (x < VALUE ? x : VALUE) - (VALUE - 1);
++}
++
++TYPE __attribute__((noipa))
++f4 (TYPE x)
++{
++  return (x < VALUE ? x : VALUE) - (VALUE + 1);
++}
++
++TYPE __attribute__((noipa))
++f5 (TYPE x)
++{
++  return (x < VALUE ? x : VALUE) - (VALUE + 2);
++}
++
++TYPE __attribute__((noipa))
++f6 (TYPE x)
++{
++  return (x < VALUE ? x : VALUE) - (VALUE - 2);
++}
++
++int
++main (void)
++{
++  TYPE min_test = TYPE_MIN;
++  if (TYPE_MIN < 0 && VALUE > 0)
++    min_test += VALUE;
++
++  if (f1 (min_test) != min_test - VALUE)
++    __builtin_abort ();
++  if (f1 (VALUE - 1) != -1)
++    __builtin_abort ();
++  if (f1 (VALUE) != 0)
++    __builtin_abort ();
++  if (f1 (VALUE + 1) != 0)
++    __builtin_abort ();
++  if (f1 (TYPE_MAX) != 0)
++    __builtin_abort ();
++
++  if (f2 (min_test) != min_test - VALUE)
++    __builtin_abort ();
++  if (f2 (VALUE - 1) != -1)
++    __builtin_abort ();
++  if (f2 (VALUE) != 0)
++    __builtin_abort ();
++  if (f2 (VALUE + 1) != 0)
++    __builtin_abort ();
++  if (f2 (TYPE_MAX) != 0)
++    __builtin_abort ();
++
++  if (f3 (min_test) != min_test - VALUE + 1)
++    __builtin_abort ();
++  if (f3 (VALUE - 1) != 0)
++    __builtin_abort ();
++  if (f3 (VALUE) != 1)
++    __builtin_abort ();
++  if (f3 (VALUE + 1) != 1)
++    __builtin_abort ();
++  if (f3 (TYPE_MAX) != 1)
++    __builtin_abort ();
++
++  if (f4 (min_test + 1) != min_test - VALUE)
++    __builtin_abort ();
++  if (f4 (VALUE - 1) != -2)
++    __builtin_abort ();
++  if (f4 (VALUE) != -1)
++    __builtin_abort ();
++  if (f4 (VALUE + 1) != -1)
++    __builtin_abort ();
++  if (f4 (TYPE_MAX) != -1)
++    __builtin_abort ();
++
++  if (VALUE >= min_test + 2 && f5 (min_test + 2) != min_test - VALUE)
++    __builtin_abort ();
++  if (f5 (VALUE - 1) != -3)
++    __builtin_abort ();
++  if (f5 (VALUE) != -2)
++    __builtin_abort ();
++  if (f5 (VALUE + 1) != -2)
++    __builtin_abort ();
++  if (f5 (TYPE_MAX) != -2)
++    __builtin_abort ();
++
++  if (f6 (min_test) != min_test - VALUE + 2)
++    __builtin_abort ();
++  if (f6 (VALUE - 1) != 1)
++    __builtin_abort ();
++  if (f6 (VALUE) != 2)
++    __builtin_abort ();
++  if (f6 (VALUE + 1) != 2)
++    __builtin_abort ();
++  if (f6 (TYPE_MAX) != 2)
++    __builtin_abort ();
++
++  return 0;
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/min_plus_2.c b/gcc/testsuite/gcc.target/aarch64/min_plus_2.c
+new file mode 100644
+index 000000000..bc0141b72
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/min_plus_2.c
+@@ -0,0 +1,35 @@
++/* { dg-do run } */
++/* { dg-options "-O2 --save-temps" } */
++/* { dg-final { check-function-bodies "**" "" "" } } */
++
++/*
++** f1:
++**	subs	(x[0-9]+), x0, #?4094
++**	csel	x0, \1, xzr, l[te]
++**	ret
++*/
++/*
++** f2:
++**	subs	(x[0-9]+), x0, #?4094
++**	csel	x0, \1, xzr, l[te]
++**	ret
++*/
++/*
++** f3:
++**	subs	(x[0-9]+), x0, #?4093
++**	csinc	x0, \1, xzr, le
++**	ret
++*/
++/*
++** f4:
++**	subs	(x[0-9]+), x0, #?4095
++**	csinv	x0, \1, xzr, lt
++**	ret
++*/
++
++#define TYPE int64_t
++#define TYPE_MIN INT64_MIN
++#define TYPE_MAX INT64_MAX
++#define VALUE 4094
++
++#include "min_plus_1.c"
+diff --git a/gcc/testsuite/gcc.target/aarch64/min_plus_3.c b/gcc/testsuite/gcc.target/aarch64/min_plus_3.c
+new file mode 100644
+index 000000000..1808e4b0c
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/min_plus_3.c
+@@ -0,0 +1,35 @@
++/* { dg-do run } */
++/* { dg-options "-O2 --save-temps" } */
++/* { dg-final { check-function-bodies "**" "" "" } } */
++
++/*
++** f1:
++**	subs	(w[0-9]+), w0, #?4095
++**	csel	w0, \1, wzr, l[te]
++**	ret
++*/
++/*
++** f2:
++**	subs	(w[0-9]+), w0, #?4095
++**	csel	w0, \1, wzr, l[te]
++**	ret
++*/
++/*
++** f3:
++**	subs	(w[0-9]+), w0, #?4094
++**	csinc	w0, \1, wzr, le
++**	ret
++*/
++/*
++** f4:
++**	subs	(w[0-9]+), w0, #?4096
++**	csinv	w0, \1, wzr, lt
++**	ret
++*/
++
++#define TYPE int32_t
++#define TYPE_MIN INT32_MIN
++#define TYPE_MAX INT32_MAX
++#define VALUE 4095
++
++#include "min_plus_1.c"
+diff --git a/gcc/testsuite/gcc.target/aarch64/min_plus_4.c b/gcc/testsuite/gcc.target/aarch64/min_plus_4.c
+new file mode 100644
+index 000000000..6c581fed6
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/min_plus_4.c
+@@ -0,0 +1,30 @@
++/* { dg-do run } */
++/* { dg-options "-O2 --save-temps" } */
++/* { dg-final { check-function-bodies "**" "" "" } } */
++
++/*
++** f1:
++**	subs	(x[0-9]+), x0, #?4096
++**	csel	x0, \1, xzr, l[te]
++**	ret
++*/
++/*
++** f2:
++**	subs	(x[0-9]+), x0, #?4096
++**	csel	x0, \1, xzr, l[te]
++**	ret
++*/
++/*
++** f3:
++**	subs	(x[0-9]+), x0, #?4095
++**	csinc	x0, \1, xzr, le
++**	ret
++*/
++/* f4 out of range */
++
++#define TYPE int64_t
++#define TYPE_MIN INT64_MIN
++#define TYPE_MAX INT64_MAX
++#define VALUE 4096
++
++#include "min_plus_1.c"
+diff --git a/gcc/testsuite/gcc.target/aarch64/min_plus_5.c b/gcc/testsuite/gcc.target/aarch64/min_plus_5.c
+new file mode 100644
+index 000000000..97542d507
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/min_plus_5.c
+@@ -0,0 +1,35 @@
++/* { dg-do run } */
++/* { dg-options "-O2 --save-temps" } */
++/* { dg-final { check-function-bodies "**" "" "" } } */
++
++/*
++** f1:
++**	subs	(w[0-9]+), w0, #?4095
++**	csel	w0, \1, wzr, (cc|ls)
++**	ret
++*/
++/*
++** f2:
++**	subs	(w[0-9]+), w0, #?4095
++**	csel	w0, \1, wzr, (cc|ls)
++**	ret
++*/
++/*
++** f3:
++**	subs	(w[0-9]+), w0, #?4094
++**	csinc	w0, \1, wzr, ls
++**	ret
++*/
++/*
++** f4:
++**	subs	(w[0-9]+), w0, #?4096
++**	csinv	w0, \1, wzr, cc
++**	ret
++*/
++
++#define TYPE uint32_t
++#define TYPE_MIN 0
++#define TYPE_MAX UINT32_MAX
++#define VALUE 4095
++
++#include "min_plus_1.c"
+diff --git a/gcc/testsuite/gcc.target/aarch64/min_plus_6.c b/gcc/testsuite/gcc.target/aarch64/min_plus_6.c
+new file mode 100644
+index 000000000..176533cb2
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/min_plus_6.c
+@@ -0,0 +1,9 @@
++/* { dg-do run } */
++/* { dg-options "-O2 --save-temps" } */
++
++#define TYPE uint64_t
++#define TYPE_MIN 0
++#define TYPE_MAX UINT64_MAX
++#define VALUE 1
++
++#include "min_plus_1.c"
+diff --git a/gcc/testsuite/gcc.target/aarch64/min_plus_7.c b/gcc/testsuite/gcc.target/aarch64/min_plus_7.c
+new file mode 100644
+index 000000000..d6a217a51
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/min_plus_7.c
+@@ -0,0 +1,35 @@
++/* { dg-do run } */
++/* { dg-options "-O2 --save-temps" } */
++/* { dg-final { check-function-bodies "**" "" "" } } */
++
++/*
++** f1:
++**	subs	(x[0-9]+), x0, #?2
++**	csel	x0, \1, xzr, (cc|ls)
++**	ret
++*/
++/*
++** f2:
++**	subs	(x[0-9]+), x0, #?2
++**	csel	x0, \1, xzr, (cc|ls)
++**	ret
++*/
++/*
++** f3:
++**	subs	(x[0-9]+), x0, #?1
++**	csinc	x0, \1, xzr, ls
++**	ret
++*/
++/*
++** f4:
++**	subs	(x[0-9]+), x0, #?3
++**	csinv	x0, \1, xzr, cc
++**	ret
++*/
++
++#define TYPE uint64_t
++#define TYPE_MIN 0
++#define TYPE_MAX UINT64_MAX
++#define VALUE 2
++
++#include "min_plus_1.c"
+-- 
+2.27.0.windows.1
+
diff --git a/0071-PHIOPT-Disable-the-match-A-CST1-0-when-the-CST1-is-n.patch b/0071-PHIOPT-Disable-the-match-A-CST1-0-when-the-CST1-is-n.patch
new file mode 100644
index 0000000..18c2e3b
--- /dev/null
+++ b/0071-PHIOPT-Disable-the-match-A-CST1-0-when-the-CST1-is-n.patch
@@ -0,0 +1,31 @@
+From b57c55b282e7a9a7b2cc0d3843e58fd7998685e6 Mon Sep 17 00:00:00 2001
+From: zhongyunde 
+Date: Fri, 4 Nov 2022 23:19:44 +0800
+Subject: [PATCH 23/35] [PHIOPT] Disable the match A?CST1:0 when the CST1 is
+ negitive value
+
+Fix the regression of gcc.target/aarch64/sve/vcond_3.c
+
+gcc:
+        * match.pd (A?CST1:CST2): Disable the simplifcations A? (-CST1):0
+---
+ gcc/match.pd | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/gcc/match.pd b/gcc/match.pd
+index 79a0228d2..fc1a34dd3 100644
+--- a/gcc/match.pd
++++ b/gcc/match.pd
+@@ -3347,7 +3347,8 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
+     (if (integer_onep (@1))
+      (convert (convert:boolean_type_node @0)))
+     /* a ? powerof2cst : 0 -> a << (log2(powerof2cst)) */
+-    (if (INTEGRAL_TYPE_P (type) && integer_pow2p (@1))
++    (if (INTEGRAL_TYPE_P (type) && TYPE_UNSIGNED (TREE_TYPE (@1))
++         && integer_pow2p (@1))
+      (with {
+        tree shift = build_int_cst (integer_type_node, tree_log2 (@1));
+       }
+-- 
+2.27.0.windows.1
+
diff --git a/0072-Struct-Reorg-Merge-struct_layout-pass-into-struct_re.patch b/0072-Struct-Reorg-Merge-struct_layout-pass-into-struct_re.patch
new file mode 100644
index 0000000..a7c7f74
--- /dev/null
+++ b/0072-Struct-Reorg-Merge-struct_layout-pass-into-struct_re.patch
@@ -0,0 +1,1770 @@
+From 6a7b9e30955e0da5258d8c4ab8de611c8a5653a5 Mon Sep 17 00:00:00 2001
+From: liyancheng <412998149@qq.com>
+Date: Thu, 3 Nov 2022 20:11:18 +0800
+Subject: [PATCH 24/35] [Struct Reorg] Merge struct_layout pass into
+ struct_reorg
+
+1. Merge struct_layout pass into struct_reorg
+2. Merge srmode and into struct_layout_opt_level
+3. Adapt to all relevant deja tests
+---
+ gcc/common.opt                                |   2 +-
+ gcc/ipa-struct-reorg/ipa-struct-reorg.c       | 316 ++++++++----------
+ gcc/opts.c                                    |  15 +-
+ 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/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/sr_maxmin_expr.c  |   2 +-
+ gcc/testsuite/gcc.dg/struct/struct-reorg.exp  |   4 +-
+ gcc/testsuite/gcc.dg/struct/struct_reorg-1.c  |   2 +-
+ gcc/testsuite/gcc.dg/struct/struct_reorg-2.c  |   2 +-
+ gcc/testsuite/gcc.dg/struct/struct_reorg-3.c  |   2 +-
+ gcc/testsuite/gcc.dg/struct/struct_reorg-4.c  |   2 +-
+ .../gcc.dg/struct/w_prof_global_array.c       |   2 +-
+ .../gcc.dg/struct/w_prof_global_var.c         |   2 +-
+ .../gcc.dg/struct/w_prof_local_array.c        |   2 +-
+ .../gcc.dg/struct/w_prof_local_var.c          |   2 +-
+ .../gcc.dg/struct/w_prof_single_str_global.c  |   2 +-
+ gcc/testsuite/gcc.dg/struct/w_prof_two_strs.c |   2 +-
+ .../gcc.dg/struct/w_ratio_cold_str.c          |   2 +-
+ .../gcc.dg/struct/wo_prof_array_field.c       |   2 +-
+ .../struct/wo_prof_array_through_pointer.c    |   2 +-
+ .../gcc.dg/struct/wo_prof_double_malloc.c     |   2 +-
+ .../gcc.dg/struct/wo_prof_empty_str.c         |   2 +-
+ .../struct/wo_prof_escape_arg_to_local.c      |   2 +-
+ .../struct/wo_prof_escape_substr_array.c      |   2 +-
+ .../gcc.dg/struct/wo_prof_global_array.c      |   2 +-
+ .../gcc.dg/struct/wo_prof_global_var.c        |   2 +-
+ .../gcc.dg/struct/wo_prof_local_array.c       |   2 +-
+ .../gcc.dg/struct/wo_prof_local_var.c         |   2 +-
+ .../gcc.dg/struct/wo_prof_malloc_size_var-1.c |   2 +-
+ .../gcc.dg/struct/wo_prof_malloc_size_var.c   |   2 +-
+ .../struct/wo_prof_mult_field_peeling.c       |   2 +-
+ .../gcc.dg/struct/wo_prof_single_str_global.c |   2 +-
+ .../gcc.dg/struct/wo_prof_single_str_local.c  |   2 +-
+ .../gcc.dg/struct/wo_prof_two_strs.c          |   2 +-
+ gcc/timevar.def                               |   1 -
+ gcc/tree-pass.h                               |   1 -
+ gcc/tree.c                                    |   4 +-
+ 76 files changed, 222 insertions(+), 260 deletions(-)
+
+diff --git a/gcc/common.opt b/gcc/common.opt
+index be7bfee60..ad147f7a9 100644
+--- a/gcc/common.opt
++++ b/gcc/common.opt
+@@ -1881,7 +1881,7 @@ Common Ignore
+ Does nothing. Preserved for backward compatibility.
+ 
+ fipa-reorder-fields
+-Common Report Var(flag_ipa_struct_layout) Init(0) Optimization
++Common Report Var(flag_ipa_reorder_fields) Init(0) Optimization
+ Perform structure fields reorder optimizations.
+ 
+ fipa-struct-reorg
+diff --git a/gcc/ipa-struct-reorg/ipa-struct-reorg.c b/gcc/ipa-struct-reorg/ipa-struct-reorg.c
+index 54c20ca3f..08cb51fee 100644
+--- a/gcc/ipa-struct-reorg/ipa-struct-reorg.c
++++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.c
+@@ -232,12 +232,6 @@ is_from_void_ptr_parm (tree ssa_name)
+ 	  && VOID_POINTER_P (TREE_TYPE (ssa_name)));
+ }
+ 
+-enum srmode
+-{
+-  NORMAL = 0,
+-  COMPLETE_STRUCT_RELAYOUT,
+-  STRUCT_LAYOUT_OPTIMIZE
+-};
+ 
+ /* Enum the struct layout optimize level,
+    which should be the same as the option -fstruct-reorg=.  */
+@@ -245,16 +239,17 @@ enum srmode
+ enum struct_layout_opt_level
+ {
+   NONE = 0,
+-  STRUCT_REORG,
+-  STRUCT_REORDER_FIELDS,
+-  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);
+ 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;
+ 
+@@ -607,7 +602,7 @@ void
+ srtype::simple_dump (FILE *f)
+ {
+   print_generic_expr (f, type);
+-  if (current_mode == STRUCT_LAYOUT_OPTIMIZE)
++  if (current_layout_opt_level >= STRUCT_REORDER_FIELDS)
+     {
+       fprintf (f, "(%d)", TYPE_UID (type));
+     }
+@@ -656,7 +651,7 @@ srfield::create_new_fields (tree newtype[max_split],
+ 			    tree newfields[max_split],
+ 			    tree newlast[max_split])
+ {
+-  if (current_mode == STRUCT_LAYOUT_OPTIMIZE)
++  if (current_layout_opt_level >= STRUCT_REORDER_FIELDS)
+     {
+       create_new_optimized_fields (newtype, newfields, newlast);
+       return;
+@@ -857,7 +852,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_LAYOUT_OPTIMIZE)
++      && current_layout_opt_level < STRUCT_REORDER_FIELDS)
+     {
+       newtype[0] = type;
+       return false;
+@@ -885,8 +880,7 @@ srtype::create_new_type (void)
+       sprintf(id, "%d", i);
+       if (tname) 
+ 	{
+-	  name = concat (tname, current_mode == STRUCT_LAYOUT_OPTIMIZE
+-			 ? ".slo." : ".reorg.", id, NULL);
++	  name = concat (tname, ".reorg.", id, NULL);
+ 	  TYPE_NAME (newtype[i]) = build_decl (UNKNOWN_LOCATION, TYPE_DECL,
+ 				   get_identifier (name), newtype[i]);
+           free (name);
+@@ -896,8 +890,7 @@ srtype::create_new_type (void)
+   for (unsigned i = 0; i < fields.length (); i++)
+     {
+       srfield *f = fields[i];
+-      if (current_mode == STRUCT_LAYOUT_OPTIMIZE
+-	  && 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);
+@@ -921,13 +914,12 @@ srtype::create_new_type (void)
+ 
+   warn_padded = save_warn_padded;
+ 
+-  if (current_mode == STRUCT_LAYOUT_OPTIMIZE
++  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_LAYOUT_OPTIMIZE
+-	  && 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");
+     }
+@@ -1046,8 +1038,7 @@ srfunction::create_new_decls (void)
+ 	      sprintf(id, "%d", j);
+ 	      if (tname)
+ 	        {
+-		  name = concat (tname, current_mode == STRUCT_LAYOUT_OPTIMIZE
+-					? ".slo." : ".reorg.", id, NULL);
++		  name = concat (tname, ".reorg.", id, NULL);
+ 		  new_name = get_identifier (name);
+ 		  free (name);
+ 		}
+@@ -1266,7 +1257,7 @@ public:
+   {
+   }
+ 
+-  unsigned execute (enum srmode mode);
++  unsigned execute (unsigned int opt);
+   void mark_type_as_escape (tree type, escape_type, gimple *stmt = NULL);
+ 
+   // fields
+@@ -2796,7 +2787,7 @@ escape_type escape_type_volatile_array_or_ptrptr (tree type)
+     return escape_volatile;
+   if (isarraytype (type))
+     return escape_array;
+-  if (isptrptr (type) && (current_mode != STRUCT_LAYOUT_OPTIMIZE))
++  if (isptrptr (type) && (current_layout_opt_level < STRUCT_REORDER_FIELDS))
+     return escape_ptr_ptr;
+   return does_not_escape;
+ }
+@@ -2817,14 +2808,13 @@ 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_LAYOUT_OPTIMIZE)
++  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_LAYOUT_OPTIMIZE
++  if (current_layout_opt_level >= STRUCT_REORDER_FIELDS
+       && TREE_CODE (field_type) == RECORD_TYPE)
+     {
+       field_srtype->mark_escape (escape_instance_field, NULL);
+@@ -2859,7 +2849,7 @@ ipa_struct_reorg::record_struct_field_types (tree base_type,
+ 	  }
+ 	/* 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_LAYOUT_OPTIMIZE
++	if (current_layout_opt_level >= STRUCT_REORDER_FIELDS
+ 	    && TREE_CODE (field_type) == RECORD_TYPE)
+ 	  {
+ 	    base_srtype->mark_escape (escape_instance_field, NULL);
+@@ -3043,8 +3033,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_LAYOUT_OPTIMIZE)
++      if (current_layout_opt_level >= COMPLETE_STRUCT_RELAYOUT
+ 	  && TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE)
+ 	{
+ 	  e = escape_separate_instance;
+@@ -3149,7 +3138,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_LAYOUT_OPTIMIZE)
++	  if (current_layout_opt_level >= STRUCT_REORDER_FIELDS)
+ 	    {
+ 	      l_find = !(current_function->is_safe_func
+ 			 && TREE_CODE (lhs) == SSA_NAME
+@@ -3195,7 +3184,7 @@ ipa_struct_reorg::find_vars (gimple *stmt)
+ 		}
+ 	    }
+ 	}
+-      else if ((current_mode == STRUCT_LAYOUT_OPTIMIZE)
++      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
+@@ -3206,7 +3195,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_LAYOUT_OPTIMIZE)
++      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))),
+@@ -3418,8 +3407,7 @@ ipa_struct_reorg::maybe_record_stmt (cgraph_node *node, gimple *stmt)
+     default:
+       break;
+     }
+-  if (current_mode == STRUCT_LAYOUT_OPTIMIZE
+-      && 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,
+@@ -3590,11 +3578,12 @@ is_result_of_mult (tree arg, tree *num, tree struct_size)
+ 	  size_def_stmt = SSA_NAME_DEF_STMT (arg);
+ 	}
+       else if (rhs_code == NEGATE_EXPR
+-	       && current_mode == STRUCT_LAYOUT_OPTIMIZE)
++	       && 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_LAYOUT_OPTIMIZE)
++      else if (rhs_code == NOP_EXPR
++	       && current_layout_opt_level >= STRUCT_REORDER_FIELDS)
+ 	{
+ 	  return trace_calculate_diff (size_def_stmt, num);
+ 	}
+@@ -3614,17 +3603,17 @@ is_result_of_mult (tree arg, tree *num, tree struct_size)
+ bool
+ ipa_struct_reorg::handled_allocation_stmt (gimple *stmt)
+ {
+-  if ((current_mode == STRUCT_LAYOUT_OPTIMIZE)
++  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)
+@@ -3750,7 +3739,7 @@ ipa_struct_reorg::maybe_mark_or_record_other_side (tree side, tree other, gimple
+   /* 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_LAYOUT_OPTIMIZE
++  else if (current_layout_opt_level >= STRUCT_REORDER_FIELDS
+ 	   && TREE_CODE (side) == SSA_NAME
+ 	   && VOID_POINTER_P (TREE_TYPE (side))
+ 	   && SSA_NAME_VAR (side)
+@@ -4017,7 +4006,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_LAYOUT_OPTIMIZE)
++      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)))
+@@ -4081,7 +4070,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);
+@@ -4233,7 +4222,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_LAYOUT_OPTIMIZE
++		|| (current_layout_opt_level >= STRUCT_REORDER_FIELDS
+ 		    && safe_functions.contains (
+ 		       node->get_edge (stmt)->callee)))
+ 	      && VOID_POINTER_P (argtypet))
+@@ -4265,14 +4254,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_LAYOUT_OPTIMIZE)
+-    {
+-      if (!opt_for_fn (current_function_decl, flag_ipa_struct_layout))
+-	{
+-	  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))
+ 	{
+@@ -4379,7 +4361,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);
+@@ -4490,7 +4472,7 @@ ipa_struct_reorg::check_definition_call (srdecl *decl, vec &worklist)
+       check_type_and_push (gimple_call_arg (stmt, 0), decl, worklist, stmt);
+     }
+ 
+-  if (current_mode == STRUCT_LAYOUT_OPTIMIZE)
++  if (current_layout_opt_level >= STRUCT_REORDER_FIELDS)
+     {
+       if (!handled_allocation_stmt (stmt))
+ 	{
+@@ -4544,7 +4526,8 @@ ipa_struct_reorg::check_definition (srdecl *decl, vec &worklist)
+ 	}
+       return;
+     }
+-  if (current_mode == STRUCT_LAYOUT_OPTIMIZE && 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));
+@@ -4631,7 +4614,7 @@ ipa_struct_reorg::check_other_side (srdecl *decl, tree other, gimple *stmt, vec<
+     {
+       /* In Complete Struct Relayout opti, 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;
+ 	}
+@@ -4645,7 +4628,7 @@ ipa_struct_reorg::check_other_side (srdecl *decl, tree other, gimple *stmt, vec<
+       if (!get_type_field (other, base, indirect, type1, field,
+ 			   realpart, imagpart, address, escape_from_base))
+ 	{
+-	  if (current_mode == STRUCT_LAYOUT_OPTIMIZE)
++	  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
+@@ -4703,7 +4686,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_LAYOUT_OPTIMIZE || 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))
+@@ -4779,12 +4763,9 @@ ipa_struct_reorg::check_use (srdecl *decl, gimple *stmt, vec &worklist)
+       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_LAYOUT_OPTIMIZE
++      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)))
+@@ -4818,15 +4799,12 @@ ipa_struct_reorg::check_use (srdecl *decl, gimple *stmt, vec &worklist)
+       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
++      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))
+-	   || (current_mode == STRUCT_LAYOUT_OPTIMIZE
+-	       && (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);
+@@ -4945,11 +4923,11 @@ ipa_struct_reorg::record_function (cgraph_node *node)
+     escapes = escape_marked_as_used;
+   else if (!node->local)
+     {
+-      if (current_mode != STRUCT_LAYOUT_OPTIMIZE)
++      if (current_layout_opt_level < STRUCT_REORDER_FIELDS)
+ 	{
+ 	  escapes = escape_visible_function;
+ 	}
+-      if (current_mode == STRUCT_LAYOUT_OPTIMIZE && node->externally_visible)
++      else if (node->externally_visible)
+ 	{
+ 	  escapes = escape_visible_function;
+ 	}
+@@ -4959,14 +4937,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_LAYOUT_OPTIMIZE)
+-    {
+-      if (!opt_for_fn (node->decl, flag_ipa_struct_layout))
+-	{
+-	  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))
+ 	{
+@@ -4978,10 +4949,10 @@ ipa_struct_reorg::record_function (cgraph_node *node)
+   gimple_stmt_iterator si;
+ 
+   /* Add a safe func mechanism.  */
+-  if (current_mode == STRUCT_LAYOUT_OPTIMIZE)
++  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,
+@@ -5194,7 +5165,7 @@ ipa_struct_reorg::record_accesses (void)
+     }
+ 
+   /* Add a safe func mechanism.  */
+-  if (current_mode == STRUCT_LAYOUT_OPTIMIZE)
++  if (current_layout_opt_level >= STRUCT_REORDER_FIELDS)
+     {
+       record_safe_func_with_void_ptr_parm ();
+     }
+@@ -5392,8 +5363,7 @@ ipa_struct_reorg::propagate_escape_via_empty_with_no_original (void)
+ void
+ ipa_struct_reorg::prune_escaped_types (void)
+ {
+-  if (current_mode != COMPLETE_STRUCT_RELAYOUT
+-      && current_mode != STRUCT_LAYOUT_OPTIMIZE)
++  if (current_layout_opt_level == STRUCT_SPLIT)
+     {
+       /* Detect recusive types and mark them as escaping.  */
+       detect_cycles ();
+@@ -5401,7 +5371,7 @@ ipa_struct_reorg::prune_escaped_types (void)
+ 	 mark them as escaping.  */
+       propagate_escape ();
+     }
+-  if (current_mode == STRUCT_LAYOUT_OPTIMIZE)
++  if (current_layout_opt_level >= STRUCT_REORDER_FIELDS)
+     {
+       propagate_escape_via_original ();
+       propagate_escape_via_empty_with_no_original ();
+@@ -5461,7 +5431,7 @@ ipa_struct_reorg::prune_escaped_types (void)
+       if (function->args.is_empty ()
+ 	  && function->decls.is_empty ()
+ 	  && function->globals.is_empty ()
+-	  && current_mode != STRUCT_LAYOUT_OPTIMIZE)
++	  && current_layout_opt_level < STRUCT_REORDER_FIELDS)
+ 	{
+ 	  delete function;
+ 	  functions.ordered_remove (i);
+@@ -5489,7 +5459,7 @@ ipa_struct_reorg::prune_escaped_types (void)
+   /* The escape type is not deleted in STRUCT_LAYOUT_OPTIMIZE,
+      Then the type that contains the escaped type fields
+      can find complete information.  */
+-  if (current_mode != STRUCT_LAYOUT_OPTIMIZE)
++  if (current_layout_opt_level < STRUCT_REORDER_FIELDS)
+     {
+       for (unsigned i = 0; i < types.length ();)
+ 	{
+@@ -5539,7 +5509,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_LAYOUT_OPTIMIZE)
++  if (current_layout_opt_level >= STRUCT_REORDER_FIELDS)
+     {
+       for (unsigned i = 0; i < types.length (); i++)
+ 	{
+@@ -5561,14 +5531,31 @@ ipa_struct_reorg::create_new_types (void)
+ 	}
+     }
+ 
+-  if (dump_file)
++  if (current_layout_opt_level == STRUCT_SPLIT)
+     {
+-      if (newtypes)
+-	fprintf (dump_file, "\nNumber of structures to transform is %d\n", newtypes);
+-      else
+-	fprintf (dump_file, "\nNo structures to transform.\n");
++      if (dump_file)
++	{
++	  if (newtypes)
++	    fprintf (dump_file, "\nNumber of structures to transform in"
++				" struct split is %d\n", newtypes);
++	  else
++	    fprintf (dump_file, "\nNo structures to transform in"
++				" struct split.\n");
++	}
++    }
++  else
++    {
++      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;
+ }
+ 
+@@ -5663,8 +5650,7 @@ ipa_struct_reorg::create_new_args (cgraph_node *new_node)
+   char *name = NULL;
+   if (tname)
+     {
+-      name = concat (tname, current_mode == STRUCT_LAYOUT_OPTIMIZE
+-			    ? ".slo.0" : ".reorg.0", NULL);
++      name = concat (tname, ".reorg.0", NULL);
+       new_name = get_identifier (name);
+       free (name);
+     }
+@@ -5751,9 +5737,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_LAYOUT_OPTIMIZE
+-				? "slo" : "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;
+@@ -5871,7 +5855,7 @@ ipa_struct_reorg::rewrite_expr (tree expr, tree newexpr[max_split], bool ignore_
+         newbase1 = build_fold_addr_expr (newbase1);
+       if (indirect)
+ 	{
+-	  if (current_mode == STRUCT_LAYOUT_OPTIMIZE)
++	  if (current_layout_opt_level >= STRUCT_REORDER_FIELDS)
+ 	    {
+ 	      /* Supports the MEM_REF offset.
+ 		 _1 = MEM[(struct arc *)ap_1 + 72B].flow;
+@@ -5927,8 +5911,7 @@ ipa_struct_reorg::rewrite_assign (gassign *stmt, gimple_stmt_iterator *gsi)
+ {
+   bool remove = false;
+ 
+-  if (current_mode == STRUCT_LAYOUT_OPTIMIZE
+-      && 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))
+@@ -5964,10 +5947,10 @@ ipa_struct_reorg::rewrite_assign (gassign *stmt, gimple_stmt_iterator *gsi)
+       return remove;
+     }
+ 
+-  if ((current_mode != STRUCT_LAYOUT_OPTIMIZE
++  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_LAYOUT_OPTIMIZE
++      || (current_layout_opt_level >= STRUCT_REORDER_FIELDS
+ 	  && (TREE_CODE_CLASS (gimple_assign_rhs_code (stmt))
+ 	      == tcc_comparison)))
+     {
+@@ -5977,7 +5960,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_LAYOUT_OPTIMIZE
++      if (current_layout_opt_level >= STRUCT_REORDER_FIELDS
+ 	  && rhs_code != EQ_EXPR && rhs_code != NE_EXPR)
+ 	{
+ 	  code = rhs_code;
+@@ -6024,8 +6007,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_LAYOUT_OPTIMIZE
+-	  || (current_mode == STRUCT_LAYOUT_OPTIMIZE && (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);
+ 	}
+@@ -6053,7 +6037,7 @@ ipa_struct_reorg::rewrite_assign (gassign *stmt, gimple_stmt_iterator *gsi)
+     }
+ 
+   /* Support POINTER_DIFF_EXPR rewriting.  */
+-  if (current_mode == STRUCT_LAYOUT_OPTIMIZE
++  if (current_layout_opt_level >= STRUCT_REORDER_FIELDS
+       && gimple_assign_rhs_code (stmt) == POINTER_DIFF_EXPR)
+     {
+       tree rhs1 = gimple_assign_rhs1 (stmt);
+@@ -6240,7 +6224,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_LAYOUT_OPTIMIZE && 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];
+@@ -6367,9 +6352,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_LAYOUT_OPTIMIZE
++  if ((current_layout_opt_level < STRUCT_REORDER_FIELDS
+        && (rhs_code != EQ_EXPR && rhs_code != NE_EXPR))
+-      || (current_mode == STRUCT_LAYOUT_OPTIMIZE
++      || (current_layout_opt_level >= STRUCT_REORDER_FIELDS
+ 	  && TREE_CODE_CLASS (rhs_code) != tcc_comparison))
+     return false;
+   tree lhs = gimple_cond_lhs (stmt);
+@@ -6429,7 +6414,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_LAYOUT_OPTIMIZE)
++  if (current_layout_opt_level >= STRUCT_REORDER_FIELDS)
+     {
+       /* Delete debug gimple now.  */
+       return true;
+@@ -6593,7 +6578,7 @@ ipa_struct_reorg::rewrite_functions (void)
+      then don't rewrite any accesses. */
+   if (!create_new_types ())
+     {
+-      if (current_mode == STRUCT_LAYOUT_OPTIMIZE)
++      if (current_layout_opt_level >= STRUCT_REORDER_FIELDS)
+ 	{
+ 	  for (unsigned i = 0; i < functions.length (); i++)
+ 	    {
+@@ -6612,7 +6597,7 @@ ipa_struct_reorg::rewrite_functions (void)
+       return 0;
+     }
+ 
+-  if (current_mode == STRUCT_LAYOUT_OPTIMIZE && dump_file)
++  if (current_layout_opt_level >= STRUCT_REORDER_FIELDS && dump_file)
+     {
+       fprintf (dump_file, "=========== all created newtypes: ===========\n\n");
+       dump_newtypes (dump_file);
+@@ -6622,13 +6607,13 @@ ipa_struct_reorg::rewrite_functions (void)
+     {
+       retval = TODO_remove_functions;
+       create_new_functions ();
+-      if (current_mode == STRUCT_LAYOUT_OPTIMIZE)
++      if (current_layout_opt_level >= STRUCT_REORDER_FIELDS)
+ 	{
+ 	  prune_escaped_types ();
+ 	}
+     }
+ 
+-  if (current_mode == STRUCT_LAYOUT_OPTIMIZE)
++  if (current_layout_opt_level >= STRUCT_REORDER_FIELDS)
+     {
+       for (unsigned i = 0; i < functions.length (); i++)
+ 	{
+@@ -6794,13 +6779,13 @@ 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 (mode == NORMAL || mode == STRUCT_LAYOUT_OPTIMIZE)
++  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 ())
+@@ -6809,20 +6794,20 @@ ipa_struct_reorg::execute (enum srmode mode)
+ 	}
+       record_accesses ();
+       prune_escaped_types ();
+-      if (current_mode == NORMAL)
++      if (opt == STRUCT_SPLIT)
+ 	{
+ 	  analyze_types ();
+ 	}
+ 
+       ret = rewrite_functions ();
+     }
+-  else if (mode == COMPLETE_STRUCT_RELAYOUT)
++  else // do COMPLETE_STRUCT_RELAYOUT
+     {
+       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;
+@@ -6861,67 +6846,48 @@ public:
+   virtual unsigned int execute (function *)
+   {
+     unsigned int ret = 0;
+-    ret = ipa_struct_reorg ().execute (NORMAL);
+-    if (!ret)
++    unsigned int ret_reorg = 0;
++    unsigned int level = 0;
++    switch (struct_layout_optimize_level)
+       {
+-	ret = ipa_struct_reorg ().execute (COMPLETE_STRUCT_RELAYOUT);
++	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 ();
+       }
+-    return ret;
+-  }
+ 
+-}; // class pass_ipa_struct_reorg
+-
+-bool
+-pass_ipa_struct_reorg::gate (function *)
+-{
+-  return (optimize >= 3
+-	  && flag_ipa_struct_reorg
+-	  /* 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));
+-}
++    /* 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);
+ 
+-const pass_data pass_data_ipa_struct_layout =
+-{
+-  SIMPLE_IPA_PASS, // type
+-  "struct_layout", // name
+-  OPTGROUP_NONE, // optinfo_flags
+-  TV_IPA_STRUCT_LAYOUT, // tv_id
+-  0, // properties_required
+-  0, // properties_provided
+-  0, // properties_destroyed
+-  0, // todo_flags_start
+-  0, // todo_flags_finish
+-};
++    if (level >= STRUCT_REORDER_FIELDS)
++      ret = ipa_struct_reorg ().execute (level);
+ 
+-class pass_ipa_struct_layout : public simple_ipa_opt_pass
+-{
+-public:
+-  pass_ipa_struct_layout (gcc::context *ctxt)
+-    : simple_ipa_opt_pass (pass_data_ipa_struct_layout, ctxt)
+-  {}
++    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);
++      }
+ 
+-  /* opt_pass methods: */
+-  virtual bool gate (function *);
+-  virtual unsigned int execute (function *)
+-  {
+-    unsigned int ret = 0;
+-    ret = ipa_struct_reorg ().execute (STRUCT_LAYOUT_OPTIMIZE);
+-    return ret;
++    return ret | ret_reorg;
+   }
+ 
+-}; // class pass_ipa_struct_layout
++}; // class pass_ipa_struct_reorg
+ 
+ bool
+-pass_ipa_struct_layout::gate (function *)
++pass_ipa_struct_reorg::gate (function *)
+ {
+   return (optimize >= 3
+-	  && flag_ipa_struct_layout
++	  && flag_ipa_struct_reorg
+ 	  /* Don't bother doing anything if the program has errors.  */
+ 	  && !seen_error ()
+ 	  && flag_lto_partition == LTO_PARTITION_ONE
+@@ -6939,9 +6905,3 @@ make_pass_ipa_struct_reorg (gcc::context *ctxt)
+ {
+   return new pass_ipa_struct_reorg (ctxt);
+ }
+-
+-simple_ipa_opt_pass *
+-make_pass_ipa_struct_layout (gcc::context *ctxt)
+-{
+-  return new pass_ipa_struct_layout (ctxt);
+-}
+diff --git a/gcc/opts.c b/gcc/opts.c
+index c3877c24e..f12b13599 100644
+--- a/gcc/opts.c
++++ b/gcc/opts.c
+@@ -2696,15 +2696,20 @@ common_handle_option (struct gcc_options *opts,
+       break;
+ 
+     case OPT_fipa_struct_reorg_:
+-      opts->x_struct_layout_optimize_level = value;
+-      if (value > 1)
+-	{
+-	  SET_OPTION_IF_UNSET (opts, opts_set, flag_ipa_struct_layout, value);
+-	}
+       /* 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_:
+diff --git a/gcc/passes.def b/gcc/passes.def
+index 94554cc1d..f3b6048d8 100644
+--- a/gcc/passes.def
++++ b/gcc/passes.def
+@@ -175,7 +175,6 @@ along with GCC; see the file COPYING3.  If not see
+   INSERT_PASSES_AFTER (all_late_ipa_passes)
+   NEXT_PASS (pass_materialize_all_clones);
+   NEXT_PASS (pass_ipa_pta);
+-  NEXT_PASS (pass_ipa_struct_layout);
+   /* FIXME: this should 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 f62222a96..1e7341b24 100644
+--- a/gcc/symbol-summary.h
++++ b/gcc/symbol-summary.h
+@@ -61,7 +61,7 @@ protected:
+   {
+     /* In structure optimizatons, we call new to ensure that
+        the allocated memory is initialized to 0.  */
+-    if (flag_ipa_struct_layout || flag_ipa_struct_reorg)
++    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
+@@ -77,7 +77,7 @@ protected:
+       ggc_delete (item);
+     else
+       {
+-	if (flag_ipa_struct_layout || flag_ipa_struct_reorg)
++	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 4261d2352..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 "struct_layout" } } */
++/* { 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 42d38c63a..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 "struct_layout" } } */
++/* { 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 4e52564b6..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 "struct_layout" } } */
++/* { 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 894e9f460..e56bf467b 100644
+--- a/gcc/testsuite/gcc.dg/struct/dfe_extr_claw.c
++++ b/gcc/testsuite/gcc.dg/struct/dfe_extr_claw.c
+@@ -74,4 +74,4 @@ claw_snd_conn_req (struct net_device *dev, __u8 link)
+   return rc;
+ }
+ 
+-/* { dg-final { scan-ipa-dump-times "Dead field elimination" 1 "struct_layout" } } */
++/* { 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 13a226ee8..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 "struct_layout" } } */
++/* { 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 1fff2cb9d..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 "struct_layout" } } */
++/* { 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 0f577667c..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 "struct_layout" } } */
++/* { 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 9801f87f1..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 "struct_layout" } } */
++/* { 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 5570c762e..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 "struct_layout" } } */
++/* { 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 50ab9cc24..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 "struct_layout" } } */
++/* { 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 53583fe82..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 "struct_layout" } } */
++/* { 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 fd675ec2e..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 "struct_layout" } } */
++/* { 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 600e7908b..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 "struct_layout" } } */
++/* { 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 f411364a7..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 "struct_layout" } } */
++/* { 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 a4e723763..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 "struct_layout" } } */
++/* { 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 882a695b0..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." "struct_layout" } } */
+\ 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 20ecee545..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" "struct_layout" } } */
+\ 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 ad879fc11..8eb16c8d6 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 "No structures to transform." "struct_layout" } } */
+\ 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_create_fields_bug.c b/gcc/testsuite/gcc.dg/struct/rf_create_fields_bug.c
+index f0c9d8f39..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" "struct_layout" } } */
+\ 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 fa5e6c2d0..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" "struct_layout" } } */
+\ 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 2966869e7..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" "struct_layout" } } */
+\ 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 b74b9e5e9..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" "struct_layout" } } */
+\ 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_int_cast_ptr.c b/gcc/testsuite/gcc.dg/struct/rf_int_cast_ptr.c
+index cf85c6109..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" "struct_layout" } } */
+\ 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 61fd9f755..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" "struct_layout" } } */
+\ 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 2c115da02..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" "struct_layout" } } */
+\ 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 c7646d8b7..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" "struct_layout" } } */
+\ 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 01c000375..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." "struct_layout" } } */
+\ 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 f962163fe..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" "struct_layout" } } */
+\ 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 6558b1797..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" "struct_layout" } } */
+\ 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 6d528ed5b..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." "struct_layout" } } */
+\ 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 e95cf2e5d..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" "struct_layout" } } */
+\ 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 cb4054522..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" "struct_layout" } } */
+\ 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 38bddbae5..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" "struct_layout" } } */
+\ 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 86034f042..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" "struct_layout" } } */
+\ 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 aae7c4bc9..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" "struct_layout" } } */
+\ 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 8672e7552..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" "struct_layout" } } */
+\ 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 2d67434a0..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" "struct_layout" } } */
+\ 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 a8cf2b63c..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" "struct_layout" } } */
+\ 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 b6cba3c34..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" "struct_layout" } } */
+\ 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/sr_maxmin_expr.c b/gcc/testsuite/gcc.dg/struct/sr_maxmin_expr.c
+index fb135ef0b..e3d219fe1 100644
+--- a/gcc/testsuite/gcc.dg/struct/sr_maxmin_expr.c
++++ b/gcc/testsuite/gcc.dg/struct/sr_maxmin_expr.c
+@@ -22,4 +22,4 @@ main ()
+   return 0;
+ }
+ 
+-/* { dg-final { scan-ipa-dump "No structures to transform." "struct_reorg" } } */
++/* { dg-final { scan-ipa-dump "No structures to transform in struct split." "struct_reorg" } } */
+diff --git a/gcc/testsuite/gcc.dg/struct/struct-reorg.exp b/gcc/testsuite/gcc.dg/struct/struct-reorg.exp
+index ac5585813..2eebef768 100644
+--- a/gcc/testsuite/gcc.dg/struct/struct-reorg.exp
++++ b/gcc/testsuite/gcc.dg/struct/struct-reorg.exp
+@@ -64,8 +64,6 @@ gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/complete_struct_relayout
+ 	"" "-fipa-struct-reorg=1 -fdump-ipa-all -flto-partition=one -fwhole-program"
+ 
+ # -fipa-struct-reorg=2
+-gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/rf*.c]] \
+- 	"" "-fipa-struct-reorg=2 -fdump-ipa-all -flto-partition=one -fwhole-program"
+ gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/wo_prof_*.c]] \
+  	"" "-fipa-struct-reorg=2 -fdump-ipa-all -flto-partition=one -fwhole-program"
+ gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/w_ratio_*.c]] \
+@@ -80,6 +78,8 @@ gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/csr_*.c]] \
+ 	"" "-fipa-struct-reorg=2 -fdump-ipa-all -flto-partition=one -fwhole-program"
+ gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/complete_struct_relayout.c]] \
+ 	"" "-fipa-struct-reorg=2 -fdump-ipa-all -flto-partition=one -fwhole-program"
++gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/rf*.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]] \
+diff --git a/gcc/testsuite/gcc.dg/struct/struct_reorg-1.c b/gcc/testsuite/gcc.dg/struct/struct_reorg-1.c
+index 23444fe8b..a73ff8e7e 100644
+--- a/gcc/testsuite/gcc.dg/struct/struct_reorg-1.c
++++ b/gcc/testsuite/gcc.dg/struct/struct_reorg-1.c
+@@ -27,4 +27,4 @@ int main()
+   return g ();
+ }
+ 
+-/* { dg-final { scan-ipa-dump "No structures to transform." "struct_reorg" } } */
++/* { dg-final { scan-ipa-dump "No structures to transform in struct split." "struct_reorg" } } */
+diff --git a/gcc/testsuite/gcc.dg/struct/struct_reorg-2.c b/gcc/testsuite/gcc.dg/struct/struct_reorg-2.c
+index 44babd35b..d7ab7d21c 100644
+--- a/gcc/testsuite/gcc.dg/struct/struct_reorg-2.c
++++ b/gcc/testsuite/gcc.dg/struct/struct_reorg-2.c
+@@ -26,4 +26,4 @@ int main()
+   assert (f(1, 2) == 3);
+ }
+ 
+-/* { dg-final { scan-ipa-dump "Number of structures to transform is 2" "struct_reorg" } } */
++/* { dg-final { scan-ipa-dump "Number of structures to transform in struct split 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
+index 2d1f95c99..9e5b192eb 100644
+--- a/gcc/testsuite/gcc.dg/struct/struct_reorg-3.c
++++ b/gcc/testsuite/gcc.dg/struct/struct_reorg-3.c
+@@ -25,4 +25,4 @@ int main()
+   f (NULL, NULL, 1);
+ }
+ 
+-/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "struct_reorg" } } */
++/* { dg-final { scan-ipa-dump "Number of structures to transform in struct split 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
+index e5a8a6c84..27b4b56e0 100644
+--- a/gcc/testsuite/gcc.dg/struct/struct_reorg-4.c
++++ b/gcc/testsuite/gcc.dg/struct/struct_reorg-4.c
+@@ -56,4 +56,4 @@ main (void)
+   return 0;
+ }
+ 
+-/* { dg-final { scan-ipa-dump "No structures to transform." "struct_reorg" } } */
++/* { dg-final { scan-ipa-dump "No structures to transform in struct split." "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
+index 733413a94..9e0f84da8 100644
+--- a/gcc/testsuite/gcc.dg/struct/w_prof_global_array.c
++++ b/gcc/testsuite/gcc.dg/struct/w_prof_global_array.c
+@@ -26,4 +26,4 @@ main ()
+ }
+ 
+ /*--------------------------------------------------------------------------*/
+-/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "struct_reorg"  { xfail *-*-* } } } */
++/* { dg-final { scan-ipa-dump "Number of structures to transform in struct split 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
+index 0ef686e74..c868347e3 100644
+--- a/gcc/testsuite/gcc.dg/struct/w_prof_global_var.c
++++ b/gcc/testsuite/gcc.dg/struct/w_prof_global_var.c
+@@ -39,4 +39,4 @@ main ()
+ }
+ 
+ /*--------------------------------------------------------------------------*/
+-/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "struct_reorg" } } */
++/* { dg-final { scan-ipa-dump "Number of structures to transform in struct split 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
+index 23a53be53..185ff3125 100644
+--- a/gcc/testsuite/gcc.dg/struct/w_prof_local_array.c
++++ b/gcc/testsuite/gcc.dg/struct/w_prof_local_array.c
+@@ -34,4 +34,4 @@ main ()
+ }
+ 
+ /*--------------------------------------------------------------------------*/
+-/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "struct_reorg" { xfail *-*-* } } } */
++/* { dg-final { scan-ipa-dump "Number of structures to transform in struct split 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
+index 0cbb172f2..6294fb2a2 100644
+--- a/gcc/testsuite/gcc.dg/struct/w_prof_local_var.c
++++ b/gcc/testsuite/gcc.dg/struct/w_prof_local_var.c
+@@ -37,4 +37,4 @@ main ()
+ }
+ 
+ /*--------------------------------------------------------------------------*/
+-/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "struct_reorg" } } */
++/* { dg-final { scan-ipa-dump "Number of structures to transform in struct split 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
+index f900b1349..3ca4e0e71 100644
+--- a/gcc/testsuite/gcc.dg/struct/w_prof_single_str_global.c
++++ b/gcc/testsuite/gcc.dg/struct/w_prof_single_str_global.c
+@@ -28,4 +28,4 @@ main ()
+ }
+ 
+ /*--------------------------------------------------------------------------*/
+-/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "struct_reorg" } } */
++/* { dg-final { scan-ipa-dump "Number of structures to transform in struct split is 1" "struct_reorg" } } */
+diff --git a/gcc/testsuite/gcc.dg/struct/w_prof_two_strs.c b/gcc/testsuite/gcc.dg/struct/w_prof_two_strs.c
+index 13b4cdc70..ac99b9e62 100644
+--- a/gcc/testsuite/gcc.dg/struct/w_prof_two_strs.c
++++ b/gcc/testsuite/gcc.dg/struct/w_prof_two_strs.c
+@@ -61,4 +61,4 @@ main ()
+ }
+ 
+ /*--------------------------------------------------------------------------*/
+-/* { dg-final { scan-ipa-dump "Number of structures to transform is 2" "struct_reorg" } } */
++/* { dg-final { scan-ipa-dump "Number of structures to transform in struct split 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
+index dcc545964..afa145a57 100644
+--- a/gcc/testsuite/gcc.dg/struct/w_ratio_cold_str.c
++++ b/gcc/testsuite/gcc.dg/struct/w_ratio_cold_str.c
+@@ -40,4 +40,4 @@ main ()
+ 
+ /*--------------------------------------------------------------------------*/
+ /* Arrays are not handled. */
+-/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "struct_reorg" { xfail *-*-* } } } */
++/* { dg-final { scan-ipa-dump "Number of structures to transform in struct split 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
+index 6d6375fc1..7fa6ae275 100644
+--- a/gcc/testsuite/gcc.dg/struct/wo_prof_array_field.c
++++ b/gcc/testsuite/gcc.dg/struct/wo_prof_array_field.c
+@@ -23,4 +23,4 @@ int main()
+ }
+ 
+ /*--------------------------------------------------------------------------*/
+-/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "struct_reorg"  { xfail *-*-* } } } */
++/* { dg-final { scan-ipa-dump "Number of structures to transform in struct split 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
+index 9d3213408..b3bde5836 100644
+--- a/gcc/testsuite/gcc.dg/struct/wo_prof_array_through_pointer.c
++++ b/gcc/testsuite/gcc.dg/struct/wo_prof_array_through_pointer.c
+@@ -35,4 +35,4 @@ main ()
+   return 0;
+ }
+ 
+-/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "struct_reorg" { xfail *-*-* } } } */
++/* { dg-final { scan-ipa-dump "Number of structures to transform in struct split 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
+index d79992a53..f2bb82b94 100644
+--- a/gcc/testsuite/gcc.dg/struct/wo_prof_double_malloc.c
++++ b/gcc/testsuite/gcc.dg/struct/wo_prof_double_malloc.c
+@@ -26,4 +26,4 @@ int main()
+ }
+ 
+ /*--------------------------------------------------------------------------*/
+-/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "struct_reorg" { xfail *-*-* } } } */
++/* { dg-final { scan-ipa-dump "Number of structures to transform in struct split 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
+index ee9b0d765..0685cf8fe 100644
+--- a/gcc/testsuite/gcc.dg/struct/wo_prof_empty_str.c
++++ b/gcc/testsuite/gcc.dg/struct/wo_prof_empty_str.c
+@@ -41,4 +41,4 @@ main ()
+ }
+ 
+ /*--------------------------------------------------------------------------*/
+-/* { dg-final { scan-ipa-dump "No structures to transform" "struct_reorg" } } */
++/* { dg-final { scan-ipa-dump "No structures to transform in struct split" "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
+index 9ebb2b4cc..1a0a5a9c6 100644
+--- 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
+@@ -40,5 +40,5 @@ main ()
+ }
+ 
+ /*--------------------------------------------------------------------------*/
+-/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "struct_reorg"   } } */
++/* { dg-final { scan-ipa-dump "Number of structures to transform in struct split is 1" "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
+index 60d2466e1..9533538c4 100644
+--- a/gcc/testsuite/gcc.dg/struct/wo_prof_escape_substr_array.c
++++ b/gcc/testsuite/gcc.dg/struct/wo_prof_escape_substr_array.c
+@@ -30,4 +30,4 @@ main ()
+ }
+ 
+ /*--------------------------------------------------------------------------*/
+-/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "struct_reorg"  { xfail *-*-* } } } */
++/* { dg-final { scan-ipa-dump "Number of structures to transform in struct split is 1" "struct_reorg"  { xfail *-*-* } } } */
+diff --git a/gcc/testsuite/gcc.dg/struct/wo_prof_global_array.c b/gcc/testsuite/gcc.dg/struct/wo_prof_global_array.c
+index 1c5a3aa15..100a93868 100644
+--- a/gcc/testsuite/gcc.dg/struct/wo_prof_global_array.c
++++ b/gcc/testsuite/gcc.dg/struct/wo_prof_global_array.c
+@@ -29,4 +29,4 @@ main ()
+ }
+ 
+ /*--------------------------------------------------------------------------*/
+-/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "struct_reorg" { xfail *-*-* } } } */
++/* { dg-final { scan-ipa-dump "Number of structures to transform in struct split 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
+index a0d1467fe..669d0b886 100644
+--- a/gcc/testsuite/gcc.dg/struct/wo_prof_global_var.c
++++ b/gcc/testsuite/gcc.dg/struct/wo_prof_global_var.c
+@@ -42,4 +42,4 @@ main ()
+ }
+ 
+ /*--------------------------------------------------------------------------*/
+-/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "struct_reorg" } } */
++/* { dg-final { scan-ipa-dump "Number of structures to transform in struct split 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
+index 6c24e1c8b..ce6c1544c 100644
+--- a/gcc/testsuite/gcc.dg/struct/wo_prof_local_array.c
++++ b/gcc/testsuite/gcc.dg/struct/wo_prof_local_array.c
+@@ -37,4 +37,4 @@ main ()
+ }
+ 
+ /*--------------------------------------------------------------------------*/
+-/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "struct_reorg" { xfail *-*-* } } } */
++/* { dg-final { scan-ipa-dump "Number of structures to transform in struct split 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
+index 8f2f8143f..eca2ebf32 100644
+--- a/gcc/testsuite/gcc.dg/struct/wo_prof_local_var.c
++++ b/gcc/testsuite/gcc.dg/struct/wo_prof_local_var.c
+@@ -40,4 +40,4 @@ main ()
+ }
+ 
+ /*--------------------------------------------------------------------------*/
+-/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "struct_reorg" } } */
++/* { dg-final { scan-ipa-dump "Number of structures to transform in struct split 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
+index 98bf01a6d..6f8f94d7d 100644
+--- 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
+@@ -44,4 +44,4 @@ main ()
+ }
+ 
+ /*--------------------------------------------------------------------------*/
+-/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "struct_reorg" } } */
++/* { dg-final { scan-ipa-dump "Number of structures to transform in struct split 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
+index 66b0f967c..2ca729d1f 100644
+--- a/gcc/testsuite/gcc.dg/struct/wo_prof_malloc_size_var.c
++++ b/gcc/testsuite/gcc.dg/struct/wo_prof_malloc_size_var.c
+@@ -44,4 +44,4 @@ main ()
+ }
+ 
+ /*--------------------------------------------------------------------------*/
+-/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "struct_reorg" } } */
++/* { dg-final { scan-ipa-dump "Number of structures to transform in struct split 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
+index d28bcfb02..6000b2919 100644
+--- a/gcc/testsuite/gcc.dg/struct/wo_prof_mult_field_peeling.c
++++ b/gcc/testsuite/gcc.dg/struct/wo_prof_mult_field_peeling.c
+@@ -39,4 +39,4 @@ main ()
+ 
+ /*--------------------------------------------------------------------------*/
+ /* Two more fields structure is not splitted.  */
+-/* { dg-final { scan-ipa-dump "No structures to transform." "struct_reorg" } } */
++/* { dg-final { scan-ipa-dump "No structures to transform in struct split." "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
+index 37a6a43a8..f4a103409 100644
+--- a/gcc/testsuite/gcc.dg/struct/wo_prof_single_str_global.c
++++ b/gcc/testsuite/gcc.dg/struct/wo_prof_single_str_global.c
+@@ -31,4 +31,4 @@ main ()
+ }
+ 
+ /*--------------------------------------------------------------------------*/
+-/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "struct_reorg" } } */
++/* { dg-final { scan-ipa-dump "Number of structures to transform in struct split is 1" "struct_reorg" } } */
+diff --git a/gcc/testsuite/gcc.dg/struct/wo_prof_single_str_local.c b/gcc/testsuite/gcc.dg/struct/wo_prof_single_str_local.c
+index ca9a8efcf..0c97173eb 100644
+--- a/gcc/testsuite/gcc.dg/struct/wo_prof_single_str_local.c
++++ b/gcc/testsuite/gcc.dg/struct/wo_prof_single_str_local.c
+@@ -31,4 +31,4 @@ main ()
+ }
+ 
+ /*--------------------------------------------------------------------------*/
+-/* { dg-final { scan-ipa-dump "No structures to transform" "struct_reorg" } } */
++/* { dg-final { scan-ipa-dump "No structures to transform in struct split" "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
+index cba92e995..bc8eacc77 100644
+--- a/gcc/testsuite/gcc.dg/struct/wo_prof_two_strs.c
++++ b/gcc/testsuite/gcc.dg/struct/wo_prof_two_strs.c
+@@ -64,4 +64,4 @@ main ()
+ }
+ 
+ /*--------------------------------------------------------------------------*/
+-/* { dg-final { scan-ipa-dump "Number of structures to transform is 2" "struct_reorg" } } */
++/* { dg-final { scan-ipa-dump "Number of structures to transform in struct split is 2" "struct_reorg" } } */
+diff --git a/gcc/timevar.def b/gcc/timevar.def
+index e9866ebf0..2814b14f2 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_STRUCT_LAYOUT	     , "ipa struct layout optimization")
+ DEFTIMEVAR (TV_IPA_STRUCT_REORG	     , "ipa struct reorg optimization")
+ DEFTIMEVAR (TV_IPA_EXTEND_AUTO_PROFILE, "ipa extend auto profile")
+ DEFTIMEVAR (TV_IPA_OPT		     , "ipa various optimizations")
+diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
+index 09dd9b289..2b4864b89 100644
+--- a/gcc/tree-pass.h
++++ b/gcc/tree-pass.h
+@@ -510,7 +510,6 @@ 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_hsa (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_layout (gcc::context *ctxt);
+ extern simple_ipa_opt_pass *make_pass_ipa_struct_reorg (gcc::context *ctxt);
+ extern simple_ipa_opt_pass *make_pass_ipa_extend_auto_profile (gcc::context
+ 							       *ctxt);
+diff --git a/gcc/tree.c b/gcc/tree.c
+index 84a440b35..8bbd54e0d 100644
+--- a/gcc/tree.c
++++ b/gcc/tree.c
+@@ -5222,7 +5222,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_layout || flag_ipa_struct_reorg)
++  if (flag_ipa_struct_reorg
+       && lang_c_p ()
+       && flag_lto_partition == LTO_PARTITION_ONE
+       && (in_lto_p || flag_whole_program))
+@@ -5469,7 +5469,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_layout || flag_ipa_struct_reorg)
++  if (flag_ipa_struct_reorg
+       && lang_c_p ()
+       && flag_lto_partition == LTO_PARTITION_ONE
+       && (in_lto_p || flag_whole_program))
+-- 
+2.27.0.windows.1
+
diff --git a/0073-PHIOPT-Add-A-B-op-CST-B-match-and-simplify-optimizat.patch b/0073-PHIOPT-Add-A-B-op-CST-B-match-and-simplify-optimizat.patch
new file mode 100644
index 0000000..8057532
--- /dev/null
+++ b/0073-PHIOPT-Add-A-B-op-CST-B-match-and-simplify-optimizat.patch
@@ -0,0 +1,89 @@
+From 9af03694082c462bee86c167c78717089a93a188 Mon Sep 17 00:00:00 2001
+From: zhongyunde 
+Date: Sat, 5 Nov 2022 13:22:33 +0800
+Subject: [PATCH 25/35] [PHIOPT] 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 fc1a34dd3..5c5b5f89e 100644
+--- a/gcc/match.pd
++++ b/gcc/match.pd
+@@ -3383,6 +3383,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 26/35] [FORWPROP] 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.c                             |  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 ad147f7a9..6a7f66624 100644
+--- a/gcc/common.opt
++++ b/gcc/common.opt
+@@ -2069,6 +2069,10 @@ fmerge-debug-strings
+ Common Report Var(flag_merge_debug_strings) Init(1)
+ Attempt to merge identical debug strings across compilation units.
+ 
++fmerge-mull
++Common Report 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 5c5b5f89e..f6c5befd7 100644
+--- a/gcc/match.pd
++++ b/gcc/match.pd
+@@ -3404,6 +3404,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.c b/gcc/opts.c
+index f12b13599..751965e46 100644
+--- a/gcc/opts.c
++++ b/gcc/opts.c
+@@ -511,6 +511,7 @@ static const struct default_options default_options_table[] =
+     { OPT_LEVELS_2_PLUS, OPT_fvect_cost_model_, NULL, VECT_COST_MODEL_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 27/35] [FORWPROP] 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 f6c5befd7..433682afb 100644
+--- a/gcc/match.pd
++++ b/gcc/match.pd
+@@ -3404,6 +3404,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.27.0.windows.1
+
diff --git a/0076-Struct-Reorg-Fix-speccpu2006-462-double-free-I60YUV.patch b/0076-Struct-Reorg-Fix-speccpu2006-462-double-free-I60YUV.patch
new file mode 100644
index 0000000..88613ba
--- /dev/null
+++ b/0076-Struct-Reorg-Fix-speccpu2006-462-double-free-I60YUV.patch
@@ -0,0 +1,38 @@
+From b669b4512e8425f4d752ef76bf61097cf40d9b35 Mon Sep 17 00:00:00 2001
+From: zgat <1071107108@qq.com>
+Date: Thu, 17 Nov 2022 02:55:48 +0000
+Subject: [PATCH 28/35] [Struct Reorg] Fix speccpu2006 462 double free #I60YUV
+ modify gcc/tree.c. Normal operation speccpu 462 after modifed
+
+Signed-off-by: zgat <1071107108@qq.com>
+---
+ gcc/tree.c | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+diff --git a/gcc/tree.c b/gcc/tree.c
+index 2a532d15a..a61788651 100644
+--- a/gcc/tree.c
++++ b/gcc/tree.c
+@@ -5224,8 +5224,7 @@ fld_simplified_type_name (tree type)
+      optimizations.  */
+   if (flag_ipa_struct_reorg
+       && lang_c_p ()
+-      && flag_lto_partition == LTO_PARTITION_ONE
+-      && (in_lto_p || flag_whole_program))
++      && flag_lto_partition == LTO_PARTITION_ONE)
+     return TYPE_NAME (type);
+ 
+   if (!TYPE_NAME (type) || TREE_CODE (TYPE_NAME (type)) != TYPE_DECL)
+@@ -5471,8 +5470,7 @@ fld_simplified_type (tree t, class free_lang_data_d *fld)
+      optimizations.  */
+   if (flag_ipa_struct_reorg
+       && lang_c_p ()
+-      && flag_lto_partition == LTO_PARTITION_ONE
+-      && (in_lto_p || flag_whole_program))
++      && flag_lto_partition == LTO_PARTITION_ONE)
+     return t;
+   if (POINTER_TYPE_P (t))
+     return fld_incomplete_type_of (t, fld);
+-- 
+2.27.0.windows.1
+
diff --git a/0077-Struct-Reorg-Add-Safe-Structure-Pointer-Compression.patch b/0077-Struct-Reorg-Add-Safe-Structure-Pointer-Compression.patch
new file mode 100644
index 0000000..c804ea6
--- /dev/null
+++ b/0077-Struct-Reorg-Add-Safe-Structure-Pointer-Compression.patch
@@ -0,0 +1,1193 @@
+From 0445301c09926a20d5e02809b2cd35bddc9fa50e Mon Sep 17 00:00:00 2001
+From: liyancheng <412998149@qq.com>
+Date: Wed, 9 Nov 2022 21:00:04 +0800
+Subject: [PATCH 29/35] [Struct Reorg] Add Safe Structure Pointer Compression
+
+Safe structure pointer compression allows safely compressing pointers
+stored in structure to reduce the size of structure.
+Add flag -fipa-struct-reorg=4 to enable safe structure pointer compression.
+---
+ gcc/common.opt                          |   5 +-
+ gcc/ipa-struct-reorg/ipa-struct-reorg.c | 905 +++++++++++++++++++++++-
+ gcc/ipa-struct-reorg/ipa-struct-reorg.h |   4 +
+ gcc/params.opt                          |   4 +
+ 4 files changed, 877 insertions(+), 41 deletions(-)
+
+diff --git a/gcc/common.opt b/gcc/common.opt
+index 6a7f66624..c9b099817 100644
+--- a/gcc/common.opt
++++ b/gcc/common.opt
+@@ -1889,8 +1889,9 @@ Common Report 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-extend-auto-profile
+ Common Report Var(flag_ipa_extend_auto_profile)
+diff --git a/gcc/ipa-struct-reorg/ipa-struct-reorg.c b/gcc/ipa-struct-reorg/ipa-struct-reorg.c
+index 08cb51fee..3550411dc 100644
+--- a/gcc/ipa-struct-reorg/ipa-struct-reorg.c
++++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.c
+@@ -83,6 +83,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"
+@@ -145,7 +146,27 @@ namespace {
+ using namespace struct_reorg;
+ using namespace struct_relayout;
+ 
+-/* 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;
++  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)
+@@ -242,9 +263,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);
+ bool isptrptr (tree type);
+ void get_base (tree &base, tree expr);
+@@ -366,7 +393,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++)
+@@ -447,6 +477,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
+@@ -790,20 +845,31 @@ srfield::create_new_optimized_fields (tree newtype[max_split],
+       fields.safe_push (field);
+     }
+ 
+-  DECL_NAME (field) = DECL_NAME (fielddecl);
+   if (type == NULL)
+     {
++      DECL_NAME (field) = DECL_NAME (fielddecl);
+       /* Common members do not need to reconstruct.
+ 	 Otherwise, int* -> int** or void* -> void**.  */
+       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);
++      DECL_NAME (field) = DECL_NAME (fielddecl);
++      TREE_TYPE (field) = reconstruct_complex_type (TREE_TYPE (fielddecl), nt);
++      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);
+@@ -923,6 +989,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);
+@@ -1341,6 +1411,30 @@ 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);
++
++  // 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
+@@ -1391,29 +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)
+@@ -3135,6 +3206,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;
+@@ -3603,14 +3687,15 @@ 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)
+@@ -3737,15 +3822,20 @@ ipa_struct_reorg::maybe_mark_or_record_other_side (tree side, tree other, gimple
+ 	}
+     }
+   /* 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);
+@@ -4361,7 +4451,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);
+@@ -4388,6 +4478,22 @@ ipa_struct_reorg::check_alloc_num (gimple *stmt, srtype *type)
+ 				  ? 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;
++	}
+     }
+ }
+ 
+@@ -4530,7 +4636,11 @@ ipa_struct_reorg::check_definition (srdecl *decl, vec &worklist)
+       && 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);
+ 
+@@ -5509,6 +5619,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++)
+@@ -5519,9 +5631,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]);
++		    }
+ 		}
+ 	    }
+ 	}
+@@ -5906,6 +6027,556 @@ ipa_struct_reorg::rewrite_expr (tree expr, tree newexpr[max_split], bool ignore_
+   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);
++
++  gimple* cur_stmt = as_a  (cond);
++  edge e = split_block (cur_stmt->bb, cur_stmt);
++  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.  */
++  gimple* cur_stmt = as_a  (cond);
++  edge e = split_block (cur_stmt->bb, cur_stmt);
++  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)
+ {
+@@ -6109,6 +6780,9 @@ ipa_struct_reorg::rewrite_assign (gassign *stmt, gimple_stmt_iterator *gsi)
+ 	fprintf (dump_file, "replaced 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))
+ 	    {
+@@ -6183,6 +6857,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;
+     }
+@@ -6649,6 +7330,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",
+@@ -6724,6 +7411,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",
+@@ -6758,6 +7448,10 @@ ipa_struct_reorg::execute_struct_relayout (void)
+ 	{
+ 	  continue;
+ 	}
++      if (get_type_name (types[i]->type) == NULL)
++	{
++	  continue;
++	}
+       retval |= ipa_struct_relayout (type, this).execute ();
+     }
+ 
+@@ -6778,6 +7472,132 @@ 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 pointer-compression-size=[8,16,32]\"");
++    }
++}
++
+ unsigned int
+ ipa_struct_reorg::execute (unsigned int opt)
+ {
+@@ -6798,6 +7618,8 @@ ipa_struct_reorg::execute (unsigned int opt)
+ 	{
+ 	  analyze_types ();
+ 	}
++      if (opt >= POINTER_COMPRESSION_SAFE)
++	check_and_prune_struct_for_pointer_compression ();
+ 
+       ret = rewrite_functions ();
+     }
+@@ -6850,6 +7672,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;
+@@ -6862,6 +7686,9 @@ public:
+ 	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 936c0fa6f..d88799982 100644
+--- a/gcc/ipa-struct-reorg/ipa-struct-reorg.h
++++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.h
+@@ -122,7 +122,10 @@ private:
+ public:
+ 
+   tree newtype[max_split];
++  tree pc_gptr;
+   bool visited;
++  bool pc_candidate;
++  bool has_legal_alloc_num;
+   int has_alloc_array;
+ 
+   // Constructors
+@@ -144,6 +147,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 9d1faa7ab..1d355819c 100644
+--- a/gcc/params.opt
++++ b/gcc/params.opt
+@@ -984,4 +984,8 @@ High execution rate loops to be analyzed in prefetch (in%).
+ Common Joined UInteger Var(param_prefetch_func_counts_threshold) Init(100) Param Optimization
+ Threshold functions of cache miss counts to be analyzed in prefetching.
+ 
++-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.27.0.windows.1
+
diff --git a/0078-Loop-distribution-Add-isomorphic-stmts-analysis.patch b/0078-Loop-distribution-Add-isomorphic-stmts-analysis.patch
new file mode 100644
index 0000000..baeff90
--- /dev/null
+++ b/0078-Loop-distribution-Add-isomorphic-stmts-analysis.patch
@@ -0,0 +1,1007 @@
+From d334ec1579fb0668da5e23ced3b782d7f6f35d77 Mon Sep 17 00:00:00 2001
+From: benniaobufeijiushiji 
+Date: Mon, 17 Oct 2022 17:21:57 +0800
+Subject: [PATCH 30/35] [Loop-distribution] Add isomorphic stmts analysis
+
+Use option -ftree-slp-transpose-vectorize
+
+Check if loop is vectorizable before analysis.  For unvectorizable
+loops, try to find isomorphic stmts from grouped load as new seed stmts
+for distribution.
+---
+ gcc/tree-loop-distribution.c | 858 +++++++++++++++++++++++++++++++++++
+ gcc/tree-vect-loop.c         |  37 +-
+ gcc/tree-vectorizer.h        |   3 +-
+ 3 files changed, 894 insertions(+), 4 deletions(-)
+
+diff --git a/gcc/tree-loop-distribution.c b/gcc/tree-loop-distribution.c
+index 888af4894..c08af6562 100644
+--- a/gcc/tree-loop-distribution.c
++++ b/gcc/tree-loop-distribution.c
+@@ -90,6 +90,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 +117,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"
+ 
+ 
+ #define MAX_DATAREFS_NUM \
+@@ -183,6 +186,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
+@@ -640,6 +689,18 @@ class loop_distribution
+   void finalize_partitions (class loop *loop, vec
+ 			    *partitions, vec *alias_ddrs);
+ 
++  /* 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);
+   /* 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
+@@ -2900,6 +2961,803 @@ 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
++      || rdg->n_vertices > param_slp_max_insns_in_bb
++      || 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;
++      while (group_size >= vf)
++	{
++	  vec_alloc (worklist, vf);
++	  for (unsigned j = 0; j < vf; ++j)
++	    {
++	      ginfo = new _group_info ();
++	      ginfo->stmt = c_stmt_info->stmt;
++	      worklist->safe_push (ginfo);
++	      c_stmt_info = c_stmt_info->next_element;
++	    }
++	  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;
++    }
++}
++
++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);
++}
++
+ /* 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
+diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c
+index 7990e31de..1e332d3c5 100644
+--- a/gcc/tree-vect-loop.c
++++ b/gcc/tree-vect-loop.c
+@@ -2516,9 +2516,11 @@ vect_reanalyze_as_main_loop (loop_vec_info loop_vinfo, unsigned int *n_stmts)
+ 
+    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)
+ {
+   auto_vector_modes vector_modes;
+ 
+@@ -2545,6 +2547,8 @@ vect_analyze_loop (class loop *loop, vec_info_shared *shared)
+   unsigned n_stmts = 0;
+   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);
+   machine_mode next_vector_mode = VOIDmode;
+   poly_uint64 lowest_th = 0;
+   unsigned vectorized_loops = 0;
+@@ -2633,6 +2637,13 @@ vect_analyze_loop (class loop *loop, vec_info_shared *shared)
+       if (res)
+ 	{
+ 	  LOOP_VINFO_VECTORIZABLE_P (loop_vinfo) = 1;
++	  /* In loop-distribution pass, we only need to get loop_vinfo, do not
++	     conduct further operations.  */
++	  if (result_only_p)
++	    {
++	      loop->aux = (loop_vec_info) loop_vinfo;
++	      return loop_vinfo;
++	    }
+ 	  vectorized_loops++;
+ 
+ 	  /* Once we hit the desired simdlen for the first time,
+@@ -2724,7 +2735,19 @@ vect_analyze_loop (class loop *loop, vec_info_shared *shared)
+ 	}
+       else
+ 	{
+-	  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 = loop_vinfo;
++	    }
++	  else
++	    {
++	      delete loop_vinfo;
++	    }
+ 	  if (fatal)
+ 	    {
+ 	      gcc_checking_assert (first_loop_vinfo == NULL);
+@@ -2773,6 +2796,14 @@ vect_analyze_loop (class loop *loop, vec_info_shared *shared)
+       return first_loop_vinfo;
+     }
+ 
++  /* Return loop_vinfo for ldist if loop is unvectorizable.  */
++  if (result_only_p && (mode_i == vector_modes.length ()
++      || autodetected_vector_mode == VOIDmode))
++    {
++      loop->aux = (loop_vec_info) fail_loop_vinfo;
++      return fail_loop_vinfo;
++    }
++
+   return opt_loop_vec_info::propagate_failure (res);
+ }
+ 
+diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
+index 1c4a6c421..dc8175f00 100644
+--- a/gcc/tree-vectorizer.h
++++ b/gcc/tree-vectorizer.h
+@@ -1896,7 +1896,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, tree_code);
+ /* 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);
+-- 
+2.27.0.windows.1
+
diff --git a/0079-loop-vect-Transfer-arrays-using-registers-between-lo.patch b/0079-loop-vect-Transfer-arrays-using-registers-between-lo.patch
new file mode 100644
index 0000000..c004eac
--- /dev/null
+++ b/0079-loop-vect-Transfer-arrays-using-registers-between-lo.patch
@@ -0,0 +1,267 @@
+From 013544d0b477647c8835a8806c75e7b09155b8ed Mon Sep 17 00:00:00 2001
+From: benniaobufeijiushiji 
+Date: Mon, 8 Aug 2022 09:13:53 +0800
+Subject: [PATCH 31/35] [loop-vect] Transfer arrays using registers between
+ loops For vectorized stores in loop, if all succeed loops immediately use the
+ data, transfer data using registers instead of load store to prevent overhead
+ from memory access.
+
+---
+ gcc/testsuite/gcc.dg/vect/vect-perm-1.c |  45 ++++++
+ gcc/tree-vect-stmts.c                   | 181 ++++++++++++++++++++++++
+ 2 files changed, 226 insertions(+)
+ create mode 100644 gcc/testsuite/gcc.dg/vect/vect-perm-1.c
+
+diff --git a/gcc/testsuite/gcc.dg/vect/vect-perm-1.c b/gcc/testsuite/gcc.dg/vect/vect-perm-1.c
+new file mode 100644
+index 000000000..d8b29fbd5
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/vect/vect-perm-1.c
+@@ -0,0 +1,45 @@
++/* { dg-do compile { target { aarch64*-*-linux* } } } */
++/* { dg-options "-O3 -fdump-tree-vect-all-details -save-temps" } */
++
++#include 
++#include 
++
++static unsigned inline abs2 (unsigned a)
++{
++  unsigned s = ((a>>15)&0x10001)*0xffff;
++  return (a+s)^s;
++}
++
++int foo (unsigned *a00, unsigned *a11, unsigned *a22, unsigned *a33)
++{
++  unsigned tmp[4][4];
++  unsigned a0, a1, a2, a3;
++  int sum = 0;
++  for (int i = 0; i < 4; i++)
++    {
++      int t0 = a00[i] + a11[i];
++      int t1 = a00[i] - a11[i];
++      int t2 = a22[i] + a33[i];
++      int t3 = a22[i] - a33[i];
++      tmp[i][0] = t0 + t2;
++      tmp[i][2] = t0 - t2;
++      tmp[i][1] = t1 + t3;
++      tmp[i][3] = t1 - t3;
++    }
++  for (int i = 0; i < 4; i++)
++    {
++      int t0 = tmp[0][i] + tmp[1][i];
++      int t1 = tmp[0][i] - tmp[1][i];
++      int t2 = tmp[2][i] + tmp[3][i];
++      int t3 = tmp[2][i] - tmp[3][i];
++      a0 = t0 + t2;
++      a2 = t0 - t2;
++      a1 = t1 + t3;
++      a3 = t1 - t3;
++      sum += abs2 (a0) + abs2 (a1) + abs2 (a2) + abs2 (a3);
++    }
++  return (((unsigned short) sum) + ((unsigned) sum >>16)) >> 1;
++}
++
++/* { dg-final { scan-tree-dump-times "vectorized 2 loops" 1 "vect" } } */
++/* { dg-final { scan-tree-dump-times "VEC_PERM_EXPR" 16 "vect" } } */
+diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
+index 2c2197022..98b233718 100644
+--- a/gcc/tree-vect-stmts.c
++++ b/gcc/tree-vect-stmts.c
+@@ -2276,6 +2276,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.
+@@ -2434,6 +2601,20 @@ get_group_load_store_type (stmt_vec_info stmt_info, tree vectype, bool slp,
+ 	      *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.
+-- 
+2.27.0.windows.1
+
diff --git a/0080-Struct-Reorg-Add-Unsafe-Structure-Pointer-Compressio.patch b/0080-Struct-Reorg-Add-Unsafe-Structure-Pointer-Compressio.patch
new file mode 100644
index 0000000..ee51cb3
--- /dev/null
+++ b/0080-Struct-Reorg-Add-Unsafe-Structure-Pointer-Compressio.patch
@@ -0,0 +1,1061 @@
+From 7dc6940ba0f463137ff6cf98032d1e98edecde54 Mon Sep 17 00:00:00 2001
+From: liyancheng <412998149@qq.com>
+Date: Fri, 25 Nov 2022 19:36:59 +0800
+Subject: [PATCH 32/35] [Struct Reorg] Add Unsafe Structure Pointer Compression
+
+Unsafe structure pointer compression allows some danger conversions to
+achieve faster performance.
+Add flag -fipa-struct-reorg=5 to enable unsafe structure pointer compression.
+---
+ gcc/common.opt                                |   6 +-
+ gcc/ipa-struct-reorg/ipa-struct-reorg.c       | 309 +++++++++++++++---
+ .../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 +
+ 9 files changed, 757 insertions(+), 52 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 c9b099817..384595f16 100644
+--- a/gcc/common.opt
++++ b/gcc/common.opt
+@@ -1889,9 +1889,9 @@ Common Report 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-extend-auto-profile
+ Common Report Var(flag_ipa_extend_auto_profile)
+diff --git a/gcc/ipa-struct-reorg/ipa-struct-reorg.c b/gcc/ipa-struct-reorg/ipa-struct-reorg.c
+index 3550411dc..ee4893dfb 100644
+--- a/gcc/ipa-struct-reorg/ipa-struct-reorg.c
++++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.c
+@@ -264,7 +264,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,
+@@ -1266,12 +1267,12 @@ 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~80 (first half) are too far away.  */
++     65~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 > 80 && old_size < 128)
++  if (old_size > 70 && old_size < 128)
+     {
+       new_size = 128;
+     }
+@@ -1421,8 +1422,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 &);
+@@ -1996,27 +2001,95 @@ ipa_struct_relayout::maybe_rewrite_cst (tree cst, gimple_stmt_iterator *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 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);
++		      return true;
++		    }
++		}
++	    }
++	  // For pointer compression.
++	  else if (gimple_assign_rhs_code (stmt2) == PLUS_EXPR)
+ 	    {
+-	      tree num = NULL;
+-	      if (is_result_of_mult (cst, &num, TYPE_SIZE_UNIT (ctype.type)))
++	      // 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))
+ 		{
+-		  times = TREE_INT_CST_LOW (num);
+-		  ret = true;
++		  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;
++			    }
++			}
++		    }
++		}
++	    }
++	}
++    }
++  // For pointer compression.
++  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;
++		    }
+ 		}
+ 	    }
+ 	}
+-      gsi_prev (gsi);
+-      return ret;
+     }
+   return false;
+ }
+@@ -3110,7 +3183,9 @@ ipa_struct_reorg::record_var (tree decl, escape_type escapes, int arg)
+ 	  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);
+     }
+ 
+@@ -3793,7 +3868,9 @@ ipa_struct_reorg::maybe_mark_or_record_other_side (tree side, tree other, gimple
+       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;
+     }
+ 
+@@ -3810,7 +3887,9 @@ ipa_struct_reorg::maybe_mark_or_record_other_side (tree side, tree other, gimple
+       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)
+@@ -4550,7 +4629,9 @@ ipa_struct_reorg::check_definition_assign (srdecl *decl, vec &worklist)
+   /* 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;
+     }
+ 
+@@ -4897,7 +4978,9 @@ ipa_struct_reorg::check_use (srdecl *decl, gimple *stmt, vec &worklist)
+   /* 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;
+     }
+ 
+@@ -5566,9 +5649,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_LAYOUT_OPTIMIZE,
+-     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 ();)
+@@ -6052,17 +6135,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;
+@@ -6104,7 +6187,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;
+@@ -6267,6 +6350,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:
+@@ -6368,6 +6494,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);
+ }
+@@ -6430,6 +6559,79 @@ 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_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:
+@@ -6532,7 +6734,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);
+ }
+ 
+@@ -7551,18 +7756,26 @@ 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)
+@@ -7584,14 +7797,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 pointer-compression-size=[8,16,32]\"");
+@@ -7672,6 +7881,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/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 2eebef768..d7367ed96 100644
+--- a/gcc/testsuite/gcc.dg/struct/struct-reorg.exp
++++ b/gcc/testsuite/gcc.dg/struct/struct-reorg.exp
+@@ -85,6 +85,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.27.0.windows.1
+
diff --git a/0081-Loop-distribution-Insert-temp-arrays-built-from-isom.patch b/0081-Loop-distribution-Insert-temp-arrays-built-from-isom.patch
new file mode 100644
index 0000000..2197b2f
--- /dev/null
+++ b/0081-Loop-distribution-Insert-temp-arrays-built-from-isom.patch
@@ -0,0 +1,826 @@
+From ca2a541ed3425bec64f97fe277c6c02bf4f20049 Mon Sep 17 00:00:00 2001
+From: benniaobufeijiushiji 
+Date: Thu, 27 Oct 2022 10:26:34 +0800
+Subject: [PATCH 33/35] [Loop-distribution] Insert temp arrays built from
+ isomorphic stmts Use option -ftree-slp-transpose-vectorize Build temp arrays
+ for isomorphic stmt and regard them as new seed_stmts for loop distribution.
+
+---
+ gcc/testsuite/gcc.dg/tree-ssa/ins-ldist-1.c |  67 +++
+ gcc/testsuite/gcc.dg/tree-ssa/ins-ldist-2.c |  17 +
+ gcc/testsuite/gcc.dg/tree-ssa/ins-ldist-3.c |  19 +
+ gcc/tree-loop-distribution.c                | 577 +++++++++++++++++++-
+ 4 files changed, 663 insertions(+), 17 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/ins-ldist-1.c
+ create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/ins-ldist-2.c
+ create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/ins-ldist-3.c
+
+diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ins-ldist-1.c b/gcc/testsuite/gcc.dg/tree-ssa/ins-ldist-1.c
+new file mode 100644
+index 000000000..649463647
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/tree-ssa/ins-ldist-1.c
+@@ -0,0 +1,67 @@
++/* { dg-do compile { target { aarch64*-*-linux* } } } */
++/* { dg-do run { target { aarch64*-*-linux* } } } */
++/* { dg-options "-O3 -ftree-slp-transpose-vectorize -fdump-tree-ldist-all-details -save-temps" } */
++
++#include 
++#include 
++
++static unsigned inline abs2 (unsigned a)
++{
++  unsigned s = ((a>>15)&0x10001)*0xffff;
++  return (a+s)^s;
++}
++
++int foo (unsigned char *oxa, int ia, unsigned char *oxb, int ib)
++{
++  unsigned tmp[4][4];
++  unsigned a0, a1, a2, a3;
++  int sum = 0;
++  for (int i = 0; i < 4; i++, oxa += ia, oxb += ib)
++    {
++      a0 = (oxa[0] - oxb[0]) + ((oxa[4] - oxb[4]) << 16);
++      a1 = (oxa[1] - oxb[1]) + ((oxa[5] - oxb[5]) << 16);
++      a2 = (oxa[2] - oxb[2]) + ((oxa[6] - oxb[6]) << 16);
++      a3 = (oxa[3] - oxb[3]) + ((oxa[7] - oxb[7]) << 16);
++      int t0 = a0 + a1;
++      int t1 = a0 - a1;
++      int t2 = a2 + a3;
++      int t3 = a2 - a3;
++      tmp[i][0] = t0 + t2;
++      tmp[i][2] = t0 - t2;
++      tmp[i][1] = t1 + t3;
++      tmp[i][3] = t1 - t3;
++    }
++  for (int i = 0; i < 4; i++)
++    {
++      int t0 = tmp[0][i] + tmp[1][i];
++      int t1 = tmp[0][i] - tmp[1][i];
++      int t2 = tmp[2][i] + tmp[3][i];
++      int t3 = tmp[2][i] - tmp[3][i];
++      a0 = t0 + t2;
++      a2 = t0 - t2;
++      a1 = t1 + t3;
++      a3 = t1 - t3;
++      sum += abs2 (a0) + abs2 (a1) + abs2 (a2) + abs2 (a3);
++    }
++  return (((unsigned short) sum) + ((unsigned) sum >>16)) >> 1;
++}
++
++int main ()
++{
++  unsigned char oxa[128] = {0};
++  unsigned char oxb[128] = {0};
++  for (int i = 0; i < 128; i++)
++    {
++      oxa[i] += i * 3;
++      oxb[i] = i * 2;
++    }
++  int sum = foo (oxa, 16, oxb, 32);
++  if (sum != 736)
++    {
++      abort ();
++    }
++  return 0;
++}
++
++/* { dg-final { scan-tree-dump-times "Insertion done: 4 temp arrays inserted" 1 "ldist" } } */
++/* { dg-final { scan-tree-dump-times "distributed: split to 2 loops" 1 "ldist" } } */
+diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ins-ldist-2.c b/gcc/testsuite/gcc.dg/tree-ssa/ins-ldist-2.c
+new file mode 100644
+index 000000000..1b50fd27d
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/tree-ssa/ins-ldist-2.c
+@@ -0,0 +1,17 @@
++/* { dg-do compile { target { aarch64*-*-linux* } } } */
++/* { dg-options "-O3 -ftree-slp-transpose-vectorize -fdump-tree-ldist-all-details" } */
++
++unsigned a0[4], a1[4], a2[4], a3[4];
++
++void foo (unsigned char *oxa, int ia, unsigned char *oxb, int ib)
++{
++  for (int i = 0; i < 4; i++, oxa += ia, oxb += ib)
++    {
++      a0[i] = (oxa[0] - oxb[0]) + ((oxa[4] - oxb[4]) << 16);
++      a1[i] = (oxa[1] - oxb[1]) + ((oxa[5] - oxb[5]) << 16);
++      a2[i] = (oxa[2] - oxb[2]) + ((oxa[6] - oxb[6]) << 16);
++      a3[i] = (oxa[3] - oxb[3]) + ((oxa[7] - oxb[7]) << 16);
++    }
++}
++
++/* { dg-final { scan-tree-dump-times "Loop 1 not distributed." 1 "ldist" } } */
+diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ins-ldist-3.c b/gcc/testsuite/gcc.dg/tree-ssa/ins-ldist-3.c
+new file mode 100644
+index 000000000..94b992b05
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/tree-ssa/ins-ldist-3.c
+@@ -0,0 +1,19 @@
++/* { dg-do compile { target { aarch64*-*-linux* } } } */
++/* { dg-options "-O3 -ftree-slp-transpose-vectorize -fdump-tree-ldist-all-details" } */
++
++unsigned a0[4], a1[4], a2[4], a3[4];
++
++void foo (unsigned char *oxa, int ia, unsigned char *oxb, int ib)
++{
++  for (int i = 0; i < 4; i++, oxa += ia, oxb += ib)
++    {
++      a0[i] = ((oxa[0] - oxb[0]) + ((oxa[4] - oxb[4]) << 16)) + 1;
++      a1[i] = ((oxa[1] - oxb[1]) + ((oxa[5] - oxb[5]) << 16)) - 2;
++      a2[i] = ((oxa[2] - oxb[2]) + ((oxa[6] - oxb[6]) << 16)) * 3;
++      a3[i] = ((oxa[3] - oxb[3]) + ((oxa[7] - oxb[7]) << 16)) / 4;
++    }
++}
++
++/* { dg-final { scan-tree-dump-times "Insertion done: 4 temp arrays inserted" 1 "ldist" } } */
++/* { dg-final { scan-tree-dump-times "Insertion removed" 1 "ldist" } } */
++/* { dg-final { scan-tree-dump-times "Loop 1 not distributed." 1 "ldist" } } */
+\ No newline at end of file
+diff --git a/gcc/tree-loop-distribution.c b/gcc/tree-loop-distribution.c
+index c08af6562..88b56379c 100644
+--- a/gcc/tree-loop-distribution.c
++++ b/gcc/tree-loop-distribution.c
+@@ -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.
+@@ -643,7 +686,8 @@ 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.
+@@ -686,8 +730,9 @@ 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.  */
+@@ -701,6 +746,28 @@ class loop_distribution
+ 
+   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
+@@ -1913,7 +1980,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;
+@@ -1947,7 +2015,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;
+ 	}
+     }
+@@ -2909,13 +2980,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)
+@@ -2947,13 +3052,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.  */
+@@ -3758,6 +3857,404 @@ find_isomorphic_stmts (loop_vec_info vinfo, vec &stmts)
+   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
+@@ -3814,6 +4311,34 @@ loop_distribution::distribute_loop (class loop *loop, vec stmts,
+       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;
++	      stmts = work_list;
++	    }
++	  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;
+@@ -3894,7 +4419,7 @@ loop_distribution::distribute_loop (class loop *loop, vec stmts,
+       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);
+@@ -3944,7 +4469,7 @@ loop_distribution::distribute_loop (class loop *loop, vec stmts,
+ 	}
+     }
+ 
+-  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.  */
+@@ -3962,6 +4487,24 @@ loop_distribution::distribute_loop (class loop *loop, vec stmts,
+     }
+ 
+   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)))
+-- 
+2.27.0.windows.1
+
diff --git a/0082-Revert-Backport-tree-optimization-102880-make-PHI-OP.patch b/0082-Revert-Backport-tree-optimization-102880-make-PHI-OP.patch
new file mode 100644
index 0000000..3642252
--- /dev/null
+++ b/0082-Revert-Backport-tree-optimization-102880-make-PHI-OP.patch
@@ -0,0 +1,206 @@
+From 717782ec36469eb81650b07e8b5536281a59993d Mon Sep 17 00:00:00 2001
+From: zhongyunde 
+Date: Tue, 29 Nov 2022 22:12:29 +0800
+Subject: [PATCH 34/35] Revert "[Backport] tree-optimization/102880 - make
+ PHI-OPT recognize more CFGs"
+
+This reverts commit 77398954ce517aa011b7a254c7aa2858521b2093.
+---
+ gcc/testsuite/gcc.dg/tree-ssa/phi-opt-26.c | 31 ---------
+ gcc/tree-ssa-phiopt.c                      | 73 +++++++++-------------
+ 2 files changed, 29 insertions(+), 75 deletions(-)
+ delete mode 100644 gcc/testsuite/gcc.dg/tree-ssa/phi-opt-26.c
+
+diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-26.c b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-26.c
+deleted file mode 100644
+index 21aa66e38..000000000
+--- a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-26.c
++++ /dev/null
+@@ -1,31 +0,0 @@
+-/* { dg-do compile } */
+-/* { dg-options "-O -fgimple -fdump-tree-phiopt1" } */
+-
+-int __GIMPLE (ssa,startwith("phiopt"))
+-foo (int a, int b, int flag)
+-{
+-  int res;
+-
+-  __BB(2):
+-  if (flag_2(D) != 0)
+-    goto __BB6;
+-  else
+-    goto __BB4;
+-
+-  __BB(4):
+-  if (a_3(D) > b_4(D))
+-    goto __BB7;
+-  else
+-    goto __BB6;
+-
+-  __BB(6):
+-  goto __BB7;
+-
+-  __BB(7):
+-  res_1 = __PHI (__BB4: a_3(D), __BB6: b_4(D));
+-  return res_1;
+-}
+-
+-/* We should be able to detect MAX despite the extra edge into
+-   the middle BB.  */
+-/* { dg-final { scan-tree-dump "MAX" "phiopt1" } } */
+diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c
+index 079d29e74..21ac08145 100644
+--- a/gcc/tree-ssa-phiopt.c
++++ b/gcc/tree-ssa-phiopt.c
+@@ -219,6 +219,7 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads, bool early_p)
+ 
+       /* If either bb1's succ or bb2 or bb2's succ is non NULL.  */
+       if (EDGE_COUNT (bb1->succs) == 0
++          || bb2 == NULL
+ 	  || EDGE_COUNT (bb2->succs) == 0)
+         continue;
+ 
+@@ -278,14 +279,14 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads, bool early_p)
+ 	  || (e1->flags & EDGE_FALLTHRU) == 0)
+         continue;
+ 
++      /* Also make sure that bb1 only have one predecessor and that it
++	 is bb.  */
++      if (!single_pred_p (bb1)
++          || single_pred (bb1) != bb)
++	continue;
++
+       if (do_store_elim)
+ 	{
+-	  /* Also make sure that bb1 only have one predecessor and that it
+-	     is bb.  */
+-	  if (!single_pred_p (bb1)
+-	      || single_pred (bb1) != bb)
+-	    continue;
+-
+ 	  /* bb1 is the middle block, bb2 the join block, bb the split block,
+ 	     e1 the fallthrough edge from bb1 to bb2.  We can't do the
+ 	     optimization if the join block has more than two predecessors.  */
+@@ -330,11 +331,10 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads, bool early_p)
+ 	     node.  */
+ 	  gcc_assert (arg0 != NULL_TREE && arg1 != NULL_TREE);
+ 
+-	  gphi *newphi;
+-	  if (single_pred_p (bb1)
+-	      && (newphi = factor_out_conditional_conversion (e1, e2, phi,
+-							      arg0, arg1,
+-							      cond_stmt)))
++	  gphi *newphi = factor_out_conditional_conversion (e1, e2, phi,
++							    arg0, arg1,
++							    cond_stmt);
++	  if (newphi != NULL)
+ 	    {
+ 	      phi = newphi;
+ 	      /* factor_out_conditional_conversion may create a new PHI in
+@@ -355,14 +355,12 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads, bool early_p)
+ 	  else if (abs_replacement (bb, bb1, e1, e2, phi, arg0, arg1))
+ 	    cfgchanged = true;
+ 	  else if (!early_p
+-		   && single_pred_p (bb1)
+ 		   && cond_removal_in_builtin_zero_pattern (bb, bb1, e1, e2,
+ 							    phi, arg0, arg1))
+ 	    cfgchanged = true;
+ 	  else if (minmax_replacement (bb, bb1, e1, e2, phi, arg0, arg1))
+ 	    cfgchanged = true;
+-	  else if (single_pred_p (bb1)
+-		   && spaceship_replacement (bb, bb1, e1, e2, phi, arg0, arg1))
++	  else if (spaceship_replacement (bb, bb1, e1, e2, phi, arg0, arg1))
+ 	    cfgchanged = true;
+ 	}
+     }
+@@ -393,41 +391,35 @@ replace_phi_edge_with_variable (basic_block cond_block,
+ 				edge e, gphi *phi, tree new_tree)
+ {
+   basic_block bb = gimple_bb (phi);
++  basic_block block_to_remove;
+   gimple_stmt_iterator gsi;
+ 
+   /* Change the PHI argument to new.  */
+   SET_USE (PHI_ARG_DEF_PTR (phi, e->dest_idx), new_tree);
+ 
+   /* Remove the empty basic block.  */
+-  edge edge_to_remove;
+   if (EDGE_SUCC (cond_block, 0)->dest == bb)
+-    edge_to_remove = EDGE_SUCC (cond_block, 1);
+-  else
+-    edge_to_remove = EDGE_SUCC (cond_block, 0);
+-  if (EDGE_COUNT (edge_to_remove->dest->preds) == 1)
+     {
+-      e->flags |= EDGE_FALLTHRU;
+-      e->flags &= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE);
+-      e->probability = profile_probability::always ();
+-      delete_basic_block (edge_to_remove->dest);
+-
+-      /* Eliminate the COND_EXPR at the end of COND_BLOCK.  */
+-      gsi = gsi_last_bb (cond_block);
+-      gsi_remove (&gsi, true);
++      EDGE_SUCC (cond_block, 0)->flags |= EDGE_FALLTHRU;
++      EDGE_SUCC (cond_block, 0)->flags &= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE);
++      EDGE_SUCC (cond_block, 0)->probability = profile_probability::always ();
++
++      block_to_remove = EDGE_SUCC (cond_block, 1)->dest;
+     }
+   else
+     {
+-      /* If there are other edges into the middle block make
+-	 CFG cleanup deal with the edge removal to avoid
+-	 updating dominators here in a non-trivial way.  */
+-      gcond *cond = as_a  (last_stmt (cond_block));
+-      if (edge_to_remove->flags & EDGE_TRUE_VALUE)
+-	gimple_cond_make_false (cond);
+-      else
+-	gimple_cond_make_true (cond);
++      EDGE_SUCC (cond_block, 1)->flags |= EDGE_FALLTHRU;
++      EDGE_SUCC (cond_block, 1)->flags
++	&= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE);
++      EDGE_SUCC (cond_block, 1)->probability = profile_probability::always ();
++
++      block_to_remove = EDGE_SUCC (cond_block, 0)->dest;
+     }
++  delete_basic_block (block_to_remove);
+ 
+-  statistics_counter_event (cfun, "Replace PHI with variable", 1);
++  /* Eliminate the COND_EXPR at the end of COND_BLOCK.  */
++  gsi = gsi_last_bb (cond_block);
++  gsi_remove (&gsi, true);
+ 
+   if (dump_file && (dump_flags & TDF_DETAILS))
+     fprintf (dump_file,
+@@ -854,9 +846,6 @@ match_simplify_replacement (basic_block cond_bb, basic_block middle_bb,
+      allow it and move it once the transformation is done. */
+   if (!empty_block_p (middle_bb))
+     {
+-      if (!single_pred_p (middle_bb))
+-	return false;
+-
+       stmt_to_move = last_and_only_stmt (middle_bb);
+       if (!stmt_to_move)
+ 	return false;
+@@ -1236,11 +1225,6 @@ value_replacement (basic_block cond_bb, basic_block middle_bb,
+ 	}
+       else
+ 	{
+-	  if (!single_pred_p (middle_bb))
+-	    return 0;
+-	  statistics_counter_event (cfun, "Replace PHI with "
+-				    "variable/value_replacement", 1);
+-
+ 	  /* Replace the PHI arguments with arg. */
+ 	  SET_PHI_ARG_DEF (phi, e0->dest_idx, arg);
+ 	  SET_PHI_ARG_DEF (phi, e1->dest_idx, arg);
+@@ -1255,6 +1239,7 @@ value_replacement (basic_block cond_bb, basic_block middle_bb,
+             }
+           return 1;
+ 	}
++
+     }
+ 
+   /* Now optimize (x != 0) ? x + y : y to just x + y.  */
+-- 
+2.27.0.windows.1
+
diff --git a/0083-Struct-reorg-Add-struct-semi-relayout-optimize.patch b/0083-Struct-reorg-Add-struct-semi-relayout-optimize.patch
new file mode 100644
index 0000000..05581a4
--- /dev/null
+++ b/0083-Struct-reorg-Add-struct-semi-relayout-optimize.patch
@@ -0,0 +1,1297 @@
+From cebf7903906d0b530fce240b601591d6254ee53f Mon Sep 17 00:00:00 2001
+From: benniaobufeijiushiji 
+Date: Wed, 30 Nov 2022 22:42:35 +0800
+Subject: [PATCH 35/35] [Struct reorg] Add struct-semi-relayout optimize
+
+Add support for structs with multi-allocation which is escaped in
+complete-relayout.
+Add flag -fipa-struct-reorg=6 and parameter semi-relayout-level.
+---
+ gcc/common.opt                                |   7 +-
+ gcc/ipa-struct-reorg/ipa-struct-reorg.c       | 916 +++++++++++++++++-
+ gcc/ipa-struct-reorg/ipa-struct-reorg.h       |   8 +
+ gcc/params.opt                                |   4 +
+ .../gcc.dg/struct/semi_relayout_rewrite.c     |  86 ++
+ gcc/testsuite/gcc.dg/struct/struct-reorg.exp  |   4 +
+ 6 files changed, 992 insertions(+), 33 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.dg/struct/semi_relayout_rewrite.c
+
+diff --git a/gcc/common.opt b/gcc/common.opt
+index 384595f16..588e19400 100644
+--- a/gcc/common.opt
++++ b/gcc/common.opt
+@@ -1889,9 +1889,10 @@ Common Report 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-extend-auto-profile
+ Common Report Var(flag_ipa_extend_auto_profile)
+diff --git a/gcc/ipa-struct-reorg/ipa-struct-reorg.c b/gcc/ipa-struct-reorg/ipa-struct-reorg.c
+index ee4893dfb..4751711fe 100644
+--- a/gcc/ipa-struct-reorg/ipa-struct-reorg.c
++++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.c
+@@ -265,7 +265,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,
+@@ -280,6 +281,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.  */
+ 
+@@ -398,7 +400,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;
+@@ -883,6 +887,66 @@ srfield::create_new_optimized_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
+@@ -994,6 +1058,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&);
+@@ -1440,6 +1513,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 &);
++  void do_semi_relayout (gimple_stmt_iterator *, gimple *, tree &, tree &);
+ };
+ 
+ struct ipa_struct_relayout
+@@ -4528,7 +4628,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))
+@@ -4536,6 +4636,14 @@ 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.  */
+@@ -4544,6 +4652,10 @@ ipa_struct_reorg::check_alloc_num (gimple *stmt, srtype *type)
+       else if (bb->loop_father != NULL
+ 	       && loop_outer (bb->loop_father) != NULL)
+ 	{
++	  /* 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;
+ 	}
+@@ -4635,6 +4747,13 @@ ipa_struct_reorg::check_definition_assign (srdecl *decl, vec &worklist)
+       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.  */
+@@ -4679,7 +4798,8 @@ ipa_struct_reorg::check_definition_call (srdecl *decl, vec &worklist)
+ 	}
+     }
+ 
+-  check_alloc_num (stmt, type);
++  bool ptrptr = isptrptr (decl->orig_type);
++  check_alloc_num (stmt, type, ptrptr);
+   return;
+ }
+ 
+@@ -6249,6 +6369,53 @@ 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 (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.  */
+ 
+@@ -6782,6 +6949,404 @@ 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);
++  /* addr_high_1 = (intptr_t)ptr1 >> shifts  */
++  tree ptr1_cvt = fold_convert (pointer_type, ptr1);
++  tree addr_high_1 = gimplify_build2 (gsi, RSHIFT_EXPR, pointer_type,
++				      ptr1_cvt, shifts);
++  /* addr_high_2 = (intptr_t)ptr2 >> shifts  */
++  tree ptr2_cvt = fold_convert (pointer_type, ptr2);
++  tree addr_high_2 = gimplify_build2 (gsi, RSHIFT_EXPR, pointer_type,
++				      ptr2_cvt, shifts);
++  /* off1 = (intptr_t)ptr1 - (addr_high_1 << shifts)  */
++  tree bucket_start_1 = gimplify_build2 (gsi, LSHIFT_EXPR, pointer_type,
++					 addr_high_1, shifts);
++  tree off1 = gimplify_build2 (gsi, MINUS_EXPR, long_integer_type_node,
++			       ptr1_cvt, bucket_start_1);
++  /* off2 = (intptr_t)ptr2 - (addr_high_2 << shifts)  */
++  tree bucket_start_2 = gimplify_build2 (gsi, LSHIFT_EXPR, pointer_type,
++					 addr_high_2, shifts);
++  tree off2 = gimplify_build2 (gsi, MINUS_EXPR, long_integer_type_node,
++			       ptr2_cvt, bucket_start_2);
++  /* group_diff = (addr_high_1 - addr_high_2) / bucket_parts  */
++  tree bucket_sub = gimplify_build2 (gsi, MINUS_EXPR, long_integer_type_node,
++				     addr_high_1, addr_high_2);
++  tree bucket_parts = build_int_cst (long_integer_type_node,
++				     type->bucket_parts);
++  tree group_diff = gimplify_build2 (gsi, TRUNC_DIV_EXPR,
++				     long_integer_type_node,
++				     bucket_sub, bucket_parts);
++  /* off_addr_diff = off1 - off2  */
++  tree off_addr_diff = gimplify_build2 (gsi, MINUS_EXPR, long_integer_type_node,
++					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,
++					    long_integer_type_node,
++					    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, long_unsigned_type_node,
++			      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 shifts = build_int_cst (long_unsigned_type_node, semi_relayout_align);
++  gimple_stmt_iterator gsi = gsi_last_bb (new_bb);
++  gsi_insert_after (&gsi, gimple_build_nop (), GSI_NEW_STMT);
++  /* curr_group_start = (ptr >> shifts) << shifts;  */
++  tree ptr_r_1 = gimplify_build2 (&gsi, RSHIFT_EXPR, long_integer_type_node,
++				  ptr, shifts);
++  tree curr_group_start = gimplify_build2 (&gsi, LSHIFT_EXPR, long_integer_type_node,
++					   ptr_r_1, shifts);
++  /* curr_off_from_group = ptr - curr_group_start;  */
++  tree curr_off_from_group = gimplify_build2 (&gsi, MINUS_EXPR,
++					      long_integer_type_node,
++					      ptr, 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 step2 = gimplify_build2 (&gsi, LSHIFT_EXPR, long_integer_type_node,
++				step1, shifts);
++  tree step3 = gimplify_build2 (&gsi, PLUS_EXPR, long_integer_type_node,
++				curr_off_from_group, off_times_8);
++  tree step4 = gimplify_build2 (&gsi, TRUNC_MOD_EXPR, long_integer_type_node,
++				step3, build_int_cst (
++					long_integer_type_node, relayout_part_size));
++  tree step5 = gimplify_build2 (&gsi, PLUS_EXPR, long_integer_type_node,
++				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 (integer_type_node, 8);
++  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, 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);
++
++  gimple *curr_stmt = as_a  (cond);
++  edge e = split_block (curr_stmt->bb, curr_stmt);
++  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,
++				       tree lhs, tree rhs,
++				       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);
++      gimple *new_stmt = gimple_build_assign (new_l_mem_ref, new_r_mem_ref);
++      gsi_insert_before (gsi, new_stmt, GSI_SAME_STMT);
++    }
++  newlhs = new_l_mem_ref;
++  newrhs = new_r_mem_ref;
++}
++
++void
++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);
++    }
++  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);
++    }
++}
++
+ bool
+ ipa_struct_reorg::rewrite_assign (gassign *stmt, gimple_stmt_iterator *gsi)
+ {
+@@ -6876,7 +7441,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 was not a multiplicate and it slipped through.");
+ 
+       /* Add the judgment of num, support for POINTER_DIFF_EXPR.
+@@ -6898,11 +7464,34 @@ 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
+ 	    {
++	      /* 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);
+ 	    }
+@@ -6952,13 +7541,32 @@ 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;
+     }
+ 
+@@ -6985,6 +7593,8 @@ ipa_struct_reorg::rewrite_assign (gassign *stmt, gimple_stmt_iterator *gsi)
+ 	fprintf (dump_file, "replaced with:\n");
+       for (unsigned i = 0; i < max_split && (newlhs[i] || newrhs[i]); i++)
+ 	{
++	  if (current_layout_opt_level & SEMI_RELAYOUT)
++	    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]);
+@@ -7003,6 +7613,108 @@ 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 to_type = build_pointer_type (long_unsigned_type_node);
++  tree type_cast = fold_convert (to_type, ptr);
++  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. */
+ 
+@@ -7044,24 +7756,77 @@ 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.  */
+@@ -7081,8 +7846,11 @@ 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)
+ 	{
++	  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;
+@@ -7789,6 +8557,85 @@ 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
+@@ -7829,7 +8676,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 // do COMPLETE_STRUCT_RELAYOUT
+@@ -7881,6 +8729,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;
+@@ -7900,6 +8750,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 d88799982..982f43e58 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
+ {
+@@ -127,6 +130,10 @@ public:
+   bool pc_candidate;
+   bool has_legal_alloc_num;
+   int has_alloc_array;
++  bool semi_relayout;
++  hash_map new_field_offsets;
++  unsigned bucket_parts;
++  unsigned bucket_size;
+ 
+   // Constructors
+   srtype(tree type);
+@@ -148,6 +155,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 1d355819c..83fd705ee 100644
+--- a/gcc/params.opt
++++ b/gcc/params.opt
+@@ -988,4 +988,8 @@ Threshold functions of cache miss counts to be analyzed in prefetching.
+ 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=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..87c756c79
+--- /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 d7367ed96..281046b48 100644
+--- a/gcc/testsuite/gcc.dg/struct/struct-reorg.exp
++++ b/gcc/testsuite/gcc.dg/struct/struct-reorg.exp
+@@ -93,6 +93,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.27.0.windows.1
+
diff --git a/0084-MULL64-Disable-mull64-transformation-by-default.patch b/0084-MULL64-Disable-mull64-transformation-by-default.patch
new file mode 100644
index 0000000..66668b1
--- /dev/null
+++ b/0084-MULL64-Disable-mull64-transformation-by-default.patch
@@ -0,0 +1,64 @@
+From fb86109ebb10cdb82e1e3ffa37bb7e770fb7c066 Mon Sep 17 00:00:00 2001
+From: eastb233 
+Date: Wed, 7 Dec 2022 09:43:15 +0800
+Subject: [PATCH] [MULL64] Disable mull64 transformation by default
+
+This commit disables mull64 transformation by default since
+it shows some runtime failure in workloads.
+---
+ gcc/match.pd                           | 2 +-
+ gcc/opts.c                             | 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 433682afb..01f81b063 100644
+--- a/gcc/match.pd
++++ b/gcc/match.pd
+@@ -3393,7 +3393,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.c b/gcc/opts.c
+index 751965e46..f12b13599 100644
+--- a/gcc/opts.c
++++ b/gcc/opts.c
+@@ -511,7 +511,6 @@ static const struct default_options default_options_table[] =
+     { OPT_LEVELS_2_PLUS, OPT_fvect_cost_model_, NULL, VECT_COST_MODEL_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.25.1
+
diff --git a/0085-loop-distribution-Bugfix-for-loop-distribution.patch b/0085-loop-distribution-Bugfix-for-loop-distribution.patch
new file mode 100644
index 0000000..37c2a1b
--- /dev/null
+++ b/0085-loop-distribution-Bugfix-for-loop-distribution.patch
@@ -0,0 +1,58 @@
+From d73cd8783ca930724def3e9909fc484ec15404f5 Mon Sep 17 00:00:00 2001
+From: benniaobufeijiushiji 
+Date: Mon, 19 Dec 2022 11:48:12 +0800
+Subject: [PATCH 1/3] [loop-distribution] Bugfix for loop-distribution Add
+ exception in function BUILD_QUEUE when there is a null pointer in
+ grouped_loads.
+
+---
+ gcc/tree-loop-distribution.c | 16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
+
+diff --git a/gcc/tree-loop-distribution.c b/gcc/tree-loop-distribution.c
+index 88b56379c..b68b9c7eb 100644
+--- a/gcc/tree-loop-distribution.c
++++ b/gcc/tree-loop-distribution.c
+@@ -3208,16 +3208,31 @@ build_queue (loop_vec_info vinfo, unsigned vf,
+     {
+       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;
+ 	}
+@@ -3711,6 +3726,7 @@ free_ginfos (vec *> &worklists)
+       unsigned j = 0;
+       FOR_EACH_VEC_ELT (*worklist, j, ginfo)
+ 	delete ginfo;
++      vec_free (worklist);
+     }
+ }
+ 
+-- 
+2.27.0.windows.1
+
diff --git a/0086-semi-relayout-Bugfix-for-struct-semi-relayout.patch b/0086-semi-relayout-Bugfix-for-struct-semi-relayout.patch
new file mode 100644
index 0000000..81d967c
--- /dev/null
+++ b/0086-semi-relayout-Bugfix-for-struct-semi-relayout.patch
@@ -0,0 +1,26 @@
+From b2b710238e13eb2fced77d89cd8dcc86f77b6c6c Mon Sep 17 00:00:00 2001
+From: benniaobufeijiushiji 
+Date: Mon, 19 Dec 2022 15:12:24 +0800
+Subject: [PATCH 2/3] [semi-relayout] Bugfix for struct semi-relayout Bugfix
+ when relayout candidate type is null.
+
+---
+ gcc/ipa-struct-reorg/ipa-struct-reorg.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/gcc/ipa-struct-reorg/ipa-struct-reorg.c b/gcc/ipa-struct-reorg/ipa-struct-reorg.c
+index 4751711fe..2cac340c7 100644
+--- a/gcc/ipa-struct-reorg/ipa-struct-reorg.c
++++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.c
+@@ -6408,6 +6408,8 @@ ipa_struct_reorg::is_semi_relayout_candidate (tree xhs)
+         {
+ 	  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;
+-- 
+2.27.0.windows.1
+
diff --git a/0087-Backport-tree-optimization-97238-fix-typo-causing-IC.patch b/0087-Backport-tree-optimization-97238-fix-typo-causing-IC.patch
new file mode 100644
index 0000000..b47cff9
--- /dev/null
+++ b/0087-Backport-tree-optimization-97238-fix-typo-causing-IC.patch
@@ -0,0 +1,55 @@
+From ae15300352b0fa47a533af852f88e7244c2820cc Mon Sep 17 00:00:00 2001
+From: Richard Biener 
+Date: Tue, 29 Sep 2020 14:38:06 +0200
+Subject: [PATCH 3/3] [Backport] tree-optimization/97238 - fix typo causing ICE
+
+Reference: https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=29aef377d814bd342dd5a306f99e0d614623ce0e
+
+This fixes a typo causing a NULL dereference.
+
+2020-09-29  Richard Biener  
+
+	PR tree-optimization/97238
+	* tree-ssa-reassoc.c (ovce_extract_ops): Fix typo.
+
+	* gcc.dg/pr97238.c: New testcase.
+---
+ gcc/testsuite/gcc.dg/pr97238.c | 12 ++++++++++++
+ gcc/tree-ssa-reassoc.c         |  2 +-
+ 2 files changed, 13 insertions(+), 1 deletion(-)
+ create mode 100644 gcc/testsuite/gcc.dg/pr97238.c
+
+diff --git a/gcc/testsuite/gcc.dg/pr97238.c b/gcc/testsuite/gcc.dg/pr97238.c
+new file mode 100644
+index 000000000..746e93a97
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/pr97238.c
+@@ -0,0 +1,12 @@
++/* { dg-do compile } */
++/* { dg-options "-O -Wno-psabi -w" } */
++
++typedef int __attribute__ ((__vector_size__ (8))) V;
++int b, c, e;
++V d;
++
++V
++foo (void)
++{
++  return (b || e) | c > d | ((b || e) | c > d);
++}
+diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c
+index 5f978ac78..62e7c8dca 100644
+--- a/gcc/tree-ssa-reassoc.c
++++ b/gcc/tree-ssa-reassoc.c
+@@ -3853,7 +3853,7 @@ ovce_extract_ops (tree var, gassign **rets, bool *reti, tree *type,
+     return ERROR_MARK;
+ 
+   gassign *assign = dyn_cast (SSA_NAME_DEF_STMT (cond));
+-  if (stmt == NULL
++  if (assign == NULL
+       || TREE_CODE_CLASS (gimple_assign_rhs_code (assign)) != tcc_comparison)
+     return ERROR_MARK;
+ 
+-- 
+2.27.0.windows.1
+
diff --git a/0088-Backport-fix-typo-causing-ICE.patch b/0088-Backport-fix-typo-causing-ICE.patch
new file mode 100644
index 0000000..fea8ac7
--- /dev/null
+++ b/0088-Backport-fix-typo-causing-ICE.patch
@@ -0,0 +1,25 @@
+From d631be52d401d834261f86113b3a738014540b6c Mon Sep 17 00:00:00 2001
+From: xiongzhou4 
+Date: Fri, 30 Dec 2022 20:15:11 +0800
+Subject: [PATCH] Replace *vcond with vcond as we check for NULL pointer.
+
+---
+ gcc/tree-ssa-reassoc.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c
+index 62e7c8dca..1ad43dba1 100644
+--- a/gcc/tree-ssa-reassoc.c
++++ b/gcc/tree-ssa-reassoc.c
+@@ -3839,7 +3839,7 @@ ovce_extract_ops (tree var, gassign **rets, bool *reti, tree *type,
+   gassign *stmt = dyn_cast  (SSA_NAME_DEF_STMT (var));
+   if (stmt == NULL)
+     return ERROR_MARK;
+-  if (*vcond)
++  if (vcond)
+     *vcond = stmt;
+ 
+   /* ??? If we start creating more COND_EXPR, we could perform
+-- 
+2.33.0
+
diff --git a/0089-State-sysroot-option-as-validated-once-processed.patch b/0089-State-sysroot-option-as-validated-once-processed.patch
new file mode 100644
index 0000000..a3da278
--- /dev/null
+++ b/0089-State-sysroot-option-as-validated-once-processed.patch
@@ -0,0 +1,30 @@
+From a7c23eb36641d605df37f5942d188a764a2480f9 Mon Sep 17 00:00:00 2001
+From: huitailangzju <804544223@qq.com>
+Date: Tue, 14 Feb 2023 10:54:10 +0800
+Subject: [PATCH] State --sysroot option as validated once processed
+
+[Reference] https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=8e86086bd33134467cc9c2a75327d1238dc71df9
+
+Since we now save the option in the "switches" table
+to let specs use it more generally, we need to explicitly
+state that the option was validated else the driver
+will consider it "unrecognized".
+---
+ gcc/gcc.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/gcc/gcc.c b/gcc/gcc.c
+index 655beffcc..efa0b53ce 100644
+--- a/gcc/gcc.c
++++ b/gcc/gcc.c
+@@ -4193,6 +4193,7 @@ driver_handle_option (struct gcc_options *opts,
+       /* Saving this option is useful to let self-specs decide to
+ 	 provide a default one.  */
+       do_save = true;
++      validated = true;
+       break;
+ 
+     case OPT_time_:
+-- 
+2.28.0.windows.1
+
diff --git a/0090-bogus-Wstringop-overflow-with-VLA-of-elements-larger.patch b/0090-bogus-Wstringop-overflow-with-VLA-of-elements-larger.patch
new file mode 100644
index 0000000..fb51808
--- /dev/null
+++ b/0090-bogus-Wstringop-overflow-with-VLA-of-elements-larger.patch
@@ -0,0 +1,129 @@
+From bf537e82d452ee9b79f438df721c2e0dfaae12a0 Mon Sep 17 00:00:00 2001
+From: Xiong Zhou 
+Date: Fri, 5 May 2023 11:57:40 +0800
+Subject: [PATCH 1/2] - bogus -Wstringop-overflow with VLA of elements larger
+ than byte
+
+---
+ gcc/calls.c                                  |  5 ++
+ gcc/testsuite/gcc.dg/Wstringop-overflow-67.c | 92 ++++++++++++++++++++
+ 2 files changed, 97 insertions(+)
+ create mode 100644 gcc/testsuite/gcc.dg/Wstringop-overflow-67.c
+
+diff --git a/gcc/calls.c b/gcc/calls.c
+index 26894342c..45c137cee 100644
+--- a/gcc/calls.c
++++ b/gcc/calls.c
+@@ -2112,6 +2112,11 @@ maybe_warn_rdwr_sizes (rdwr_map *rwm, tree fndecl, tree fntype, tree exp)
+ 	}
+       else
+ 	{
++	  /* If the size cannot be determined clear it to keep it from
++	     being taken as real (and excessive).  */
++	  if (objsize && integer_all_onesp (objsize))
++	    objsize = NULL_TREE;
++
+ 	  /* For read-only and read-write attributes also set the source
+ 	     size.  */
+ 	  srcsize = objsize;
+diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-67.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-67.c
+new file mode 100644
+index 000000000..7b8f3f014
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-67.c
+@@ -0,0 +1,92 @@
++/* PR middle-end/100571 - bogus -Wstringop-overflow with VLA of elements
++   larger than byte
++   { dg-do compile }
++   { dg-options "-O2 -Wall" } */
++
++__attribute__ ((access (read_only, 1, 2))) void fro (int *, int);
++__attribute__ ((access (write_only, 1, 2))) void fwo (int *, int);
++__attribute__ ((access (read_write, 1, 2))) void frw (int *, int);
++
++extern __SIZE_TYPE__ n;
++
++void alloca_ro (void)
++{
++  int *a = __builtin_alloca (n * sizeof *a);
++  a[0] = 0;
++  fro (a, n);
++}
++
++void alloca_wo (void)
++{
++  int *a = __builtin_alloca (n * sizeof *a);
++  fwo (a, n);
++}
++
++void alloca_rw (void)
++{
++  int *a = __builtin_alloca (n * sizeof *a);
++  a[0] = 0;
++  frw (a, n);
++}
++
++
++void calloc_ro (void)
++{
++  int *a = __builtin_calloc (n, sizeof *a);
++  fro (a, n);
++}
++
++void calloc_wo (void)
++{
++  int *a = __builtin_calloc (n, sizeof *a);
++  fwo (a, n);
++}
++
++void calloc_rw (void)
++{
++  int *a = __builtin_calloc (n, sizeof *a);
++  a[0] = 0;
++  frw (a, n);
++}
++
++
++void malloc_ro (void)
++{
++  int *a = __builtin_malloc (n * sizeof *a);
++  a[0] = 0;
++  fro (a, n);
++}
++
++void malloc_wo (void)
++{
++  int *a = __builtin_malloc (n * sizeof *a);
++  fwo (a, n);
++}
++
++void malloc_rw (void)
++{
++  int *a = __builtin_malloc (n * sizeof *a);
++  a[0] = 0;
++  frw (a, n);
++}
++
++
++void vla_ro (void)
++{
++  int a[n];
++  a[0] = 0;
++  fro (a, n);
++}
++
++void vla_wo (void)
++{
++  int a[n];
++  fwo (a, n);
++}
++
++void vla_rw (void)
++{
++  int a[n];
++  a[0] = 0;
++  frw (a, n);
++}
+-- 
+2.33.0
+
diff --git a/0091-phiopt2-Add-option-to-control-the-simplify.patch b/0091-phiopt2-Add-option-to-control-the-simplify.patch
new file mode 100644
index 0000000..b37c1e8
--- /dev/null
+++ b/0091-phiopt2-Add-option-to-control-the-simplify.patch
@@ -0,0 +1,183 @@
+From bc6537191e91c854cc6bee3319290d7a86768957 Mon Sep 17 00:00:00 2001
+From: zhongyunde 
+Date: Wed, 10 May 2023 18:39:47 +0800
+Subject: [PATCH 2/2] [phiopt2] Add option to control the simplify
+
+The phiopt is brought in https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=c4574d23cb07340918793a5a98ae7bb2988b3791
+But may be also has some bug fixed by later commit, so disable it default temporary.
+This optimization is expected to enable after we update the gcc'base to gcc12's release version.
+---
+ gcc/common.opt                             | 4 ++++
+ gcc/testsuite/gcc.dg/tree-ssa/20040514-1.c | 2 +-
+ gcc/testsuite/gcc.dg/tree-ssa/bool-1.c     | 2 +-
+ gcc/testsuite/gcc.dg/tree-ssa/bool-2.c     | 2 +-
+ gcc/testsuite/gcc.dg/tree-ssa/phi-opt-10.c | 2 +-
+ gcc/testsuite/gcc.dg/tree-ssa/phi-opt-22.c | 2 +-
+ gcc/testsuite/gcc.dg/tree-ssa/phi-opt-4.c  | 2 +-
+ gcc/testsuite/gcc.dg/tree-ssa/phi-opt-7.c  | 2 +-
+ gcc/testsuite/gcc.dg/tree-ssa/phi-opt-8.c  | 2 +-
+ gcc/testsuite/gcc.dg/tree-ssa/pr18134.c    | 2 +-
+ gcc/testsuite/gcc.dg/tree-ssa/pr21829.c    | 2 +-
+ gcc/testsuite/gcc.dg/tree-ssa/pr96928-1.c  | 4 ++--
+ gcc/tree-ssa-phiopt.c                      | 3 +++
+ 13 files changed, 19 insertions(+), 12 deletions(-)
+
+diff --git a/gcc/common.opt b/gcc/common.opt
+index be7bfee60..5ad2def18 100644
+--- a/gcc/common.opt
++++ b/gcc/common.opt
+@@ -2781,6 +2781,10 @@ ftree-store-ccp
+ Common Ignore
+ Does nothing.  Preserved for backward compatibility.
+ 
++ftree-fold-phiopt
++Common Report Var(flag_fold_phiopt) Init(0) Optimization
++Attempt to simply the phi node with ssa form.
++
+ ftree-ch
+ Common Report Var(flag_tree_ch) Optimization
+ Enable loop header copying on trees.
+diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20040514-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20040514-1.c
+index 364ce6a69..b04316d55 100644
+--- a/gcc/testsuite/gcc.dg/tree-ssa/20040514-1.c
++++ b/gcc/testsuite/gcc.dg/tree-ssa/20040514-1.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O1 -fdump-tree-phiopt2-details" } */
++/* { dg-options "-O1 -ftree-fold-phiopt -fdump-tree-phiopt2-details" } */
+ 
+ int t( int i)
+ {
+diff --git a/gcc/testsuite/gcc.dg/tree-ssa/bool-1.c b/gcc/testsuite/gcc.dg/tree-ssa/bool-1.c
+index 401357f2f..892654108 100644
+--- a/gcc/testsuite/gcc.dg/tree-ssa/bool-1.c
++++ b/gcc/testsuite/gcc.dg/tree-ssa/bool-1.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O1 -fdump-tree-optimized" } */
++/* { dg-options "-O1 -ftree-fold-phiopt -fdump-tree-optimized" } */
+ 
+ int f(_Bool x)
+ {
+diff --git a/gcc/testsuite/gcc.dg/tree-ssa/bool-2.c b/gcc/testsuite/gcc.dg/tree-ssa/bool-2.c
+index add9cca1e..5ead90f06 100644
+--- a/gcc/testsuite/gcc.dg/tree-ssa/bool-2.c
++++ b/gcc/testsuite/gcc.dg/tree-ssa/bool-2.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O1 -fdump-tree-optimized" } */
++/* { dg-options "-O1 -ftree-fold-phiopt -fdump-tree-optimized" } */
+ 
+ int f(_Bool x)
+ {
+diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-10.c b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-10.c
+index 4c190e6af..7b678fafc 100644
+--- a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-10.c
++++ b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-10.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O1 -fdump-tree-optimized" } */
++/* { dg-options "-O1 -ftree-fold-phiopt -fdump-tree-optimized" } */
+ 
+ int nem1_phi (unsigned long a) { return a ? -1 : 0; }
+ int eqm1_phi (unsigned long a) { return a ? 0 : -1; }
+diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-22.c b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-22.c
+index fd3706666..23b679644 100644
+--- a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-22.c
++++ b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-22.c
+@@ -1,6 +1,6 @@
+ /* PR tree-optimization/97690 */
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -fdump-tree-phiopt2" } */
++/* { dg-options "-O2 -ftree-fold-phiopt -fdump-tree-phiopt2" } */
+ 
+ int foo (_Bool d) { return d ? 2 : 0; }
+ int bar (_Bool d) { return d ? 1 : 0; }
+diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-4.c b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-4.c
+index 3bdb85609..4efd9afc4 100644
+--- a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-4.c
++++ b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-4.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O1 -fdump-tree-optimized" } */
++/* { dg-options "-O1 -ftree-fold-phiopt -fdump-tree-optimized" } */
+ 
+ _Bool t();
+ _Bool t1();
+diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-7.c b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-7.c
+index 18ecbd52a..60dcc6733 100644
+--- a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-7.c
++++ b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-7.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O1 -fdump-tree-optimized" } */
++/* { dg-options "-O1 -ftree-fold-phiopt -fdump-tree-optimized" } */
+ 
+ int g(int,int);
+ int f(int t, int c)
+diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-8.c b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-8.c
+index 98c596b6a..aaa71a317 100644
+--- a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-8.c
++++ b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-8.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O -fdump-tree-optimized -fdump-tree-phiopt2" } */
++/* { dg-options "-O -ftree-fold-phiopt -fdump-tree-optimized -fdump-tree-phiopt2" } */
+ 
+ int g(int,int);
+ int f(int t, int c)
+diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr18134.c b/gcc/testsuite/gcc.dg/tree-ssa/pr18134.c
+index cd40ab2c1..efb1907cf 100644
+--- a/gcc/testsuite/gcc.dg/tree-ssa/pr18134.c
++++ b/gcc/testsuite/gcc.dg/tree-ssa/pr18134.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O1 -fdump-tree-optimized" } */
++/* { dg-options "-O1 -ftree-fold-phiopt -fdump-tree-optimized" } */
+ 
+ int  foo (int a)
+ {
+diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr21829.c b/gcc/testsuite/gcc.dg/tree-ssa/pr21829.c
+index 8f5ae5127..8c8ada905 100644
+--- a/gcc/testsuite/gcc.dg/tree-ssa/pr21829.c
++++ b/gcc/testsuite/gcc.dg/tree-ssa/pr21829.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -fdump-tree-optimized" } */
++/* { dg-options "-O2 -ftree-fold-phiopt -fdump-tree-optimized" } */
+ 
+ int test(int v)
+ {
+diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr96928-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr96928-1.c
+index a2770e5e8..88c13806a 100644
+--- a/gcc/testsuite/gcc.dg/tree-ssa/pr96928-1.c
++++ b/gcc/testsuite/gcc.dg/tree-ssa/pr96928-1.c
+@@ -1,9 +1,9 @@
+ /* PR tree-optimization/96928 */
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -fdump-tree-phiopt2" } */
++/* { dg-options "-O2 -ftree-fold-phiopt -fdump-tree-phiopt2 -fdump-tree-optimized" } */
+ /* { dg-final { scan-tree-dump-times " = a_\[0-9]*\\\(D\\\) >> " 5 "phiopt2" } } */
+ /* { dg-final { scan-tree-dump-times " = ~c_\[0-9]*\\\(D\\\);" 1 "phiopt2" } } */
+-/* { dg-final { scan-tree-dump-times " = ~" 1 "phiopt2" } } */
++/* { dg-final { scan-tree-dump-times " = ~" 1 "optimized" } } */
+ /* { dg-final { scan-tree-dump-times " = \[abc_0-9\\\(\\\)D]* \\\^ " 5 "phiopt2" } } */
+ /* { dg-final { scan-tree-dump-not "a < 0" "phiopt2" } } */
+ 
+diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c
+index 51a2d3684..b7012932f 100644
+--- a/gcc/tree-ssa-phiopt.c
++++ b/gcc/tree-ssa-phiopt.c
+@@ -839,6 +839,9 @@ match_simplify_replacement (basic_block cond_bb, basic_block middle_bb,
+   tree result;
+   gimple *stmt_to_move = NULL;
+ 
++  if (!flag_fold_phiopt)
++    return false;
++
+   /* Special case A ? B : B as this will always simplify to B. */
+   if (operand_equal_for_phi_arg_p (arg0, arg1))
+     return false;
+-- 
+2.33.0
+
diff --git a/0092-gimple-Factor-the-code-to-avoid-depending-auto-featu.patch b/0092-gimple-Factor-the-code-to-avoid-depending-auto-featu.patch
new file mode 100644
index 0000000..c73e472
--- /dev/null
+++ b/0092-gimple-Factor-the-code-to-avoid-depending-auto-featu.patch
@@ -0,0 +1,170 @@
+From 3cddb0b4960e5983404bbebb11e31ffb62e98350 Mon Sep 17 00:00:00 2001
+From: zhongyunde 
+Date: Sat, 13 May 2023 10:04:02 +0800
+Subject: [PATCH 1/5] [gimple] Factor the code to avoid depending auto feature
+
+The lambda function with captrue can't use a function pointer
+to express, so use a class to model.
+---
+ gcc/config/aarch64/aarch64.c |   8 +--
+ gcc/gimple-match-head.c      | 115 ++++++++++++++++++++++++-----------
+ 2 files changed, 85 insertions(+), 38 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
+index 85dbd3898..10e037325 100644
+--- a/gcc/config/aarch64/aarch64.c
++++ b/gcc/config/aarch64/aarch64.c
+@@ -3098,10 +3098,10 @@ aarch64_maxmin_plus_const (rtx_code code, rtx *operands, bool generate_p)
+ 		    == x <= y ? x - y : 0              [z == y]
+ 		    == x < y ? x - y : 0               [z == y]
+ 		    == x < y + 1 ? x - (y + 1) : -1    [z == y + 1].  */
+-  auto maxmin_val = rtx_mode_t (maxmin_op, mode);
+-  auto add_val = rtx_mode_t (add_op, mode);
+-  auto sub_val = wi::neg (add_val);
+-  auto diff = wi::sub (maxmin_val, sub_val);
++  rtx_mode_t maxmin_val = rtx_mode_t (maxmin_op, mode);
++  rtx_mode_t add_val = rtx_mode_t (add_op, mode);
++  wide_int sub_val = wi::neg (add_val);
++  wide_int diff = wi::sub (maxmin_val, sub_val);
+   if (!(diff == 0
+ 	|| (diff == 1 && wi::gt_p (maxmin_val, sub_val, sgn))
+ 	|| (diff == -1 && wi::lt_p (maxmin_val, sub_val, sgn))))
+diff --git a/gcc/gimple-match-head.c b/gcc/gimple-match-head.c
+index c1dea1734..061aef39c 100644
+--- a/gcc/gimple-match-head.c
++++ b/gcc/gimple-match-head.c
+@@ -1023,10 +1023,87 @@ gimple_extract (gimple *stmt, gimple_match_op *res_op,
+ bool
+ gimple_extract_op (gimple *stmt, gimple_match_op *res_op)
+ {
+-  auto nop = [](tree op) { return op; };
++  /* This function is not called by other function now, so leave the
++     lambda to minimize modifiers.  */
++  tree (*nop)(tree) = [](tree op)
++  {
++    return op;
++  };
+   return gimple_extract (stmt, res_op, nop, nop);
+ }
+ 
++/* The std=gnu++98 doesn't support c++ auto feature, and the origin
++   lambda capture some variables, so they can't be replaced with a
++   simple function pointer.  */
++class __lambda_valueize
++{
++  typedef tree (*tree_op_func)(tree);
++
++  public:
++  inline tree operator () (tree op) const
++  {
++    return do_valueize (op, top_valueize, valueized);
++  }
++
++  private:
++  tree_op_func &top_valueize;
++  bool &valueized;
++
++  public:
++  __lambda_valueize (tree_op_func &_top_valueize, bool &_valueized)
++  : top_valueize{_top_valueize}, valueized {_valueized}
++  {}
++};
++
++class __lambda_condition
++{
++  typedef tree (*tree_op_func)(tree);
++
++  public:
++  inline tree operator () (tree op) const
++  {
++    bool cond_valueized = false;
++    tree lhs = do_valueize (TREE_OPERAND (op, 0), top_valueize,
++			    cond_valueized);
++    tree rhs = do_valueize (TREE_OPERAND (op, 1), top_valueize,
++			    cond_valueized);
++    gimple_match_op res_op2 (res_op->cond, TREE_CODE (op),
++			     TREE_TYPE (op), lhs, rhs);
++    if ((gimple_resimplify2 (seq, &res_op2, valueize) || cond_valueized)
++	&& res_op2.code.is_tree_code ())
++      {
++	if (TREE_CODE_CLASS ((tree_code) res_op2.code) == tcc_comparison)
++	  {
++	    valueized = true;
++	    return build2 (res_op2.code, TREE_TYPE (op), res_op2.ops[0],
++			   res_op2.ops[1]);
++	  }
++	else if (res_op2.code == SSA_NAME
++		 || res_op2.code == INTEGER_CST
++		 || res_op2.code == VECTOR_CST)
++	  {
++	    valueized = true;
++	    return res_op2.ops[0];
++	  }
++      }
++    return do_valueize (op, top_valueize, valueized);
++  }
++
++  private:
++  tree_op_func &top_valueize;
++  tree_op_func &valueize;
++  bool &valueized;
++  gimple_match_op *&res_op;
++  gimple_seq *&seq;
++
++  public:
++  __lambda_condition (tree_op_func &_top_valueize, tree_op_func &_valueize,
++      bool &_valueized, gimple_match_op *&_res_op, gimple_seq *&_seq)
++  : top_valueize{_top_valueize}, valueize{_valueize}, valueized {_valueized},
++    res_op {_res_op}, seq {_seq}
++  {}
++};
++
+ /* The main STMT based simplification entry.  It is used by the fold_stmt
+    and the fold_stmt_to_constant APIs.  */
+ 
+@@ -1035,39 +1112,9 @@ gimple_simplify (gimple *stmt, gimple_match_op *res_op, gimple_seq *seq,
+ 		 tree (*valueize)(tree), tree (*top_valueize)(tree))
+ {
+   bool valueized = false;
+-  auto valueize_op = [&](tree op)
+-    {
+-      return do_valueize (op, top_valueize, valueized);
+-    };
+-  auto valueize_condition = [&](tree op) -> tree
+-    {
+-      bool cond_valueized = false;
+-      tree lhs = do_valueize (TREE_OPERAND (op, 0), top_valueize,
+-			      cond_valueized);
+-      tree rhs = do_valueize (TREE_OPERAND (op, 1), top_valueize,
+-			      cond_valueized);
+-      gimple_match_op res_op2 (res_op->cond, TREE_CODE (op),
+-			       TREE_TYPE (op), lhs, rhs);
+-      if ((gimple_resimplify2 (seq, &res_op2, valueize)
+-	   || cond_valueized)
+-	  && res_op2.code.is_tree_code ())
+-	{
+-	  if (TREE_CODE_CLASS ((tree_code) res_op2.code) == tcc_comparison)
+-	    {
+-	      valueized = true;
+-	      return build2 (res_op2.code, TREE_TYPE (op),
+-			     res_op2.ops[0], res_op2.ops[1]);
+-	    }
+-	  else if (res_op2.code == SSA_NAME
+-		   || res_op2.code == INTEGER_CST
+-		   || res_op2.code == VECTOR_CST)
+-	    {
+-	      valueized = true;
+-	      return res_op2.ops[0];
+-	    }
+-	}
+-      return valueize_op (op);
+-    };
++  __lambda_valueize valueize_op = __lambda_valueize{top_valueize, valueized};
++  __lambda_condition valueize_condition = __lambda_condition{top_valueize,
++      valueize, valueized, res_op, seq};
+ 
+   if (!gimple_extract (stmt, res_op, valueize_op, valueize_condition))
+     return false;
+-- 
+2.33.0
+
diff --git a/0093-StructReorg-Fix-escape_cast_another_ptr-check-bug.patch b/0093-StructReorg-Fix-escape_cast_another_ptr-check-bug.patch
new file mode 100644
index 0000000..a007943
--- /dev/null
+++ b/0093-StructReorg-Fix-escape_cast_another_ptr-check-bug.patch
@@ -0,0 +1,112 @@
+From 9527d026dceb1e4f9d9f5c117dacfdfa65ce2735 Mon Sep 17 00:00:00 2001
+From: Mingchuan Wu 
+Date: Tue, 23 May 2023 21:03:58 +0800
+Subject: [PATCH 2/5] [StructReorg] Fix escape_cast_another_ptr check bug
+
+In the other side check, escape mark is added
+when the replacement struct type exists.
+---
+ gcc/ipa-struct-reorg/ipa-struct-reorg.c       | 15 +++---
+ .../struct/wo_prof_escape_replace_type.c      | 49 +++++++++++++++++++
+ 2 files changed, 57 insertions(+), 7 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.dg/struct/wo_prof_escape_replace_type.c
+
+diff --git a/gcc/ipa-struct-reorg/ipa-struct-reorg.c b/gcc/ipa-struct-reorg/ipa-struct-reorg.c
+index 2cac340c7..218140f58 100644
+--- a/gcc/ipa-struct-reorg/ipa-struct-reorg.c
++++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.c
+@@ -688,6 +688,8 @@ srtype::analyze (void)
+       info and/or static heuristics to differentiate splitting process.  */
+   if (fields.length () == 2)
+     {
++      /* 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)
+ 	{
+@@ -4921,7 +4923,9 @@ ipa_struct_reorg::check_other_side (srdecl *decl, tree other, gimple *stmt, vec<
+     }
+ 
+   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 opti, if lhs type is the same
+ 	 as rhs type, we could return without any harm.  */
+@@ -4961,13 +4965,10 @@ ipa_struct_reorg::check_other_side (srdecl *decl, tree other, gimple *stmt, vec<
+ 
+       return;
+     }
+-  if (!is_replace_type (inner_type (t), type->type))
+-    {
+-      if (t1)
+-	t1->mark_escape (escape_cast_another_ptr, stmt);
++  if (t1)
++    t1->mark_escape (escape_cast_another_ptr, stmt);
+ 
+-      type->mark_escape (escape_cast_another_ptr, stmt);
+-    }
++  type->mark_escape (escape_cast_another_ptr, stmt);
+ }
+ 
+ 
+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..d0a7b505e
+--- /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 in struct split." "struct_reorg" } } */
+-- 
+2.33.0
+
diff --git a/0094-Backport-Fix-zero-masking-for-vcvtps2ph-when-dest-op.patch b/0094-Backport-Fix-zero-masking-for-vcvtps2ph-when-dest-op.patch
new file mode 100644
index 0000000..10dc835
--- /dev/null
+++ b/0094-Backport-Fix-zero-masking-for-vcvtps2ph-when-dest-op.patch
@@ -0,0 +1,172 @@
+From 5b473317f6b1890238f1778d0fdebf8ed09292d9 Mon Sep 17 00:00:00 2001
+From: liuhongt 
+Date: Fri, 29 May 2020 13:38:49 +0800
+Subject: [PATCH 3/5] [Backport] Fix zero-masking for vcvtps2ph when dest
+ operand is memory.
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=43088bb4dadd3d14b6b594c5f9363fe879f3d7f7
+
+When dest is memory, zero-masking is not valid, only merging-masking is available,
+
+2020-06-24  Hongtao Liu  
+
+gcc/ChangeLog:
+	PR target/95254
+	* config/i386/sse.md (*vcvtps2ph_store):
+	Refine from *vcvtps2ph_store.
+	(vcvtps2ph256): Refine constraint from vm to v.
+	(avx512f_vcvtps2ph512): Ditto.
+	(*vcvtps2ph256): New define_insn.
+	(*avx512f_vcvtps2ph512): Ditto.
+	* config/i386/subst.md (merge_mask): New define_subst.
+	(merge_mask_name): New define_subst_attr.
+	(merge_mask_operand3): Ditto.
+
+gcc/testsuite/ChangeLog:
+	* gcc.target/i386/avx512f-vcvtps2ph-pr95254.c: New test.
+	* gcc.target/i386/avx512vl-vcvtps2ph-pr95254.c: Ditto.
+---
+ gcc/config/i386/sse.md                        | 32 ++++++++++++++++---
+ gcc/config/i386/subst.md                      | 12 +++++++
+ .../i386/avx512f-vcvtps2ph-pr95254.c          | 12 +++++++
+ .../i386/avx512vl-vcvtps2ph-pr95254.c         | 18 +++++++++++
+ 4 files changed, 70 insertions(+), 4 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.target/i386/avx512f-vcvtps2ph-pr95254.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/avx512vl-vcvtps2ph-pr95254.c
+
+diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md
+index bf01e1d74..915b8e3d2 100644
+--- a/gcc/config/i386/sse.md
++++ b/gcc/config/i386/sse.md
+@@ -21354,19 +21354,19 @@
+    (set_attr "prefix" "maybe_evex")
+    (set_attr "mode" "V4SF")])
+ 
+-(define_insn "*vcvtps2ph_store"
++(define_insn "*vcvtps2ph_store"
+   [(set (match_operand:V4HI 0 "memory_operand" "=m")
+ 	(unspec:V4HI [(match_operand:V4SF 1 "register_operand" "v")
+ 		      (match_operand:SI 2 "const_0_to_255_operand" "N")]
+ 		     UNSPEC_VCVTPS2PH))]
+   "TARGET_F16C || TARGET_AVX512VL"
+-  "vcvtps2ph\t{%2, %1, %0|%0, %1, %2}"
++  "vcvtps2ph\t{%2, %1, %0|%0, %1, %2}"
+   [(set_attr "type" "ssecvt")
+    (set_attr "prefix" "maybe_evex")
+    (set_attr "mode" "V4SF")])
+ 
+ (define_insn "vcvtps2ph256"
+-  [(set (match_operand:V8HI 0 "nonimmediate_operand" "=vm")
++  [(set (match_operand:V8HI 0 "register_operand" "=v")
+ 	(unspec:V8HI [(match_operand:V8SF 1 "register_operand" "v")
+ 		      (match_operand:SI 2 "const_0_to_255_operand" "N")]
+ 		     UNSPEC_VCVTPS2PH))]
+@@ -21377,8 +21377,20 @@
+    (set_attr "btver2_decode" "vector")
+    (set_attr "mode" "V8SF")])
+ 
++(define_insn "*vcvtps2ph256"
++  [(set (match_operand:V8HI 0 "memory_operand" "=m")
++	(unspec:V8HI [(match_operand:V8SF 1 "register_operand" "v")
++		      (match_operand:SI 2 "const_0_to_255_operand" "N")]
++		     UNSPEC_VCVTPS2PH))]
++  "TARGET_F16C || TARGET_AVX512VL"
++  "vcvtps2ph\t{%2, %1, %0|%0, %1, %2}"
++  [(set_attr "type" "ssecvt")
++   (set_attr "prefix" "maybe_evex")
++   (set_attr "btver2_decode" "vector")
++   (set_attr "mode" "V8SF")])
++
+ (define_insn "avx512f_vcvtps2ph512"
+-  [(set (match_operand:V16HI 0 "nonimmediate_operand" "=vm")
++  [(set (match_operand:V16HI 0 "register_operand" "=v")
+ 	(unspec:V16HI
+ 	  [(match_operand:V16SF 1 "register_operand" "v")
+ 	   (match_operand:SI 2 "const_0_to_255_operand" "N")]
+@@ -21389,6 +21401,18 @@
+    (set_attr "prefix" "evex")
+    (set_attr "mode" "V16SF")])
+ 
++(define_insn "*avx512f_vcvtps2ph512"
++  [(set (match_operand:V16HI 0 "memory_operand" "=m")
++	(unspec:V16HI
++	  [(match_operand:V16SF 1 "register_operand" "v")
++	   (match_operand:SI 2 "const_0_to_255_operand" "N")]
++	  UNSPEC_VCVTPS2PH))]
++  "TARGET_AVX512F"
++  "vcvtps2ph\t{%2, %1, %0|%0, %1, %2}"
++  [(set_attr "type" "ssecvt")
++   (set_attr "prefix" "evex")
++   (set_attr "mode" "V16SF")])
++
+ ;; For gather* insn patterns
+ (define_mode_iterator VEC_GATHER_MODE
+ 		      [V2DI V2DF V4DI V4DF V4SI V4SF V8SI V8SF])
+diff --git a/gcc/config/i386/subst.md b/gcc/config/i386/subst.md
+index 4a1c9b080..27eb3430d 100644
+--- a/gcc/config/i386/subst.md
++++ b/gcc/config/i386/subst.md
+@@ -75,6 +75,18 @@
+ 	  (match_operand:SUBST_V 2 "nonimm_or_0_operand" "0C")
+ 	  (match_operand: 3 "register_operand" "Yk")))])
+ 
++(define_subst_attr "merge_mask_name" "merge_mask" "" "_merge_mask")
++(define_subst_attr "merge_mask_operand3" "merge_mask" "" "%{%3%}")
++(define_subst "merge_mask"
++  [(set (match_operand:SUBST_V 0)
++        (match_operand:SUBST_V 1))]
++  "TARGET_AVX512F"
++  [(set (match_dup 0)
++        (vec_merge:SUBST_V
++	  (match_dup 1)
++	  (match_dup 0)
++	  (match_operand: 2 "register_operand" "Yk")))])
++
+ (define_subst_attr "mask_scalar_merge_name" "mask_scalar_merge" "" "_mask")
+ (define_subst_attr "mask_scalar_merge_operand3" "mask_scalar_merge" "" "%{%3%}")
+ (define_subst_attr "mask_scalar_merge_operand4" "mask_scalar_merge" "" "%{%4%}")
+diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vcvtps2ph-pr95254.c b/gcc/testsuite/gcc.target/i386/avx512f-vcvtps2ph-pr95254.c
+new file mode 100644
+index 000000000..9e0da9473
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/avx512f-vcvtps2ph-pr95254.c
+@@ -0,0 +1,12 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -mavx512f" } */
++
++#include
++extern __m256i res;
++void
++foo (__m512 a, __mmask16 m)
++{
++  res = _mm512_maskz_cvtps_ph (m, a, 10);
++}
++
++/* { dg-final { scan-assembler-not "vcvtps2ph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]\[^\n\]*res\[^\n\]*\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)"} } */
+diff --git a/gcc/testsuite/gcc.target/i386/avx512vl-vcvtps2ph-pr95254.c b/gcc/testsuite/gcc.target/i386/avx512vl-vcvtps2ph-pr95254.c
+new file mode 100644
+index 000000000..0c685ea66
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/avx512vl-vcvtps2ph-pr95254.c
+@@ -0,0 +1,18 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -mavx512vl -mavx512f" } */
++
++#include
++extern __m128i res;
++void
++foo (__m256 a, __mmask8 m)
++{
++  res = _mm256_maskz_cvtps_ph (m, a, 10);
++}
++
++void
++foo1 (__m128 a, __mmask8 m)
++{
++  res = _mm_maskz_cvtps_ph (m, a, 10);
++}
++
++/* { dg-final { scan-assembler-not "vcvtps2ph\[ \\t\]+\[^\{\n\]*%\[xy\]mm\[0-9\]\[^\n\]*res\[^\n\]*\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)"} } */
+-- 
+2.33.0
+
diff --git a/0095-Struct-reorg-Fix-the-use-of-as_a.patch b/0095-Struct-reorg-Fix-the-use-of-as_a.patch
new file mode 100644
index 0000000..77a8880
--- /dev/null
+++ b/0095-Struct-reorg-Fix-the-use-of-as_a.patch
@@ -0,0 +1,49 @@
+From 1ab2b199a30db4ec605581a5a23b5c258a127db6 Mon Sep 17 00:00:00 2001
+From: dingguangya 
+Date: Fri, 26 May 2023 09:27:38 +0800
+Subject: [PATCH 4/5] [Struct reorg] Fix the use of as_a
+
+The as_a function is an internal type conversion
+function in gcc, which should be: gimple * ->gcond * when used,
+so fix the problem with function usage at this.
+---
+ gcc/ipa-struct-reorg/ipa-struct-reorg.c | 9 +++------
+ 1 file changed, 3 insertions(+), 6 deletions(-)
+
+diff --git a/gcc/ipa-struct-reorg/ipa-struct-reorg.c b/gcc/ipa-struct-reorg/ipa-struct-reorg.c
+index 2cac340c7..b0e4624b2 100644
+--- a/gcc/ipa-struct-reorg/ipa-struct-reorg.c
++++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.c
+@@ -6607,8 +6607,7 @@ ipa_struct_reorg::compress_candidate_with_check (gimple_stmt_iterator *gsi,
+   gimple_set_location (cond, UNKNOWN_LOCATION);
+   gsi_insert_before (gsi, cond, GSI_SAME_STMT);
+ 
+-  gimple* cur_stmt = as_a  (cond);
+-  edge e = split_block (cur_stmt->bb, cur_stmt);
++  edge e = split_block (cond->bb, cond);
+   basic_block split_src_bb = e->src;
+   basic_block split_dst_bb = e->dest;
+ 
+@@ -6847,8 +6846,7 @@ ipa_struct_reorg::decompress_candidate_with_check (gimple_stmt_iterator *gsi,
+   gsi_insert_before (gsi, cond, GSI_SAME_STMT);
+ 
+   /* Split bb.  */
+-  gimple* cur_stmt = as_a  (cond);
+-  edge e = split_block (cur_stmt->bb, cur_stmt);
++  edge e = split_block (cond->bb, cond);
+   basic_block split_src_bb = e->src;
+   basic_block split_dst_bb = e->dest;
+ 
+@@ -7133,8 +7131,7 @@ ipa_struct_reorg::rewrite_pointer_plus_integer (gimple *stmt,
+   gimple_set_location (cond, UNKNOWN_LOCATION);
+   gsi_insert_before (gsi, cond, GSI_SAME_STMT);
+ 
+-  gimple *curr_stmt = as_a  (cond);
+-  edge e = split_block (curr_stmt->bb, curr_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);
+-- 
+2.33.0
+
diff --git a/0096-libquadmath-Revert-Enable-libquadmath-on-kunpeng.patch b/0096-libquadmath-Revert-Enable-libquadmath-on-kunpeng.patch
new file mode 100644
index 0000000..4811c21
--- /dev/null
+++ b/0096-libquadmath-Revert-Enable-libquadmath-on-kunpeng.patch
@@ -0,0 +1,474 @@
+From 95dc65ad458a6c781536e30e65fdeec42349a0c9 Mon Sep 17 00:00:00 2001
+From: eastb233 
+Date: Wed, 31 May 2023 10:39:56 +0800
+Subject: [PATCH 1/3] [libquadmath] Revert "Enable libquadmath on kunpeng"
+
+This reverts commit 85740d3cc56fda699beae689b5d73233d16097af.
+
+Revert original libquadmath feature to refactor it.
+---
+ libquadmath/Makefile.in | 353 ++++++++++++++++++++--------------------
+ libquadmath/quadmath.h  |   6 +-
+ 2 files changed, 178 insertions(+), 181 deletions(-)
+
+diff --git a/libquadmath/Makefile.in b/libquadmath/Makefile.in
+index 66df9c922..8c0112122 100644
+--- a/libquadmath/Makefile.in
++++ b/libquadmath/Makefile.in
+@@ -90,7 +90,7 @@ POST_UNINSTALL = :
+ build_triplet = @build@
+ host_triplet = @host@
+ target_triplet = @target@
+-#libquadmath_la_DEPENDENCIES =
++@BUILD_LIBQUADMATH_FALSE@libquadmath_la_DEPENDENCIES =
+ subdir = .
+ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+ am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \
+@@ -147,68 +147,68 @@ am__installdirs = "$(DESTDIR)$(toolexeclibdir)" "$(DESTDIR)$(infodir)" \
+ 	"$(DESTDIR)$(libsubincludedir)"
+ LTLIBRARIES = $(toolexeclib_LTLIBRARIES)
+ am__dirstamp = $(am__leading_dot)dirstamp
+-am_libquadmath_la_OBJECTS = math/x2y2m1q.lo \
+-	math/acoshq.lo math/fmodq.lo \
+-	math/acosq.lo math/frexpq.lo \
+-	math/rem_pio2q.lo math/asinhq.lo \
+-	math/hypotq.lo math/remainderq.lo \
+-	math/asinq.lo math/rintq.lo \
+-	math/atan2q.lo math/isinfq.lo \
+-	math/roundq.lo math/atanhq.lo \
+-	math/isnanq.lo math/scalblnq.lo \
+-	math/atanq.lo math/j0q.lo \
+-	math/scalbnq.lo math/cbrtq.lo \
+-	math/j1q.lo math/signbitq.lo \
+-	math/ceilq.lo math/jnq.lo \
+-	math/sincos_table.lo math/complex.lo \
+-	math/ldexpq.lo math/sincosq.lo \
+-	math/copysignq.lo math/lgammaq.lo \
+-	math/sincosq_kernel.lo math/coshq.lo \
+-	math/llroundq.lo math/sinhq.lo \
+-	math/cosq.lo math/log10q.lo \
+-	math/sinq.lo math/cosq_kernel.lo \
+-	math/log1pq.lo math/sinq_kernel.lo \
+-	math/erfq.lo math/logq.lo \
+-	math/sqrtq.lo math/expm1q.lo \
+-	math/lroundq.lo math/tanhq.lo \
+-	math/expq.lo math/modfq.lo \
+-	math/tanq.lo math/fabsq.lo \
+-	math/nanq.lo math/tgammaq.lo \
+-	math/finiteq.lo math/nextafterq.lo \
+-	math/truncq.lo math/floorq.lo \
+-	math/powq.lo math/fmaq.lo \
+-	math/logbq.lo math/exp2q.lo \
+-	math/issignalingq.lo \
+-	math/lgammaq_neg.lo \
+-	math/lgammaq_product.lo \
+-	math/tanq_kernel.lo \
+-	math/tgammaq_product.lo \
+-	math/casinhq_kernel.lo math/cacoshq.lo \
+-	math/cacosq.lo math/casinhq.lo \
+-	math/casinq.lo math/catanhq.lo \
+-	math/catanq.lo math/cimagq.lo \
+-	math/conjq.lo math/cprojq.lo \
+-	math/crealq.lo math/fdimq.lo \
+-	math/fmaxq.lo math/fminq.lo \
+-	math/ilogbq.lo math/llrintq.lo \
+-	math/log2q.lo math/lrintq.lo \
+-	math/nearbyintq.lo math/remquoq.lo \
+-	math/ccoshq.lo math/cexpq.lo \
+-	math/clog10q.lo math/clogq.lo \
+-	math/csinq.lo math/csinhq.lo \
+-	math/csqrtq.lo math/ctanq.lo \
+-	math/ctanhq.lo printf/addmul_1.lo \
+-	printf/add_n.lo printf/cmp.lo \
+-	printf/divrem.lo printf/flt1282mpn.lo \
+-	printf/fpioconst.lo printf/lshift.lo \
+-	printf/mul_1.lo printf/mul_n.lo \
+-	printf/mul.lo printf/printf_fphex.lo \
+-	printf/printf_fp.lo \
+-	printf/quadmath-printf.lo \
+-	printf/rshift.lo printf/submul_1.lo \
+-	printf/sub_n.lo strtod/strtoflt128.lo \
+-	strtod/mpn2flt128.lo \
+-	strtod/tens_in_limb.lo
++@BUILD_LIBQUADMATH_TRUE@am_libquadmath_la_OBJECTS = math/x2y2m1q.lo \
++@BUILD_LIBQUADMATH_TRUE@	math/acoshq.lo math/fmodq.lo \
++@BUILD_LIBQUADMATH_TRUE@	math/acosq.lo math/frexpq.lo \
++@BUILD_LIBQUADMATH_TRUE@	math/rem_pio2q.lo math/asinhq.lo \
++@BUILD_LIBQUADMATH_TRUE@	math/hypotq.lo math/remainderq.lo \
++@BUILD_LIBQUADMATH_TRUE@	math/asinq.lo math/rintq.lo \
++@BUILD_LIBQUADMATH_TRUE@	math/atan2q.lo math/isinfq.lo \
++@BUILD_LIBQUADMATH_TRUE@	math/roundq.lo math/atanhq.lo \
++@BUILD_LIBQUADMATH_TRUE@	math/isnanq.lo math/scalblnq.lo \
++@BUILD_LIBQUADMATH_TRUE@	math/atanq.lo math/j0q.lo \
++@BUILD_LIBQUADMATH_TRUE@	math/scalbnq.lo math/cbrtq.lo \
++@BUILD_LIBQUADMATH_TRUE@	math/j1q.lo math/signbitq.lo \
++@BUILD_LIBQUADMATH_TRUE@	math/ceilq.lo math/jnq.lo \
++@BUILD_LIBQUADMATH_TRUE@	math/sincos_table.lo math/complex.lo \
++@BUILD_LIBQUADMATH_TRUE@	math/ldexpq.lo math/sincosq.lo \
++@BUILD_LIBQUADMATH_TRUE@	math/copysignq.lo math/lgammaq.lo \
++@BUILD_LIBQUADMATH_TRUE@	math/sincosq_kernel.lo math/coshq.lo \
++@BUILD_LIBQUADMATH_TRUE@	math/llroundq.lo math/sinhq.lo \
++@BUILD_LIBQUADMATH_TRUE@	math/cosq.lo math/log10q.lo \
++@BUILD_LIBQUADMATH_TRUE@	math/sinq.lo math/cosq_kernel.lo \
++@BUILD_LIBQUADMATH_TRUE@	math/log1pq.lo math/sinq_kernel.lo \
++@BUILD_LIBQUADMATH_TRUE@	math/erfq.lo math/logq.lo \
++@BUILD_LIBQUADMATH_TRUE@	math/sqrtq.lo math/expm1q.lo \
++@BUILD_LIBQUADMATH_TRUE@	math/lroundq.lo math/tanhq.lo \
++@BUILD_LIBQUADMATH_TRUE@	math/expq.lo math/modfq.lo \
++@BUILD_LIBQUADMATH_TRUE@	math/tanq.lo math/fabsq.lo \
++@BUILD_LIBQUADMATH_TRUE@	math/nanq.lo math/tgammaq.lo \
++@BUILD_LIBQUADMATH_TRUE@	math/finiteq.lo math/nextafterq.lo \
++@BUILD_LIBQUADMATH_TRUE@	math/truncq.lo math/floorq.lo \
++@BUILD_LIBQUADMATH_TRUE@	math/powq.lo math/fmaq.lo \
++@BUILD_LIBQUADMATH_TRUE@	math/logbq.lo math/exp2q.lo \
++@BUILD_LIBQUADMATH_TRUE@	math/issignalingq.lo \
++@BUILD_LIBQUADMATH_TRUE@	math/lgammaq_neg.lo \
++@BUILD_LIBQUADMATH_TRUE@	math/lgammaq_product.lo \
++@BUILD_LIBQUADMATH_TRUE@	math/tanq_kernel.lo \
++@BUILD_LIBQUADMATH_TRUE@	math/tgammaq_product.lo \
++@BUILD_LIBQUADMATH_TRUE@	math/casinhq_kernel.lo math/cacoshq.lo \
++@BUILD_LIBQUADMATH_TRUE@	math/cacosq.lo math/casinhq.lo \
++@BUILD_LIBQUADMATH_TRUE@	math/casinq.lo math/catanhq.lo \
++@BUILD_LIBQUADMATH_TRUE@	math/catanq.lo math/cimagq.lo \
++@BUILD_LIBQUADMATH_TRUE@	math/conjq.lo math/cprojq.lo \
++@BUILD_LIBQUADMATH_TRUE@	math/crealq.lo math/fdimq.lo \
++@BUILD_LIBQUADMATH_TRUE@	math/fmaxq.lo math/fminq.lo \
++@BUILD_LIBQUADMATH_TRUE@	math/ilogbq.lo math/llrintq.lo \
++@BUILD_LIBQUADMATH_TRUE@	math/log2q.lo math/lrintq.lo \
++@BUILD_LIBQUADMATH_TRUE@	math/nearbyintq.lo math/remquoq.lo \
++@BUILD_LIBQUADMATH_TRUE@	math/ccoshq.lo math/cexpq.lo \
++@BUILD_LIBQUADMATH_TRUE@	math/clog10q.lo math/clogq.lo \
++@BUILD_LIBQUADMATH_TRUE@	math/csinq.lo math/csinhq.lo \
++@BUILD_LIBQUADMATH_TRUE@	math/csqrtq.lo math/ctanq.lo \
++@BUILD_LIBQUADMATH_TRUE@	math/ctanhq.lo printf/addmul_1.lo \
++@BUILD_LIBQUADMATH_TRUE@	printf/add_n.lo printf/cmp.lo \
++@BUILD_LIBQUADMATH_TRUE@	printf/divrem.lo printf/flt1282mpn.lo \
++@BUILD_LIBQUADMATH_TRUE@	printf/fpioconst.lo printf/lshift.lo \
++@BUILD_LIBQUADMATH_TRUE@	printf/mul_1.lo printf/mul_n.lo \
++@BUILD_LIBQUADMATH_TRUE@	printf/mul.lo printf/printf_fphex.lo \
++@BUILD_LIBQUADMATH_TRUE@	printf/printf_fp.lo \
++@BUILD_LIBQUADMATH_TRUE@	printf/quadmath-printf.lo \
++@BUILD_LIBQUADMATH_TRUE@	printf/rshift.lo printf/submul_1.lo \
++@BUILD_LIBQUADMATH_TRUE@	printf/sub_n.lo strtod/strtoflt128.lo \
++@BUILD_LIBQUADMATH_TRUE@	strtod/mpn2flt128.lo \
++@BUILD_LIBQUADMATH_TRUE@	strtod/tens_in_limb.lo
+ libquadmath_la_OBJECTS = $(am_libquadmath_la_OBJECTS)
+ AM_V_lt = $(am__v_lt_@AM_V@)
+ am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+@@ -218,8 +218,8 @@ libquadmath_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ 	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ 	$(AM_CFLAGS) $(CFLAGS) $(libquadmath_la_LDFLAGS) $(LDFLAGS) -o \
+ 	$@
+-am_libquadmath_la_rpath = -rpath \
+-	$(toolexeclibdir)
++@BUILD_LIBQUADMATH_TRUE@am_libquadmath_la_rpath = -rpath \
++@BUILD_LIBQUADMATH_TRUE@	$(toolexeclibdir)
+ AM_V_P = $(am__v_P_@AM_V@)
+ am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+ am__v_P_0 = false
+@@ -337,7 +337,7 @@ CFLAGS = @CFLAGS@
+ CPP = @CPP@
+ CPPFLAGS = @CPPFLAGS@
+ CYGPATH_W = @CYGPATH_W@
+-DEFS = @DEFS@ -D__float128="long double"
++DEFS = @DEFS@
+ DEPDIR = @DEPDIR@
+ DSYMUTIL = @DSYMUTIL@
+ DUMPBIN = @DUMPBIN@
+@@ -409,7 +409,7 @@ datadir = @datadir@
+ datarootdir = @datarootdir@
+ docdir = @docdir@
+ dvidir = @dvidir@
+-enable_shared = yes
++enable_shared = @enable_shared@
+ enable_static = @enable_static@
+ exec_prefix = @exec_prefix@
+ get_gcc_base_ver = @get_gcc_base_ver@
+@@ -451,109 +451,109 @@ top_build_prefix = @top_build_prefix@
+ top_builddir = @top_builddir@
+ top_srcdir = @top_srcdir@
+ AUTOMAKE_OPTIONS = foreign info-in-builddir
+-ACLOCAL_AMFLAGS = -I .. -I ../config
+-AM_CPPFLAGS = -I $(top_srcdir)/../include
+-AM_CFLAGS = $(XCFLAGS)
+-gcc_version := $(shell @get_gcc_base_ver@ $(top_srcdir)/../gcc/BASE-VER)
+-@LIBQUAD_USE_SYMVER_FALSE@version_arg = 
+-@LIBQUAD_USE_SYMVER_GNU_TRUE@@LIBQUAD_USE_SYMVER_TRUE@version_arg = -Wl,--version-script=$(srcdir)/quadmath.map
+-@LIBQUAD_USE_SYMVER_SUN_TRUE@@LIBQUAD_USE_SYMVER_TRUE@version_arg = -Wl,-M,quadmath.map-sun
+-@LIBQUAD_USE_SYMVER_FALSE@version_dep = 
+-@LIBQUAD_USE_SYMVER_GNU_TRUE@@LIBQUAD_USE_SYMVER_TRUE@version_dep = $(srcdir)/quadmath.map
+-@LIBQUAD_USE_SYMVER_SUN_TRUE@@LIBQUAD_USE_SYMVER_TRUE@version_dep = quadmath.map-sun
+-toolexeclib_LTLIBRARIES = libquadmath.la
+-libquadmath_la_LIBADD = 
+-libquadmath_la_LDFLAGS = -version-info `grep -v '^\#' $(srcdir)/libtool-version` \
+-			 $(version_arg) $(lt_host_flags) -lm
+-
+-libquadmath_la_DEPENDENCIES = $(version_dep) $(libquadmath_la_LIBADD)
+-nodist_libsubinclude_HEADERS = quadmath.h quadmath_weak.h
+-libsubincludedir = $(libdir)/gcc/$(target_alias)/$(gcc_version)/include
+-libquadmath_la_SOURCES = \
+-  math/x2y2m1q.c math/acoshq.c math/fmodq.c \
+-  math/acosq.c math/frexpq.c \
+-  math/rem_pio2q.c math/asinhq.c math/hypotq.c math/remainderq.c \
+-  math/asinq.c math/rintq.c math/atan2q.c math/isinfq.c \
+-  math/roundq.c math/atanhq.c math/isnanq.c math/scalblnq.c math/atanq.c \
+-  math/j0q.c math/scalbnq.c math/cbrtq.c math/j1q.c math/signbitq.c \
+-  math/ceilq.c math/jnq.c math/sincos_table.c math/complex.c math/ldexpq.c \
+-  math/sincosq.c math/copysignq.c math/lgammaq.c math/sincosq_kernel.c \
+-  math/coshq.c math/llroundq.c math/sinhq.c math/cosq.c math/log10q.c \
+-  math/sinq.c math/cosq_kernel.c math/log1pq.c math/sinq_kernel.c \
+-  math/erfq.c math/logq.c math/sqrtq.c math/expm1q.c math/lroundq.c \
+-  math/tanhq.c math/expq.c math/modfq.c math/tanq.c math/fabsq.c \
+-  math/nanq.c math/tgammaq.c math/finiteq.c math/nextafterq.c \
+-  math/truncq.c math/floorq.c math/powq.c math/fmaq.c math/logbq.c \
+-  math/exp2q.c math/issignalingq.c math/lgammaq_neg.c math/lgammaq_product.c \
+-  math/tanq_kernel.c math/tgammaq_product.c math/casinhq_kernel.c \
+-  math/cacoshq.c math/cacosq.c math/casinhq.c math/casinq.c \
+-  math/catanhq.c math/catanq.c math/cimagq.c math/conjq.c math/cprojq.c \
+-  math/crealq.c math/fdimq.c math/fmaxq.c math/fminq.c math/ilogbq.c \
+-  math/llrintq.c math/log2q.c math/lrintq.c math/nearbyintq.c math/remquoq.c \
+-  math/ccoshq.c math/cexpq.c math/clog10q.c math/clogq.c math/csinq.c \
+-  math/csinhq.c math/csqrtq.c math/ctanq.c math/ctanhq.c \
+-  printf/addmul_1.c printf/add_n.c printf/cmp.c printf/divrem.c \
+-  printf/flt1282mpn.c printf/fpioconst.c printf/lshift.c printf/mul_1.c \
+-  printf/mul_n.c printf/mul.c printf/printf_fphex.c printf/printf_fp.c \
+-  printf/quadmath-printf.c printf/rshift.c printf/submul_1.c printf/sub_n.c \
+-  strtod/strtoflt128.c strtod/mpn2flt128.c strtod/tens_in_limb.c
++@BUILD_LIBQUADMATH_TRUE@ACLOCAL_AMFLAGS = -I .. -I ../config
++@BUILD_LIBQUADMATH_TRUE@AM_CPPFLAGS = -I $(top_srcdir)/../include
++@BUILD_LIBQUADMATH_TRUE@AM_CFLAGS = $(XCFLAGS)
++@BUILD_LIBQUADMATH_TRUE@gcc_version := $(shell @get_gcc_base_ver@ $(top_srcdir)/../gcc/BASE-VER)
++@BUILD_LIBQUADMATH_TRUE@@LIBQUAD_USE_SYMVER_FALSE@version_arg = 
++@BUILD_LIBQUADMATH_TRUE@@LIBQUAD_USE_SYMVER_GNU_TRUE@@LIBQUAD_USE_SYMVER_TRUE@version_arg = -Wl,--version-script=$(srcdir)/quadmath.map
++@BUILD_LIBQUADMATH_TRUE@@LIBQUAD_USE_SYMVER_SUN_TRUE@@LIBQUAD_USE_SYMVER_TRUE@version_arg = -Wl,-M,quadmath.map-sun
++@BUILD_LIBQUADMATH_TRUE@@LIBQUAD_USE_SYMVER_FALSE@version_dep = 
++@BUILD_LIBQUADMATH_TRUE@@LIBQUAD_USE_SYMVER_GNU_TRUE@@LIBQUAD_USE_SYMVER_TRUE@version_dep = $(srcdir)/quadmath.map
++@BUILD_LIBQUADMATH_TRUE@@LIBQUAD_USE_SYMVER_SUN_TRUE@@LIBQUAD_USE_SYMVER_TRUE@version_dep = quadmath.map-sun
++@BUILD_LIBQUADMATH_TRUE@toolexeclib_LTLIBRARIES = libquadmath.la
++@BUILD_LIBQUADMATH_TRUE@libquadmath_la_LIBADD = 
++@BUILD_LIBQUADMATH_TRUE@libquadmath_la_LDFLAGS = -version-info `grep -v '^\#' $(srcdir)/libtool-version` \
++@BUILD_LIBQUADMATH_TRUE@			 $(version_arg) $(lt_host_flags) -lm
++
++@BUILD_LIBQUADMATH_TRUE@libquadmath_la_DEPENDENCIES = $(version_dep) $(libquadmath_la_LIBADD)
++@BUILD_LIBQUADMATH_TRUE@nodist_libsubinclude_HEADERS = quadmath.h quadmath_weak.h
++@BUILD_LIBQUADMATH_TRUE@libsubincludedir = $(libdir)/gcc/$(target_alias)/$(gcc_version)/include
++@BUILD_LIBQUADMATH_TRUE@libquadmath_la_SOURCES = \
++@BUILD_LIBQUADMATH_TRUE@  math/x2y2m1q.c math/acoshq.c math/fmodq.c \
++@BUILD_LIBQUADMATH_TRUE@  math/acosq.c math/frexpq.c \
++@BUILD_LIBQUADMATH_TRUE@  math/rem_pio2q.c math/asinhq.c math/hypotq.c math/remainderq.c \
++@BUILD_LIBQUADMATH_TRUE@  math/asinq.c math/rintq.c math/atan2q.c math/isinfq.c \
++@BUILD_LIBQUADMATH_TRUE@  math/roundq.c math/atanhq.c math/isnanq.c math/scalblnq.c math/atanq.c \
++@BUILD_LIBQUADMATH_TRUE@  math/j0q.c math/scalbnq.c math/cbrtq.c math/j1q.c math/signbitq.c \
++@BUILD_LIBQUADMATH_TRUE@  math/ceilq.c math/jnq.c math/sincos_table.c math/complex.c math/ldexpq.c \
++@BUILD_LIBQUADMATH_TRUE@  math/sincosq.c math/copysignq.c math/lgammaq.c math/sincosq_kernel.c \
++@BUILD_LIBQUADMATH_TRUE@  math/coshq.c math/llroundq.c math/sinhq.c math/cosq.c math/log10q.c \
++@BUILD_LIBQUADMATH_TRUE@  math/sinq.c math/cosq_kernel.c math/log1pq.c math/sinq_kernel.c \
++@BUILD_LIBQUADMATH_TRUE@  math/erfq.c math/logq.c math/sqrtq.c math/expm1q.c math/lroundq.c \
++@BUILD_LIBQUADMATH_TRUE@  math/tanhq.c math/expq.c math/modfq.c math/tanq.c math/fabsq.c \
++@BUILD_LIBQUADMATH_TRUE@  math/nanq.c math/tgammaq.c math/finiteq.c math/nextafterq.c \
++@BUILD_LIBQUADMATH_TRUE@  math/truncq.c math/floorq.c math/powq.c math/fmaq.c math/logbq.c \
++@BUILD_LIBQUADMATH_TRUE@  math/exp2q.c math/issignalingq.c math/lgammaq_neg.c math/lgammaq_product.c \
++@BUILD_LIBQUADMATH_TRUE@  math/tanq_kernel.c math/tgammaq_product.c math/casinhq_kernel.c \
++@BUILD_LIBQUADMATH_TRUE@  math/cacoshq.c math/cacosq.c math/casinhq.c math/casinq.c \
++@BUILD_LIBQUADMATH_TRUE@  math/catanhq.c math/catanq.c math/cimagq.c math/conjq.c math/cprojq.c \
++@BUILD_LIBQUADMATH_TRUE@  math/crealq.c math/fdimq.c math/fmaxq.c math/fminq.c math/ilogbq.c \
++@BUILD_LIBQUADMATH_TRUE@  math/llrintq.c math/log2q.c math/lrintq.c math/nearbyintq.c math/remquoq.c \
++@BUILD_LIBQUADMATH_TRUE@  math/ccoshq.c math/cexpq.c math/clog10q.c math/clogq.c math/csinq.c \
++@BUILD_LIBQUADMATH_TRUE@  math/csinhq.c math/csqrtq.c math/ctanq.c math/ctanhq.c \
++@BUILD_LIBQUADMATH_TRUE@  printf/addmul_1.c printf/add_n.c printf/cmp.c printf/divrem.c \
++@BUILD_LIBQUADMATH_TRUE@  printf/flt1282mpn.c printf/fpioconst.c printf/lshift.c printf/mul_1.c \
++@BUILD_LIBQUADMATH_TRUE@  printf/mul_n.c printf/mul.c printf/printf_fphex.c printf/printf_fp.c \
++@BUILD_LIBQUADMATH_TRUE@  printf/quadmath-printf.c printf/rshift.c printf/submul_1.c printf/sub_n.c \
++@BUILD_LIBQUADMATH_TRUE@  strtod/strtoflt128.c strtod/mpn2flt128.c strtod/tens_in_limb.c
+ 
+ 
+ # Work around what appears to be a GNU make bug handling MAKEFLAGS
+ # values defined in terms of make variables, as is the case for CC and
+ # friends when we are called from the top level Makefile.
+-AM_MAKEFLAGS = \
+-	"AR_FLAGS=$(AR_FLAGS)" \
+-	"CC_FOR_BUILD=$(CC_FOR_BUILD)" \
+-	"CFLAGS=$(CFLAGS)" \
+-	"CXXFLAGS=$(CXXFLAGS)" \
+-	"CFLAGS_FOR_BUILD=$(CFLAGS_FOR_BUILD)" \
+-	"CFLAGS_FOR_TARGET=$(CFLAGS_FOR_TARGET)" \
+-	"INSTALL=$(INSTALL)" \
+-	"INSTALL_DATA=$(INSTALL_DATA)" \
+-	"INSTALL_PROGRAM=$(INSTALL_PROGRAM)" \
+-	"INSTALL_SCRIPT=$(INSTALL_SCRIPT)" \
+-	"JC1FLAGS=$(JC1FLAGS)" \
+-	"LDFLAGS=$(LDFLAGS)" \
+-	"LIBCFLAGS=$(LIBCFLAGS)" \
+-	"LIBCFLAGS_FOR_TARGET=$(LIBCFLAGS_FOR_TARGET)" \
+-	"MAKE=$(MAKE)" \
+-	"MAKEINFO=$(MAKEINFO) $(MAKEINFOFLAGS)" \
+-	"PICFLAG=$(PICFLAG)" \
+-	"PICFLAG_FOR_TARGET=$(PICFLAG_FOR_TARGET)" \
+-	"SHELL=$(SHELL)" \
+-	"RUNTESTFLAGS=$(RUNTESTFLAGS)" \
+-	"exec_prefix=$(exec_prefix)" \
+-	"infodir=$(infodir)" \
+-	"libdir=$(libdir)" \
+-	"prefix=$(prefix)" \
+-	"includedir=$(includedir)" \
+-	"AR=$(AR)" \
+-	"AS=$(AS)" \
+-  "CC=$(CC)" \
+-	"CXX=$(CXX)" \
+-	"LD=$(LD)" \
+-	"LIBCFLAGS=$(LIBCFLAGS)" \
+-	"NM=$(NM)" \
+-	"PICFLAG=$(PICFLAG)" \
+-	"RANLIB=$(RANLIB)" \
+-	"DESTDIR=$(DESTDIR)"
++@BUILD_LIBQUADMATH_TRUE@AM_MAKEFLAGS = \
++@BUILD_LIBQUADMATH_TRUE@	"AR_FLAGS=$(AR_FLAGS)" \
++@BUILD_LIBQUADMATH_TRUE@	"CC_FOR_BUILD=$(CC_FOR_BUILD)" \
++@BUILD_LIBQUADMATH_TRUE@	"CFLAGS=$(CFLAGS)" \
++@BUILD_LIBQUADMATH_TRUE@	"CXXFLAGS=$(CXXFLAGS)" \
++@BUILD_LIBQUADMATH_TRUE@	"CFLAGS_FOR_BUILD=$(CFLAGS_FOR_BUILD)" \
++@BUILD_LIBQUADMATH_TRUE@	"CFLAGS_FOR_TARGET=$(CFLAGS_FOR_TARGET)" \
++@BUILD_LIBQUADMATH_TRUE@	"INSTALL=$(INSTALL)" \
++@BUILD_LIBQUADMATH_TRUE@	"INSTALL_DATA=$(INSTALL_DATA)" \
++@BUILD_LIBQUADMATH_TRUE@	"INSTALL_PROGRAM=$(INSTALL_PROGRAM)" \
++@BUILD_LIBQUADMATH_TRUE@	"INSTALL_SCRIPT=$(INSTALL_SCRIPT)" \
++@BUILD_LIBQUADMATH_TRUE@	"JC1FLAGS=$(JC1FLAGS)" \
++@BUILD_LIBQUADMATH_TRUE@	"LDFLAGS=$(LDFLAGS)" \
++@BUILD_LIBQUADMATH_TRUE@	"LIBCFLAGS=$(LIBCFLAGS)" \
++@BUILD_LIBQUADMATH_TRUE@	"LIBCFLAGS_FOR_TARGET=$(LIBCFLAGS_FOR_TARGET)" \
++@BUILD_LIBQUADMATH_TRUE@	"MAKE=$(MAKE)" \
++@BUILD_LIBQUADMATH_TRUE@	"MAKEINFO=$(MAKEINFO) $(MAKEINFOFLAGS)" \
++@BUILD_LIBQUADMATH_TRUE@	"PICFLAG=$(PICFLAG)" \
++@BUILD_LIBQUADMATH_TRUE@	"PICFLAG_FOR_TARGET=$(PICFLAG_FOR_TARGET)" \
++@BUILD_LIBQUADMATH_TRUE@	"SHELL=$(SHELL)" \
++@BUILD_LIBQUADMATH_TRUE@	"RUNTESTFLAGS=$(RUNTESTFLAGS)" \
++@BUILD_LIBQUADMATH_TRUE@	"exec_prefix=$(exec_prefix)" \
++@BUILD_LIBQUADMATH_TRUE@	"infodir=$(infodir)" \
++@BUILD_LIBQUADMATH_TRUE@	"libdir=$(libdir)" \
++@BUILD_LIBQUADMATH_TRUE@	"prefix=$(prefix)" \
++@BUILD_LIBQUADMATH_TRUE@	"includedir=$(includedir)" \
++@BUILD_LIBQUADMATH_TRUE@	"AR=$(AR)" \
++@BUILD_LIBQUADMATH_TRUE@	"AS=$(AS)" \
++@BUILD_LIBQUADMATH_TRUE@	"CC=$(CC)" \
++@BUILD_LIBQUADMATH_TRUE@	"CXX=$(CXX)" \
++@BUILD_LIBQUADMATH_TRUE@	"LD=$(LD)" \
++@BUILD_LIBQUADMATH_TRUE@	"LIBCFLAGS=$(LIBCFLAGS)" \
++@BUILD_LIBQUADMATH_TRUE@	"NM=$(NM)" \
++@BUILD_LIBQUADMATH_TRUE@	"PICFLAG=$(PICFLAG)" \
++@BUILD_LIBQUADMATH_TRUE@	"RANLIB=$(RANLIB)" \
++@BUILD_LIBQUADMATH_TRUE@	"DESTDIR=$(DESTDIR)"
+ 
+ 
+ # Subdir rules rely on $(FLAGS_TO_PASS)
+-FLAGS_TO_PASS = $(AM_MAKEFLAGS)
+-MAKEOVERRIDES = 
+-@GENINSRC_FALSE@STAMP_GENINSRC = 
++@BUILD_LIBQUADMATH_TRUE@FLAGS_TO_PASS = $(AM_MAKEFLAGS)
++@BUILD_LIBQUADMATH_TRUE@MAKEOVERRIDES = 
++@BUILD_LIBQUADMATH_TRUE@@GENINSRC_FALSE@STAMP_GENINSRC = 
+ 
+ # AM_CONDITIONAL on configure option --generated-files-in-srcdir
+-@GENINSRC_TRUE@STAMP_GENINSRC = stamp-geninsrc
+-ALL_LOCAL_DEPS = $(STAMP_GENINSRC)
+-@BUILD_INFO_FALSE@STAMP_BUILD_INFO = 
++@BUILD_LIBQUADMATH_TRUE@@GENINSRC_TRUE@STAMP_GENINSRC = stamp-geninsrc
++@BUILD_LIBQUADMATH_TRUE@ALL_LOCAL_DEPS = $(STAMP_GENINSRC)
++@BUILD_INFO_FALSE@@BUILD_LIBQUADMATH_TRUE@STAMP_BUILD_INFO = 
+ 
+ # AM_CONDITIONAL on configure check ACX_CHECK_PROG_VER([MAKEINFO])
+-@BUILD_INFO_TRUE@STAMP_BUILD_INFO = stamp-build-info
+-CLEANFILES = $(STAMP_GENINSRC) $(STAMP_BUILD_INFO)
+-MAINTAINERCLEANFILES = $(srcdir)/libquadmath.info
++@BUILD_INFO_TRUE@@BUILD_LIBQUADMATH_TRUE@STAMP_BUILD_INFO = stamp-build-info
++@BUILD_LIBQUADMATH_TRUE@CLEANFILES = $(STAMP_GENINSRC) $(STAMP_BUILD_INFO)
++@BUILD_LIBQUADMATH_TRUE@MAINTAINERCLEANFILES = $(srcdir)/libquadmath.info
+ 
+ # Automake Documentation:
+ # If your package has Texinfo files in many directories, you can use the
+@@ -564,8 +564,8 @@ TEXINFO_TEX = ../gcc/doc/include/texinfo.tex
+ 
+ # Defines info, dvi, pdf and html targets
+ MAKEINFOFLAGS = -I $(srcdir)/../gcc/doc/include
+-info_TEXINFOS = 
+-info_TEXINFOS = libquadmath.texi
++@BUILD_LIBQUADMATH_FALSE@info_TEXINFOS = 
++@BUILD_LIBQUADMATH_TRUE@info_TEXINFOS = libquadmath.texi
+ libquadmath_TEXINFOS = libquadmath-vers.texi
+ MULTISRCTOP = 
+ MULTIBUILDTOP = 
+@@ -1187,7 +1187,6 @@ distclean-tags:
+ 	-rm -f cscope.out cscope.in.out cscope.po.out cscope.files
+ check-am: all-am
+ check: check-am
+-#all-local
+ all-am: Makefile $(INFO_DEPS) $(LTLIBRARIES) $(HEADERS) config.h \
+ 		all-local
+ installdirs:
+@@ -1426,22 +1425,22 @@ uninstall-am: uninstall-dvi-am uninstall-html-am uninstall-info-am \
+ 
+ .PRECIOUS: Makefile
+ 
+-@LIBQUAD_USE_SYMVER_SUN_TRUE@@LIBQUAD_USE_SYMVER_TRUE@quadmath.map-sun : $(srcdir)/quadmath.map \
+-@LIBQUAD_USE_SYMVER_SUN_TRUE@@LIBQUAD_USE_SYMVER_TRUE@		$(top_srcdir)/../contrib/make_sunver.pl \
+-@LIBQUAD_USE_SYMVER_SUN_TRUE@@LIBQUAD_USE_SYMVER_TRUE@		$(libquadmath_la_OBJECTS) $(libquadmath_la_LIBADD)
+-@LIBQUAD_USE_SYMVER_SUN_TRUE@@LIBQUAD_USE_SYMVER_TRUE@	perl $(top_srcdir)/../contrib/make_sunver.pl \
+-@LIBQUAD_USE_SYMVER_SUN_TRUE@@LIBQUAD_USE_SYMVER_TRUE@	  $(srcdir)/quadmath.map \
+-@LIBQUAD_USE_SYMVER_SUN_TRUE@@LIBQUAD_USE_SYMVER_TRUE@	 `echo $(libquadmath_la_OBJECTS) $(libquadmath_la_LIBADD) | \
+-@LIBQUAD_USE_SYMVER_SUN_TRUE@@LIBQUAD_USE_SYMVER_TRUE@	   sed 's,\([^/ 	]*\)\.l\([ao]\),.libs/\1.\2,g'` \
+-@LIBQUAD_USE_SYMVER_SUN_TRUE@@LIBQUAD_USE_SYMVER_TRUE@	 > $@ || (rm -f $@ ; exit 1)
+-
+-stamp-geninsrc: libquadmath.info
+-	cp -p $(top_builddir)/libquadmath.info $(srcdir)/libquadmath.info
+-	@touch $@
+-
+-stamp-build-info: libquadmath.texi $(libquadmath_TEXINFOS)
+-	$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir) -o libquadmath.info $(srcdir)/libquadmath.texi
+-	@touch $@
++@BUILD_LIBQUADMATH_TRUE@@LIBQUAD_USE_SYMVER_SUN_TRUE@@LIBQUAD_USE_SYMVER_TRUE@quadmath.map-sun : $(srcdir)/quadmath.map \
++@BUILD_LIBQUADMATH_TRUE@@LIBQUAD_USE_SYMVER_SUN_TRUE@@LIBQUAD_USE_SYMVER_TRUE@		$(top_srcdir)/../contrib/make_sunver.pl \
++@BUILD_LIBQUADMATH_TRUE@@LIBQUAD_USE_SYMVER_SUN_TRUE@@LIBQUAD_USE_SYMVER_TRUE@		$(libquadmath_la_OBJECTS) $(libquadmath_la_LIBADD)
++@BUILD_LIBQUADMATH_TRUE@@LIBQUAD_USE_SYMVER_SUN_TRUE@@LIBQUAD_USE_SYMVER_TRUE@	perl $(top_srcdir)/../contrib/make_sunver.pl \
++@BUILD_LIBQUADMATH_TRUE@@LIBQUAD_USE_SYMVER_SUN_TRUE@@LIBQUAD_USE_SYMVER_TRUE@	  $(srcdir)/quadmath.map \
++@BUILD_LIBQUADMATH_TRUE@@LIBQUAD_USE_SYMVER_SUN_TRUE@@LIBQUAD_USE_SYMVER_TRUE@	 `echo $(libquadmath_la_OBJECTS) $(libquadmath_la_LIBADD) | \
++@BUILD_LIBQUADMATH_TRUE@@LIBQUAD_USE_SYMVER_SUN_TRUE@@LIBQUAD_USE_SYMVER_TRUE@	   sed 's,\([^/ 	]*\)\.l\([ao]\),.libs/\1.\2,g'` \
++@BUILD_LIBQUADMATH_TRUE@@LIBQUAD_USE_SYMVER_SUN_TRUE@@LIBQUAD_USE_SYMVER_TRUE@	 > $@ || (rm -f $@ ; exit 1)
++
++@BUILD_LIBQUADMATH_TRUE@stamp-geninsrc: libquadmath.info
++@BUILD_LIBQUADMATH_TRUE@	cp -p $(top_builddir)/libquadmath.info $(srcdir)/libquadmath.info
++@BUILD_LIBQUADMATH_TRUE@	@touch $@
++
++@BUILD_LIBQUADMATH_TRUE@stamp-build-info: libquadmath.texi $(libquadmath_TEXINFOS)
++@BUILD_LIBQUADMATH_TRUE@	$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir) -o libquadmath.info $(srcdir)/libquadmath.texi
++@BUILD_LIBQUADMATH_TRUE@	@touch $@
+ 
+ all-local: $(ALL_LOCAL_DEPS)
+ 
+diff --git a/libquadmath/quadmath.h b/libquadmath/quadmath.h
+index faa5977cb..81eb957d2 100644
+--- a/libquadmath/quadmath.h
++++ b/libquadmath/quadmath.h
+@@ -27,9 +27,6 @@ Boston, MA 02110-1301, USA.  */
+ extern "C" {
+ #endif
+ 
+-#ifdef AARCH64_QUADMATH
+-typedef long double __float128;
+-#endif
+ /* Define the complex type corresponding to __float128
+    ("_Complex __float128" is not allowed) */
+ #if (!defined(_ARCH_PPC)) || defined(__LONG_DOUBLE_IEEE128__)
+@@ -163,9 +160,10 @@ extern int quadmath_snprintf (char *str, size_t size,
+ #define FLT128_MAX_10_EXP 4932
+ 
+ 
++#define HUGE_VALQ __builtin_huge_valq()
+ /* 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) */
+ 
+ #define M_Eq		2.718281828459045235360287471352662498Q  /* e */
+ #define M_LOG2Eq	1.442695040888963407359924681001892137Q  /* log_2 e */
+-- 
+2.33.0
+
diff --git a/0097-libquadmath-refactor-Enable-libquadmath-on-kunpeng.patch b/0097-libquadmath-refactor-Enable-libquadmath-on-kunpeng.patch
new file mode 100644
index 0000000..1ddcef5
--- /dev/null
+++ b/0097-libquadmath-refactor-Enable-libquadmath-on-kunpeng.patch
@@ -0,0 +1,197 @@
+From 60e80a17a7019026dc7e2da9dc597c9fdf426e33 Mon Sep 17 00:00:00 2001
+From: eastb233 
+Date: Wed, 31 May 2023 10:48:47 +0800
+Subject: [PATCH 2/3] [libquadmath][refactor] 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 b5b212c06..da41959ee 100644
+--- 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
+@@ -10816,7 +10818,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 10821 "configure"
+ #include "confdefs.h"
+ 
+ #if HAVE_DLFCN_H
+@@ -10922,7 +10924,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 10927 "configure"
+ #include "confdefs.h"
+ 
+ #if HAVE_DLFCN_H
+@@ -12715,6 +12717,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
+@@ -12766,6 +12773,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
+@@ -13224,6 +13236,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.
+ 
+@@ -13407,6 +13427,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 f9d745e60..0b8511f04 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
+@@ -380,6 +385,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/0098-AArch64-Rewrite-the-tsv110-option.patch b/0098-AArch64-Rewrite-the-tsv110-option.patch
new file mode 100644
index 0000000..d441343
--- /dev/null
+++ b/0098-AArch64-Rewrite-the-tsv110-option.patch
@@ -0,0 +1,114 @@
+From 4a0b942c8f6643509e6e9a605c99a258a6523308 Mon Sep 17 00:00:00 2001
+From: d00573793 
+Date: Wed, 31 May 2023 17:00:24 +0800
+Subject: [PATCH 3/3] [AArch64] Rewrite the tsv110 option
+
+Reset the more appropriate options for tsv110.
+---
+ gcc/common/config/aarch64/aarch64-common.c | 76 ++++++++++++++++++++++
+ 1 file changed, 76 insertions(+)
+
+diff --git a/gcc/common/config/aarch64/aarch64-common.c b/gcc/common/config/aarch64/aarch64-common.c
+index 51bd319d6..2a23a605d 100644
+--- a/gcc/common/config/aarch64/aarch64-common.c
++++ b/gcc/common/config/aarch64/aarch64-common.c
+@@ -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/0099-Struct-Reorg-Add-escape-propagate-on-external-functi.patch b/0099-Struct-Reorg-Add-escape-propagate-on-external-functi.patch
new file mode 100644
index 0000000..db9038e
--- /dev/null
+++ b/0099-Struct-Reorg-Add-escape-propagate-on-external-functi.patch
@@ -0,0 +1,258 @@
+From c6370dc949c39319ef1c31d0b42efc041d27379a Mon Sep 17 00:00:00 2001
+From: huang-xiaoquan 
+Date: Thu, 8 Jun 2023 11:37:09 +0800
+Subject: [PATCH] [Struct Reorg] Add escape propagate on external functions
+ using type
+
+External functions may use members of members through structure pointers.
+Therefore, escape propagation of member types of types used by external
+functions is added.
+---
+ gcc/ipa-struct-reorg/ipa-struct-reorg.c       | 71 +++++++++++++++++--
+ gcc/testsuite/gcc.dg/struct/dfe_extr_claw.c   |  7 ++
+ .../gcc.dg/struct/rf_external_func_types.c    | 69 ++++++++++++++++++
+ 3 files changed, 140 insertions(+), 7 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.dg/struct/rf_external_func_types.c
+
+diff --git a/gcc/ipa-struct-reorg/ipa-struct-reorg.c b/gcc/ipa-struct-reorg/ipa-struct-reorg.c
+index 7de4fee0e..367bcf210 100644
+--- a/gcc/ipa-struct-reorg/ipa-struct-reorg.c
++++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.c
+@@ -1412,6 +1412,7 @@ public:
+   srglobal globals;
+   srfunction *current_function;
+   hash_set  safe_functions;
++  auto_vec ext_func_types;
+ 
+   bool done_recording;
+ 
+@@ -1426,6 +1427,7 @@ public:
+   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);
+@@ -3131,7 +3133,14 @@ ipa_struct_reorg::record_type (tree type)
+     return NULL;
+ 
+   if (dump_file && (dump_flags & TDF_DETAILS))
+-    fprintf (dump_file, "Recording new type: %u.\n", typeuid);
++    {
++      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);
+@@ -4478,6 +4487,18 @@ 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;
+     }
+@@ -5672,6 +5693,35 @@ ipa_struct_reorg::propagate_escape_via_empty_with_no_original (void)
+     }
+ }
+ 
++/* 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
+@@ -5689,6 +5739,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 ();
+     }
+ 
+   if (dump_file && (dump_flags & TDF_DETAILS))
+@@ -8242,8 +8293,9 @@ 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);
+ 		}
+ 	      pop_cfun ();
+ 	    }
+@@ -8278,8 +8330,9 @@ ipa_struct_reorg::rewrite_functions (void)
+ 	    {
+ 	      fprintf (dump_file, "==== Before create decls: %dth_%s ====\n\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);
+ 	    }
+ 	  pop_cfun ();
+ 	}
+@@ -8313,8 +8366,9 @@ ipa_struct_reorg::rewrite_functions (void)
+ 	{
+ 	  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);
+ 	  fprintf (dump_file, "\n======== Start to rewrite: %dth_%s ========\n",
+ 		   i, f->node->name ());
+ 	}
+@@ -8659,6 +8713,9 @@ 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", opt);
++
+   if (opt != COMPLETE_STRUCT_RELAYOUT)
+     {
+       current_layout_opt_level = opt;
+diff --git a/gcc/testsuite/gcc.dg/struct/dfe_extr_claw.c b/gcc/testsuite/gcc.dg/struct/dfe_extr_claw.c
+index e56bf467b..f9e2cf471 100644
+--- a/gcc/testsuite/gcc.dg/struct/dfe_extr_claw.c
++++ b/gcc/testsuite/gcc.dg/struct/dfe_extr_claw.c
+@@ -42,6 +42,13 @@ 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)
+ {
+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..2a9bea783
+--- /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." "struct_reorg" } } */
+\ No newline at end of file
+-- 
+2.33.0
+
diff --git a/0100-PGO-kernel-Add-fkernel-pgo-option-to-support-PGO-ker.patch b/0100-PGO-kernel-Add-fkernel-pgo-option-to-support-PGO-ker.patch
new file mode 100644
index 0000000..a77c072
--- /dev/null
+++ b/0100-PGO-kernel-Add-fkernel-pgo-option-to-support-PGO-ker.patch
@@ -0,0 +1,46 @@
+From 90d3ef0637c66045eeab78ccf04e9ff51b9b451a Mon Sep 17 00:00:00 2001
+From: xiongzhou4 
+Date: Thu, 1 Jun 2023 09:28:27 +0800
+Subject: [PATCH 5/5] [PGO kernel] Add fkernel-pgo option to support PGO kernel
+ compilation.
+
+If specified, disable TLS setting of instrumentation variables in
+gcc/tree-profile.c, as kernel does not support TLS.
+---
+ gcc/common.opt     | 4 ++++
+ gcc/tree-profile.c | 4 +++-
+ 2 files changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/gcc/common.opt b/gcc/common.opt
+index 238c97db8..6f0ed7cea 100644
+--- a/gcc/common.opt
++++ b/gcc/common.opt
+@@ -2302,6 +2302,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 Report 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-partial-training
+ Common Report Var(flag_profile_partial_training) Optimization
+ Do not assume that functions never executed during the train run are cold.
+diff --git a/gcc/tree-profile.c b/gcc/tree-profile.c
+index 6c0838261..924817472 100644
+--- a/gcc/tree-profile.c
++++ b/gcc/tree-profile.c
+@@ -105,7 +105,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/0101-To-resolve-the-SPEC-.548-fluctuation-problem-revert-.patch b/0101-To-resolve-the-SPEC-.548-fluctuation-problem-revert-.patch
new file mode 100644
index 0000000..836197a
--- /dev/null
+++ b/0101-To-resolve-the-SPEC-.548-fluctuation-problem-revert-.patch
@@ -0,0 +1,26 @@
+From 962eda7f0336c883c52c33a9b61a19f7e80ea9e2 Mon Sep 17 00:00:00 2001
+From: root 
+Date: Tue, 6 Jun 2023 22:29:03 +0800
+Subject: [PATCH] To resolve the SPEC .548 fluctuation problem, revert GCC
+ commit 835d50c66aa5bde2f354a6e63a2afa7d2f76a05a
+
+---
+ gcc/config/aarch64/aarch64.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
+index 85dbd3898..116b4b8ca 100644
+--- a/gcc/config/aarch64/aarch64.c
++++ b/gcc/config/aarch64/aarch64.c
+@@ -12726,7 +12726,7 @@ cost_plus:
+ 	  }
+ 
+ 	if (GET_MODE_CLASS (mode) == MODE_INT
+-	    && (aarch64_plus_immediate (op1, mode)
++	    && ((CONST_INT_P (op1) && aarch64_uimm12_shift (INTVAL (op1))) 
+ 		|| aarch64_sve_addvl_addpl_immediate (op1, mode)))
+ 	  {
+ 	    *cost += rtx_cost (op0, mode, PLUS, 0, speed);
+-- 
+2.33.0
+
diff --git a/0102-GOMP-Enabling-moutline-atomics-improves-libgomp-perf.patch b/0102-GOMP-Enabling-moutline-atomics-improves-libgomp-perf.patch
new file mode 100644
index 0000000..019af78
--- /dev/null
+++ b/0102-GOMP-Enabling-moutline-atomics-improves-libgomp-perf.patch
@@ -0,0 +1,34 @@
+From 8aeb2d4d05f6c0ba949fa3fa85ea5ac75a7255c9 Mon Sep 17 00:00:00 2001
+From: d00573793 
+Date: Mon, 19 Jun 2023 23:56:49 +0800
+Subject: [PATCH] [GOMP] Enabling moutline-atomics improves libgomp performance
+ in multi-thread scenarios
+
+Libgomp is used in multi-thread scenarios,
+Enabling moutline-atomics improves performance.
+
+diff --git a/libgomp/configure.tgt b/libgomp/configure.tgt
+index 4790a31e3..e5b558be0 100644
+--- a/libgomp/configure.tgt
++++ b/libgomp/configure.tgt
+@@ -30,6 +30,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
++
+ # Since we require POSIX threads, assume a POSIX system by default.
+ config_path="posix"
+ 
+-- 
+2.27.0.windows.1
+
diff --git a/0103-test-Add-option-ftree-fold-phiopt-to-avoid-fail-NFC.patch b/0103-test-Add-option-ftree-fold-phiopt-to-avoid-fail-NFC.patch
new file mode 100644
index 0000000..6bc7758
--- /dev/null
+++ b/0103-test-Add-option-ftree-fold-phiopt-to-avoid-fail-NFC.patch
@@ -0,0 +1,143 @@
+From 1d0bbeb4171f21baf18db6a802bd0b9685e2d25b Mon Sep 17 00:00:00 2001
+From: zhongyunde 
+Date: Tue, 20 Jun 2023 08:59:57 +0800
+Subject: [PATCH] [test] Add option -ftree-fold-phiopt to avoid fail, NFC
+
+Fix https://gitee.com/openeuler/gcc/issues/I7EQCC?from=project-issue
+---
+ gcc/testsuite/c-c++-common/ubsan/pr85213.c                | 2 +-
+ gcc/testsuite/gcc.dg/uninit-8.c                           | 2 +-
+ gcc/testsuite/gcc.target/aarch64/bics_3.c                 | 2 +-
+ gcc/testsuite/gcc.target/aarch64/scalar-vca.c             | 2 +-
+ gcc/testsuite/gcc.target/aarch64/scalar_intrinsics.c      | 2 +-
+ gcc/testsuite/gcc.target/aarch64/simd/int_comparisons_1.c | 2 +-
+ gcc/testsuite/gcc.target/aarch64/simd/vcaled_f64.c        | 2 +-
+ gcc/testsuite/gcc.target/aarch64/simd/vcales_f32.c        | 2 +-
+ gcc/testsuite/gcc.target/aarch64/simd/vcaltd_f64.c        | 2 +-
+ gcc/testsuite/gcc.target/aarch64/simd/vcalts_f32.c        | 2 +-
+ 10 files changed, 10 insertions(+), 10 deletions(-)
+
+diff --git a/gcc/testsuite/c-c++-common/ubsan/pr85213.c b/gcc/testsuite/c-c++-common/ubsan/pr85213.c
+index 8a6be81d2..804c29da7 100644
+--- a/gcc/testsuite/c-c++-common/ubsan/pr85213.c
++++ b/gcc/testsuite/c-c++-common/ubsan/pr85213.c
+@@ -1,6 +1,6 @@
+ /* PR sanitizer/85213 */
+ /* { dg-do compile } */
+-/* { dg-options "-O1 -fsanitize=undefined -fcompare-debug" } */
++/* { dg-options "-O1 -ftree-fold-phiopt -fsanitize=undefined -fcompare-debug" } */
+ 
+ int
+ foo (int x)
+diff --git a/gcc/testsuite/gcc.dg/uninit-8.c b/gcc/testsuite/gcc.dg/uninit-8.c
+index 98700f4aa..e8fd942cf 100644
+--- a/gcc/testsuite/gcc.dg/uninit-8.c
++++ b/gcc/testsuite/gcc.dg/uninit-8.c
+@@ -3,7 +3,7 @@
+    May be the same as uninit-1.c.  */
+ 
+ /* { dg-do compile } */
+-/* { dg-options "-O -Wuninitialized" } */
++/* { dg-options "-O -ftree-fold-phiopt -Wuninitialized" } */
+ 
+ #include 
+ 
+diff --git a/gcc/testsuite/gcc.target/aarch64/bics_3.c b/gcc/testsuite/gcc.target/aarch64/bics_3.c
+index 3257df622..ab6f0210e 100644
+--- a/gcc/testsuite/gcc.target/aarch64/bics_3.c
++++ b/gcc/testsuite/gcc.target/aarch64/bics_3.c
+@@ -1,5 +1,5 @@
+ /* { dg-do run } */
+-/* { dg-options "-O2 --save-temps" } */
++/* { dg-options "-O2 -ftree-fold-phiopt --save-temps" } */
+ 
+ extern void abort (void);
+ 
+diff --git a/gcc/testsuite/gcc.target/aarch64/scalar-vca.c b/gcc/testsuite/gcc.target/aarch64/scalar-vca.c
+index 40a359725..58ce99328 100644
+--- a/gcc/testsuite/gcc.target/aarch64/scalar-vca.c
++++ b/gcc/testsuite/gcc.target/aarch64/scalar-vca.c
+@@ -1,5 +1,5 @@
+ /* { dg-do run } */
+-/* { dg-options "-O3 --save-temps" } */
++/* { dg-options "-O3 -ftree-fold-phiopt --save-temps" } */
+ 
+ #include 
+ 
+diff --git a/gcc/testsuite/gcc.target/aarch64/scalar_intrinsics.c b/gcc/testsuite/gcc.target/aarch64/scalar_intrinsics.c
+index c2e13b651..bcd7e4c83 100644
+--- a/gcc/testsuite/gcc.target/aarch64/scalar_intrinsics.c
++++ b/gcc/testsuite/gcc.target/aarch64/scalar_intrinsics.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -dp" } */
++/* { dg-options "-O2 -ftree-fold-phiopt -dp" } */
+ 
+ #include 
+ 
+diff --git a/gcc/testsuite/gcc.target/aarch64/simd/int_comparisons_1.c b/gcc/testsuite/gcc.target/aarch64/simd/int_comparisons_1.c
+index f2c55922f..3f989257b 100644
+--- a/gcc/testsuite/gcc.target/aarch64/simd/int_comparisons_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/simd/int_comparisons_1.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O3 -fno-inline" } */
++/* { dg-options "-O3 -ftree-fold-phiopt -fno-inline" } */
+ 
+ /* Scan-assembler test, so, incorporate as little other code as possible.  */
+ 
+diff --git a/gcc/testsuite/gcc.target/aarch64/simd/vcaled_f64.c b/gcc/testsuite/gcc.target/aarch64/simd/vcaled_f64.c
+index 198b18b4e..357d0f61a 100644
+--- a/gcc/testsuite/gcc.target/aarch64/simd/vcaled_f64.c
++++ b/gcc/testsuite/gcc.target/aarch64/simd/vcaled_f64.c
+@@ -1,7 +1,7 @@
+ /* Test the vcaled_f64 AArch64 SIMD intrinsic.  */
+ 
+ /* { dg-do run } */
+-/* { dg-options "-save-temps -O3" } */
++/* { dg-options "-save-temps -O3 -ftree-fold-phiopt" } */
+ 
+ #include "arm_neon.h"
+ 
+diff --git a/gcc/testsuite/gcc.target/aarch64/simd/vcales_f32.c b/gcc/testsuite/gcc.target/aarch64/simd/vcales_f32.c
+index 6b58501f3..a2b5a5f50 100644
+--- a/gcc/testsuite/gcc.target/aarch64/simd/vcales_f32.c
++++ b/gcc/testsuite/gcc.target/aarch64/simd/vcales_f32.c
+@@ -1,7 +1,7 @@
+ /* Test the vcales_f32 AArch64 SIMD intrinsic.  */
+ 
+ /* { dg-do run } */
+-/* { dg-options "-save-temps -O3" } */
++/* { dg-options "-save-temps -O3 -ftree-fold-phiopt" } */
+ 
+ #include "arm_neon.h"
+ 
+diff --git a/gcc/testsuite/gcc.target/aarch64/simd/vcaltd_f64.c b/gcc/testsuite/gcc.target/aarch64/simd/vcaltd_f64.c
+index 50a3b2718..d77f68378 100644
+--- a/gcc/testsuite/gcc.target/aarch64/simd/vcaltd_f64.c
++++ b/gcc/testsuite/gcc.target/aarch64/simd/vcaltd_f64.c
+@@ -1,7 +1,7 @@
+ /* Test the vcaltd_f64 AArch64 SIMD intrinsic.  */
+ 
+ /* { dg-do run } */
+-/* { dg-options "-save-temps -O3" } */
++/* { dg-options "-save-temps -O3 -ftree-fold-phiopt" } */
+ 
+ #include "arm_neon.h"
+ 
+diff --git a/gcc/testsuite/gcc.target/aarch64/simd/vcalts_f32.c b/gcc/testsuite/gcc.target/aarch64/simd/vcalts_f32.c
+index 1807e0b95..d723b9ac5 100644
+--- a/gcc/testsuite/gcc.target/aarch64/simd/vcalts_f32.c
++++ b/gcc/testsuite/gcc.target/aarch64/simd/vcalts_f32.c
+@@ -1,7 +1,7 @@
+ /* Test the vcalts_f32 AArch64 SIMD intrinsic.  */
+ 
+ /* { dg-do run } */
+-/* { dg-options "-save-temps -O3" } */
++/* { dg-options "-save-temps -O3 -ftree-fold-phiopt" } */
+ 
+ #include "arm_neon.h"
+ 
+-- 
+2.33.0
+
diff --git a/0104-aarch64-Use-local-frame-vars-in-shrink-wrapping-code.patch b/0104-aarch64-Use-local-frame-vars-in-shrink-wrapping-code.patch
new file mode 100644
index 0000000..1cc0839
--- /dev/null
+++ b/0104-aarch64-Use-local-frame-vars-in-shrink-wrapping-code.patch
@@ -0,0 +1,348 @@
+From 153060b97c667bbd06caad9c3fc1f9f6fe7266df Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Fri, 16 Jun 2023 16:43:41 +0100
+Subject: [PATCH] aarch64: Use local frame vars in shrink-wrapping code
+
+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.c (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.c | 115 ++++++++++++++++++-----------------
+ 1 file changed, 60 insertions(+), 55 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
+index e6bf5ae3808..368bb394105 100644
+--- a/gcc/config/aarch64/aarch64.c
++++ b/gcc/config/aarch64/aarch64.c
+@@ -7403,6 +7403,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;
+@@ -7417,8 +7418,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_candidate1
+-	      || regno == cfun->machine->frame.wb_candidate2))
++	  && (regno == frame.wb_candidate1
++	      || regno == frame.wb_candidate2))
+ 	continue;
+ 
+       if (cfun->machine->reg_is_wrapped_separately[regno])
+@@ -7426,7 +7427,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;
+ 
+@@ -7439,7 +7440,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
+@@ -7461,8 +7462,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;
+@@ -7512,6 +7512,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;
+@@ -7528,13 +7529,13 @@ aarch64_restore_callee_saves (poly_int64 start_offset, unsigned start,
+       rtx reg, mem;
+ 
+       if (skip_wb
+-	  && (regno == cfun->machine->frame.wb_candidate1
+-	      || regno == cfun->machine->frame.wb_candidate2))
++	  && (regno == frame.wb_candidate1
++	      || regno == frame.wb_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,
+@@ -7545,8 +7546,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;
+@@ -7640,6 +7640,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);
+ 
+@@ -7656,18 +7657,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;
+ 
+@@ -7686,11 +7687,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_candidate1;
+-  unsigned reg2 = cfun->machine->frame.wb_candidate2;
++  unsigned reg1 = frame.wb_candidate1;
++  unsigned reg2 = frame.wb_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.  */
+@@ -7799,6 +7800,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);
+@@ -7813,9 +7815,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;
+ 
+@@ -7840,14 +7842,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);
+@@ -7869,7 +7871,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);
+@@ -7964,6 +7966,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;
+@@ -7984,25 +7987,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))
+ 	{
+@@ -8291,17 +8294,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_candidate1;
+-  unsigned reg2 = cfun->machine->frame.wb_candidate2;
+-  bool emit_frame_chain = cfun->machine->frame.emit_frame_chain;
++    = frame.below_hard_fp_saved_regs_size;
++  unsigned reg1 = frame.wb_candidate1;
++  unsigned reg2 = frame.wb_candidate2;
++  bool emit_frame_chain = frame.emit_frame_chain;
+   rtx_insn *insn;
+ 
+   if (flag_stack_clash_protection && known_eq (callee_adjust, 0))
+@@ -8367,7 +8371,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.  */
+@@ -8470,15 +8474,16 @@ aarch64_use_return_insn_p (void)
+ void
+ aarch64_expand_epilogue (bool for_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_candidate1;
+-  unsigned reg2 = cfun->machine->frame.wb_candidate2;
++    = frame.below_hard_fp_saved_regs_size;
++  unsigned reg1 = frame.wb_candidate1;
++  unsigned reg2 = frame.wb_candidate2;
+   rtx cfi_ops = NULL;
+   rtx_insn *insn;
+   /* A stack clash protection prologue may not have left EP0_REGNUM or
+@@ -8511,7 +8516,7 @@ aarch64_expand_epilogue (bool for_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)
+@@ -11170,24 +11175,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.39.3
diff --git a/0105-aarch64-Avoid-a-use-of-callee_offset.patch b/0105-aarch64-Avoid-a-use-of-callee_offset.patch
new file mode 100644
index 0000000..9b6d88c
--- /dev/null
+++ b/0105-aarch64-Avoid-a-use-of-callee_offset.patch
@@ -0,0 +1,72 @@
+From 901269e14884a86c532b99fb41d5f46b519344f0 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 27 Jun 2023 11:12:21 +0100
+Subject: [PATCH] aarch64: Avoid a use of callee_offset
+
+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.c (aarch64_expand_prologue): Use
+	chain_offset rather than callee_offset.
+---
+ gcc/config/aarch64/aarch64.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
+index 368bb394105..2aaf187bcc3 100644
+--- a/gcc/config/aarch64/aarch64.c
++++ b/gcc/config/aarch64/aarch64.c
+@@ -8299,7 +8299,6 @@ aarch64_expand_prologue (void)
+   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;
+@@ -8408,8 +8407,7 @@ aarch64_expand_prologue (void)
+ 	     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));
+ 	    }
+-- 
+2.39.3
diff --git a/0106-aarch64-Explicitly-handle-frames-with-no-saved-registers.patch b/0106-aarch64-Explicitly-handle-frames-with-no-saved-registers.patch
new file mode 100644
index 0000000..b1ba615
--- /dev/null
+++ b/0106-aarch64-Explicitly-handle-frames-with-no-saved-registers.patch
@@ -0,0 +1,47 @@
+From c8ffe35ca907e0042524a5369158fcb5631d5108 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Fri, 16 Jun 2023 17:00:51 +0100
+Subject: [PATCH] aarch64: Explicitly handle frames with no saved registers
+
+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.c (aarch64_layout_frame): Explicitly
+	allocate the frame in one go if there are no saved registers.
+---
+ gcc/config/aarch64/aarch64.c | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
+index 2aaf187bcc3..81537c01951 100644
+--- a/gcc/config/aarch64/aarch64.c
++++ b/gcc/config/aarch64/aarch64.c
+@@ -7035,9 +7035,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.39.3
diff --git a/0107-aarch64-Add-bytes_below_saved_regs-to-frame-info.patch b/0107-aarch64-Add-bytes_below_saved_regs-to-frame-info.patch
new file mode 100644
index 0000000..a8f6d44
--- /dev/null
+++ b/0107-aarch64-Add-bytes_below_saved_regs-to-frame-info.patch
@@ -0,0 +1,232 @@
+From 781490f3e1bd3789048485981e5039300abf41cb Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Fri, 16 Jun 2023 16:55:12 +0100
+Subject: [PATCH] aarch64: Add bytes_below_saved_regs to frame info
+
+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.c (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.c | 71 ++++++++++++++++++------------------
+ gcc/config/aarch64/aarch64.h |  5 +++
+ 2 files changed, 41 insertions(+), 35 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
+index 81537c01951..6109518189f 100644
+--- a/gcc/config/aarch64/aarch64.c
++++ b/gcc/config/aarch64/aarch64.c
+@@ -6902,6 +6902,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.  */
+@@ -7006,18 +7008,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;
+ 
+@@ -7033,7 +7035,7 @@ aarch64_layout_frame (void)
+   else if (frame.wb_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;
+@@ -7041,31 +7043,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,
+@@ -7075,30 +7077,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]
+@@ -7106,10 +7107,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.  */
+@@ -7672,7 +7673,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.  */
+@@ -7821,7 +7822,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);
+@@ -7875,7 +7876,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)
+@@ -7949,10 +7950,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
+@@ -8161,7 +8162,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 9be4ec3d280..083ffbfbc53 100644
+--- a/gcc/config/aarch64/aarch64.h
++++ b/gcc/config/aarch64/aarch64.h
+@@ -820,6 +820,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.39.3
diff --git a/0108-aarch64-Add-bytes_below_hard_fp-to-frame-info.patch b/0108-aarch64-Add-bytes_below_hard_fp-to-frame-info.patch
new file mode 100644
index 0000000..a95a651
--- /dev/null
+++ b/0108-aarch64-Add-bytes_below_hard_fp-to-frame-info.patch
@@ -0,0 +1,83 @@
+From a519149de34facf645064c1ea5748aeb7d72aca4 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 27 Jun 2023 11:17:33 +0100
+Subject: [PATCH] aarch64: Add bytes_below_hard_fp to frame info
+
+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.c (aarch64_layout_frame): Initialize it.
+	(aarch64_expand_epilogue): Use it instead of
+	below_hard_fp_saved_regs_size.
+---
+ gcc/config/aarch64/aarch64.c | 6 +++---
+ gcc/config/aarch64/aarch64.h | 5 +++++
+ 2 files changed, 8 insertions(+), 3 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
+index 6109518189f..2652515b361 100644
+--- a/gcc/config/aarch64/aarch64.c
++++ b/gcc/config/aarch64/aarch64.c
+@@ -6954,6 +6954,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.  */
+@@ -8481,8 +8482,7 @@ aarch64_expand_epilogue (bool for_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_candidate1;
+   unsigned reg2 = frame.wb_candidate2;
+   rtx cfi_ops = NULL;
+@@ -8538,7 +8538,7 @@ aarch64_expand_epilogue (bool for_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 083ffbfbc53..a4cbc678cef 100644
+--- a/gcc/config/aarch64/aarch64.h
++++ b/gcc/config/aarch64/aarch64.h
+@@ -829,6 +829,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.39.3
diff --git a/0109-aarch64-Tweak-aarch64_save-restore_callee_saves.patch b/0109-aarch64-Tweak-aarch64_save-restore_callee_saves.patch
new file mode 100644
index 0000000..8e01e1a
--- /dev/null
+++ b/0109-aarch64-Tweak-aarch64_save-restore_callee_saves.patch
@@ -0,0 +1,220 @@
+From 6ef2e97b16bea4d4ce2cd52de444a3a2595504d6 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 27 Jun 2023 11:21:41 +0100
+Subject: [PATCH] aarch64: Tweak aarch64_save/restore_callee_saves
+
+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.c (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.c | 56 ++++++++++++++++++------------------
+ gcc/config/aarch64/aarch64.h |  4 ---
+ 2 files changed, 28 insertions(+), 32 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
+index 2652515b361..884002e3b7b 100644
+--- a/gcc/config/aarch64/aarch64.c
++++ b/gcc/config/aarch64/aarch64.c
+@@ -7028,7 +7028,6 @@ aarch64_layout_frame (void)
+   frame.final_adjust = 0;
+   frame.callee_adjust = 0;
+   frame.sve_callee_adjust = 0;
+-  frame.callee_offset = 0;
+ 
+   HOST_WIDE_INT max_push_offset = 0;
+   if (frame.wb_candidate2 != INVALID_REGNUM)
+@@ -7068,7 +7067,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,
+@@ -7398,12 +7396,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)
+ {
+@@ -7431,7 +7430,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;
+ 
+@@ -7442,9 +7443,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
+@@ -7508,12 +7507,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;
+@@ -7539,7 +7539,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,
+@@ -8304,8 +8306,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_candidate1;
+   unsigned reg2 = frame.wb_candidate2;
+   bool emit_frame_chain = frame.emit_frame_chain;
+@@ -8377,8 +8377,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)
+     {
+@@ -8386,7 +8386,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
+@@ -8426,7 +8426,7 @@ aarch64_expand_prologue (void)
+       emit_insn (gen_stack_tie (stack_pointer_rtx, 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))
+@@ -8436,16 +8436,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);
+ }
+@@ -8480,7 +8481,6 @@ aarch64_expand_epilogue (bool for_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_candidate1;
+@@ -8548,13 +8548,13 @@ aarch64_expand_epilogue (bool for_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);
+-  aarch64_restore_callee_saves (callee_offset - sve_callee_adjust,
++  aarch64_restore_callee_saves (final_adjust + sve_callee_adjust,
+ 				R0_REGNUM, R30_REGNUM,
+ 				callee_adjust != 0, &cfi_ops);
+ 
+diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
+index a4cbc678cef..405b7545913 100644
+--- a/gcc/config/aarch64/aarch64.h
++++ b/gcc/config/aarch64/aarch64.h
+@@ -856,10 +856,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.39.3
diff --git a/0110-aarch64-Only-calculate-chain_offset-if-there-is-a-chain.patch b/0110-aarch64-Only-calculate-chain_offset-if-there-is-a-chain.patch
new file mode 100644
index 0000000..407924e
--- /dev/null
+++ b/0110-aarch64-Only-calculate-chain_offset-if-there-is-a-chain.patch
@@ -0,0 +1,43 @@
+From 176001612860c2b04133c1de26eb673860800865 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 27 Jun 2023 11:24:27 +0100
+Subject: [PATCH] aarch64: Only calculate chain_offset if there is a chain
+
+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.c (aarch64_expand_prologue): Move the
+	calculation of chain_offset into the emit_frame_chain block.
+---
+ gcc/config/aarch64/aarch64.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
+index 884002e3b7b..69cfa4b86a6 100644
+--- a/gcc/config/aarch64/aarch64.c
++++ b/gcc/config/aarch64/aarch64.c
+@@ -8372,16 +8372,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.39.3
diff --git a/0111-aarch64-Rename-locals_offset-to-bytes_above_locals.patch b/0111-aarch64-Rename-locals_offset-to-bytes_above_locals.patch
new file mode 100644
index 0000000..0d9b4ee
--- /dev/null
+++ b/0111-aarch64-Rename-locals_offset-to-bytes_above_locals.patch
@@ -0,0 +1,90 @@
+From 45365e7aeb03a56ac4ec0781764017952645348f Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 27 Jun 2023 11:25:40 +0100
+Subject: [PATCH] aarch64: Rename locals_offset to bytes_above_locals
+MIME-Version: 1.0
+Content-Type: text/plain; charset=utf8
+Content-Transfer-Encoding: 8bit
+
+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.c (aarch64_layout_frame)
+	(aarch64_initial_elimination_offset): Update accordingly.
+---
+ gcc/config/aarch64/aarch64.c | 6 +++---
+ gcc/config/aarch64/aarch64.h | 6 +++---
+ 2 files changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
+index 69cfa4b86a6..456b8b3308c 100644
+--- a/gcc/config/aarch64/aarch64.c
++++ b/gcc/config/aarch64/aarch64.c
+@@ -7022,7 +7022,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;
+@@ -11184,13 +11184,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 405b7545913..41a84799175 100644
+--- a/gcc/config/aarch64/aarch64.h
++++ b/gcc/config/aarch64/aarch64.h
+@@ -834,10 +834,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.39.3
diff --git a/0112-aarch64-Rename-hard_fp_offset-to-bytes_above_hard_fp.patch b/0112-aarch64-Rename-hard_fp_offset-to-bytes_above_hard_fp.patch
new file mode 100644
index 0000000..dae0e44
--- /dev/null
+++ b/0112-aarch64-Rename-hard_fp_offset-to-bytes_above_hard_fp.patch
@@ -0,0 +1,147 @@
+From ba6a8c0b2cb27af94913f6dea26e10106e38ec3e Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 27 Jun 2023 11:28:11 +0100
+Subject: [PATCH] aarch64: Rename hard_fp_offset to bytes_above_hard_fp
+MIME-Version: 1.0
+Content-Type: text/plain; charset=utf8
+Content-Transfer-Encoding: 8bit
+
+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.c (aarch64_layout_frame)
+	(aarch64_expand_prologue): Update accordingly.
+	(aarch64_initial_elimination_offset): Likewise.
+---
+ gcc/config/aarch64/aarch64.c | 26 +++++++++++++-------------
+ gcc/config/aarch64/aarch64.h |  6 +++---
+ 2 files changed, 16 insertions(+), 16 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
+index 456b8b3308c..81ddb99c165 100644
+--- a/gcc/config/aarch64/aarch64.c
++++ b/gcc/config/aarch64/aarch64.c
+@@ -7014,7 +7014,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.  */
+@@ -7035,13 +7035,13 @@ aarch64_layout_frame (void)
+   else if (frame.wb_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.
+ 
+@@ -7058,8 +7058,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:
+ 
+@@ -7077,12 +7077,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:
+@@ -7092,7 +7092,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;
+     }
+@@ -7107,7 +7107,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;
+     }
+@@ -8379,7 +8379,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)
+@@ -11181,10 +11181,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 41a84799175..9839e18a27e 100644
+--- a/gcc/config/aarch64/aarch64.h
++++ b/gcc/config/aarch64/aarch64.h
+@@ -839,10 +839,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.39.3
diff --git a/0113-aarch64-Tweak-frame_size-comment.patch b/0113-aarch64-Tweak-frame_size-comment.patch
new file mode 100644
index 0000000..0094a9f
--- /dev/null
+++ b/0113-aarch64-Tweak-frame_size-comment.patch
@@ -0,0 +1,34 @@
+From b5e2fcfa7a1c722fe426132562af4a96fff9fb5c Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Thu, 22 Jun 2023 22:26:30 +0100
+Subject: [PATCH] aarch64: Tweak frame_size comment
+MIME-Version: 1.0
+Content-Type: text/plain; charset=utf8
+Content-Transfer-Encoding: 8bit
+
+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 9839e18a27e..8d8916c7227 100644
+--- a/gcc/config/aarch64/aarch64.h
++++ b/gcc/config/aarch64/aarch64.h
+@@ -844,8 +844,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.39.3
diff --git a/0114-aarch64-Measure-reg_offset-from-the-bottom-of-the-frame.patch b/0114-aarch64-Measure-reg_offset-from-the-bottom-of-the-frame.patch
new file mode 100644
index 0000000..da5ad6a
--- /dev/null
+++ b/0114-aarch64-Measure-reg_offset-from-the-bottom-of-the-frame.patch
@@ -0,0 +1,194 @@
+From ae7192e24b8fd6b3f14b44de03bebc6af92c13ed Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 27 Jun 2023 11:36:08 +0100
+Subject: [PATCH] aarch64: Measure reg_offset from the bottom of the frame
+
+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.c (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.c | 53 ++++++++++++++++--------------------
+ gcc/config/aarch64/aarch64.h |  3 ++
+ 2 files changed, 27 insertions(+), 29 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
+index 81ddb99c165..1ed335f5487 100644
+--- a/gcc/config/aarch64/aarch64.c
++++ b/gcc/config/aarch64/aarch64.c
+@@ -6826,7 +6826,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);
+@@ -6902,7 +6901,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
+@@ -6914,7 +6915,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
+@@ -6932,10 +6934,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 ();
+ 	}
+@@ -6952,9 +6954,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.  */
+@@ -7005,9 +7008,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
+@@ -7430,9 +7434,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;
+ 
+@@ -7539,9 +7541,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,
+@@ -7669,14 +7669,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.  */
+@@ -7823,9 +7821,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);
+@@ -7877,9 +7873,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)
+@@ -7995,7 +7989,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 8d8916c7227..1c3c62639cb 100644
+--- a/gcc/config/aarch64/aarch64.h
++++ b/gcc/config/aarch64/aarch64.h
+@@ -809,6 +809,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.39.3
diff --git a/0115-aarch64-Simplify-top-of-frame-allocation.patch b/0115-aarch64-Simplify-top-of-frame-allocation.patch
new file mode 100644
index 0000000..77ba598
--- /dev/null
+++ b/0115-aarch64-Simplify-top-of-frame-allocation.patch
@@ -0,0 +1,54 @@
+From ff7193c5313d736e20aa66c33abeaf102cc6c152 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Fri, 16 Jun 2023 17:44:39 +0100
+Subject: [PATCH] aarch64: Simplify top of frame allocation
+
+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.c (aarch64_layout_frame): Simplify
+	the allocation of the top of the frame.
+---
+ gcc/config/aarch64/aarch64.c | 23 ++++++++---------------
+ 1 file changed, 8 insertions(+), 15 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
+index 1ed335f5487..70542c6e13f 100644
+--- a/gcc/config/aarch64/aarch64.c
++++ b/gcc/config/aarch64/aarch64.c
+@@ -7010,23 +7010,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);
++  poly_int64 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.39.3
diff --git a/0116-aarch64-Minor-initial-adjustment-tweak.patch b/0116-aarch64-Minor-initial-adjustment-tweak.patch
new file mode 100644
index 0000000..e9066b2
--- /dev/null
+++ b/0116-aarch64-Minor-initial-adjustment-tweak.patch
@@ -0,0 +1,37 @@
+From 5854b895a92e9fe8b26a051442d44a6fd685512a Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Thu, 22 Jun 2023 22:18:45 +0100
+Subject: [PATCH] aarch64: Minor initial adjustment tweak
+
+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.c (aarch64_layout_frame): Tweak
+	calculation of initial_adjust for frames in which all saves
+	are SVE saves.
+---
+ gcc/config/aarch64/aarch64.c | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
+index 70542c6e13f..08a8667bbc1 100644
+--- a/gcc/config/aarch64/aarch64.c
++++ b/gcc/config/aarch64/aarch64.c
+@@ -7071,11 +7071,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.39.3
diff --git a/0117-aarch64-Tweak-stack-clash-boundary-condition.patch b/0117-aarch64-Tweak-stack-clash-boundary-condition.patch
new file mode 100644
index 0000000..826f53e
--- /dev/null
+++ b/0117-aarch64-Tweak-stack-clash-boundary-condition.patch
@@ -0,0 +1,124 @@
+From af6bac9775e7d2bc94e4e3600740c3c475e117b5 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 27 Jun 2023 15:11:44 +0100
+Subject: [PATCH] aarch64: Tweak stack clash boundary condition
+
+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.c (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.c                  |  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.c b/gcc/config/aarch64/aarch64.c
+index 08a8667bbc1..43240af8ae4 100644
+--- a/gcc/config/aarch64/aarch64.c
++++ b/gcc/config/aarch64/aarch64.c
+@@ -7962,9 +7962,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 00000000000..0d8a25d73a2
+--- /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.39.3
diff --git a/0118-aarch64-Put-LR-save-probe-in-first-16-bytes.patch b/0118-aarch64-Put-LR-save-probe-in-first-16-bytes.patch
new file mode 100644
index 0000000..75a9fec
--- /dev/null
+++ b/0118-aarch64-Put-LR-save-probe-in-first-16-bytes.patch
@@ -0,0 +1,269 @@
+From 128abc59aedc06b4418ac57d08a484e1fd92dee2 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 27 Jun 2023 15:12:55 +0100
+Subject: [PATCH] aarch64: Put LR save probe in first 16 bytes
+
+-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, but a later
+patch deals with that.
+
+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.c (aarch64_layout_frame): Ensure that
+	the LR save slot is in the first 16 bytes of the register save area.
+	(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/config/aarch64/aarch64.c                  |  65 +++++------
+ .../aarch64/stack-check-prologue-18.c         | 103 ++++++++++++++++++
+ 2 files changed, 130 insertions(+), 38 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/stack-check-prologue-18.c
+
+diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
+index 43240af8ae4..3d73c5f352f 100644
+--- a/gcc/config/aarch64/aarch64.c
++++ b/gcc/config/aarch64/aarch64.c
+@@ -6958,26 +6958,38 @@ 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;
++
++#define ALLOCATE_GPR_SLOT(REGNO)				\
++  do								\
++    {								\
++      frame.reg_offset[REGNO] = offset;				\
++      if (frame.wb_candidate1 == INVALID_REGNUM)		\
++	frame.wb_candidate1 = (REGNO);				\
++      else if (frame.wb_candidate2 == INVALID_REGNUM)		\
++	frame.wb_candidate2 = (REGNO);				\
++      offset += UNITS_PER_WORD;					\
++    }								\
++  while (0)
++
+   if (frame.emit_frame_chain)
+     {
+       /* FP and LR are placed in the linkage record.  */
+-      frame.reg_offset[R29_REGNUM] = offset;
+-      frame.wb_candidate1 = R29_REGNUM;
+-      frame.reg_offset[R30_REGNUM] = offset + UNITS_PER_WORD;
+-      frame.wb_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_candidate1 == INVALID_REGNUM)
+-	  frame.wb_candidate1 = regno;
+-	else if (frame.wb_candidate2 == INVALID_REGNUM)
+-	  frame.wb_candidate2 = regno;
+-	offset += UNITS_PER_WORD;
+-      }
++      ALLOCATE_GPR_SLOT (regno);
++
++#undef ALLOCATE_GPR_SLOT
+ 
+   poly_int64 max_int_offset = offset;
+   offset = aligned_upper_bound (offset, STACK_BOUNDARY / BITS_PER_UNIT);
+@@ -7968,29 +7980,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.  */
+@@ -8170,8 +8159,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 00000000000..b646f040b54
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/stack-check-prologue-18.c
+@@ -0,0 +1,103 @@
++/* { 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;
++}
+-- 
+2.39.3
diff --git a/0119-aarch64-Simplif-yprobe-of-final-frame-allocation.patch b/0119-aarch64-Simplif-yprobe-of-final-frame-allocation.patch
new file mode 100644
index 0000000..e59baf2
--- /dev/null
+++ b/0119-aarch64-Simplif-yprobe-of-final-frame-allocation.patch
@@ -0,0 +1,98 @@
+From c940aadecb4f623a39abe16b6c62b307e2b10638 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 8 Aug 2023 01:57:26 +0100
+Subject: [PATCH] aarch64: Simplify probe of final frame allocation
+
+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.c (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/config/aarch64/aarch64.c                         | 12 ++++--------
+ .../gcc.target/aarch64/stack-check-prologue-17.c     |  2 +-
+ .../gcc.target/aarch64/stack-check-prologue-18.c     |  4 ++--
+ 3 files changed, 7 insertions(+), 11 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
+index 3d73c5f352f..37c6219b07a 100644
+--- a/gcc/config/aarch64/aarch64.c
++++ b/gcc/config/aarch64/aarch64.c
+@@ -8153,16 +8153,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)
+@@ -8173,8 +8169,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 0d8a25d73a2..f0ec1389771 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 b646f040b54..71d33ba34e9 100644
+--- a/gcc/testsuite/gcc.target/aarch64/stack-check-prologue-18.c
++++ b/gcc/testsuite/gcc.target/aarch64/stack-check-prologue-18.c
+@@ -10,7 +10,7 @@ void g();
+ **	str	x30, \[sp\]
+ **	...
+ **	sub	sp, sp, #4064
+-**	str	xzr, \[sp\]
++**	str	xzr, \[sp, #?1024\]
+ **	cbnz	w0, .*
+ **	bl	g
+ **	...
+@@ -52,7 +52,7 @@ int test1(int z) {
+ **	str	x30, \[sp\]
+ **	...
+ **	sub	sp, sp, #1040
+-**	str	xzr, \[sp\]
++**	str	xzr, \[sp, #?1024\]
+ **	cbnz	w0, .*
+ **	bl	g
+ **	...
+-- 
+2.39.3
diff --git a/0120-aarch64-Explicitly-record-probe-registers-in-frame-info.patch b/0120-aarch64-Explicitly-record-probe-registers-in-frame-info.patch
new file mode 100644
index 0000000..e10da56
--- /dev/null
+++ b/0120-aarch64-Explicitly-record-probe-registers-in-frame-info.patch
@@ -0,0 +1,275 @@
+From 3c73e7bc86a918c2c24b3ad96b2d44716a5e2614 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 27 Jun 2023 11:50:34 +0100
+Subject: [PATCH] aarch64: Explicitly record probe registers in frame info
+
+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.c (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.c                  | 67 +++++++++++++++----
+ gcc/config/aarch64/aarch64.h                  |  8 +++
+ .../aarch64/sve/pcs/stack_clash_3.c           |  6 +-
+ 3 files changed, 64 insertions(+), 17 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
+index 37c6219b07a..2dea9b5617d 100644
+--- a/gcc/config/aarch64/aarch64.c
++++ b/gcc/config/aarch64/aarch64.c
+@@ -6897,13 +6897,10 @@ 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.  */
+-  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
+@@ -6911,6 +6908,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;
+       }
+@@ -6948,6 +6947,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;
+ 	}
+@@ -6957,11 +6958,19 @@ 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;
+ 
+ #define ALLOCATE_GPR_SLOT(REGNO)				\
+   do								\
+     {								\
++      if (frame.hard_fp_save_and_probe == INVALID_REGNUM)	\
++	frame.hard_fp_save_and_probe = (REGNO);			\
+       frame.reg_offset[REGNO] = offset;				\
+       if (frame.wb_candidate1 == INVALID_REGNUM)		\
+ 	frame.wb_candidate1 = (REGNO);				\
+@@ -6998,6 +7007,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
+@@ -7021,6 +7032,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);
+@@ -7120,6 +7142,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
+@@ -7669,13 +7710,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;
+@@ -7710,6 +7744,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;
+ }
+@@ -8246,8 +8287,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 1c3c62639cb..5279503fd09 100644
+--- a/gcc/config/aarch64/aarch64.h
++++ b/gcc/config/aarch64/aarch64.h
+@@ -877,6 +877,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;
+ };
+ 
+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 3e01ec36c3a..3530a0d504b 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.39.3
diff --git a/0121-aarch64-Remove-below_hard_fp_saved_regs_size.patch b/0121-aarch64-Remove-below_hard_fp_saved_regs_size.patch
new file mode 100644
index 0000000..c86e6db
--- /dev/null
+++ b/0121-aarch64-Remove-below_hard_fp_saved_regs_size.patch
@@ -0,0 +1,158 @@
+From 1c659316abe90c98b98494c9f13bd040e25063d8 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Thu, 22 Jun 2023 22:15:39 +0100
+Subject: [PATCH] aarch64: Remove below_hard_fp_saved_regs_size
+
+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.c (aarch64_layout_frame): Update accordingly.
+---
+ gcc/config/aarch64/aarch64.c | 46 +++++++++++++++++-------------------
+ gcc/config/aarch64/aarch64.h |  7 ------
+ 2 files changed, 22 insertions(+), 31 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
+index 2dea9b5617d..91833473c75 100644
+--- a/gcc/config/aarch64/aarch64.c
++++ b/gcc/config/aarch64/aarch64.c
+@@ -6955,9 +6955,9 @@ 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);
++  poly_int64 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],
+@@ -7031,9 +7031,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)
++  poly_int64 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)));
+@@ -7042,7 +7041,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);
+@@ -7068,7 +7067,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
+@@ -7081,7 +7080,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
+@@ -7100,8 +7099,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:
+ 
+@@ -7123,7 +7121,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
+@@ -7138,7 +7136,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;
+     }
+ 
+@@ -8252,17 +8250,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 5279503fd09..b0d13cf08ec 100644
+--- a/gcc/config/aarch64/aarch64.h
++++ b/gcc/config/aarch64/aarch64.h
+@@ -820,18 +820,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.39.3
+
diff --git a/0122-aarch64-Make-stack-smash-canary-protect-saved-registers.patch b/0122-aarch64-Make-stack-smash-canary-protect-saved-registers.patch
new file mode 100644
index 0000000..513a464
--- /dev/null
+++ b/0122-aarch64-Make-stack-smash-canary-protect-saved-registers.patch
@@ -0,0 +1,297 @@
+From dad1c82acf67a8a1cc68e2acf3ec89a503e361fc Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Thu, 15 Jun 2023 19:16:52 +0100
+Subject: [PATCH] aarch64: Make stack smash canary protect saved registers
+
+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.c (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.c                  | 47 +++++++--
+ .../gcc.target/aarch64/stack-protector-8.c    | 95 +++++++++++++++++++
+ .../gcc.target/aarch64/stack-protector-9.c    | 33 +++++++
+ 3 files changed, 169 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.c b/gcc/config/aarch64/aarch64.c
+index 91833473c75..ce701b91a3f 100644
+--- a/gcc/config/aarch64/aarch64.c
++++ b/gcc/config/aarch64/aarch64.c
+@@ -6820,6 +6820,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).  */
+@@ -6831,6 +6845,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 ();
+ 
+@@ -6897,8 +6912,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;
+ 
+@@ -7043,15 +7066,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);
+-  poly_int64 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;
+@@ -8247,10 +8273,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       |
+ 	+-------------------------------+
+@@ -8262,6 +8288,10 @@ aarch64_epilogue_uses (int regno)
+ 	+-------------------------------+
+ 	|  SVE predicate registers      |
+ 	+-------------------------------+
++	|  local variables (2)          |
++	+-------------------------------+
++	|  padding (2)                  |
++	+-------------------------------+
+ 	|  dynamic allocation           |
+ 	+-------------------------------+
+ 	|  padding                      |
+@@ -8271,6 +8301,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.
+@@ -8462,6 +8495,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))
++    emit_insn (gen_stack_tie (stack_pointer_rtx, 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 00000000000..e71d820e365
+--- /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 00000000000..58f322aa480
+--- /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.39.3
diff --git a/cpp b/cpp
deleted file mode 100644
index 83a3685..0000000
--- a/cpp
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-# Traditionally, /lib/cpp only knew about C.
-exec /usr/bin/cpp -xc "$@"
diff --git a/gcc.spec b/gcc.spec
index aac72db..2d6831d 100644
--- a/gcc.spec
+++ b/gcc.spec
@@ -1,767 +1,3063 @@
-#
-# spec file for package gcc
-#
-# Copyright (c) 2021 SUSE LLC
-#
-# All modifications and additions to the file contributed by third parties
-# remain the property of their copyright owners, unless otherwise agreed
-# upon. The license for this file, and modifications and additions to the
-# file, is the same license as for the pristine package itself (unless the
-# license for the pristine package is not an Open Source License, in which
-# case the license is the MIT License). An "Open Source License" is a
-# license that conforms to the Open Source Definition (Version 1.9)
-# published by the Open Source Initiative.
-
-# Please submit bugfixes or comments via https://bugs.opensuse.org/
-#
-
-
-Name:           gcc
-%define separate_bi32 0
-%define separate_bi64 0
-%ifarch ppc
-%define separate_bi64 1
+%global gcc_version 10.3.1
+%global gcc_major 10.3.1
+%global _unpackaged_files_terminate_build 0
+%global _performance_build 1
+
+%undefine _hardened_build
+%undefine _annotated_build
+
+%global build_ada 0
+%global build_objc 1
+%global build_go 0
+%global build_d 0
+%global build_check 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
+%global build_libasan 1
+%else
+%global build_libasan 0
+%endif
+%ifarch x86_64 ppc64 ppc64le aarch64
+%global build_libtsan 1
+%else
+%global build_libtsan 0
 %endif
-%ifarch x86_64 s390x ppc64
-%define separate_bi32 1
+%ifarch x86_64 ppc64 ppc64le aarch64
+%global build_liblsan 1
+%else
+%global build_liblsan 0
+%endif
+%ifarch %{ix86} x86_64 ppc ppc64 ppc64le ppc64p7 s390 s390x %{arm} aarch64
+%global build_libubsan 1
+%else
+%global build_libubsan 0
 %endif
-# Ada currently fails to build on a few platforms, enable it only
-# on those that work
-# Note that AdaCore only supports %ix86, x86_64 and ia64
-%ifarch %ix86 x86_64 ppc ppc64 ppc64le s390 s390x ia64 aarch64
-%define build_ada 1
+%ifarch %{ix86} x86_64 ppc ppc64 ppc64le ppc64p7 s390 s390x %{arm} aarch64 %{mips} riscv64
+%global build_libatomic 1
 %else
-# alpha hppa arm
-%define build_ada 0
-%endif
-Url:            http://gcc.gnu.org/
-%define gcc_version 7
-%define gcc_suffix 7
-Version:        7
-Release:        3.9.1
-Summary:        The system GNU C Compiler
-License:        GPL-3.0+
-Group:          Development/Languages/C and C++
-Provides:       c_compiler
-
-Requires:       cpp
-Requires:       gcc%{gcc_version}
-BuildRoot:      %{_tmppath}/%{name}-%{version}-build
-BuildRequires:  gcc%{gcc_version}
-Source:         cpp
+%global build_libatomic 0
+%endif
+%ifarch %{ix86} x86_64 %{arm} alpha ppc ppc64 ppc64le ppc64p7 s390 s390x aarch64
+%global build_libitm 1
+%else
+%global build_libitm 0
+%endif
+%global build_isl 1
+%global build_libstdcxx_docs 0
+%ifarch %{ix86} x86_64 ppc ppc64 ppc64le ppc64p7 s390 s390x %{arm} aarch64 %{mips}
+%global attr_ifunc 1
+%else
+%global attr_ifunc 0
+%endif
+%ifarch riscv64
+%global _lib lib
+%global _smp_mflags -j8
+%endif
 
-%description
-The system GNU C Compiler.
+Summary: Various compilers (C, C++, Objective-C, ...)
+Name: gcc
+Version: %{gcc_version}
+Release: 38
+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-10.3.0/gcc-10.3.0.tar.xz
+%global isl_version 0.15
+
+BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
+BuildRequires: binutils >= 2.31
+BuildRequires: glibc-headers
+BuildRequires: libtool, zlib-devel, texinfo, flex, bison
+BuildRequires: gmp-devel >= 4.1.2-8, mpfr-devel >= 3.1.0, libmpc-devel >= 0.8.1
+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
+BuildRequires: /lib/libc.so.6 /usr/lib/libc.so /lib64/libc.so.6 /usr/lib64/libc.so
+%endif
+%if %{build_ada}
+BuildRequires: gcc-gnat >= 3.1, libgnat >= 3.1
+%endif
+%ifarch ia64
+BuildRequires: libunwind >= 0.98
+%endif
+%if %{build_isl}
+BuildRequires: isl >= %{isl_version}, isl-devel >= %{isl_version}
+Requires: isl >= %{isl_version}, isl-devel >= %{isl_version}
+%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}
+%if !%{build_ada}
+Obsoletes: gcc-gnat < %{version}-%{release}
+%endif
+Obsoletes: gcc-java < %{version}-%{release}
+AutoReq: true
+Provides: bundled(libiberty)
+Provides: gcc(major) = %{gcc_major}
+
+
+Patch1: 0001-libquadmath-Enable-libquadmath-on-kunpeng.patch
+Patch2: 0002-Backport-cselim-Extend-to-check-non-trapping-for-mor.patch
+Patch3: 0003-version-Set-version-to-10.3.1.patch
+Patch4: 0004-Backport-tree-optimization-Avoid-issueing-loads-in-S.patch
+Patch5: 0005-Backport-tree-optimization-Fix-load-eliding-in-SM.patch
+Patch6: 0006-simdmath-Enable-simdmath-on-kunpeng.patch
+Patch7: 0007-Vect-Enable-skipping-vectorization-on-reduction-chai.patch
+Patch8: 0008-Backport-tree-optimization-Add-checks-to-avoid-spoil.patch
+Patch9: 0009-Backport-expand-Simplify-removing-subregs-when-expan.patch
+Patch10: 0010-Backport-tree-optimization-94963-avoid-bogus-uninit-.patch
+Patch11: 0011-simdmath-Enable-64-bits-simd-when-test-simd_pcs_attr.patch
+Patch12: 0012-fp-model-Enable-fp-model-on-kunpeng.patch
+Patch13: 0013-LoopElim-Redundant-loop-elimination-optimization.patch
+Patch14: 0014-Backport-StructReorg-Structure-reorganization-optimi.patch
+Patch15: 0015-CompleteStructReorg-Complete-Structure-Reorganizatio.patch
+Patch16: 0016-StructReorg-Bugfix-in-certain-scenarios.patch
+Patch17: 0017-mcmodel-Enable-mcmodel-medium-on-kunpeng.patch
+Patch18: 0018-StructReorderFields-Structure-reorder-fields.patch
+Patch19: 0019-StructReorderFields-Fix-bugs-and-improve-mechanism.patch
+Patch20: 0020-Backport-vect-Fix-an-ICE-in-vect_recog_mask_conversi.patch
+Patch21: 0021-mcmodel-Bugfix-for-mcmodel-medium-on-x86.patch
+Patch22: 0022-StructReorderFields-Fix-pointer-layer-check-bug.patch
+Patch23: 0023-StructReorderFields-Add-pointer-offset-check.patch
+Patch24: 0024-StructReorderFields-Add-lto-and-whole-program-gate.patch
+Patch25: 0025-AutoPrefetch-Support-cache-misses-profile.patch
+Patch26: 0026-AutoFDO-Enable-discriminator-and-MCF-algorithm-on-Au.patch
+Patch27: 0027-Autoprefetch-Support-auto-feedback-prefetch.patch
+Patch28: 0028-AutoPrefetch-Handle-the-case-that-the-basic-block-br.patch
+Patch29: 0029-AutoBOLT-Support-saving-feedback-count-info-to-ELF-s.patch
+Patch30: 0030-AutoBOLT-Add-bolt-linker-plugin-2-3.patch
+Patch31: 0031-AutoBOLT-Enable-BOLT-linker-plugin-on-aarch64-3-3.patch
+Patch32: 0032-Autoprefetch-Prune-invaild-loops-containing-edges-wh.patch
+Patch33: 0033-AutoFdo-Fix-memory-leaks-in-autofdo-and-autoprefetch.patch
+Patch34: 0034-Backport-sanitizer-Fix-asan-against-glibc-2.34-PR100.patch
+Patch35: 0035-ccmp-Add-another-optimization-opportunity-for-ccmp-i.patch
+Patch36: 0036-StructReorg-Refactoring-reorder-fields-to-struct-lay.patch
+Patch38: 0038-DFE-Add-Dead-Field-Elimination-in-Struct-Reorg.patch
+Patch39: 0039-Backport-ipa-sra-Fix-thinko-when-overriding-safe_to_.patch
+Patch40: 0040-Backport-ifcvt-Allow-constants-for-noce_convert_mult.patch
+Patch41: 0041-Backport-Register-sysroot-in-the-driver-switches-tab.patch
+Patch42: 0042-DFE-Fix-bugs.patch
+Patch45: 0045-Transposed-SLP-Enable-Transposed-SLP.patch
+Patch46: 0046-ArrayWidenCompare-Add-a-new-optimization-for-array-c.patch
+Patch47: 0047-DFE-Fix-the-bug-caused-by-inconsistent-types.patch
+Patch48: 0048-Struct-Reorg-Type-simplify-limitation-when-in-struct.patch
+Patch49: 0049-build-Add-some-file-right-to-executable.patch             
+Patch50: 0050-Backport-phiopt-Optimize-x-1024-0-to-int-x-10-PR9769.patch
+Patch51: 0051-Backport-phiopt-Fix-up-conditional_replacement-PR993.patch
+Patch52: 0052-Backport-phiopt-Handle-bool-in-two_value_replacement.patch
+Patch53: 0053-Backport-phiopt-Optimize-x-__builtin_clz-x-32-in-GIM.patch
+Patch54: 0054-Backport-phiopt-Optimize-x-__builtin_clz-x-32-in-GIM.patch
+Patch55: 0055-Backport-phiopt-Optimize-x-0-y-y-to-x-31-y-PR96928.patch  
+Patch56: 0056-Backport-phiopt-Optimize-x-y-cmp-z-PR94589.patch          
+Patch57: 0057-Backport-Add-support-for-__builtin_bswap128.patch         
+Patch58: 0058-Backport-tree-optimization-95393-fold-MIN-MAX_EXPR-g.patch
+Patch59: 0059-Backport-Add-a-couple-of-A-CST1-CST2-match-and-simpl.patch
+Patch60: 0060-Backport-Optimize-x-0-y-y-to-x-31-y-in-match.pd.patch     
+Patch61: 0061-Backport-Replace-conditional_replacement-with-match-.patch
+Patch62: 0062-Backport-Allow-match-and-simplified-phiopt-to-run-in.patch
+Patch63: 0063-Backport-Improve-match_simplify_replacement-in-phi-o.patch
+Patch64: 0064-Backport-phiopt-Use-gphi-phi-instead-of-gimple-phi-s.patch
+Patch65: 0065-Backport-Optimize-x-bswap-x-0-in-tree-ssa-phiopt.patch    
+Patch66: 0066-Backport-tree-optimization-102880-make-PHI-OPT-recog.patch
+Patch67: 0067-Backport-tree-Add-vector_element_bits-_tree-PR94980-.patch
+Patch68: 0068-Backport-Lower-VEC_COND_EXPR-into-internal-functions.patch
+Patch69: 0069-Backport-gimple-match-Add-a-gimple_extract_op-functi.patch
+Patch70: 0070-Backport-aarch64-Fix-subs_compare_2.c-regression-PR1.patch
+Patch71: 0071-PHIOPT-Disable-the-match-A-CST1-0-when-the-CST1-is-n.patch
+Patch72: 0072-Struct-Reorg-Merge-struct_layout-pass-into-struct_re.patch
+Patch73: 0073-PHIOPT-Add-A-B-op-CST-B-match-and-simplify-optimizat.patch
+Patch74: 0074-FORWPROP-Fold-series-of-instructions-into-mul.patch       
+Patch75: 0075-FORWPROP-Fold-series-of-instructions-into-umulh.patch     
+Patch76: 0076-Struct-Reorg-Fix-speccpu2006-462-double-free-I60YUV.patch 
+Patch77: 0077-Struct-Reorg-Add-Safe-Structure-Pointer-Compression.patch 
+Patch78: 0078-Loop-distribution-Add-isomorphic-stmts-analysis.patch     
+Patch79: 0079-loop-vect-Transfer-arrays-using-registers-between-lo.patch
+Patch80: 0080-Struct-Reorg-Add-Unsafe-Structure-Pointer-Compressio.patch
+Patch81: 0081-Loop-distribution-Insert-temp-arrays-built-from-isom.patch
+Patch82: 0082-Revert-Backport-tree-optimization-102880-make-PHI-OP.patch
+Patch83: 0083-Struct-reorg-Add-struct-semi-relayout-optimize.patch
+Patch84: 0084-MULL64-Disable-mull64-transformation-by-default.patch
+Patch85: 0085-loop-distribution-Bugfix-for-loop-distribution.patch
+Patch86: 0086-semi-relayout-Bugfix-for-struct-semi-relayout.patch
+Patch87: 0087-Backport-tree-optimization-97238-fix-typo-causing-IC.patch
+Patch88: 0088-Backport-fix-typo-causing-ICE.patch
+Patch89: 0089-State-sysroot-option-as-validated-once-processed.patch
+Patch90: 0090-bogus-Wstringop-overflow-with-VLA-of-elements-larger.patch
+Patch91: 0091-phiopt2-Add-option-to-control-the-simplify.patch
+Patch92: 0092-gimple-Factor-the-code-to-avoid-depending-auto-featu.patch
+Patch93: 0093-StructReorg-Fix-escape_cast_another_ptr-check-bug.patch
+Patch94: 0094-Backport-Fix-zero-masking-for-vcvtps2ph-when-dest-op.patch
+Patch95: 0095-Struct-reorg-Fix-the-use-of-as_a.patch
+Patch96: 0096-libquadmath-Revert-Enable-libquadmath-on-kunpeng.patch
+Patch97: 0097-libquadmath-refactor-Enable-libquadmath-on-kunpeng.patch
+Patch98: 0098-AArch64-Rewrite-the-tsv110-option.patch
+Patch99: 0099-Struct-Reorg-Add-escape-propagate-on-external-functi.patch
+Patch100: 0100-PGO-kernel-Add-fkernel-pgo-option-to-support-PGO-ker.patch
+Patch101: 0101-To-resolve-the-SPEC-.548-fluctuation-problem-revert-.patch
+Patch102: 0102-GOMP-Enabling-moutline-atomics-improves-libgomp-perf.patch
+Patch103: 0103-test-Add-option-ftree-fold-phiopt-to-avoid-fail-NFC.patch
+Patch104: 0104-aarch64-Use-local-frame-vars-in-shrink-wrapping-code.patch
+Patch105: 0105-aarch64-Avoid-a-use-of-callee_offset.patch
+Patch106: 0106-aarch64-Explicitly-handle-frames-with-no-saved-registers.patch
+Patch107: 0107-aarch64-Add-bytes_below_saved_regs-to-frame-info.patch
+Patch108: 0108-aarch64-Add-bytes_below_hard_fp-to-frame-info.patch
+Patch109: 0109-aarch64-Tweak-aarch64_save-restore_callee_saves.patch
+Patch110: 0110-aarch64-Only-calculate-chain_offset-if-there-is-a-chain.patch
+Patch111: 0111-aarch64-Rename-locals_offset-to-bytes_above_locals.patch
+Patch112: 0112-aarch64-Rename-hard_fp_offset-to-bytes_above_hard_fp.patch
+Patch113: 0113-aarch64-Tweak-frame_size-comment.patch
+Patch114: 0114-aarch64-Measure-reg_offset-from-the-bottom-of-the-frame.patch
+Patch115: 0115-aarch64-Simplify-top-of-frame-allocation.patch
+Patch116: 0116-aarch64-Minor-initial-adjustment-tweak.patch
+Patch117: 0117-aarch64-Tweak-stack-clash-boundary-condition.patch
+Patch118: 0118-aarch64-Put-LR-save-probe-in-first-16-bytes.patch
+Patch119: 0119-aarch64-Simplif-yprobe-of-final-frame-allocation.patch
+Patch120: 0120-aarch64-Explicitly-record-probe-registers-in-frame-info.patch
+Patch121: 0121-aarch64-Remove-below_hard_fp_saved_regs_size.patch
+Patch122: 0122-aarch64-Make-stack-smash-canary-protect-saved-registers.patch
+
+%global gcc_target_platform %{_arch}-linux-gnu
+
+%if %{build_go}
+# Avoid stripping these libraries and binaries.
+%global __os_install_post \
+chmod 644 %{buildroot}%{_prefix}/%{_lib}/libgo.so.16.* \
+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.16.* \
+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 10.
+You'll need this package in order to compile C code.
+
+%package -n libgcc
+Summary: GCC version 10 shared support library
+Autoreq: false
+%if !%{build_ada}
+Obsoletes: libgnat < %{version}-%{release}
+%endif
+Obsoletes: libmudflap
+Obsoletes: libmudflap-devel
+Obsoletes: libmudflap-static
+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 gcc-32bit
-Summary:        The system GNU C Compiler
-License:        GPL-3.0+
-Group:          Development/Languages/C and C++
-Requires:       gcc = %{version}
-Requires:       gcc%{gcc_version}-32bit
+%package -n libstdc++-devel
+Summary: Header files and libraries for C++ development
+Requires: libstdc++%{?_isa} = %{version}-%{release}
+Autoreq: true
 
-%description -n gcc-32bit
-The system GNU C Compiler.
+%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
 
-%package -n gcc-64bit
-Summary:        The system GNU C Compiler
-License:        GPL-3.0+
-Group:          Development/Languages/C and C++
-Requires:       gcc = %{version}
-Requires:       gcc%{gcc_version}-64bit
+%description -n libgfortran-static
+This package contains static Fortran libraries.
 
-%description -n gcc-64bit
-The system GNU C Compiler.
+%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
 
-%package -n cpp
-Summary:        The system GNU Preprocessor
-License:        GPL-3.0+
-Group:          Development/Languages/C and C++
-Requires:       cpp%{gcc_version}
+%description -n libgphobos
+This package contains D shared library which is needed to run
+D dynamically linked programs.
 
-%description -n cpp
-The system GNU Preprocessor.
+%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 gcc-devel
-Summary:        The system GNU C Compiler Plugin development files
-License:        GPL-3.0+
-Group:          Development/Languages/C and C++
-Requires:       gcc = %{version}
-Requires:       gcc%{gcc_version}-devel
+%package -n libgomp
+Summary: GCC OpenMP v4.5 shared support library
 
-%description -n gcc-devel
-The system GNU C Compiler Plugin development files.
+%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}
 
-%package -n gcc-locale
-Summary:        The system GNU Compiler locale files
-License:        GPL-3.0+
-Group:          Development/Languages/C and C++
-Requires:       gcc%{gcc_version}-locale
+%description gdb-plugin
+This package contains GCC plugin for GDB C expression evaluation.
 
-%description -n gcc-locale
-The system GNU Compiler locale files.
+%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}
 
-%package -n gcc-info
-Summary:        The system GNU Compiler documentation
-License:        GFDL-1.2
-Group:          Development/Languages/C and C++
-PreReq:         gcc%{gcc_version}-info
+%description -n libgccjit-devel
+This package contains header files and documentation for GCC JIT front-end.
 
-%description -n gcc-info
-The system GNU Compiler documentation.
+%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}
 
-%package -n gcc-c++
-Summary:        The system GNU C++ Compiler
-License:        GPL-3.0+
-Group:          Development/Languages/C and C++
-Provides:       c++_compiler
-Requires:       gcc = %{version}
-Requires:       gcc%{gcc_version}-c++
+%description -n libquadmath-devel
+This package contains headers for building Fortran programs using
+REAL*16 and programs using __float128 math.
 
-%description -n gcc-c++
-The system GNU C++ Compiler.
+%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 gcc-c++-32bit
-Summary:        The system GNU C++ Compiler
-License:        GPL-3.0+
-Group:          Development/Languages/C and C++
-Requires:       gcc%{gcc_version}-c++-32bit
-Requires:       gcc-32bit = %{version}
-Requires:       gcc-c++ = %{version}
+%package -n libitm
+Summary: The GNU Transactional Memory library
 
-%description -n gcc-c++-32bit
-The system GNU C++ Compiler 32 bit support.
+%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}
 
-%package -n gcc-c++-64bit
-Summary:        The system GNU C++ Compiler
-License:        GPL-3.0+
-Group:          Development/Languages/C and C++
-Requires:       gcc%{gcc_version}-c++-64bit
-Requires:       gcc-64bit = %{version}
-Requires:       gcc-c++ = %{version}
+%description -n libitm-devel
+This package contains headers and support files for the
+GNU Transactional Memory library.
 
-%description -n gcc-c++-64bit
-The system GNU C++ Compiler 64 bit support.
+%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
 
-%package -n libstdc++-devel
-Summary:        The system GNU C++ development files
-License:        GPL-3.0-with-GCC-exception
-Group:          System/Libraries
-Requires:       libstdc++6-devel-gcc%{gcc_version}
+%description -n libatomic
+This package contains the GNU Atomic library
+which is a GCC support runtime library for atomic operations not supported
+by hardware.
 
-%description -n libstdc++-devel
-The system GNU C++ development files.
+%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 libstdc++-devel-32bit
-Summary:        The system GNU C++ 32bit development files
-License:        GPL-3.0-with-GCC-exception
-Group:          System/Libraries
-Requires:       libstdc++-devel
-Requires:       libstdc++6-devel-gcc%{gcc_version}-32bit
+%package -n libasan
+Summary: The Address Sanitizer runtime library
 
-%description -n libstdc++-devel-32bit
-The system GNU C++ 32bit development files.
+%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}
 
-%package -n libstdc++-devel-64bit
-Summary:        The system GNU C++ 64bit development files
-License:        GPL-3.0-with-GCC-exception
-Group:          System/Libraries
-Requires:       libstdc++-devel
-Requires:       libstdc++6-devel-gcc%{gcc_version}-64bit
+%description -n libasan-static
+This package contains Address Sanitizer static runtime library.
 
-%description -n libstdc++-devel-64bit
-The system GNU C++ 64bit development files.
+%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}
 
-%package -n gcc-fortran
-Summary:        The system GNU Fortran Compiler
-License:        GPL-3.0+
-Group:          Development/Languages/Fortran
-Requires:       gcc = %{version}
-Requires:       gcc%{gcc_version}-fortran
+%description -n libtsan-static
+This package contains Thread Sanitizer static runtime library.
 
-%description -n gcc-fortran
-The system GNU Fortran Compiler.
+%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 gcc-fortran-32bit
-Summary:        The system GNU Fortran Compiler
-License:        GPL-3.0+
-Group:          Development/Languages/Fortran
-Requires:       gcc%{gcc_version}-fortran-32bit
-Requires:       gcc-fortran = %{version}
+%package -n libubsan-static
+Summary: The Undefined Behavior Sanitizer static library
+Requires: libubsan = %{version}-%{release}
 
-%description -n gcc-fortran-32bit
-The system GNU Fortran Compiler 32 bit support.
+%description -n libubsan-static
+This package contains Undefined Behavior Sanitizer static runtime library.
 
+%package -n liblsan
+Summary: The Leak Sanitizer runtime library
 
-%package -n gcc-fortran-64bit
-Summary:        The system GNU Fortran Compiler
-License:        GPL-3.0+
-Group:          Development/Languages/Fortran
-Requires:       gcc%{gcc_version}-fortran-64bit
-Requires:       gcc-fortran = %{version}
+%description -n liblsan
+This package contains the Leak Sanitizer library
+which is used for -fsanitize=leak instrumented programs.
 
-%description -n gcc-fortran-64bit
-The system GNU Fortran Compiler 64 bit support.
+%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
 
-%package -n gcc-objc
-Summary:        The system GNU Objective C Compiler
-License:        GPL-3.0+
-Group:          Development/Languages/Other
-Requires:       gcc = %{version}
-Requires:       gcc%{gcc_version}-objc
-%ifarch ppc64
-Obsoletes:      gcc-objc-64bit
+%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-10.3.0
+/bin/pwd
+
+%patch1 -p1
+%patch2 -p1
+%patch3 -p1
+%patch4 -p1
+%patch5 -p1
+%patch6 -p1
+%patch7 -p1
+%patch8 -p1
+%patch9 -p1
+%patch10 -p1
+%patch11 -p1
+%patch12 -p1
+%patch13 -p1
+%patch14 -p1
+%patch15 -p1
+%patch16 -p1
+%patch17 -p1
+%patch18 -p1
+%patch19 -p1
+%patch20 -p1
+%patch21 -p1
+%patch22 -p1
+%patch23 -p1
+%patch24 -p1
+%patch25 -p1
+%patch26 -p1
+%patch27 -p1
+%patch28 -p1
+%patch29 -p1
+%patch30 -p1
+%patch31 -p1
+%patch32 -p1
+%patch33 -p1
+%patch34 -p1
+%patch35 -p1
+%patch36 -p1
+%patch38 -p1
+%patch39 -p1
+%patch40 -p1
+%patch41 -p1
+%patch42 -p1
+%patch45 -p1
+%patch46 -p1
+%patch47 -p1
+%patch48 -p1
+%patch49 -p1
+%patch50 -p1
+%patch51 -p1
+%patch52 -p1
+%patch53 -p1
+%patch54 -p1
+%patch55 -p1
+%patch56 -p1
+%patch57 -p1
+%patch58 -p1
+%patch59 -p1
+%patch60 -p1
+%patch61 -p1
+%patch62 -p1
+%patch63 -p1
+%patch64 -p1
+%patch65 -p1
+%patch66 -p1
+%patch67 -p1
+%patch68 -p1
+%patch69 -p1
+%patch70 -p1
+%patch71 -p1
+%patch72 -p1
+%patch73 -p1
+%patch74 -p1
+%patch75 -p1
+%patch76 -p1
+%patch77 -p1
+%patch78 -p1
+%patch79 -p1
+%patch80 -p1
+%patch81 -p1
+%patch82 -p1
+%patch83 -p1
+%patch84 -p1
+%patch85 -p1
+%patch86 -p1
+%patch87 -p1
+%patch88 -p1
+%patch89 -p1
+%patch90 -p1
+%patch91 -p1
+%patch92 -p1
+%patch93 -p1
+%patch94 -p1
+%patch95 -p1
+%patch96 -p1
+%patch97 -p1
+%patch98 -p1
+%patch99 -p1
+%patch100 -p1
+%patch101 -p1
+%patch102 -p1
+%patch103 -p1
+%patch104 -p1
+%patch105 -p1
+%patch106 -p1
+%patch107 -p1
+%patch108 -p1
+%patch109 -p1
+%patch110 -p1
+%patch111 -p1
+%patch112 -p1
+%patch113 -p1
+%patch114 -p1
+%patch115 -p1
+%patch116 -p1
+%patch117 -p1
+%patch118 -p1
+%patch119 -p1
+%patch120 -p1
+%patch121 -p1
+%patch122 -p1
+
+%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 x86_64
+OPT_FLAGS=`echo $OPT_FLAGS|sed -e 's/-fcf-protection/ /g'`
+%endif
+%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
+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"
+export extra_ldflags_libobjc="-Wl,-z,relro,-z,now"
+export FCFLAGS="$OPT_FLAGS"
+CC="$CC" CFLAGS="$OPT_FLAGS" \
+	 CXXFLAGS="`echo " $OPT_FLAGS " | sed 's/ -Wall / /g;s/ -fexceptions / /g' \
+		   |  sed 's/ -Werror=format-security / /'`" \
+	 LDFLAGS="$OPT_LDFLAGS" \
+	 CFLAGS_FOR_TARGET="$OPT_FLAGS" \
+	 CXXFLAGS_FOR_TARGET="$OPT_FLAGS" \
+	 XCFLAGS="$OPT_FLAGS" TCFLAGS="$OPT_FLAGS" GCJFLAGS="$OPT_FLAGS" \
+	 ../configure --prefix=%{_prefix} --mandir=%{_mandir} --infodir=%{_infodir} \
+	   --enable-shared --enable-threads=posix --enable-checking=release \
+	   --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions \
+	   --enable-gnu-unique-object --enable-linker-build-id --with-linker-hash-style=gnu \
+	   --enable-languages=c,c++,fortran${enablelobjc}${enablelada}${enablelgo}${enableld},lto --enable-plugin \
+	   --enable-initfini-array --disable-libgcj --with-isl --without-cloog \
+	   --enable-gnu-indirect-function --build=%{gcc_target_platform} \
+	   --with-stage1-ldflags="$OPT_LDFLAGS" \
+	   --with-boot-ldflags="$OPT_LDFLAGS" --disable-bootstrap \
+%ifarch x86_64
+	   --with-tune=generic \
+	   --with-arch_32=x86-64 \
+	   --disable-multilib
+%endif
+%ifarch aarch64
+	   --with-multilib-list=lp64 \
+	   --enable-bolt
+%endif
+%ifarch riscv64
+	   --with-arch=rv64g --with-abi=lp64d \
+	   --disable-libquadmath --disable-multilib
 %endif
 
-%description -n gcc-objc
-The system GNU Objective C Compiler.
-
-
-
-%package -n gcc-objc-32bit
-Summary:        The system GNU Objective C Compiler
-License:        GPL-3.0+
-Group:          Development/Languages/Other
-Requires:       gcc%{gcc_version}-objc-32bit
-Requires:       gcc-objc = %{version}
-
-%description -n gcc-objc-32bit
-The system GNU Objective C Compiler 32 bit support.
+%ifarch sparc sparcv9 sparc64
+make %{?_smp_mflags} BOOT_CFLAGS="$OPT_FLAGS" bootstrap
+%else
+make %{?_smp_mflags} BOOT_CFLAGS="$OPT_FLAGS" BOOT_LDFLAGS="-pie -Wl,-z,relro,-z,now"
+%endif
 
+# 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 /'`" \
+	XCFLAGS="$OPT_FLAGS" TCFLAGS="$OPT_FLAGS" \
+	../../configure --disable-bootstrap --enable-host-shared \
+	--enable-languages=jit \
+%ifarch x86_64
+	--with-tune=generic \
+	--with-arch_32=x86-64 \
+	--disable-multilib
+%endif
+%ifarch aarch64
+	--with-multilib-list=lp64 \
+	--enable-bolt
+%endif
+%ifarch riscv64
+	--with-arch=rv64g --with-abi=lp64d \
+	--disable-libquadmath --disable-multilib
+%endif
+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 %{?_smp_mflags} -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 %{?_smp_mflags} doc-html-doxygen
+make %{?_smp_mflags} 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}
 
-%package -n gcc-objc-64bit
-Summary:        The system GNU Objective C Compiler
-License:        GPL-3.0+
-Group:          Development/Languages/Other
-Requires:       gcc%{gcc_version}-objc-64bit
-Requires:       gcc-objc = %{version}
+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
 
-%description -n gcc-objc-64bit
-The system GNU Objective C Compiler 64 bit support.
+(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 ../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
 
-%package -n gcc-obj-c++
-Summary:        The system GNU Objective C++ Compiler
-License:        GPL-3.0+
-Group:          Development/Languages/Other
-Requires:       gcc%{gcc_version}-obj-c++
-Requires:       gcc-objc = %{version}
 
-%description -n gcc-obj-c++
-The system GNU Objective C++ Compiler.
+cd obj-%{gcc_target_platform}
 
+TARGET_PLATFORM=%{gcc_target_platform}
 
+# There are some MP bugs in libstdc++ Makefiles
+make %{?_smp_mflags} -C %{gcc_target_platform}/libstdc++-v3
 
-%package -n gcc-PIE
-Summary:        A default configuration to build all binaries in PIE mode
-License:        GPL-3.0+
-Group:          Development/Languages/Other
-Requires:       gcc
+make prefix=%{buildroot}%{_prefix} mandir=%{buildroot}%{_mandir} \
+  infodir=%{buildroot}%{_infodir} install
+%if %{build_ada}
+chmod 644 %{buildroot}%{_infodir}/gnat*
+%endif
 
-%description -n gcc-PIE
-This package contains a configuration file (spec) that changes the
-compilers default setting to build all ELF binaries in the Position
-Independend Executable (PIE) variant. This enables better address
-space randomization (ASLR).
+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
 
-%package -n gcc-ada
-Summary:        The system GNU Ada Compiler
-License:        GPL-3.0+
-Group:          Development/Languages/C and C++
-Requires:       gcc = %{version}
-Requires:       gcc%{gcc_version}-ada
+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
 
-%description -n gcc-ada
-The system GNU Ada Compiler.
+# 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
 
-%package -n gcc-ada-32bit
-Summary:        The system GNU Ada Compiler
-License:        GPL-3.0+
-Group:          Development/Languages/C and C++
-Requires:       gcc%{gcc_version}-ada-32bit
-Requires:       gcc-ada = %{version}
+%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
 
-%description -n gcc-ada-32bit
-The system GNU Ada Compiler 32 bit support.
+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
 
-%package -n gcc-ada-64bit
-Summary:        The system GNU Ada Compiler
-License:        GPL-3.0+
-Group:          Development/Languages/C and C++
-Requires:       gcc%{gcc_version}-ada-64bit
-Requires:       gcc-ada = %{version}
+find %{buildroot} -name \*.la | xargs rm -f
 
-%description -n gcc-ada-64bit
-The system GNU Ada Compiler 64 bit support.
+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
+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
 
-%package -n gcc-go
-Summary:        The system GNU Go Compiler
-License:        GPL-3.0+
-Group:          Development/Languages/C and C++
-Requires:       gcc = %{version}
-Requires:       gcc%{gcc_version}-go
-Requires(post): update-alternatives
-Requires(postun): update-alternatives
+mv -f %{buildroot}%{_prefix}/%{_lib}/libgomp.spec $FULLPATH/
 
-%description -n gcc-go
-The system GNU Go Compiler.
+%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
 
-%package -n gcc-go-32bit
-Summary:        The system GNU Go Compiler
-License:        GPL-3.0+
-Group:          Development/Languages/C and C++
-Requires:       gcc%{gcc_version}-go-32bit
-Requires:       gcc-go = %{version}
+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
 
-%description -n gcc-go-32bit
-The system GNU Go Compiler 32bit support.
+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
+
+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.16.* libgo.so
+%endif
+%if %{build_libquadmath}
+ln -sf ../../../libquadmath.so.0.* libquadmath.so
+%endif
+%if %{build_d}
+ln -sf ../../../libgdruntime.so.1.* libgdruntime.so
+ln -sf ../../../libgphobos.so.1.* 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.6.* libasan.so
+mv ../../../libasan_preinit.o libasan_preinit.o
+%endif
+%if %{build_libubsan}
+ln -sf ../../../libubsan.so.1.* libubsan.so
+%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.16.* libgo.so
+%endif
+%if %{build_libquadmath}
+ln -sf ../../../../%{_lib}/libquadmath.so.0.* libquadmath.so
+%endif
+%if %{build_d}
+ln -sf ../../../../%{_lib}/libgdruntime.so.1.* libgdruntime.so
+ln -sf ../../../../%{_lib}/libgphobos.so.1.* 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.6.* 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.0.* | 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}/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
 
-%package -n gcc-go-64bit
-Summary:        The system GNU Go Compiler
-License:        GPL-3.0+
-Group:          Development/Languages/C and C++
-Requires:       gcc%{gcc_version}-go-64bit
-Requires:       gcc-go = %{version}
+%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-9.so
+ln -sf ../../../../../libgnat-*.so libgnat.so
+ln -sf ../../../../../libgnat-*.so libgnat-9.so
+else
+ln -sf ../../../../../../%{_lib}/libgnarl-*.so libgnarl.so
+ln -sf ../../../../../../%{_lib}/libgnarl-*.so libgnarl-9.so
+ln -sf ../../../../../../%{_lib}/libgnat-*.so libgnat.so
+ln -sf ../../../../../../%{_lib}/libgnat-*.so libgnat-9.so
+fi
+popd
+else
+pushd $FULLPATH/adalib
+if [ "%{_lib}" = "lib" ]; then
+ln -sf ../../../../libgnarl-*.so libgnarl.so
+ln -sf ../../../../libgnarl-*.so libgnarl-9.so
+ln -sf ../../../../libgnat-*.so libgnat.so
+ln -sf ../../../../libgnat-*.so libgnat-9.so
+else
+ln -sf ../../../../../%{_lib}/libgnarl-*.so libgnarl.so
+ln -sf ../../../../../%{_lib}/libgnarl-*.so libgnarl-9.so
+ln -sf ../../../../../%{_lib}/libgnat-*.so libgnat.so
+ln -sf ../../../../../%{_lib}/libgnat-*.so libgnat-9.so
+fi
+popd
+fi
+%endif
 
-%description -n gcc-go-64bit
-The system GNU Go Compiler 64bit support.
+%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.16.* | sed 's,^.*libg,libg,'`' )' > libgo.so
+echo 'INPUT ( %{_prefix}/lib64/'`echo ../../../../lib/libgo.so.16.* | 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.1.* | sed 's,^.*libg,libg,'`' )' > libgdruntime.so
+echo 'INPUT ( %{_prefix}/lib64/'`echo ../../../../lib/libgdruntime.so.1.* | sed 's,^.*libg,libg,'`' )' > 64/libgdruntime.so
+echo 'INPUT ( %{_prefix}/lib/'`echo ../../../../lib/libgphobos.so.1.* | sed 's,^.*libg,libg,'`' )' > libgphobos.so
+echo 'INPUT ( %{_prefix}/lib64/'`echo ../../../../lib/libgphobos.so.1.* | 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.6.* | sed 's,^.*liba,liba,'`' )' > libasan.so
+echo 'INPUT ( %{_prefix}/lib64/'`echo ../../../../lib/libasan.so.6.* | 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/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.16.* | sed 's,^.*libg,libg,'`' )' > libgo.so
+echo 'INPUT ( %{_prefix}/lib/'`echo ../../../../lib64/libgo.so.16.* | 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.1.* | sed 's,^.*libg,libg,'`' )' > libgdruntime.so
+echo 'INPUT ( %{_prefix}/lib/'`echo ../../../../lib64/libgdruntime.so.1.* | sed 's,^.*libg,libg,'`' )' > 32/libgdruntime.so
+echo 'INPUT ( %{_prefix}/lib64/'`echo ../../../../lib64/libgphobos.so.1.* | sed 's,^.*libg,libg,'`' )' > libgphobos.so
+echo 'INPUT ( %{_prefix}/lib/'`echo ../../../../lib64/libgphobos.so.1.* | 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.6.* | sed 's,^.*liba,liba,'`' )' > libasan.so
+echo 'INPUT ( %{_prefix}/lib/'`echo ../../../../lib64/libasan.so.6.* | 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/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}/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 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
 
-%prep 
+# 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.*
+chrpath -d %{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.1.*
+chmod 755 %{buildroot}%{_prefix}/%{_lib}/libgphobos.so.1.*
+%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.6.*
+chrpath -d %{buildroot}%{_prefix}/%{_lib}/libasan.so.6.*
+%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.0.*
+chrpath -d %{buildroot}%{_prefix}/%{_lib}/libtsan.so.0.*
+%endif
+%if %{build_liblsan}
+chmod 755 %{buildroot}%{_prefix}/%{_lib}/liblsan.so.0.*
+chrpath -d %{buildroot}%{_prefix}/%{_lib}/liblsan.so.0.*
+%endif
+%if %{build_go}
+# Avoid stripping these libraries and binaries.
+chmod 644 %{buildroot}%{_prefix}/%{_lib}/libgo.so.16.*
+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
 
-%install
-mkdir -p $RPM_BUILD_ROOT/lib
-mkdir -p $RPM_BUILD_ROOT%{_prefix}/bin
-mkdir -p $RPM_BUILD_ROOT%{_mandir}/man1
-mkdir -p $RPM_BUILD_ROOT%{_infodir}
-mkdir -p $RPM_BUILD_ROOT%{_prefix}/share/doc/packages/gcc-objc/
-mkdir -p $RPM_BUILD_ROOT%{_prefix}/share/doc/packages/gcc-obj-c++/
-# Link all the binaries
-for program in \
-        gcc gcov gcov-dump gcov-tool \
-        g++ \
-        cpp \
-        gfortran \
-        gccgo \
 %if %{build_ada}
-	gnat gnatbind gnatbl gnatchop gnatclean gnatfind gnatkr \
-	gnatlink gnatls gnatmake gnatname gnatprep gnatxref gprmake \
+chmod 755 %{buildroot}%{_prefix}/%{_lib}/libgnarl*so*
+chmod 755 %{buildroot}%{_prefix}/%{_lib}/libgnat*so*
 %endif
-	gcc-ar gcc-nm gcc-ranlib \
-    ; do
-  ln -sf $program-%{gcc_suffix} $RPM_BUILD_ROOT%{_prefix}/bin/$program
+
+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
-# For go and gofmt use alternatives since they are shared with golang
-mkdir -p %{buildroot}%{_sysconfdir}/alternatives
-ln -sf %{_sysconfdir}/alternatives/go %{buildroot}%{_bindir}/go
-ln -sf %{_sysconfdir}/alternatives/gofmt %{buildroot}%{_bindir}/gofmt
-# Link section 1 manpages
-for man1 in \
-        gcc gcov gcov-dump gcov-tool \
-        g++ \
-        cpp \
-        gfortran \
-	gccgo \
-    ; do
-  ln -sf $man1-%{gcc_suffix}.1.gz $RPM_BUILD_ROOT%{_mandir}/man1/$man1.1.gz
+
+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
-# Link info pages
-for info in cpp gcc gfortran ; do
-  ln -sf $info-%{gcc_suffix}.info.gz $RPM_BUILD_ROOT%{_infodir}/$info.info.gz
+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
-# Provide the traditional /lib/cpp that only handles C
-cp $RPM_SOURCE_DIR/cpp $RPM_BUILD_ROOT/lib/
-chmod 755 $RPM_BUILD_ROOT/lib/cpp
-# Provide extra symlinks
-ln -sf g++-%{gcc_suffix} $RPM_BUILD_ROOT%{_prefix}/bin/c++
-ln -sf gcc-%{gcc_suffix} $RPM_BUILD_ROOT%{_prefix}/bin/cc
-ln -sf g++-%{gcc_suffix}.1.gz $RPM_BUILD_ROOT%{_mandir}/man1/c++.1.gz
-ln -sf gcc-%{gcc_suffix}.1.gz $RPM_BUILD_ROOT%{_mandir}/man1/cc.1.gz
-# Install the LTO linker plugin so it is auto-loaded by BFD
-mkdir -p $RPM_BUILD_ROOT%{_prefix}/lib/bfd-plugins
-ln -s `gcc-%{gcc_suffix} -print-file-name=liblto_plugin.so.0.0.0` $RPM_BUILD_ROOT%{_prefix}/lib/bfd-plugins/liblto_plugin.so.0.0.0
-
-dir=`gcc-%{gcc_suffix} -print-prog-name=cc1`
-dir=${dir%/cc1}
-mkdir -p $RPM_BUILD_ROOT/$dir
-cat > $RPM_BUILD_ROOT/$dir/defaults.spec < $FULLPATH/rpmver
 
-%postun -n gcc-go
-if [ $1 -eq 0 ] ; then
-  update-alternatives --remove go %{_bindir}/go-%{gcc_suffix}
+%check
+cd obj-%{gcc_target_platform}
+
+%if %{build_check}
+# run the tests.
+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
 
-%files
-%defattr(-,root,root)
-%{_prefix}/bin/gcc
+# 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 libgquadmath
+
+%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-dump
 %{_prefix}/bin/gcov-tool
+%{_prefix}/bin/gcov-dump
 %{_prefix}/bin/gcc-ar
 %{_prefix}/bin/gcc-nm
 %{_prefix}/bin/gcc-ranlib
-%dir %{_prefix}/lib/bfd-plugins
-%{_prefix}/lib/bfd-plugins/liblto_plugin.so.0.0.0
-%doc %{_mandir}/man1/gcc.1.gz
-%doc %{_mandir}/man1/cc.1.gz
-%doc %{_mandir}/man1/gcov.1.gz
-%doc %{_mandir}/man1/gcov-dump.1.gz
-%doc %{_mandir}/man1/gcov-tool.1.gz
-
-%files -n cpp
-%defattr(-,root,root)
-/lib/cpp
-%{_prefix}/bin/cpp
-%doc %{_mandir}/man1/cpp.1.gz
-
-# Plugins are only enabled for Tumbleweed
-%if 0%{!?sle_version:1}
-%files -n gcc-devel
-%defattr(-,root,root)
-# empty - only for the dependency
+%{_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
+%{_prefix}/bin/%{gcc_target_platform}-gcc-%{gcc_major}
+%{_mandir}/man1/gcc.1*
+%{_mandir}/man1/gcov.1*
+%{_mandir}/man1/gcov-tool.1*
+%{_mandir}/man1/gcov-dump.1*
+%{_mandir}/man1/lto-dump.1*
+%{_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*
+%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
+%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
+%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
+%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
+%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 gcc-c++
-%defattr(-,root,root)
+%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++
-%doc %{_mandir}/man1/g++.1.gz
-%doc %{_mandir}/man1/c++.1.gz
-
-%files -n gcc-fortran
-%defattr(-,root,root)
-%{_prefix}/bin/gfortran
-%doc %{_mandir}/man1/gfortran.1.gz
-
-%files -n gcc-objc
-%defattr(-,root,root)
-# empty - only for the dependency
-
-%files -n gcc-obj-c++
-%defattr(-,root,root)
-# empty - only for the dependency
-
-%files -n gcc-PIE
-%defattr(-,root,root)
-/usr/lib*/gcc/*-suse-linux*/*/defaults.spec
-
-%files -n gcc-locale
-%defattr(-,root,root)
-# empty - only for the dependency
-
-%files -n gcc-info
-%defattr(-,root,root)
-%{_infodir}/cpp.info.gz
-%{_infodir}/gcc.info.gz
-%{_infodir}/gfortran.info.gz
+%{_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
+%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/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/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}/libsupc++.a
+%endif
+%doc rpm.doc/changelogs/gcc/cp/ChangeLog*
 
-%if %{build_ada}
-%files -n gcc-ada
-%defattr(-,root,root)
-%{_prefix}/bin/gnat
-%{_prefix}/bin/gnatbind
-%{_prefix}/bin/gnatbl
-%{_prefix}/bin/gnatchop
-%{_prefix}/bin/gnatclean
-%{_prefix}/bin/gnatfind
-%{_prefix}/bin/gnatkr
-%{_prefix}/bin/gnatlink
-%{_prefix}/bin/gnatls
-%{_prefix}/bin/gnatmake
-%{_prefix}/bin/gnatname
-%{_prefix}/bin/gnatprep
-%{_prefix}/bin/gnatxref
-%{_prefix}/bin/gprmake
+%files -n libstdc++
+%{_prefix}/%{_lib}/libstdc++.so.6*
+# Package symlink to keep compatibility
+%ifarch riscv64
+%{_datadir}/gdb/auto-load/%{_prefix}/%{_lib}/lp64d
 %endif
+%{_datadir}/gdb/auto-load/%{_prefix}/%{_lib}/libstdc*gdb.py*
+%dir %{_prefix}/share/gcc-%{gcc_major}
+%dir %{_prefix}/share/gcc-%{gcc_major}/python
+%{_prefix}/share/gcc-%{gcc_major}/python/libstdcxx
 
 %files -n libstdc++-devel
-%defattr(-,root,root)
-# empty - only for the dependency
-
-%files -n gcc-go
-%defattr(-,root,root)
-%{_bindir}/gccgo
-%{_bindir}/go
-%{_bindir}/gofmt
-%ghost %{_sysconfdir}/alternatives/go
-%ghost %{_sysconfdir}/alternatives/gofmt
-%doc %{_mandir}/man1/gccgo.1.gz
+%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
+%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
+%endif
+%ifnarch sparcv9 sparc64 ppc ppc64 ppc64p7
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libstdc++fs.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 %{separate_bi32}
+%if %{build_libstdcxx_docs}
+%files -n libstdc++-docs
+%{_mandir}/man3/*
+%doc rpm.doc/libstdc++-v3/html
+%endif
 
-%files -n gcc-32bit
-%defattr(-,root,root)
-# empty - only for the dependency
+%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 -n gcc-c++-32bit
-%defattr(-,root,root)
-# empty - only for the dependency
+%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 libstdc++-devel-32bit
-%defattr(-,root,root)
-# empty - only for the dependency
+%files -n libobjc
+%{_prefix}/%{_lib}/libobjc.so.4*
+%endif
 
-%files -n gcc-fortran-32bit
-%defattr(-,root,root)
-# empty - only for the dependency
+%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
 
-%files -n gcc-objc-32bit
-%defattr(-,root,root)
-# empty - only for the dependency
+%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.1*
+%{_prefix}/%{_lib}/libgphobos.so.1*
+%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 -n gcc-ada-32bit
-%defattr(-,root,root)
-# empty - only for the dependency
+%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 gcc-go-32bit
-%defattr(-,root,root)
-# empty - only for the dependency
+%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 %{separate_bi64}
 
-%files -n gcc-64bit
-%defattr(-,root,root)
-# empty - only for the dependency
+%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
 
-%files -n gcc-c++-64bit
-%defattr(-,root,root)
-# empty - only for the dependency
+%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
 
-%files -n libstdc++-devel-64bit
-%defattr(-,root,root)
-# empty - only for the dependency
+%if %{build_libasan}
+%files -n libasan
+%{_prefix}/%{_lib}/libasan.so.6*
+
+%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
 
-%files -n gcc-fortran-64bit
-%defattr(-,root,root)
-# empty - only for the dependency
+%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
 
-%files -n gcc-objc-64bit
-%defattr(-,root,root)
-# empty - only for the dependency
+%if %{build_libtsan}
+%files -n libtsan
+%{_prefix}/%{_lib}/libtsan.so.0*
+
+%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_ada}
-%files -n gcc-ada-64bit
-%defattr(-,root,root)
-# empty - only for the dependency
+%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
 
-%files -n gcc-go-64bit
-%defattr(-,root,root)
-# empty - only for the dependency
+%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.16*
+%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
-* Fri Jul  9 2021 rguenther@suse.com
-- With gcc-PIE add -pie even when -fPIC is specified but we are
-  not linking a shared library.  [boo#1185348]
-- Fix postun of gcc-go alternative.
-* Wed Jun 13 2018 rguenther@suse.com
-- Add gccgo symlink, add go and gofmt as alternatives to support
-  parallel install of golang.  [bnc#1096677]
-* Tue Jun  5 2018 rguenther@suse.com
-- Fix gcc-PIE spec to properly honor -no-pie at link time.
-  [bnc#1096008]
-* Fri Jun  9 2017 rguenther@suse.com
-- Fix gcc-devel guard to use %%sle_version.  [bnc#1043590]
-* Wed Jun  7 2017 rguenther@suse.com
-- Guard gcc-devel so it is only built on Tumbleweed.
-- Remove bogus link to versioned g++.info file which doesn't exist.
-  Instead refer to gcc.info from the g++ info directory entry.
-  [bnc#922419]
-* Tue Jun  6 2017 mliska@suse.cz
-- Include gcov-tool and gcov-dump binaries.
-* Thu Apr 13 2017 rguenther@suse.com
-- Remove README in empty packages only required for SLE11 and older.
-- Remove now empty %%build section.
-* Tue Apr  4 2017 rguenther@suse.com
-- Fix dependencies of libstdc++-devel-{32,64}-bit.
-* Thu Mar 23 2017 rguenther@suse.com
-- Switch gcc to default 7.
-- Remove unrelated README.packaging.
-* Fri Feb 10 2017 rguenther@suse.com
-- Enable Ada for s390x.
-* Mon Jan 23 2017 rguenther@suse.com
-- Remove java related packages, those are in a separate gcc-java now.
-* Thu Aug 18 2016 rguenther@suse.com
-- Add gcc-devel package.
-* Wed Apr 27 2016 rguenther@suse.com
-- Switch gcc to default 6.
-* Thu Apr 14 2016 rguenther@suse.com
-- Enable Ada for ppc64le and aarch64.
-* Thu May 21 2015 rguenther@suse.com
-- Properly query gcc-%%gcc_suffix for paths.
-* Tue May 19 2015 rguenther@suse.com
-- Fix bogus requires to gcc5-c++-{32,64}bit.
-* Fri May  8 2015 rguenther@suse.com
-- Adjust for GCC 5 package renames.
-* Mon Apr 20 2015 rguenther@suse.com
-- Switch gcc to default 5.
-- Add gcc-go{,-32bit,-64bit} packages.
-* Mon Mar  2 2015 schwab@suse.de
-- Add gcc-ada-32bit and gcc-ada-64bit packages only if building Ada
-* Wed Feb 25 2015 rguenther@suse.com
-- Add gcc-ada-32bit and gcc-ada-64bit packages.
-* Wed Feb  4 2015 meissner@suse.com
-- add a gcc-PIE subpackage, which enables building PIE binaries
-  by default using the defaults.spec file. bsc#912298
-* Mon Aug  4 2014 rguenther@suse.com
-- Add libstdc++-devel-32bit and libstdc++-devel-64bit packages.
-  [bnc#890226]
-* Fri Mar 21 2014 rguenther@suse.com
-- Link to the system compiler LTO plugin from /usr/lib/bfd-plugins.
-* Tue Feb  4 2014 rguenther@suse.com
-- Remove gcc-z9 wrapper which is obsolete.
-* Mon Dec  2 2013 rguenther@suse.com
-- Move gcc-ar, gcc-nm and gcc-ranlib to the gcc package instead
-  of packaging them separately.
-* Wed Jun 19 2013 rguenther@suse.com
-- Package gcc-ar, gcc-nm and gcc-ranlib wrapping ar, nm and ranlib
-  in a plugin-aware fashion.
-* Mon May 27 2013 rguenther@suse.com
-- Switch gcc to default 4.8.
-* Mon Jan  7 2013 rguenther@suse.com
-- Re-enable Ada for ppc64.
-* Thu Dec 13 2012 rguenther@suse.com
-- Add BuildRequires to gcc$version, required for cc1 path detection.
-* Wed Nov 28 2012 rguenther@suse.com
-- Rework gcc-info.
-  * Install symlinks to the versioned info files and adjust
-    install_info calls.  [bnc#756182]
-  * Provide uninstall hook that removes the alias entries.
-* Thu Oct  4 2012 dmueller@suse.com
-- remove gcc-ada subpackage for those architectures that
-  don't have a gccXX-ada package
-* Wed Apr 18 2012 rguenther@suse.com
-- Switch gcc to default 4.7.
-* Fri Jan 27 2012 rguenther@suse.com
-- Change licenses to follow SPDX convention.
-* Mon Sep 26 2011 dmueller@suse.de
-- use the target gcc binary for finding the right cc1 path
-* Wed May 11 2011 rguenther@novell.com
-- Switch gcc to default 4.6.
-* Thu Feb 10 2011 rguenther@novell.com
-- Fix licenses to match those of the system compiler.  [bnc#670658]
-* Tue Jan 25 2011 rguenther@novell.com
-- Fix string quoting.  [bnc#666416]
-* Wed Jan 12 2011 rguenther@novell.com
-- Uglify spec file formatting.
-* Fri Dec 10 2010 rguenther@novell.com
-- Add info directory aliases for unversioned variants of the
-  GCC user manuals.  [bnc#635355]
-* Mon Nov 29 2010 rguenther@novell.com
-- Drop libffi packages.
-* Fri Feb 26 2010 rguenther@novell.com
-- Fix gcc-c++-32bit and gcc-c++-64bit again.
-* Thu Feb 25 2010 rguenther@suse.de
-- Drop c++_compiler provides from gcc-c++-32bit and gcc-c++-64bit.
-* Thu Feb 25 2010 rguenther@suse.de
-- Re-add gcc-c++-32bit and gcc-c++-64bit packages.
-* Tue Feb 16 2010 coolo@novell.com
-- Switch gcc to default 4.5.
-* Mon Apr 27 2009 rguenther@suse.de
-- Switch gcc default to 4.4.
-* Mon Feb 16 2009 rguenther@suse.de
-- Enable links for classpath binaries and manpages again.
-* Fri Jan  9 2009 rguenther@suse.de
-- On ppc64 obsolete gcc-objc-64bit by gcc-objc.
-* Thu Dec  4 2008 matz@suse.de
-- Add new gcc-z9 package on s390 and s390x to change the
-  default -march and -mtune settings.
-* Wed May  7 2008 rguenther@suse.de
-- Make dependencies between the gcc subpackages versioned. [bnc#385305]
-* Fri Nov 23 2007 rguenther@suse.de
-- Make gcc-gij dependency of gcc-java a recommendation, all java
-  tools are back to the gcc-java package.  Require libgcj-devel
-  from gcc-java.
-- Revert /lib/cpp changes.
-* Fri Nov 16 2007 rguenther@suse.de
-- For now disable symlinking of binaries and manpages that
-  conflict with the classpath package.
-* Tue Nov 13 2007 rguenther@suse.de
-- Make /lib/cpp traditional and avoid GCC and target specific
-  defines.
-* Tue Oct 30 2007 rguenther@suse.de
-- Add gcc-gij dependency to gcc-java as it contains many of the
-  tools formerly packaged in the gcc-java package.
-* Mon Sep 24 2007 rguenther@suse.de
-- Switch gcc default to 4.3.
-* Fri Jul 27 2007 rguenther@suse.de
-- Fix typo.
-* Tue Jul 24 2007 rguenther@suse.de
-- Add 32bit and 64bit variants of gcc-gij.  [#293423]
-* Fri Jul  6 2007 rguenther@suse.de
-- Mark ppc64 as separate bi-32.
-* Thu Jun 14 2007 ro@suse.de
-- Do not mark README.packaging as NoSource. (again)
-* Fri Jun  8 2007 rguenther@suse.de
-- Switch gcc default to 4.2.  [#275939]
-* Tue Apr 24 2007 rguenther@suse.de
-- Do not link to grmic and grmiregistry, they conflict with
-  the classpath package versions.
-* Tue Jan 16 2007 rguenther@suse.de
-- Do not mark README.packaging as NoSource.
-* Thu Nov  9 2006 rguenther@suse.de
-- Remove gcc-c++-32bit and gcc-c++-64bit packages.
-* Tue Oct 31 2006 dmueller@suse.de
-- don't build as root
-* Mon Oct 30 2006 rguenther@suse.de
-- Make gcc architecture dependent again.  [#215971]
-* Thu Oct 26 2006 rguenther@suse.de
-- Add dependencies to the gcc and non-32/64bit packages.  [#215217]
-* Tue Sep 19 2006 rguenther@suse.de
-- New gcc-gij package.
-* Fri Aug 25 2006 rguenther@suse.de
-- Add 32bit and 64bit support packages to gcc, gcc-c++, gcc-fortran,
-  gcc-objc and libffi-devel.
-* Thu Aug 24 2006 rguenther@suse.de
-- Make gcc require cpp to pull in /lib/cpp.
-* Fri Aug 18 2006 rguenther@suse.de
-- gcc obsoletes gcc-mudflap which is no longer.
-* Mon Aug  7 2006 rguenther@suse.de
-- Provide gcc-mudflap, gcc-info and gcc-locale packages [#197515].
-* Fri Jul 14 2006 rguenther@suse.de
-- New package.
+* Tue Oct 10 2023 Xiong Zhou  - 10.3.1-38
+- Type:Backport
+- ID:NA
+- SUG:NA
+- DESC: Fix CVE-2023-4039.
+
+* Wed Jun 28 2023 dingguangya  - 10.3.1-37
+- Type:Spec
+- ID:NA
+- SUG:NA
+- DESC: Sync patch from openeuler/gcc
+
+* Mon Jun 19 2023 dingguangya  - 10.3.1-36
+- Type:Spec
+- ID:NA
+- SUG:NA
+- DESC: Sync patch from openeuler/gcc
+
+* Wed Jun 14 2023 Wang Ding  - 10.3.1-35
+- Type:Spec
+- ID:NA
+- SUG:NA
+- DESC: To resolve the spec 548 fluctuation problem, revert GCC commit.
+
+* Fri Jun 9 2023 Wang Ding  - 10.3.1-34
+- Type:Sync
+- ID:NA
+- SUG:NA
+- DESC:Add PGO kernel option to support PGO kernel
+
+* Fri Jun 9 2023 huangxiaoquan  - 10.3.1-33
+- Type:Sync
+- ID:NA
+- SUG:NA
+- DESC:Sync patch from openeuler/gcc
+
+* Thu Jun 8 2023 huangxiaoquan  - 10.3.1-32
+- Type:Sync
+- ID:NA
+- SUG:NA
+- DESC:Sync patch from openeuler/gcc
+
+* Sat Jun 3 2023 Wang Ding  - 10.3.1-31
+- Type:Sync
+- ID:NA
+- SUG:NA
+- DESC:Revert patch97 and correct the incorrect patch number
+
+* Fri Jun 2 2023 Wang Ding  - 10.3.1-30
+- Type:Sync
+- ID:NA
+- SUG:NA
+- DESC:Sync patch from openeuler/gcc
+
+* Wed May 24 2023 liyancheng <412998149@qq.com> - 10.3.1-29
+- Type:Revert
+- ID:NA
+- SUG:NA
+- DESC:Revert patch89
+       The glibc version of oe-22.03 is 2.34, so revert it
+
+* Mon May 22 2023 huangxiaoquan  - 10.3.1-28
+- Type:Sync
+- ID:NA
+- SUG:NA
+- DESC:Sync patch from openeuler/gcc
+
+* Wed Apr 12 2023 huangxiaoquan  - 10.3.1-27
+- Type:enhancement
+- ID:NA
+- SUG:NA
+- DESC:enable isl and add --with-isl
+
+* Fri Mar 24 2023 huangxiaoquan  - 10.3.1-26
+- Type:SPEC
+- ID:NA
+- SUG:NA
+- DESC:Enable-languages uses variables
+
+* Mon Mar 20 2023 huangxiaoquan  - 10.3.1-25
+- Type:Revert
+- ID:NA
+- SUG:NA
+- DESC:Revert without pie option
+
+* Thu Mar 9 2023 huangxiaoquan  - 10.3.1-24
+- Type:Fix
+- ID:NA
+- SUG:NA
+- DESC:Add pie and delete rpath in libgfortran
+
+* Sun Feb 26 2023 huitailang <804544223@qq.com> - 10.3.1-23
+- Type:Sync
+- ID:NA
+- SUG:NA
+- DESC:Sync patch from openeuler/gcc
+       Fix sysroot option once processed.
+
+* Tue Jan 10 2023 liyancheng <412998149@qq.com> - 10.3.1-22
+- Type:Sync
+- ID:NA
+- SUG:NA
+- DESC:Sync patch from openeuler/gcc
+       Fix conflict with glibc 2.36.
+
+* Fri Dec 30 2022 Xiong Zhou  - 10.3.1-21
+- Type:Sync
+- ID:NA
+- SUG:NA
+- DESC:Sync patch from openeuler/gcc
+       Fix typo in tree-ssa-reassoc.c.
+
+* Fri Dec 23 2022 benniaobufeijiushiji  - 10.3.1-20
+- Type:Sync
+- ID:NA
+- SUG:NA
+- DESC:Sync patch from openeuler/gcc
+       Bugfix for loop-distribution, semi-relayout and mull64.
+
+* Mon Dec 19 2022 liyancheng <412998149@qq.com> - 10.3.1-19
+- Type:Fix
+- ID:NA
+- SUG:NA
+- DESC:Delete rpath in liblsan,libasan,libubsan,libtsan
+
+* Thu Dec 8 2022 liyancheng <412998149@qq.com> - 10.3.1-18
+- Type:Sync
+- ID:NA
+- SUG:NA
+- DESC:Sync patch from openeuler/gcc, fix wrong date
+
+* Thu Dec 1 2022 benniaobufeijiushiji  - 10.3.1-17
+- Type:Sync
+- ID:NA
+- SUG:NA
+- DESC:Sync patch from openeuler/gcc
+
+* Fri Sep 16 2022 eastb233  - 10.3.1-16
+- Type:Sync
+- ID:NA
+- SUG:NA
+- DESC:Sync patch from openeuler/gcc
+
+* Thu Sep 8 2022 benniaobufeijiushiji  - 10.3.1-15
+- Type:Sync
+- ID:NA
+- SUG:NA
+- DESC:Sync patch from openeuler/gcc
+
+* Tue Aug 16 2022 benniaobufeijiushiji  - 10.3.1-14
+- Type:Revert
+- ID:NA
+- SUG:NA
+- DESC:Remove 2 unnecessary patches
+
+* Mon Aug 8 2022 benniaobufeijiushiji  - 10.3.1-13
+- Type:Sync
+- ID:NA
+- SUG:NA
+- DESC:Sync patch from openeuler/gcc
+
+* Fri Jul 08 2022 zhaomengmeng  - 10.3.1-12
+- Type:SPEC
+- ID:NA
+- SUG:NA
+- DESC:Enable libgccjit
+
+* Fri May 6 2022 liyancheng <412998149@qq.com> - 10.3.1-11
+- Type:Sync
+- ID:NA
+- SUG:NA
+- DESC:Sync patch from openeuler/gcc
+
+* Tue Mar 22 2022 benniaobufeijiushiji  - 10.3.1-10
+- Type:Sync
+- ID:NA
+- SUG:NA
+- DESC:Sync patch from openeuler/gcc
+
+* Wed Mar 2 2022 benniaobufeijiushiji  - 10.3.1-9
+- Type:Sync
+- ID:NA
+- SUG:NA
+- DESC:Sync patch from openeuler/gcc
+
+* Tue Mar 1 2022 benniaobufeijiushiji  - 10.3.1-8
+- Type:SPEC
+- ID:NA
+- SUG:NA
+- DESC:Remove date in release
+
+* Wed Feb 23 2022 benniaobufeijiushiji  - 10.3.1-20220223.7
+- Type:Sync
+- ID:NA
+- SUG:NA
+- DESC:Sync patch from openeuler/gcc
+
+* Wed Jan 05 2022 eastb233  - 10.3.1-20220105.6
+- Type:SPEC
+- ID:NA
+- SUG:NA
+- DESC:Return the ownership of gdb/auto-load folder to gdb-headless
+
+* Tue Sep 14 2021 eastb233  - 10.3.1-20210914.5
+- Type:Sync
+- ID:NA
+- SUG:NA
+- DESC:Sync patch from openeuler/gcc
+
+* Fri Aug 27 2021 eastb233  - 10.3.1-20210827.4
+- Type:RISC-V
+- ID:NA
+- SUG:NA
+- DESC:Adapts to the RISC-V backend construction
+
+* Thu Aug 19 2021 eastb233  - 10.3.1-20210819.3
+- Type:Sync
+- ID:NA
+- SUG:NA
+- DESC:Sync patch from openeuler/gcc
+
+* Wed Jul 28 2021 eastb233  - 10.3.0-20210728.2
+- Type:Sync
+- ID:NA
+- SUG:NA
+- DESC:Sync patch from openeuler/gcc
+
+* Tue Jul 27 2021 eastb233  - 10.3.0-20210727.1
+- Type:Init
+- ID:NA
+- SUG:NA
+- DESC:Init GCC 10.3.0 repository
diff --git a/sources b/sources
index e69de29..c06ca90 100644
--- a/sources
+++ b/sources
@@ -0,0 +1 @@
+443c15b92614a3ce8f22e3b24ca2226a  gcc-10.3.0.tar.xz
-- 
cgit v1.2.3