summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCoprDistGit <infra@openeuler.org>2023-10-17 02:15:03 +0000
committerCoprDistGit <infra@openeuler.org>2023-10-17 02:15:03 +0000
commitd82826d1a1c7ea45a761dfbf76b879712c7332ec (patch)
tree973a28470803b27c914f813f43d43f8932763ea3
parentb868000cf68cec0c9cd45fbf89a83173dea7c5eb (diff)
automatic import of gccopeneuler22.03_LTS
-rw-r--r--.gitignore1
-rw-r--r--0001-libquadmath-Enable-libquadmath-on-kunpeng.patch473
-rw-r--r--0002-Backport-cselim-Extend-to-check-non-trapping-for-mor.patch318
-rw-r--r--0003-version-Set-version-to-10.3.1.patch31
-rw-r--r--0004-Backport-tree-optimization-Avoid-issueing-loads-in-S.patch138
-rw-r--r--0005-Backport-tree-optimization-Fix-load-eliding-in-SM.patch66
-rw-r--r--0006-simdmath-Enable-simdmath-on-kunpeng.patch289
-rw-r--r--0007-Vect-Enable-skipping-vectorization-on-reduction-chai.patch68
-rw-r--r--0008-Backport-tree-optimization-Add-checks-to-avoid-spoil.patch97
-rw-r--r--0009-Backport-expand-Simplify-removing-subregs-when-expan.patch141
-rw-r--r--0010-Backport-tree-optimization-94963-avoid-bogus-uninit-.patch98
-rw-r--r--0011-simdmath-Enable-64-bits-simd-when-test-simd_pcs_attr.patch23
-rw-r--r--0012-fp-model-Enable-fp-model-on-kunpeng.patch397
-rw-r--r--0013-LoopElim-Redundant-loop-elimination-optimization.patch499
-rw-r--r--0014-Backport-StructReorg-Structure-reorganization-optimi.patch5966
-rw-r--r--0015-CompleteStructReorg-Complete-Structure-Reorganizatio.patch2134
-rw-r--r--0016-StructReorg-Bugfix-in-certain-scenarios.patch486
-rw-r--r--0017-mcmodel-Enable-mcmodel-medium-on-kunpeng.patch622
-rw-r--r--0018-StructReorderFields-Structure-reorder-fields.patch5370
-rw-r--r--0019-StructReorderFields-Fix-bugs-and-improve-mechanism.patch296
-rw-r--r--0020-Backport-vect-Fix-an-ICE-in-vect_recog_mask_conversi.patch128
-rw-r--r--0021-mcmodel-Bugfix-for-mcmodel-medium-on-x86.patch23
-rw-r--r--0022-StructReorderFields-Fix-pointer-layer-check-bug.patch167
-rw-r--r--0023-StructReorderFields-Add-pointer-offset-check.patch87
-rw-r--r--0024-StructReorderFields-Add-lto-and-whole-program-gate.patch90
-rw-r--r--0025-AutoPrefetch-Support-cache-misses-profile.patch669
-rw-r--r--0026-AutoFDO-Enable-discriminator-and-MCF-algorithm-on-Au.patch353
-rw-r--r--0027-Autoprefetch-Support-auto-feedback-prefetch.patch1000
-rw-r--r--0028-AutoPrefetch-Handle-the-case-that-the-basic-block-br.patch151
-rw-r--r--0029-AutoBOLT-Support-saving-feedback-count-info-to-ELF-s.patch548
-rw-r--r--0030-AutoBOLT-Add-bolt-linker-plugin-2-3.patch21748
-rw-r--r--0031-AutoBOLT-Enable-BOLT-linker-plugin-on-aarch64-3-3.patch1945
-rw-r--r--0032-Autoprefetch-Prune-invaild-loops-containing-edges-wh.patch82
-rw-r--r--0033-AutoFdo-Fix-memory-leaks-in-autofdo-and-autoprefetch.patch130
-rw-r--r--0034-Backport-sanitizer-Fix-asan-against-glibc-2.34-PR100.patch72
-rw-r--r--0035-ccmp-Add-another-optimization-opportunity-for-ccmp-i.patch342
-rw-r--r--0036-StructReorg-Refactoring-reorder-fields-to-struct-lay.patch1115
-rw-r--r--0038-DFE-Add-Dead-Field-Elimination-in-Struct-Reorg.patch902
-rw-r--r--0039-Backport-ipa-sra-Fix-thinko-when-overriding-safe_to_.patch143
-rw-r--r--0040-Backport-ifcvt-Allow-constants-for-noce_convert_mult.patch59
-rw-r--r--0041-Backport-Register-sysroot-in-the-driver-switches-tab.patch40
-rw-r--r--0042-DFE-Fix-bugs.patch665
-rw-r--r--0045-Transposed-SLP-Enable-Transposed-SLP.patch3009
-rw-r--r--0046-ArrayWidenCompare-Add-a-new-optimization-for-array-c.patch1982
-rw-r--r--0047-DFE-Fix-the-bug-caused-by-inconsistent-types.patch379
-rw-r--r--0048-Struct-Reorg-Type-simplify-limitation-when-in-struct.patch146
-rw-r--r--0049-build-Add-some-file-right-to-executable.patch21
-rw-r--r--0050-Backport-phiopt-Optimize-x-1024-0-to-int-x-10-PR9769.patch186
-rw-r--r--0051-Backport-phiopt-Fix-up-conditional_replacement-PR993.patch92
-rw-r--r--0052-Backport-phiopt-Handle-bool-in-two_value_replacement.patch122
-rw-r--r--0053-Backport-phiopt-Optimize-x-__builtin_clz-x-32-in-GIM.patch256
-rw-r--r--0054-Backport-phiopt-Optimize-x-__builtin_clz-x-32-in-GIM.patch69
-rw-r--r--0055-Backport-phiopt-Optimize-x-0-y-y-to-x-31-y-PR96928.patch218
-rw-r--r--0056-Backport-phiopt-Optimize-x-y-cmp-z-PR94589.patch1067
-rw-r--r--0057-Backport-Add-support-for-__builtin_bswap128.patch253
-rw-r--r--0058-Backport-tree-optimization-95393-fold-MIN-MAX_EXPR-g.patch113
-rw-r--r--0059-Backport-Add-a-couple-of-A-CST1-CST2-match-and-simpl.patch91
-rw-r--r--0060-Backport-Optimize-x-0-y-y-to-x-31-y-in-match.pd.patch155
-rw-r--r--0061-Backport-Replace-conditional_replacement-with-match-.patch249
-rw-r--r--0062-Backport-Allow-match-and-simplified-phiopt-to-run-in.patch174
-rw-r--r--0063-Backport-Improve-match_simplify_replacement-in-phi-o.patch259
-rw-r--r--0064-Backport-phiopt-Use-gphi-phi-instead-of-gimple-phi-s.patch103
-rw-r--r--0065-Backport-Optimize-x-bswap-x-0-in-tree-ssa-phiopt.patch212
-rw-r--r--0066-Backport-tree-optimization-102880-make-PHI-OPT-recog.patch251
-rw-r--r--0067-Backport-tree-Add-vector_element_bits-_tree-PR94980-.patch250
-rw-r--r--0068-Backport-Lower-VEC_COND_EXPR-into-internal-functions.patch1063
-rw-r--r--0069-Backport-gimple-match-Add-a-gimple_extract_op-functi.patch379
-rw-r--r--0070-Backport-aarch64-Fix-subs_compare_2.c-regression-PR1.patch1004
-rw-r--r--0071-PHIOPT-Disable-the-match-A-CST1-0-when-the-CST1-is-n.patch31
-rw-r--r--0072-Struct-Reorg-Merge-struct_layout-pass-into-struct_re.patch1770
-rw-r--r--0073-PHIOPT-Add-A-B-op-CST-B-match-and-simplify-optimizat.patch89
-rw-r--r--0074-FORWPROP-Fold-series-of-instructions-into-mul.patch130
-rw-r--r--0075-FORWPROP-Fold-series-of-instructions-into-umulh.patch105
-rw-r--r--0076-Struct-Reorg-Fix-speccpu2006-462-double-free-I60YUV.patch38
-rw-r--r--0077-Struct-Reorg-Add-Safe-Structure-Pointer-Compression.patch1193
-rw-r--r--0078-Loop-distribution-Add-isomorphic-stmts-analysis.patch1007
-rw-r--r--0079-loop-vect-Transfer-arrays-using-registers-between-lo.patch267
-rw-r--r--0080-Struct-Reorg-Add-Unsafe-Structure-Pointer-Compressio.patch1061
-rw-r--r--0081-Loop-distribution-Insert-temp-arrays-built-from-isom.patch826
-rw-r--r--0082-Revert-Backport-tree-optimization-102880-make-PHI-OP.patch206
-rw-r--r--0083-Struct-reorg-Add-struct-semi-relayout-optimize.patch1297
-rw-r--r--0084-MULL64-Disable-mull64-transformation-by-default.patch64
-rw-r--r--0085-loop-distribution-Bugfix-for-loop-distribution.patch58
-rw-r--r--0086-semi-relayout-Bugfix-for-struct-semi-relayout.patch26
-rw-r--r--0087-Backport-tree-optimization-97238-fix-typo-causing-IC.patch55
-rw-r--r--0088-Backport-fix-typo-causing-ICE.patch25
-rw-r--r--0089-State-sysroot-option-as-validated-once-processed.patch30
-rw-r--r--0090-bogus-Wstringop-overflow-with-VLA-of-elements-larger.patch129
-rw-r--r--0091-phiopt2-Add-option-to-control-the-simplify.patch183
-rw-r--r--0092-gimple-Factor-the-code-to-avoid-depending-auto-featu.patch170
-rw-r--r--0093-StructReorg-Fix-escape_cast_another_ptr-check-bug.patch112
-rw-r--r--0094-Backport-Fix-zero-masking-for-vcvtps2ph-when-dest-op.patch172
-rw-r--r--0095-Struct-reorg-Fix-the-use-of-as_a.patch49
-rw-r--r--0096-libquadmath-Revert-Enable-libquadmath-on-kunpeng.patch474
-rw-r--r--0097-libquadmath-refactor-Enable-libquadmath-on-kunpeng.patch197
-rw-r--r--0098-AArch64-Rewrite-the-tsv110-option.patch114
-rw-r--r--0099-Struct-Reorg-Add-escape-propagate-on-external-functi.patch258
-rw-r--r--0100-PGO-kernel-Add-fkernel-pgo-option-to-support-PGO-ker.patch46
-rw-r--r--0101-To-resolve-the-SPEC-.548-fluctuation-problem-revert-.patch26
-rw-r--r--0102-GOMP-Enabling-moutline-atomics-improves-libgomp-perf.patch34
-rw-r--r--0103-test-Add-option-ftree-fold-phiopt-to-avoid-fail-NFC.patch143
-rw-r--r--0104-aarch64-Use-local-frame-vars-in-shrink-wrapping-code.patch348
-rw-r--r--0105-aarch64-Avoid-a-use-of-callee_offset.patch72
-rw-r--r--0106-aarch64-Explicitly-handle-frames-with-no-saved-registers.patch47
-rw-r--r--0107-aarch64-Add-bytes_below_saved_regs-to-frame-info.patch232
-rw-r--r--0108-aarch64-Add-bytes_below_hard_fp-to-frame-info.patch83
-rw-r--r--0109-aarch64-Tweak-aarch64_save-restore_callee_saves.patch220
-rw-r--r--0110-aarch64-Only-calculate-chain_offset-if-there-is-a-chain.patch43
-rw-r--r--0111-aarch64-Rename-locals_offset-to-bytes_above_locals.patch90
-rw-r--r--0112-aarch64-Rename-hard_fp_offset-to-bytes_above_hard_fp.patch147
-rw-r--r--0113-aarch64-Tweak-frame_size-comment.patch34
-rw-r--r--0114-aarch64-Measure-reg_offset-from-the-bottom-of-the-frame.patch194
-rw-r--r--0115-aarch64-Simplify-top-of-frame-allocation.patch54
-rw-r--r--0116-aarch64-Minor-initial-adjustment-tweak.patch37
-rw-r--r--0117-aarch64-Tweak-stack-clash-boundary-condition.patch124
-rw-r--r--0118-aarch64-Put-LR-save-probe-in-first-16-bytes.patch269
-rw-r--r--0119-aarch64-Simplif-yprobe-of-final-frame-allocation.patch98
-rw-r--r--0120-aarch64-Explicitly-record-probe-registers-in-frame-info.patch275
-rw-r--r--0121-aarch64-Remove-below_hard_fp_saved_regs_size.patch158
-rw-r--r--0122-aarch64-Make-stack-smash-canary-protect-saved-registers.patch297
-rw-r--r--cpp3
-rw-r--r--gcc.spec3554
-rw-r--r--sources1
123 files changed, 76208 insertions, 632 deletions
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 <bule1@huawei.com>
+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 <yangyang305@huawei.com>
+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<double>(s_1) and MEM<long>(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 <name_to_bb>
++struct refs_hasher : free_ptr_hash<ref_to_bb>
+ {
+- 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<tree> *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<tree> *m_nontrapping;
+
+ /* The hash table for remembering what we've seen. */
+- hash_table<ssa_names_hasher> m_seen_ssa_names;
++ hash_table<refs_hasher> 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 <z.zhanghaijian@huawei.com>
+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 <z.zhanghaijian@huawei.com>
+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<mem_ref_loc> 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<edge> 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 <z.zhanghaijian@huawei.com>
+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<edge> 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<edge> 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 <bule1@huawei.com>
+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=<number> 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 <zhoukaipeng3@huawei.com>
+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 <yangyang305@huawei.com>
+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 <z.zhanghaijian@huawei.com>
+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 <emmintrin.h>
+ __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 <z.zhanghaijian@huawei.com>
+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<edge> 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 <bule1@huawei.com>
+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 <bule1@huawei.com>
+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 <xiezhiheng@huawei.com>
+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<tree> * 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<tree> *);
++
++/* 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<tree> *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<tree> *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 <SSA_NAME (bb1), 0 (bb2), 0 (bb3)>
++*/
++static bool
++check_uses_phi (const_tree ssa_name, gimple *stmt, hash_set<tree> *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,
++ <bb 1>
++ if (cond)
++ goto <bb 2>
++ else
++ goto <bb 3>
++
++ <bb 2>
++ # _tmp2 = PHI <0 (bb 1), _tmp3 (bb 3)>
++ {BODY}
++ if (cond)
++ goto <bb 3>
++ else
++ goto <bb 4>
++
++ <bb 3>
++ # _tmp3 = PHI <0 (bb 1), _tmp2 (bb 2)>
++ {BODY}
++ if (cond)
++ goto <bb 2>
++ else
++ goto <bb 4>
++
++ <bb 4>
++ ...
++ */
++ 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<tree> *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
++ <pre bb>
++ arg1 = base (rhs11) + cst (rhs12); [def1]
++ goto <bb 0>
++
++ <bb 2>
++ arg2 = result (rhs21) + cst (rhs22); [def2]
++
++ <bb 0>
++ # result = PHI <arg1 (pre bb), arg2 (bb 2)>
++ _v = *result; [g01]
++ if (_v == 0) [g02]
++ goto <bb 1>
++ else
++ goto <bb 2>
++
++ <bb 1>
++ _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 <bb 2>
++ else
++ goto <bb 1>
++ */
++ 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
++ <bb 1>
++ _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<tree> *hset = new hash_set<tree>;
++ 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 <xiezhiheng@huawei.com>
+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
++<http://www.gnu.org/licenses/>. */
++
++/* 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 <apinski@cavium.com>
++
++This file is part of GCC.
++
++GCC is free software; you can redistribute it and/or modify it under
++the terms of the GNU General Public License as published by the Free
++Software Foundation; either version 3, or (at your option) any later
++version.
++
++GCC is distributed in the hope that it will be useful, but WITHOUT ANY
++WARRANTY; without even the implied warranty of MERCHANTABILITY or
++FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
++for more details.
++
++You should have received a copy of the GNU General Public License
++along with GCC; see the file COPYING3. If not see
++<http://www.gnu.org/licenses/>. */
++
++/* 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<srtype> types;
++ auto_vec_del<srfunction> 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<srdecl*>&);
++ void check_uses (srdecl *decl, vec<srdecl*>&);
++ void check_use (srdecl *decl, gimple *stmt, vec<srdecl*>&);
++ void check_type_and_push (tree newdecl, srtype *type, vec<srdecl*> &worklist, gimple *stmt);
++ void check_other_side (srdecl *decl, tree other, gimple *stmt, vec<srdecl*> &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<tree> 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<a> 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 <gasm*>(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<greturn*>(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 <gassign *> (stmt));
++ break;
++ case GIMPLE_CALL:
++ maybe_record_call (node, as_a <gcall *> (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 = <alloc_func> (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<srdecl*> &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<srdecl*> &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<srdecl*> &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<srdecl*> &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 <gasm*>(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<srdecl*> &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<srdecl *> 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<tree> params;
++ push_function_arg_decls (&params, decl);
++ vec<ipa_adjusted_param, va_gc> *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<tree> 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<tree> 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 <gassign *> (stmt), gsi);
++ case GIMPLE_CALL:
++ return rewrite_call (as_a <gcall *> (stmt), gsi);
++ case GIMPLE_COND:
++ return rewrite_cond (as_a <gcond *> (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 <apinski@cavium.com>
++
++This file is part of GCC.
++
++GCC is free software; you can redistribute it and/or modify it under
++the terms of the GNU General Public License as published by the Free
++Software Foundation; either version 3, or (at your option) any later
++version.
++
++GCC is distributed in the hope that it will be useful, but WITHOUT ANY
++WARRANTY; without even the implied warranty of MERCHANTABILITY or
++FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
++for more details.
++
++You should have received a copy of the GNU General Public License
++along with GCC; see the file COPYING3. If not see
++<http://www.gnu.org/licenses/>. */
++
++#ifndef IPA_STRUCT_REORG_H
++#define IPA_STRUCT_REORG_H
++
++namespace struct_reorg {
++
++const int max_split = 2;
++
++template <typename type>
++struct auto_vec_del : auto_vec<type*>
++{
++ ~auto_vec_del();
++};
++
++template <typename T>
++auto_vec_del<T>::~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<srdecl*> args;
++ auto_vec<srdecl*> globals;
++ auto_vec_del<srdecl> 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<srfield> fields;
++
++ // array of fields that use this type.
++ auto_vec<srfield*> field_sites;
++
++ // array of functions which use directly the type
++ auto_vec<srfunction*> functions;
++
++ auto_vec_del<sraccess> 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
++# <http://www.gnu.org/licenses/>.
++
++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 <assert.h>
++
++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 <stdlib.h>
++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 <stdlib.h>
++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 <stdlib.h>
++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 <stdlib.h>
++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 <stdlib.h>
++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 <stdlib.h>
++typedef struct
++{
++ int a;
++ int b;
++}str_t;
++
++#define N 3
++
++str_t str;
++
++int
++main ()
++{
++ int i;
++ int res = 1<<(1<<N);
++ str.a = 2;
++
++ for (i = 0; i < N; i++)
++ str.a = str.a * str.a;
++
++ if (str.a != res)
++ abort ();
++
++ /* POSIX ignores all but the 8 low-order bits, but other
++ environments may not. */
++ return (str.a & 255);
++}
++
++/*--------------------------------------------------------------------------*/
++/* { dg-final { scan-ipa-dump "Number of structures to transform 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
+new file mode 100644
+index 00000000000..13b4cdc7088
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/struct/w_prof_two_strs.c
+@@ -0,0 +1,64 @@
++#include <stdlib.h>
++
++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 <stdlib.h>
++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 <stdlib.h>
++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 <stdlib.h>
++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 <stdlib.h>
++
++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 <stdlib.h>
++
++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 <stdlib.h>
++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 <stdlib.h>
++
++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 <stdlib.h>
++
++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 <stdlib.h>
++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 <stdlib.h>
++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 <stdlib.h>
++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 <stdlib.h>
++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 <stdlib.h>
++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 <stdlib.h>
++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 <stdlib.h>
++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 <stdlib.h>
++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 <stdlib.h>
++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 <stdlib.h>
++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 <stdlib.h>
++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 <stdlib.h>
++typedef struct
++{
++ int a;
++ int b;
++}str_t;
++
++#define N 3
++
++str_t str;
++
++int
++main ()
++{
++ int i;
++ int res = 1<<(1<<N);
++ str.a = 2;
++
++ for (i = 0; i < N; i++)
++ str.a = str.a * str.a;
++
++ if (str.a != res)
++ abort ();
++
++ /* POSIX ignores all but the 8 low-order bits, but other
++ environments may not. */
++ return (str.a & 255);
++}
++
++/*--------------------------------------------------------------------------*/
++/* { dg-final { scan-ipa-dump "Number of structures to transform 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
+new file mode 100644
+index 00000000000..ca9a8efcf8f
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/struct/wo_prof_single_str_local.c
+@@ -0,0 +1,34 @@
++/* { dg-do compile } */
++/* { dg-do run } */
++
++#include <stdlib.h>
++typedef struct
++{
++ int a;
++ int b;
++}str_t;
++
++#define N 3
++
++int
++main ()
++{
++ int i;
++ int res = 1<<(1<<N);
++ str_t str;
++
++ str.a = 2;
++
++ for (i = 0; i < N; i++)
++ str.a = str.a * str.a;
++
++ if (str.a != res)
++ abort ();
++
++ /* POSIX ignores all but the 8 low-order bits, but other
++ environments may not. */
++ return (str.a & 255);
++}
++
++/*--------------------------------------------------------------------------*/
++/* { dg-final { scan-ipa-dump "No structures to transform" "struct_reorg" } } */
+diff --git a/gcc/testsuite/gcc.dg/struct/wo_prof_single_str_pointer.c b/gcc/testsuite/gcc.dg/struct/wo_prof_single_str_pointer.c
+new file mode 100644
+index 00000000000..baa95bddf6f
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/struct/wo_prof_single_str_pointer.c
+@@ -0,0 +1,38 @@
++/* { dg-do compile } */
++/* { dg-do run } */
++
++#include <stdlib.h>
++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 <stdlib.h>
++
++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 <xiezhiheng@huawei.com>
+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<srtype> types;
+ auto_vec_del<srfunction> 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<srdecl*>&);
+ void check_uses (srdecl *decl, vec<srdecl*>&);
+ void check_use (srdecl *decl, gimple *stmt, vec<srdecl*>&);
+@@ -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 &times);
++ 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 <gassign *> (stmt), gsi);
++ case GIMPLE_CALL:
++ return rewrite_call (as_a <gcall *> (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 &times)
++{
++ 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<srdecl*>
+
+ }
+
++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<srdecl*> &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<srdecl*> &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<srdecl*> &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<srdecl*> &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 <stdlib.h>
++
++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 <stdlib.h>
++
++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
++# <http://www.gnu.org/licenses/>.
++
++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 <stdlib.h>
++#include <stdio.h>
++
++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 <stdlib.h>
++#include <stdio.h>
++
++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 <stdlib.h>
++#include <stdio.h>
++
++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 <stdlib.h>
++#include <stdio.h>
++
++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 <stdlib.h>
++#include <stdio.h>
++
++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 <stdlib.h>
++#include <stdio.h>
++
++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 <stdlib.h>
++
++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 <stdlib.h>
++
++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 <xiezhiheng@huawei.com>
+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 <stdio.h>
++#include <stdlib.h>
++
++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 <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++
++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 <bule1@huawei.com>
+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_<mode>"
++ [(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_<mode>"
++ [(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_<mode>"
+ [(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_<mode>"
++ [(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_<mode>"
+ [(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=<number> 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 <huangxiaoquan1@huawei.com>
+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 <tree, auto_vec <tree> > 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 <tree> &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<srfunction> functions;
+ srglobal globals;
+ srfunction *current_function;
++ hash_set <cgraph_node *> 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<srdecl*> &worklist);
++ void check_definition_call (srdecl *decl, vec<srdecl*> &worklist);
+ void check_definition (srdecl *decl, vec<srdecl*>&);
+ void check_uses (srdecl *decl, vec<srdecl*>&);
+ void check_use (srdecl *decl, gimple *stmt, vec<srdecl*>&);
+- void check_type_and_push (tree newdecl, srtype *type, vec<srdecl*> &worklist, gimple *stmt);
++ void check_type_and_push (tree newdecl, srdecl *decl,
++ vec<srdecl*> &worklist, gimple *stmt);
+ void check_other_side (srdecl *decl, tree other, gimple *stmt, vec<srdecl*> &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 <tree, int> &map,
++ auto_vec <tree> &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 <tree, int> &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 <tree, int> &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 <tree, int> &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 &current_node,
++ hash_map <tree, int> &ptr_layers,
++ auto_vec <tree> &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 &current_node,
++ hash_map <tree, int> &ptr_layers,
++ auto_vec <tree> &ssa_name_stack)
+ {
+- static hash_set<tree> 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 &current_node,
++ hash_map <tree, int> &ptr_layers,
++ auto_vec <tree> &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 &current_node, gimple *use_stmt,
++ hash_map <tree, int> &ptr_layers,
++ auto_vec <tree> &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 &current_node, gimple *use_stmt,
++ hash_map <tree, int> &ptr_layers,
++ auto_vec <tree> &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 <tree, int> &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 <tree, int> &ptr_layers,
++ auto_vec <tree> &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 <tree, int> &ptr_layers,
++ auto_vec <tree> &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 <tree, int> ptr_layers;
++ auto_vec <tree> 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 <cgraph_edge *> callers = node->collect_callers ();
++ auto_vec <cgraph_edge *> 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<tree> 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<srdecl*> &worklist, gimple *stmt)
++ipa_struct_reorg::check_type_and_push (tree newdecl, srdecl *decl,
++ vec<srdecl*> &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<srdecl*>
+ 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<srdecl*>
+ /* 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<srdecl*> &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<srdecl*> &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<srdecl*> &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<srdecl*> &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<srdecl*> &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<srdecl*> &worklist)
+ {
+@@ -3234,7 +4537,7 @@ ipa_struct_reorg::check_use (srdecl *decl, gimple *stmt, vec<srdecl*> &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<srdecl*> &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<srdecl*> &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<srdecl*> &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<srdecl*> &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<srdecl*> &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<srdecl*> &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 <tree> *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<srdecl*> args;
+ auto_vec<srdecl*> globals;
+ auto_vec_del<srdecl> 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 <stdio.h>
++#include <stdlib.h>
++
++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 <stdio.h>
++#include <stdlib.h>
++
++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 <stdio.h>
++#include <stdlib.h>
++#include <assert.h>
++
++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 <stdio.h>
++#include <stdlib.h>
++
++#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 <stdio.h>
++#include <stdlib.h>
++
++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 <stdio.h>
++#include <stdlib.h>
++
++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 <stdio.h>
++#include <stdlib.h>
++
++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 <stdio.h>
++#include <stdlib.h>
++
++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 <stdio.h>
++#include <stdlib.h>
++
++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 <stdio.h>
++#include <stdlib.h>
++
++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 <stdio.h>
++#include <stdlib.h>
++
++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 <stdio.h>
++#include <stdlib.h>
++
++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 <stdio.h>
++#include <stdlib.h>
++
++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 <stdio.h>
++#include <stdlib.h>
++
++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 <stdio.h>
++#include <stdlib.h>
++
++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 <stdio.h>
++#include <stdlib.h>
++
++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 <stdio.h>
++#include <stdlib.h>
++
++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 <stdio.h>
++#include <stdlib.h>
++
++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 <stdio.h>
++#include <stdlib.h>
++
++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 <stdio.h>
++#include <stdlib.h>
++
++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 <stdio.h>
++#include <stdlib.h>
++
++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 <huangxiaoquan1@huawei.com>
+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<srdecl*>&);
+ void check_use (srdecl *decl, gimple *stmt, vec<srdecl*>&);
+ void check_type_and_push (tree newdecl, srdecl *decl,
+- vec<srdecl*> &worklist, gimple *stmt);
++ vec<srdecl*> &worklist, gimple *stmt);
+ void check_other_side (srdecl *decl, tree other, gimple *stmt, vec<srdecl*> &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 <stdio.h>
++#include <stdlib.h>
++
++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 <z.zhanghaijian@huawei.com>
+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<c; i++)
++ {
++ f= 4 <= d;
++ k= a > 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 <bule1@huawei.com>
+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 <huangxiaoquan1@huawei.com>
+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 &current_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 &current_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 <huangxiaoquan1@huawei.com>
+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 <stdio.h>
++#include <stdlib.h>
++
++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 <huangxiaoquan1@huawei.com>
+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 <stdlib.h>
+ 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 <linda7@huawei.com>
+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 <map>
++#include <vector>
++#include <algorithm>
+
+ /* 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 <func_decl, count> */
++static bool
++event_count_cmp (std::pair<unsigned, gcov_type> &a,
++ std::pair<unsigned, gcov_type> &b)
++{
++ return a.second > b.second;
++}
++
+ /* Represent a source location: (function_decl, lineno). */
+ typedef std::pair<tree, unsigned> 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<location_t, gcov_type> loc_count_map;
++ typedef std::map<unsigned, gcov_type> func_count_map;
++
++ /* Map of function_uid to its descending order rank of counts. */
++ typedef std::map<unsigned, unsigned> rank_map;
++
++ /* Mapping hardware events to corresponding basic maps. */
++ typedef std::map<event_type, loc_count_map> event_loc_count_map;
++ typedef std::map<event_type, func_count_map> event_func_count_map;
++ typedef std::map<event_type, rank_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<std::pair<unsigned, gcov_type> > 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<edge, gcov_type>;
++
++ /* 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 <huangxiaoquan1@huawei.com>
+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 <map>
+-#include <vector>
+-#include <algorithm>
+
+ /* 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
+ <http://www.gnu.org/licenses/>. */
+
+ #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 <unsigned int, unsigned int> uid_rank_map;
++typedef std::map <location_t, unsigned int> loc_rank_map;
++typedef std::vector <std::pair<location_t, gcov_type> > loc_gcov_type_vec;
++typedef std::map <location_t, std::vector<gimple *> > loc_gimple_vec_map;
++
++static loc_rank_map ref_rank;
++
++/* Callback function for event_count comparison. */
++
++static bool
++event_count_cmp (std::pair<unsigned int, gcov_type> &a,
++ std::pair<unsigned int, gcov_type> &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 <basic_block, bb_bp> &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 <basic_block, bb_bp> &bb_branch_prob,
++ int& max_path, hash_set <basic_block> &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 <basic_block, bb_bp> &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 <basic_block, bb_bp> &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 <basic_block> 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 <basic_block, bb_bp> 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<edge> 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 <dingguangya1@huawei.com>
+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
++# <http://www.gnu.org/licenses/>.
++
++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,
++ ...
++ <bb 3> [local count: 20000]
++ if (f_2 != 0)
++ goto <bb 6>; [INV]
++ else
++ goto <bb 7>; [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:
++# <https://lists.gnu.org/archive/html/automake/2012-07/msg00001.html>
++# <https://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>
++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: <http://austingroupbugs.net/view.php?id=542>
++
++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: <https://www.gnu.org/software/coreutils/>.
++
++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 <conftest.tar])
++ AM_RUN_LOG([cat conftest.dir/file])
++ grep GrepMe conftest.dir/file >/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
++<http://www.gnu.org/licenses/>. */
++
++/* 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:
++ <is symbol?> <closest elf symbol or DSO name> <relative FROM address>
++ <is symbol?> <closest elf symbol or DSO name> <relative TO address>
++ <number of mispredictions> <number of branches>
++
++ Examples:
++
++ 1 main 58 1 main 78 0 100
++
++ BB info mode when profile collect from AutoFDO:
++ <is symbol?> <closest elf symbol or DSO name> <relative address> <count>
++
++ 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 <stdint.h>
++#endif
++#include <assert.h>
++#include <errno.h>
++#include <string.h>
++#include <stdlib.h>
++#include <stdio.h>
++#include <inttypes.h>
++#include <sys/stat.h>
++#include <unistd.h>
++#include <fcntl.h>
++#include <sys/types.h>
++#ifdef HAVE_SYS_WAIT_H
++#include <sys/wait.h>
++#endif
++#include <filenames.h>
++#include <hashtab.h>
++#include "simple-object.h"
++#include "plugin-api.h"
++
++namespace LIBIBERTY
++{
++#include <libiberty.h>
++}
++using LIBIBERTY::xmalloc;
++using LIBIBERTY::lbasename;
++using LIBIBERTY::xstrdup;
++using LIBIBERTY::concat;
++using LIBIBERTY::lrealpath;
++
++#include <vector>
++#include <string>
++#include <map>
++#include <set>
++
++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<jump_info> 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<string> gcc_options;
++
++/* Map of <weak_function_name, vector<function_info>> */
++static map<string, vector<struct func_info>> 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 <dlfcn.h> header file. */
++#undef HAVE_DLFCN_H
++
++/* Define to 1 if you have the <inttypes.h> header file. */
++#undef HAVE_INTTYPES_H
++
++/* Define to 1 if you have the <memory.h> header file. */
++#undef HAVE_MEMORY_H
++
++/* Define to 1 if you have the <stdint.h> header file. */
++#undef HAVE_STDINT_H
++
++/* Define to 1 if you have the <stdlib.h> header file. */
++#undef HAVE_STDLIB_H
++
++/* Define to 1 if you have the <strings.h> header file. */
++#undef HAVE_STRINGS_H
++
++/* Define to 1 if you have the <string.h> header file. */
++#undef HAVE_STRING_H
++
++/* Define to 1 if you have the <sys/stat.h> header file. */
++#undef HAVE_SYS_STAT_H
++
++/* Define to 1 if you have the <sys/types.h> header file. */
++#undef HAVE_SYS_TYPES_H
++
++/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */
++#undef HAVE_SYS_WAIT_H
++
++/* Define to 1 if you have the <unistd.h> 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 <sys/synch.h>,
++ <pthread.h>, or <semaphore.h> 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 </dev/null
++exec 6>&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 <stdio.h>
++#ifdef HAVE_SYS_TYPES_H
++# include <sys/types.h>
++#endif
++#ifdef HAVE_SYS_STAT_H
++# include <sys/stat.h>
++#endif
++#ifdef STDC_HEADERS
++# include <stdlib.h>
++# include <stddef.h>
++#else
++# ifdef HAVE_STDLIB_H
++# include <stdlib.h>
++# endif
++#endif
++#ifdef HAVE_STRING_H
++# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
++# include <memory.h>
++# endif
++# include <string.h>
++#endif
++#ifdef HAVE_STRINGS_H
++# include <strings.h>
++#endif
++#ifdef HAVE_INTTYPES_H
++# include <inttypes.h>
++#endif
++#ifdef HAVE_STDINT_H
++# include <stdint.h>
++#endif
++#ifdef HAVE_UNISTD_H
++# include <unistd.h>
++#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<lib dir> if you have libraries in a
++ nonstandard directory <lib dir>
++ LIBS libraries to pass to the linker, e.g. -l<library>
++ CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
++ you have headers in a nonstandard directory <include dir>
++ 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 <limits.h> declares $2.
++ For example, HP-UX 11i <limits.h> declares gettimeofday. */
++#define $2 innocuous_$2
++
++/* System header to define __stub macros and hopefully few prototypes,
++ which can conflict with char $2 (); below.
++ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
++ <limits.h> exists even on freestanding compilers. */
++
++#ifdef __STDC__
++# include <limits.h>
++#else
++# include <assert.h>
++#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:
++# <https://lists.gnu.org/archive/html/automake/2012-07/msg00001.html>
++# <https://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>
++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: <http://austingroupbugs.net/view.php?id=542>
++
++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: <https://www.gnu.org/software/coreutils/>.
++
++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 <stdio.h>
++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 <stdarg.h>
++#include <stdio.h>
++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 <limits.h> to <assert.h> if __STDC__ is defined, since
++ # <limits.h> 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 <limits.h>
++#else
++# include <assert.h>
++#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 <ac_nonexistent.h>
++_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 <limits.h> to <assert.h> if __STDC__ is defined, since
++ # <limits.h> 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 <limits.h>
++#else
++# include <assert.h>
++#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 <ac_nonexistent.h>
++_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 <stdlib.h>
++#include <stdarg.h>
++#include <string.h>
++#include <float.h>
++
++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 <string.h>
++
++_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 <stdlib.h>
++
++_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 <ctype.h>
++#include <stdlib.h>
++#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 <stdarg.h>
++#include <stdio.h>
++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 <sys/types.h>
++ /* 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 <sys/types.h>
++ /* 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 <sys/types.h>
++ /* 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 <sys/types.h>
++ /* 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 <sys/types.h>
++ /* 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 </dev/null` in
++ *GNU* | *'with BFD'*)
++ test "$with_gnu_ld" != no && break
++ ;;
++ *)
++ test "$with_gnu_ld" != yes && break
++ ;;
++ esac
++ fi
++ done
++ IFS="$lt_save_ifs"
++else
++ lt_cv_path_LD="$LD" # Let the user override the test with a path.
++fi
++fi
++
++LD="$lt_cv_path_LD"
++if test -n "$LD"; then
++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&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 </dev/null` in
++*GNU* | *'with BFD'*)
++ lt_cv_prog_gnu_ld=yes
++ ;;
++*)
++ lt_cv_prog_gnu_ld=no
++ ;;
++esac
++fi
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_gnu_ld" >&5
++$as_echo "$lt_cv_prog_gnu_ld" >&6; }
++with_gnu_ld=$lt_cv_prog_gnu_ld
++
++
++
++
++
++
++
++
++
++{ $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 <jrb3@best.com> 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<name>.so
++ # instead of lib<name>.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 <dlfcn.h>
++#endif
++
++#include <stdio.h>
++
++#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 <dlfcn.h>
++#endif
++
++#include <stdio.h>
++
++#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 <limits.h> to <assert.h> if __STDC__ is defined, since
++ # <limits.h> 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 <limits.h>
++#else
++# include <assert.h>
++#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 <ac_nonexistent.h>
++_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 <limits.h> to <assert.h> if __STDC__ is defined, since
++ # <limits.h> 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 <limits.h>
++#else
++# include <assert.h>
++#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 <ac_nonexistent.h>
++_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 </dev/null` in
++ *GNU* | *'with BFD'*)
++ test "$with_gnu_ld" != no && break
++ ;;
++ *)
++ test "$with_gnu_ld" != yes && break
++ ;;
++ esac
++ fi
++ done
++ IFS="$lt_save_ifs"
++else
++ lt_cv_path_LD="$LD" # Let the user override the test with a path.
++fi
++fi
++
++LD="$lt_cv_path_LD"
++if test -n "$LD"; then
++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&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 </dev/null` in
++*GNU* | *'with BFD'*)
++ lt_cv_prog_gnu_ld=yes
++ ;;
++*)
++ lt_cv_prog_gnu_ld=no
++ ;;
++esac
++fi
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_gnu_ld" >&5
++$as_echo "$lt_cv_prog_gnu_ld" >&6; }
++with_gnu_ld=$lt_cv_prog_gnu_ld
++
++
++
++
++
++
++
++ # 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 <jrb3@best.com> 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<name>.so
++ # instead of lib<name>.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 <sys/types.h>
++#include <sys/wait.h>
++#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 2>/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
++' <conf$$subs.awk | sed '
++/^[^""]/{
++ N
++ s/\n//
++}
++' >>$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
++' <confdefs.h | sed '
++s/'"$ac_delim"'/"\\\
++"/g' >>$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=*:%<fcompare-debug*} \
+ %{flto} %{fno-lto} %{flto=*} %l " LINK_PIE_SPEC \
+ "%{fuse-ld=*:-fuse-ld=%*} " LINK_COMPRESS_DEBUG_SPEC \
+@@ -1089,6 +1091,7 @@ static const char *endfile_spec = ENDFILE_SPEC;
+ static const char *startfile_spec = STARTFILE_SPEC;
+ static const char *linker_name_spec = LINKER_NAME;
+ static const char *linker_plugin_file_spec = "";
++static const char *linker_auto_bolt_plugin_file_spec = "";
+ static const char *lto_wrapper_spec = "";
+ static const char *lto_gcc_spec = "";
+ static const char *post_link_spec = POST_LINK_SPEC;
+@@ -1594,6 +1597,8 @@ static struct spec_list static_specs[] =
+ INIT_STATIC_SPEC ("multilib_reuse", &multilib_reuse),
+ INIT_STATIC_SPEC ("linker", &linker_name_spec),
+ INIT_STATIC_SPEC ("linker_plugin_file", &linker_plugin_file_spec),
++ INIT_STATIC_SPEC ("linker_auto_bolt_plugin_file",
++ &linker_auto_bolt_plugin_file_spec),
+ INIT_STATIC_SPEC ("lto_wrapper", &lto_wrapper_spec),
+ INIT_STATIC_SPEC ("lto_gcc", &lto_gcc_spec),
+ INIT_STATIC_SPEC ("post_link", &post_link_spec),
+@@ -8339,6 +8344,23 @@ driver::maybe_run_linker (const char *argv0) const
+ }
+ #endif
+ lto_gcc_spec = argv0;
++
++ /* Set bolt-plugin. */
++ const char *fauto_bolt = "fauto-bolt";
++ const char *fbolt_use = "fbolt-use";
++ if (switch_matches (fauto_bolt, fauto_bolt + strlen (fauto_bolt), 1)
++ || switch_matches (fbolt_use, fbolt_use + strlen (fbolt_use), 1))
++ {
++ linker_auto_bolt_plugin_file_spec = find_a_file (&exec_prefixes,
++ BOLTPLUGINSONAME, X_OK, false);
++ if (!linker_auto_bolt_plugin_file_spec)
++ {
++ fatal_error (input_location,
++ "-fauto-bolt or -fbolt-use is used,",
++ " but %s file is not found",
++ BOLTPLUGINSONAME);
++ }
++ }
+ }
+
+ /* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables
+--
+2.27.0
+
diff --git a/0032-Autoprefetch-Prune-invaild-loops-containing-edges-wh.patch b/0032-Autoprefetch-Prune-invaild-loops-containing-edges-wh.patch
new file mode 100644
index 0000000..aa15df4
--- /dev/null
+++ b/0032-Autoprefetch-Prune-invaild-loops-containing-edges-wh.patch
@@ -0,0 +1,82 @@
+From 071d19832d788422034a3b052ff7ce91e1010344 Mon Sep 17 00:00:00 2001
+From: dingguangya <dingguangya1@huawei.com>
+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 <basic_block, bb_bp> &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 <dingguangya1@huawei.com>
+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 <basic_block, bb_bp> &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 <jakub@redhat.com>
+
+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 <dingguangya1@huawei.com>
+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=<number> 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<tree> 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 <ivtmp.5_12 (2), ivtmp.5_11 (3)>
++ _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 <bb 4>; [10.70%]
++ else
++ goto <bb 3>; [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<srdecl*> &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<srdecl*> &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<srdecl*> &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<srdecl*> &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 <wumingchuan1992@foxmail.com>
+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<tree, tree> 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 <stdio.h>
++#include <stdlib.h>
++
++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 <stdio.h>
++#include <stdlib.h>
++
++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 <stdio.h>
++#include <stdlib.h>
++
++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 <stdio.h>
++#include <stdlib.h>
++
++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 <stdio.h>
++#include <stdlib.h>
++
++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 <stdio.h>
++#include <stdlib.h>
++
++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 <stdio.h>
++#include <stdlib.h>
++
++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 <mjambor@suse.cz>
+
+(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 <hainque@adacore.com>
+
+ 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 <wumingchuan1992@foxmail.com>
+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<tree, tree>::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 <luo_hailing@qq.com>
+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 <stdio.h>
++#include <stdlib.h>
++#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 <stdio.h>
++#include <stdlib.h>
++#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 <stdio.h>
++#include <stdlib.h>
++#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 <stdio.h>
++#include <stdlib.h>
++#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 <stdio.h>
++#include <stdlib.h>
++#include <math.h>
++#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 <stdio.h>
++#include <stdlib.h>
++#include <math.h>
++#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 <stdio.h>
++#include <stdlib.h>
++#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 <stdio.h>
++#include <stdlib.h>
++#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<tree> 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<tree> dr_chain, unsigned int length,
++ unsigned int array_num, stmt_vec_info stmt_info,
++ gimple_stmt_iterator *gsi, vec<tree> *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 <vect1, vect2,
++ {0, array_num, 2*array_num, ..., (2*group-1)*array_num,
++ 1, 1+array_num, 1+2*array_num, ..., 1+(2*group-1)*array_num,
++ ...,
++ array_num/2-1, (array_num/2-1)+array_num, ...,
++ (array_num/2-1)+(2*group-1)*array_num}>
++ low_first = VEC_PERM_EXPR <vect1, vect2,
++ {array_num/2, array_num/2+array_num, array_num/2+2*array_num,
++ ..., array_num/2+(2*group-1)*array_num,
++ array_num/2+1, array_num/2+1+array_num,
++ ..., array_num/2+1+(2*group-1)*array_num,
++ ...,
++ array_num-1, array_num-1+array_num,
++ ..., array_num-1+(2*group-1)*array_num}> */
++ 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 <vect1, vect2, {0, 1, ..., group-1,
++ nelt, nelt+1, ..., nelt+group-1,
++ group, group+1, ..., 2*group-1,
++ nelt+group, nelt+group+1, ..., nelt+2*group-1,
++ ...}>
++ low = VEC_PERM_EXPR <vect1, vect2,
++ {nelt/2, nelt/2+1, ..., nelt/2+group-1,
++ nelt*3/2, nelt*3/2+1, ..., nelt*3/2+group-1,
++ nelt/2+group, nelt/2+group+1, ..., nelt/2+2*group-1,
++ nelt*3/2+group, nelt*3/2+group+1, ..., nelt*3/2+2*group-1,
++ ...}> */
++ 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 <bb_vec_info> (vinfo);
+ unsigned HOST_WIDE_INT const_nunits;
+ if (is_a <bb_vec_info> (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<tree> &innermost_inits,
++ vec<tree> &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<tree> &innermost_inits,
++ const vec<tree> &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<void *>(grp1_);
++ stmt_vec_info grp2 = *(stmt_vec_info *)const_cast<void *>(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<stmt_vec_info> 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<tree> innermost_inits;
++ auto_vec<tree> innermost_offsets;
++
++ /* A set of stmt_vec_info with same store type. Analyze them if their size
++ is suitable to transpose. */
++ auto_vec<stmt_vec_info> 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<void *> (stmtinfo_a_);
++ stmt_vec_info stmtinfo_b
++ = *(stmt_vec_info *) const_cast<void *> (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<bool> &visited,
++ vec<stmt_vec_info> &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<stmt_vec_info> 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<bool> visited (bb_vinfo->grouped_loads.length ());
++ auto_vec<stmt_vec_info> 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<stmt_vec_info> 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<bool> &visited,
++ vec<stmt_vec_info> &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<stmt_vec_info> 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<stmt_vec_info> 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<stmt_vec_info> grouped_stores_merge;
++ auto_vec<bool> 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<stmt_vec_info> 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<stmt_vec_info>
++vect_transform_back_slp_grouped_store (bb_vec_info bb_vinfo,
++ stmt_vec_info first_stmt_info)
++{
++ auto_vec<stmt_vec_info> grouped_stores_split;
++ for (unsigned int i = 0; i < bb_vinfo->scalar_stores.length (); i++)
++ {
++ vec<stmt_vec_info> 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<stmt_vec_info> 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<stmt_vec_info> 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<tree> dr_chain, unsigned int num_each,
++ stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
++ vec<tree> *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<tree> dr_chain_transposed (num_each);
++ auto_vec<tree> 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 (vec<tree>vec_oprnds, vec<tree> *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 <bb_vec_info> (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 <bb_vec_info> (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<unsigned> &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<unsigned> &group_idx,
++ const vec<unsigned> &load_permutation,
++ unsigned int group_size_b,
++ unsigned &new_group_size,
++ vec<unsigned> &group_from)
++{
++ /* group_num_vec: only stores the group_loads IDs which are caculated from
++ load_permutation. */
++ auto_vec<unsigned> 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<unsigned> 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<unsigned> &new_load_permutation,
++ const vec<unsigned> &old_load_permutation,
++ slp_tree slp_node, bool &this_load_permuted,
++ const vec<unsigned> &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<unsigned> &group_idx,
++ vec<unsigned> &new_load_permutation)
++{
++ /* Generate the old load permutations from SLP_NODE. */
++ vec<unsigned> 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<unsigned> 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<tree> &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<constructor_elt, va_gc> *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<unsigned> 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<tree>& dr_chain, slp_tree slp_node,
++ gimple_stmt_iterator *gsi)
++{
++ vec<constructor_elt, va_gc> *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<unsigned> 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<tree>& 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<unsigned> 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 <bb_vec_info> (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 <bb_vec_info> (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<unsigned> 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 <bb_vec_info> (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<unsigned> 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<ddr_p> 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<stmt_vec_info> grouped_stores;
+
++ /* All interleaving chains of loads, represented by the first
++ stmt in the chain. */
++ auto_vec<stmt_vec_info> grouped_loads;
++
++ /* All interleaving chains of stores (before transposed), represented by all
++ stmt in the chain. */
++ auto_vec<vec<stmt_vec_info> > 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<void *>(a_);
++ unsigned int b = *(unsigned int *)const_cast<void *>(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<tree> ,unsigned int, stmt_vec_info,
+ gimple_stmt_iterator *, vec<tree> *);
++extern void vect_transpose_store_chain (vec<tree>, unsigned int, unsigned int,
++ stmt_vec_info, gimple_stmt_iterator *,
++ vec<tree> *);
+ 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<tree> ,
+ 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 <dingguangya1@huawei.com>
+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 <stdint.h>
++#include <stdio.h>
++
++#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 <stdint.h>
++#include <stdio.h>
++
++#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 <stdint.h>
++#include <stdio.h>
++
++#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 <stdint.h>
++#include <stdio.h>
++
++#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 <stdint.h>
++#include <stdio.h>
++
++#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 <stdint.h>
++#include <stdio.h>
++
++#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 <stdint.h>
++#include <stdio.h>
++
++#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 <stdint.h>
++#include <stdio.h>
++
++#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
++<http://www.gnu.org/licenses/>. */
++
++#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 <basic_block, tree> 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<edge> 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<tree> 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: <bb 7>
++ len_16 = len_10 + 1
++ Create simple copy statement when prolog_assign does not exist;
++ eg: <bb 7>
++ 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: <bb 9>
++ _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: <bb 10>
++ _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: <bb 11>
++ 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: <bb 12>
++ _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: <bb 14>
++ # len_31 = PHI <len_17 (13), len_37 (16)>
++ 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: <bb 15>
++ _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: <bb 16>
++ 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 <wumingchuan1992@foxmail.com>
+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 <xiezhiheng@huawei.com>
+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 <zhongyunde@huawei.com>
+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 <jakub@redhat.com>
+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 <jakub@redhat.com>
+
+ 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 <jakub@redhat.com>
+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 <jakub@redhat.com>
+
+ 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 <jakub@redhat.com>
+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 <jakub@redhat.com>
+
+ PR tree-optimization/96232
+ * tree-ssa-phiopt.c (two_value_replacement): Optimize even boolean lhs
+ cases as long as arg0 has wider precision and conditional_replacement
+ doesn't handle that case.
+ (tree_ssa_phiopt_worker): Don't call two_value_replacement during
+ early phiopt.
+
+ * 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 <jakub@redhat.com>
+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 <jakub@redhat.com>
+
+ 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<tree> *);
+ 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,
+
+ <bb 4>
+ 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 <jakub@redhat.com>
+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 <jakub@redhat.com>
+
+ * 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 <jakub@redhat.com>
+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 <jakub@redhat.com>
+
+ 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 <jakub@redhat.com>
+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 <jakub@redhat.com>
+
+ 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 <compare>
++
++#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 <compare>
++
++#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:
++ <bb 2> : // cond3_bb (== cond2_bb)
++ if (x_4(D) != y_5(D))
++ goto <bb 3>; [INV]
++ else
++ goto <bb 6>; [INV]
++
++ <bb 3> : // cond_bb
++ if (x_4(D) < y_5(D))
++ goto <bb 6>; [INV]
++ else
++ goto <bb 4>; [INV]
++
++ <bb 4> : // middle_bb
++
++ <bb 6> : // phi_bb
++ # iftmp.0_2 = PHI <1(4), 0(2), -1(3)>
++ _1 = iftmp.0_2 == 0;
++
++ and for partial ordering <=> something like:
++
++ <bb 2> : // cond3_bb
++ if (a_3(D) == b_5(D))
++ goto <bb 6>; [50.00%]
++ else
++ goto <bb 3>; [50.00%]
++
++ <bb 3> [local count: 536870913]: // cond2_bb
++ if (a_3(D) < b_5(D))
++ goto <bb 6>; [50.00%]
++ else
++ goto <bb 4>; [50.00%]
++
++ <bb 4> [local count: 268435456]: // cond_bb
++ if (a_3(D) > b_5(D))
++ goto <bb 6>; [50.00%]
++ else
++ goto <bb 5>; [50.00%]
++
++ <bb 5> [local count: 134217728]: // middle_bb
++
++ <bb 6> [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 <gcond *> (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 <gcond *> (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
+
+ <bb 2>
+--
+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 <ebotcazou@gcc.gnu.org>
+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 <rguenther@suse.de>
+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 <rguenther@suse.de>
+
+ 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<s, 0>. */
++/* { 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 <apinski@marvell.com>
+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 <apinski@marvell.com>
+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 <apinski@marvell.com>
+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 <apinski@marvell.com>
+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 <apinski@marvell.com>
+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 <jakub@redhat.com>
+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 <jakub@redhat.com>
+
+ * 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<tree> *);
+ static bool cond_if_else_store_replacement (basic_block, basic_block, basic_block);
+ static hash_set<tree> * 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 <roger@nextmovesoftware.com>
+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 <roger@nextmovesoftware.com>
+
+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<tree> *);
+ 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
+
+ <bb 2>
+ 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 <rguenther@suse.de>
+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) /
+ /\ /
+ / <BB>
+ / |
+ # PHI <a, b>
+
+rather than
+
+ if (a > b) |
+ /\ |
+ <BB> \ |
+ / \ |
+ # PHI <a, b, b>
+
+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 <rguenther@suse.de>
+
+ 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 <gcond *> (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 <richard.sandiford@arm.com>
+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 <richard.sandiford@arm.com>
+
+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 <richard.sandiford@arm.com>
++
++ 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 <mliska@suse.cz>
+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 <x, y>, expand it a VEC_COND_EXPR <x <= y, x, y>
+- and similarly for MAX <x, y>. */
+ 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
++<http://www.gnu.org/licenses/>. */
++
++#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<tree, unsigned int> *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<gassign *> (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<gassign *> (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<gassign *> (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<tree, unsigned int> 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 <OP0, OP1>, 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 <gassign *> (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<gassign *> (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<operand_entry *> *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<operand_entry *> *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<operand_entry *> *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 <richard.sandiford@arm.com>
+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<typename ValueizeOp, typename ValueizeCondition>
++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 <richard.sandiford@arm.com>
+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 <tmp>, OPERANDS[1], -OPERANDS[3]
++ or
++ ADDS <tmp>, OPERANDS[1], OPERANDS[3]
++
++ followed by:
++
++ <insn> OPERANDS[0], <tmp>, [wx]zr, <cond>
++
++ where <insn> 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 <cond>
++ OPERANDS[6] = <tmp>
++ 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 (<CODE>, 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 (<CODE>, 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 <stdint.h>
++
++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 <stdint.h>
++
++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 <zhongyunde@huawei.com>
+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<tree, tree> 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<srdecl*> &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<srdecl*> &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<srdecl*> &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<srdecl*> &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 <zhongyunde@huawei.com>
+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)<<BN_BITS4)&BN_MASK2)
++
++unsigned int test_m(unsigned long in0, unsigned long in1) {
++ unsigned long m, m1, lt, ht, bl, bh;
++ lt = LBITS(in0);
++ ht = HBITS(in0);
++ bl = LBITS(in1);
++ bh = HBITS(in1);
++ m = bh * lt;
++ m1 = bl * ht;
++ ht = bh * ht;
++ m = (m + m1) & BN_MASK2;
++ if (m < m1) ht += L2HBITS((unsigned long)1);
++ return ht + m;
++}
++
++/* { dg-final { scan-tree-dump "COND_EXPR in block 2 and PHI in block 4 converted to straightline code" "phiopt2" } } */
+--
+2.27.0.windows.1
+
diff --git a/0074-FORWPROP-Fold-series-of-instructions-into-mul.patch b/0074-FORWPROP-Fold-series-of-instructions-into-mul.patch
new file mode 100644
index 0000000..d864621
--- /dev/null
+++ b/0074-FORWPROP-Fold-series-of-instructions-into-mul.patch
@@ -0,0 +1,130 @@
+From 2a2d0ba6a26d64f4c1f9352bb2c69dea8b67d6a6 Mon Sep 17 00:00:00 2001
+From: zhongyunde <zhongyunde@huawei.com>
+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=<number> Limit diagnostics to <number> 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)<<BN_BITS4)&BN_MASK2)
++
++void mul64(unsigned long in0, unsigned long in1,
++ unsigned long &retLo, unsigned long &retHi) {
++ unsigned long m00, m01, m10, m11, al, ah, bl, bh;
++ unsigned long Addc, addc32, low;
++ al = LBITS(in0);
++ ah = HBITS(in0);
++ bl = LBITS(in1);
++ bh = HBITS(in1);
++ m10 = bh * al;
++ m00 = bl * al;
++ m01 = bl * ah;
++ m11 = bh * ah;
++ Addc = (m10 + m01) & BN_MASK2;
++ if (Addc < m01) m11 += L2HBITS((unsigned long)1);
++ m11 += HBITS(Addc);
++ addc32 = L2HBITS(Addc);
++ low = (m00 + addc32) & BN_MASK2; if (low < addc32) m11++;
++ retLo = low;
++ retHi = m11;
++}
++
++/* { dg-final { scan-tree-dump "gimple_simplified to low_18 = in0_4" "forwprop1" } } */
+--
+2.27.0.windows.1
+
diff --git a/0075-FORWPROP-Fold-series-of-instructions-into-umulh.patch b/0075-FORWPROP-Fold-series-of-instructions-into-umulh.patch
new file mode 100644
index 0000000..e8a58aa
--- /dev/null
+++ b/0075-FORWPROP-Fold-series-of-instructions-into-umulh.patch
@@ -0,0 +1,105 @@
+From 315911bd3ae6f42366779e262ab76d9ed79359a0 Mon Sep 17 00:00:00 2001
+From: zhongyunde <zhongyunde@huawei.com>
+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<srdecl*> &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 <gimple *> (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 <gimple *> (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 <linda7@huawei.com>
+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<vec<gimple *> *, int> stmts_profit;
++
++/* MAP of vector factor VF and corresponding stmts_profit PAIR. */
++typedef std::map<unsigned, stmts_profit> 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<unsigned, unsigned> 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<tree, group_iteration> isomer_stmt_lhs;
++
+ /* Data dependence type. */
+
+ enum rdg_dep_type
+@@ -640,6 +689,18 @@ class loop_distribution
+ void finalize_partitions (class loop *loop, vec<struct partition *>
+ *partitions, vec<ddr_p> *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<vec<group_info> *> &worklists)
++{
++ stmt_vec_info stmt_info;
++ unsigned i = 0;
++ group_info ginfo = NULL;
++ vec<group_info> *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<data_reference_p, 2> 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<tree> &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<gimple *> &tmp_stmts, vec<tree> &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_info> *group, unsigned group_num,
++ unsigned iteration, isomer_stmt_lhs &isomer_lhs,
++ vec<gimple *> tmp_stmts, int &profit,
++ vec<unsigned> &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_info> *group, vec<gimple *> &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_info> *group, unsigned group_num,
++ unsigned iteration, vec<gimple *> &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_info> *group, vec<tree> &hetero_lhs,
++ vec<gimple *> &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_info> *group, unsigned group_num,
++ unsigned iteration, int &profit,
++ vec<gimple *> &tmp_stmts, isomer_stmt_lhs &isomer_lhs,
++ vec<tree> &hetero_lhs, vec<unsigned> &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_info> *group, unsigned group_num, unsigned iteration,
++ int &profit, vec<unsigned> &merged_groups,
++ isomer_stmt_lhs &isomer_lhs, vec<tree> &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<gimple *> 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<vec<group_info> *> &circular_queue,
++ vec<unsigned> &merged_groups)
++{
++ unsigned i = 0;
++ vec<group_info> *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<vec<group_info> *> &circular_queue,
++ vec<gimple *> *&stmts, vec<unsigned> &merged_groups)
++{
++ unsigned front = 0;
++ vec<group_info> *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<vec<group_info> *> &groups, isomer_stmt_lhs &isomer_lhs)
++{
++ vec<group_info> *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<vec<group_info> *> &circular_queue,
++ stmts_profit &profit_pair, unsigned vf,
++ bool &reach_vdef)
++{
++ isomer_stmt_lhs isomer_lhs;
++ auto_vec<tree> hetero_lhs;
++ auto_vec<unsigned> merged_groups;
++ vec<group_info> *group = NULL;
++ /* True if analysis finishes. */
++ bool done = false;
++ int profit_sum = 0;
++ vec<gimple *> *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<vec<group_info> *> &worklists)
++{
++ vec<group_info> *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<gimple *> &stmts)
++{
++ vf_stmts_profit_map::iterator iter;
++ int profit = 0;
++ int max = 0;
++ vec<gimple *> *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<gimple *> &stmts)
++{
++ unsigned vf = get_max_vf (vinfo);
++ if (vf == 0)
++ return false;
++ auto_vec<vec<group_info> *> 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 <linda7@huawei.com>
+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 <stdio.h>
++#include <stdlib.h>
++
++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<gimple *> &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<data_reference_p> *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<gimple *> &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<data_reference_p> 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<basic_block> &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<gimple *> 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<basic_block> 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<srdecl*> &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<srdecl*> &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 <stdlib.h>
++#include <math.h>
++
++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 <stdio.h>
++#include <stdlib.h>
++
++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 <stdio.h>
++#include <stdlib.h>
++
++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 <stdio.h>
++#include <stdlib.h>
++
++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 <stdio.h>
++#include <stdlib.h>
++
++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 <stdlib.h>
++#include <math.h>
++
++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 <linda7@huawei.com>
+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 <stdio.h>
++#include <stdlib.h>
++
++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<tree> *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<struct partition *>
+- *partitions, vec<ddr_p> *alias_ddrs);
++ void finalize_partitions (class loop *loop,
++ vec<struct partition *> *partitions,
++ vec<ddr_p> *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<gimple *> seed_stmts,
++ hash_set<tree> *tmp_array_vars, bitmap producers);
++
++ void build_producers (loop_p loop, bitmap producers,
++ vec<gimple *> &transformed);
++
++ void do_insertion (loop_p loop, struct graph *flow_only_rdg, tree iv,
++ bitmap cut_points, hash_set <tree> *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<struct partition *> *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 <tree> *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<struct partition *> *partitions)
+ }
+ }
+
++void
++loop_distribution::merge_remaining_partitions
++ (vec<struct partition *> *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<struct partition *> *partitions,
+- vec<ddr_p> *alias_ddrs)
++ vec<ddr_p> *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<gimple *> &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<gimple *> 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<gimple *> 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<unsigned, 16> 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<gimple *> 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<tree> *tmp_array_vars, vec<gimple *> *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<gimple *> &transformed)
++{
++ auto_vec<gimple *, 10> 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<tree> *tmp_array_vars,
++ bitmap producers)
++{
++ if (dump_file && (dump_flags & TDF_DETAILS))
++ fprintf (dump_file, "=== do insertion ===\n");
++
++ auto_vec<gimple *> 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<gimple *> seed_stmts,
++ hash_set<tree> *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<gimple *> *);
++
+ /* 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<gimple *> 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<tree> tmp_array_vars;
++
++ /* STMTs that define those inserted TMP_ARRAYs. */
++ auto_bitmap producers;
++
++ /* New SEED_STMTS after insertion. */
++ auto_vec<gimple *> 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<gimple *> 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<gimple *> 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<gimple *> 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 <zhongyunde@huawei.com>
+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 <gcond *> (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 <linda7@huawei.com>
+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<tree, tree> replace_type_map;
++hash_map<tree, tree> 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<srdecl*> &worklist);
+ void check_definition_call (srdecl *decl, vec<srdecl*> &worklist);
+ void check_definition (srdecl *decl, vec<srdecl*>&);
+@@ -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<srdecl*> &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<srdecl*> &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 <gimple *> (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 <typename type>
+ struct auto_vec_del : auto_vec<type*>
+ {
+@@ -127,6 +130,10 @@ public:
+ bool pc_candidate;
+ bool has_legal_alloc_num;
+ int has_alloc_array;
++ bool semi_relayout;
++ hash_map<tree, unsigned long> 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 <stdio.h>
++#include <stdlib.h>
++
++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 <xiezhiheng@huawei.com>
+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 <linda7@huawei.com>
+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<vec<group_info> *> &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 <linda7@huawei.com>
+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 <rguenther@suse.de>
+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 <rguenther@suse.de>
+
+ 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<gassign *> (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 <xiongzhou4@huawei.com>
+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 <gassign *> (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 <xiongzhou4@huawei.com>
+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 <zhongyunde@huawei.com>
+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 <zhongyunde@huawei.com>
+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 <wumingchuan1992@foxmail.com>
+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<tree, tree>::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 <stdlib.h>
++
++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 <hongtao.liu@intel.com>
+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 <hongtao.liu@inte.com>
+
+gcc/ChangeLog:
+ PR target/95254
+ * config/i386/sse.md (*vcvtps2ph_store<merge_mask_name>):
+ Refine from *vcvtps2ph_store<mask_name>.
+ (vcvtps2ph256<mask_name>): Refine constraint from vm to v.
+ (<mask_codefor>avx512f_vcvtps2ph512<mask_name>): Ditto.
+ (*vcvtps2ph256<merge_mask_name>): New define_insn.
+ (*avx512f_vcvtps2ph512<merge_mask_name>): 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<mask_name>"
++(define_insn "*vcvtps2ph_store<merge_mask_name>"
+ [(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<mask_operand3>|%0<mask_operand3>, %1, %2}"
++ "vcvtps2ph\t{%2, %1, %0<merge_mask_operand3>|%0<merge_mask_operand3>, %1, %2}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "prefix" "maybe_evex")
+ (set_attr "mode" "V4SF")])
+
+ (define_insn "vcvtps2ph256<mask_name>"
+- [(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<merge_mask_name>"
++ [(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<merge_mask_operand3>|%0<merge_mask_operand3>, %1, %2}"
++ [(set_attr "type" "ssecvt")
++ (set_attr "prefix" "maybe_evex")
++ (set_attr "btver2_decode" "vector")
++ (set_attr "mode" "V8SF")])
++
+ (define_insn "<mask_codefor>avx512f_vcvtps2ph512<mask_name>"
+- [(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<merge_mask_name>"
++ [(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<merge_mask_operand3>|%0<merge_mask_operand3>, %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:<avx512fmaskmode> 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:<avx512fmaskmode> 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<immintrin.h>
++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<immintrin.h>
++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 <dingguangya1@huawei.com>
+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 <gimple *> (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 <gimple *> (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 <gimple *> (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 <xiezhiheng@huawei.com>
+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 <xiezhiheng@huawei.com>
+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 <dingguangya1@huawei.com>
+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 <huangxiaoquan1@huawei.com>
+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 <cgraph_node *> safe_functions;
++ auto_vec<srtype *> 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<srtype *> 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 <stdio.h>
++#include <stdlib.h>
++
++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 <xiongzhou4@huawei.com>
+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 <root@localhost.localdomain>
+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 <dingguangya1@huawei.com>
+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 <zhongyunde@huawei.com>
+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 <limits.h>
+
+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 <arm_neon.h>
+
+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 <arm_neon.h>
+
+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 <richard.sandiford@arm.com>
+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 <richard.sandiford@arm.com>
+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 <richard.sandiford@arm.com>
+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 <richard.sandiford@arm.com>
+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 <richard.sandiford@arm.com>
+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 <richard.sandiford@arm.com>
+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 <richard.sandiford@arm.com>
+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 <richard.sandiford@arm.com>
+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 <richard.sandiford@arm.com>
+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 <richard.sandiford@arm.com>
+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 <richard.sandiford@arm.com>
+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 <richard.sandiford@arm.com>
+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 <richard.sandiford@arm.com>
+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 <richard.sandiford@arm.com>
+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 <richard.sandiford@arm.com>
+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 <richard.sandiford@arm.com>
+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 <richard.sandiford@arm.com>
+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 <richard.sandiford@arm.com>
+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 <richard.sandiford@arm.com>
+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 <<EOF
+#ifndef _CPP_CPPCONFIG_WRAPPER
+#define _CPP_CPPCONFIG_WRAPPER 1
+#include <bits/wordsize.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 <<EOF
-*default_spec:
-%%{pie|fpic|fPIC|fpie|fPIE|no-pie|fno-pic|fno-PIC|fno-pie|fno-PIE|shared|static|nostdlib|nodefaultlibs|nostartfiles:;:-fPIE}%%{fno-pic|fno-PIC|fno-pie|fno-PIE|pie|no-pie|shared|static|nostdlib|nodefaultlibs|nostartfiles:;: -pie}
+exec gcc $fl ${1+"$@"}
EOF
+chmod 755 %{buildroot}%{_prefix}/bin/c?9
+
+cd ..
+%find_lang %{name}
+%find_lang cpplib
+
+# Remove binaries we will not be including, so that they don't end up in
+# gcc-debuginfo
+rm -f %{buildroot}%{_prefix}/%{_lib}/{libffi*,libiberty.a} || :
+rm -f $FULLEPATH/install-tools/{mkheaders,fixincl}
+rm -f %{buildroot}%{_prefix}/lib/{32,64}/libiberty.a
+rm -f %{buildroot}%{_prefix}/%{_lib}/libssp*
+rm -f %{buildroot}%{_prefix}/%{_lib}/libvtv* || :
+rm -f %{buildroot}%{_prefix}/bin/%{_target_platform}-gfortran || :
+rm -f %{buildroot}%{_prefix}/bin/%{_target_platform}-gccgo || :
+rm -f %{buildroot}%{_prefix}/bin/%{_target_platform}-gcj || :
+rm -f %{buildroot}%{_prefix}/bin/%{_target_platform}-gcc-ar || :
+rm -f %{buildroot}%{_prefix}/bin/%{_target_platform}-gcc-nm || :
+rm -f %{buildroot}%{_prefix}/bin/%{_target_platform}-gcc-ranlib || :
+rm -f %{buildroot}%{_prefix}/bin/%{_target_platform}-gdc || :
+
+%ifarch %{multilib_64_archs}
+# Remove libraries for the other arch on multilib arches
+rm -f %{buildroot}%{_prefix}/lib/lib*.so*
+rm -f %{buildroot}%{_prefix}/lib/lib*.a
+rm -f %{buildroot}/lib/libgcc_s*.so*
+%if %{build_go}
+rm -rf %{buildroot}%{_prefix}/lib/go/%{gcc_major}/%{gcc_target_platform}
+%ifnarch sparc64 ppc64 ppc64p7
+ln -sf %{multilib_32_arch}-%{_vendor}-%{_target_os} %{buildroot}%{_prefix}/lib/go/%{gcc_major}/%{gcc_target_platform}
+%endif
+%endif
+%else
+%ifarch sparcv9 ppc
+rm -f %{buildroot}%{_prefix}/lib64/lib*.so*
+rm -f %{buildroot}%{_prefix}/lib64/lib*.a
+rm -f %{buildroot}/lib64/libgcc_s*.so*
+%if %{build_go}
+rm -rf %{buildroot}%{_prefix}/lib64/go/%{gcc_major}/%{gcc_target_platform}
+%endif
+%endif
+%endif
-%post -n gcc-go
-# we don't want a BuildRequires on gccN-go but otherwise the install
-# step of the build fails, so simply skip the script when gccN-go isn't there
-if [ -f %{_bindir}/go-%{gcc_suffix} ] ; then
-update-alternatives \
- --install %{_bindir}/go go %{_bindir}/go-%{gcc_suffix} 100 \
- --slave %{_bindir}/gofmt gofmt %{_bindir}/gofmt-%{gcc_suffix}
-fi
+rm -f %{buildroot}%{mandir}/man3/ffi*
+
+# Help plugins find out nvra.
+echo gcc-%{version}-%{release}.%{_arch} > $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 <lua>
+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 <lua>
+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 <xiongzhou4@huawei.com> - 10.3.1-38
+- Type:Backport
+- ID:NA
+- SUG:NA
+- DESC: Fix CVE-2023-4039.
+
+* Wed Jun 28 2023 dingguangya <dingguangya1@huawei.com> - 10.3.1-37
+- Type:Spec
+- ID:NA
+- SUG:NA
+- DESC: Sync patch from openeuler/gcc
+
+* Mon Jun 19 2023 dingguangya <dingguangya1@huawei.com> - 10.3.1-36
+- Type:Spec
+- ID:NA
+- SUG:NA
+- DESC: Sync patch from openeuler/gcc
+
+* Wed Jun 14 2023 Wang Ding <wangding16@huawei.com> - 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 <wangding16@huawei.com> - 10.3.1-34
+- Type:Sync
+- ID:NA
+- SUG:NA
+- DESC:Add PGO kernel option to support PGO kernel
+
+* Fri Jun 9 2023 huangxiaoquan <huangxiaoquan1@huawei.com> - 10.3.1-33
+- Type:Sync
+- ID:NA
+- SUG:NA
+- DESC:Sync patch from openeuler/gcc
+
+* Thu Jun 8 2023 huangxiaoquan <huangxiaoquan1@huawei.com> - 10.3.1-32
+- Type:Sync
+- ID:NA
+- SUG:NA
+- DESC:Sync patch from openeuler/gcc
+
+* Sat Jun 3 2023 Wang Ding <wangding16@huawei.com> - 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 <wangding16@huawei.com> - 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 <huangxiaoquan1@huawei.com> - 10.3.1-28
+- Type:Sync
+- ID:NA
+- SUG:NA
+- DESC:Sync patch from openeuler/gcc
+
+* Wed Apr 12 2023 huangxiaoquan <huangxiaoquan1@huawei.com> - 10.3.1-27
+- Type:enhancement
+- ID:NA
+- SUG:NA
+- DESC:enable isl and add --with-isl
+
+* Fri Mar 24 2023 huangxiaoquan <huangxiaoquan1@huawei.com> - 10.3.1-26
+- Type:SPEC
+- ID:NA
+- SUG:NA
+- DESC:Enable-languages uses variables
+
+* Mon Mar 20 2023 huangxiaoquan <huangxiaoquan1@huawei.com> - 10.3.1-25
+- Type:Revert
+- ID:NA
+- SUG:NA
+- DESC:Revert without pie option
+
+* Thu Mar 9 2023 huangxiaoquan <huangxiaoquan1@huawei.com> - 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 <xiongzhou4@huawei.com> - 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 <linda7@huawei.com> - 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 <linda7@huawei.com> - 10.3.1-17
+- Type:Sync
+- ID:NA
+- SUG:NA
+- DESC:Sync patch from openeuler/gcc
+
+* Fri Sep 16 2022 eastb233 <xiezhiheng@huawei.com> - 10.3.1-16
+- Type:Sync
+- ID:NA
+- SUG:NA
+- DESC:Sync patch from openeuler/gcc
+
+* Thu Sep 8 2022 benniaobufeijiushiji <linda7@huawei.com> - 10.3.1-15
+- Type:Sync
+- ID:NA
+- SUG:NA
+- DESC:Sync patch from openeuler/gcc
+
+* Tue Aug 16 2022 benniaobufeijiushiji <linda7@huawei.com> - 10.3.1-14
+- Type:Revert
+- ID:NA
+- SUG:NA
+- DESC:Remove 2 unnecessary patches
+
+* Mon Aug 8 2022 benniaobufeijiushiji <linda7@huawei.com> - 10.3.1-13
+- Type:Sync
+- ID:NA
+- SUG:NA
+- DESC:Sync patch from openeuler/gcc
+
+* Fri Jul 08 2022 zhaomengmeng <zhaomengmeng@kylinos.cn> - 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 <linda7@huawei.com> - 10.3.1-10
+- Type:Sync
+- ID:NA
+- SUG:NA
+- DESC:Sync patch from openeuler/gcc
+
+* Wed Mar 2 2022 benniaobufeijiushiji <linda7@huawei.com> - 10.3.1-9
+- Type:Sync
+- ID:NA
+- SUG:NA
+- DESC:Sync patch from openeuler/gcc
+
+* Tue Mar 1 2022 benniaobufeijiushiji <linda7@huawei.com> - 10.3.1-8
+- Type:SPEC
+- ID:NA
+- SUG:NA
+- DESC:Remove date in release
+
+* Wed Feb 23 2022 benniaobufeijiushiji <linda7@huawei.com> - 10.3.1-20220223.7
+- Type:Sync
+- ID:NA
+- SUG:NA
+- DESC:Sync patch from openeuler/gcc
+
+* Wed Jan 05 2022 eastb233 <xiezhiheng@huawei.com> - 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 <xiezhiheng@huawei.com> - 10.3.1-20210914.5
+- Type:Sync
+- ID:NA
+- SUG:NA
+- DESC:Sync patch from openeuler/gcc
+
+* Fri Aug 27 2021 eastb233 <xiezhiheng@huawei.com> - 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 <xiezhiheng@huawei.com> - 10.3.1-20210819.3
+- Type:Sync
+- ID:NA
+- SUG:NA
+- DESC:Sync patch from openeuler/gcc
+
+* Wed Jul 28 2021 eastb233 <xiezhiheng@huawei.com> - 10.3.0-20210728.2
+- Type:Sync
+- ID:NA
+- SUG:NA
+- DESC:Sync patch from openeuler/gcc
+
+* Tue Jul 27 2021 eastb233 <xiezhiheng@huawei.com> - 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