aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.4.3
diff options
context:
space:
mode:
authorJing Yu <jingyu@google.com>2011-01-30 22:18:29 -0800
committerJing Yu <jingyu@google.com>2011-01-30 22:18:29 -0800
commit4a66e756636cb8364582ea503abd10d76f5b4aa3 (patch)
tree9660204ec085888a0601a6460c967b204a63d5f3 /gcc-4.4.3
parentb6be42e837844cce5283f42fcfac31e6d66a277d (diff)
downloadtoolchain_gcc-4a66e756636cb8364582ea503abd10d76f5b4aa3.tar.gz
toolchain_gcc-4a66e756636cb8364582ea503abd10d76f5b4aa3.tar.bz2
toolchain_gcc-4a66e756636cb8364582ea503abd10d76f5b4aa3.zip
Upgrade gcc-4.4.3 for Android toolchain.
- Backport upstream patches to support arm hardfp. - Backport gcc-4.5 patches to support -march=atom. Now it is able to build atom toolchain with glibc from this branch - Develop a bunch of optimizations - Fix a few arm dejagnu failures To-do list: - Support Android/atom - Fix ia32 bootstrap failure Change-Id: I5e10dcd21620d4d8ca984d1d1707a76067e61691
Diffstat (limited to 'gcc-4.4.3')
-rw-r--r--gcc-4.4.3/Makefile.in14
-rw-r--r--gcc-4.4.3/README.google1232
-rwxr-xr-xgcc-4.4.3/configure30
-rw-r--r--gcc-4.4.3/configure.ac22
-rw-r--r--gcc-4.4.3/gcc/ChangeLog.ix86274
-rw-r--r--gcc-4.4.3/gcc/Makefile.in76
-rw-r--r--gcc-4.4.3/gcc/attribs.c5
-rw-r--r--gcc-4.4.3/gcc/builtin-types.def4
-rw-r--r--gcc-4.4.3/gcc/builtins.def3
-rw-r--r--gcc-4.4.3/gcc/c-common.c74
-rw-r--r--gcc-4.4.3/gcc/c-cppbuiltin.c5
-rw-r--r--gcc-4.4.3/gcc/c-opts.c36
-rw-r--r--gcc-4.4.3/gcc/c.opt10
-rw-r--r--gcc-4.4.3/gcc/caller-save.c2
-rw-r--r--gcc-4.4.3/gcc/calls.c4
-rw-r--r--gcc-4.4.3/gcc/cfgexpand.c171
-rw-r--r--gcc-4.4.3/gcc/cgraph.c33
-rw-r--r--gcc-4.4.3/gcc/cgraph.h12
-rw-r--r--gcc-4.4.3/gcc/cgraphbuild.c30
-rw-r--r--gcc-4.4.3/gcc/common.opt51
-rw-r--r--gcc-4.4.3/gcc/config.gcc40
-rw-r--r--gcc-4.4.3/gcc/config.in12
-rw-r--r--gcc-4.4.3/gcc/config/arm/arm-protos.h4
-rw-r--r--gcc-4.4.3/gcc/config/arm/arm.c1197
-rw-r--r--gcc-4.4.3/gcc/config/arm/arm.h99
-rw-r--r--gcc-4.4.3/gcc/config/arm/arm.md22
-rw-r--r--gcc-4.4.3/gcc/config/arm/bpabi.h14
-rw-r--r--gcc-4.4.3/gcc/config/arm/constraints.md21
-rw-r--r--gcc-4.4.3/gcc/config/arm/linux-eabi.h1
-rw-r--r--gcc-4.4.3/gcc/config/arm/t-arm-elf7
-rw-r--r--gcc-4.4.3/gcc/config/arm/thumb2.md57
-rw-r--r--gcc-4.4.3/gcc/config/i386/atom.md796
-rw-r--r--gcc-4.4.3/gcc/config/i386/cpuid.h2
-rw-r--r--gcc-4.4.3/gcc/config/i386/cygming.h4
-rw-r--r--gcc-4.4.3/gcc/config/i386/driver-i386.c23
-rw-r--r--gcc-4.4.3/gcc/config/i386/i386-c.c9
-rw-r--r--gcc-4.4.3/gcc/config/i386/i386-protos.h8
-rw-r--r--gcc-4.4.3/gcc/config/i386/i386.c912
-rw-r--r--gcc-4.4.3/gcc/config/i386/i386.h22
-rw-r--r--gcc-4.4.3/gcc/config/i386/i386.md219
-rw-r--r--gcc-4.4.3/gcc/config/i386/i386.opt12
-rw-r--r--gcc-4.4.3/gcc/config/i386/linux-unwind.h2
-rw-r--r--gcc-4.4.3/gcc/config/i386/linux.h2
-rw-r--r--gcc-4.4.3/gcc/config/i386/linux64.h10
-rw-r--r--gcc-4.4.3/gcc/config/i386/lwpintrin.h100
-rw-r--r--gcc-4.4.3/gcc/config/i386/mingw32.h2
-rw-r--r--gcc-4.4.3/gcc/config/i386/ppro.md8
-rw-r--r--gcc-4.4.3/gcc/config/i386/sse.md62
-rw-r--r--gcc-4.4.3/gcc/config/i386/ssemath.h25
-rw-r--r--gcc-4.4.3/gcc/config/i386/x86intrin.h4
-rw-r--r--gcc-4.4.3/gcc/config/linux-android.h6
-rw-r--r--gcc-4.4.3/gcc/config/linux.h8
-rw-r--r--gcc-4.4.3/gcc/config/mips/linux64.h4
-rw-r--r--gcc-4.4.3/gcc/config/rs6000/linux64.h2
-rw-r--r--gcc-4.4.3/gcc/config/rs6000/sysv4.h7
-rw-r--r--gcc-4.4.3/gcc/config/sparc/sparc.c10
-rwxr-xr-xgcc-4.4.3/gcc/configure123
-rw-r--r--gcc-4.4.3/gcc/configure.ac65
-rw-r--r--gcc-4.4.3/gcc/coverage.c178
-rw-r--r--gcc-4.4.3/gcc/coverage.h11
-rw-r--r--gcc-4.4.3/gcc/cp/call.c81
-rw-r--r--gcc-4.4.3/gcc/cp/class.c18
-rw-r--r--gcc-4.4.3/gcc/cp/cp-lang.c8
-rw-r--r--gcc-4.4.3/gcc/cp/cp-tree.h34
-rw-r--r--gcc-4.4.3/gcc/cp/cvt.c2
-rw-r--r--gcc-4.4.3/gcc/cp/error.c47
-rw-r--r--gcc-4.4.3/gcc/cp/lang-specs.h6
-rw-r--r--gcc-4.4.3/gcc/cp/name-lookup.c21
-rw-r--r--gcc-4.4.3/gcc/cp/parser.c50
-rw-r--r--gcc-4.4.3/gcc/cp/pt.c100
-rw-r--r--gcc-4.4.3/gcc/cp/typeck2.c23
-rw-r--r--gcc-4.4.3/gcc/dbgcnt.def1
-rw-r--r--gcc-4.4.3/gcc/doc/extend.texi48
-rw-r--r--gcc-4.4.3/gcc/doc/gcov.texi10
-rw-r--r--gcc-4.4.3/gcc/doc/install.texi5
-rw-r--r--gcc-4.4.3/gcc/doc/invoke.texi204
-rw-r--r--gcc-4.4.3/gcc/doc/md.texi5
-rw-r--r--gcc-4.4.3/gcc/doc/tm.texi31
-rw-r--r--gcc-4.4.3/gcc/dwarf2out.c56
-rw-r--r--gcc-4.4.3/gcc/dyn-ipa.c379
-rw-r--r--gcc-4.4.3/gcc/esp.h145
-rw-r--r--gcc-4.4.3/gcc/explow.c4
-rw-r--r--gcc-4.4.3/gcc/expr.h2
-rw-r--r--gcc-4.4.3/gcc/final.c122
-rw-r--r--gcc-4.4.3/gcc/flags.h10
-rw-r--r--gcc-4.4.3/gcc/fold-const.c41
-rw-r--r--gcc-4.4.3/gcc/fortran/module.c2
-rw-r--r--gcc-4.4.3/gcc/function.h4
-rw-r--r--gcc-4.4.3/gcc/gcc.c41
-rw-r--r--gcc-4.4.3/gcc/gcov-dump.c51
-rw-r--r--gcc-4.4.3/gcc/gcov-io.c385
-rw-r--r--gcc-4.4.3/gcc/gcov-io.h288
-rw-r--r--gcc-4.4.3/gcc/gcov.c501
-rw-r--r--gcc-4.4.3/gcc/genautomata.c159
-rw-r--r--gcc-4.4.3/gcc/ggc-page.c6
-rw-r--r--gcc-4.4.3/gcc/ggc.h2
-rw-r--r--gcc-4.4.3/gcc/ipa-cp.c2
-rw-r--r--gcc-4.4.3/gcc/ipa-inline.c645
-rw-r--r--gcc-4.4.3/gcc/ipa-struct-reorg.c2
-rw-r--r--gcc-4.4.3/gcc/ira.c4
-rw-r--r--gcc-4.4.3/gcc/l-ipo.c4
-rw-r--r--gcc-4.4.3/gcc/langhooks-def.h2
-rw-r--r--gcc-4.4.3/gcc/langhooks.c2
-rw-r--r--gcc-4.4.3/gcc/langhooks.h7
-rw-r--r--gcc-4.4.3/gcc/libgcov.c1422
-rw-r--r--gcc-4.4.3/gcc/mversn-dispatch.c1705
-rw-r--r--gcc-4.4.3/gcc/objc/lang-specs.h10
-rw-r--r--gcc-4.4.3/gcc/objcp/lang-specs.h8
-rw-r--r--gcc-4.4.3/gcc/optabs.c3
-rw-r--r--gcc-4.4.3/gcc/opts.c62
-rw-r--r--gcc-4.4.3/gcc/params.def89
-rw-r--r--gcc-4.4.3/gcc/passes.c18
-rw-r--r--gcc-4.4.3/gcc/pmu-profile.c1553
-rw-r--r--gcc-4.4.3/gcc/postreload.c2
-rw-r--r--gcc-4.4.3/gcc/predict.c20
-rw-r--r--gcc-4.4.3/gcc/profile.c17
-rw-r--r--gcc-4.4.3/gcc/profile.h6
-rw-r--r--gcc-4.4.3/gcc/real.c49
-rw-r--r--gcc-4.4.3/gcc/real.h2
-rw-r--r--gcc-4.4.3/gcc/rtl.def6
-rw-r--r--gcc-4.4.3/gcc/rtl.h1
-rw-r--r--gcc-4.4.3/gcc/simplify-got.c15
-rw-r--r--gcc-4.4.3/gcc/target-def.h2
-rw-r--r--gcc-4.4.3/gcc/target.h8
-rw-r--r--gcc-4.4.3/gcc/targhooks.c6
-rw-r--r--gcc-4.4.3/gcc/targhooks.h1
-rw-r--r--gcc-4.4.3/gcc/testsuite/ChangeLog.ix8656
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/abi/forced.C2
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/debug/dwarf2/lineno-simple1.C13
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/debug/dwarf2/pr41063.C20
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/debug/dwarf2/pr44641.C43
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/debug/dwarf2/pr46527.C18
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/init/pr42556.C10
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/ipa/ipa-cp-1.C309
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/lookup/koenig5.C32
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/lookup/koenig6.C18
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/mversn10.C54
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/mversn10a.C37
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/mversn12.C43
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/mversn14.C26
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/mversn14a.C8
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/mversn16.C39
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/mversn8.C44
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/mversn9.C31
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/other/crash-5.C16
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/other/crash-7.C19
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/other/crash-8.C109
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/template/crash56.C4
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/template/defarg13.C19
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/template/error39.C11
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_common.h47
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-50.C22
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-51.C44
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-52.C39
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-53.C40
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-54.C35
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-55.C38
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-56.C36
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-57.C22
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-58.C32
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-59.C34
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-60.C37
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-61.C15
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-62.C18
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-65.C30
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-66.C35
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-67.C32
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-68.C34
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-69.C31
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-70.C38
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/torture/mversn11.C40
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/torture/mversn5.C28
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/torture/mversn5.h5
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/torture/mversn5a.C12
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/tree-prof/mversn13.C37
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/tree-prof/mversn15.C23
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/tree-prof/mversn15a.C26
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/uninit-pred-3_a.C77
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/uninit-pred-3_b.C87
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/warn/Wnonnull-1.C16
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/warn/Wnull-conversion-1.C2
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/warn/Wnull-conversion-2.C2
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/warn/Wself-assign-1.C4
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/warn/Wself-assign-2.C6
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/warn/Wself-assign-3.C2
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/warn/Wself-assign-4.C2
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/warn/Wself-assign-5.C38
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/warn/Wself-assign-non-pod-1.C54
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/warn/Wself-assign-non-pod-2.C31
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/warn/Wself-assign-non-pod-3.C35
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/warn/Wself-assign-non-pod-4.C48
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/warn/Wself-assign-non-pod-5.C38
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.dg/warn/nonnull2.C14
-rw-r--r--gcc-4.4.3/gcc/testsuite/g++.old-deja/g++.ns/koenig5.C4
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.c-torture/compile/pr22379.c2
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.c-torture/compile/pr42632.c2
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.c-torture/execute/pr44575.c49
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.dg/always_inline2.c4
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.dg/always_inline3.c4
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.dg/always_inline4.c23
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.dg/autopar/reduc-1.c2
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.dg/builtin-apply2.c1
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.dg/ipa/ipa-4.c2
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.dg/mversn2.c47
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.dg/mversn3.c30
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.dg/mversn4.c29
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.dg/mversn4.h5
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.dg/mversn4a.c13
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.dg/mversn6.c29
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.dg/mversn7.c45
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.dg/nrv6.c22
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.dg/overlay1.c70
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.dg/overlay2.c18
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.dg/overlay3.c18
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.dg/overlay4.c25
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.dg/overlay5.c24
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.dg/pr43564.c16
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.dg/sibcall-1.c2
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.dg/sibcall-2.c2
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.dg/sibcall-3.c4
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.dg/sibcall-4.c4
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.dg/sibcall-6.c4
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.dg/torture/mversn1.c31
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.dg/torture/stackalign/builtin-apply-4.c1
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.dg/torture/stackalign/stackalign.exp1
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.dg/tree-prof/ffvpt-pro-1.c14
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.dg/tree-prof/ffvpt-pro-2.c14
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.dg/tree-prof/ffvpt-pro-3.c14
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.dg/tree-prof/ffvpt-pro-4.c13
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.dg/tree-prof/ffvpt-pro.h17
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.dg/tree-prof/inliner-1.c2
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.dg/tree-ssa/alias_bug.c61
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-25.c4
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.dg/tree-ssa/integer-addr.c29
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.dg/tree-ssa/update-threading.c2
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.dg/uninit-13.c3
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.dg/vect/costmodel/i386/i386-costmodel-vect.exp2
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.dg/vect/costmodel/x86_64/x86_64-costmodel-vect.exp2
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.dg/vect/vect.exp2
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.dg/winline-5.c2
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/aapcs.exp35
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/abitest.h122
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp1.c17
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp10.c38
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp11.c39
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp12.c38
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp13.c39
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp14.c24
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp15.c20
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp16.c22
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp17.c20
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp2.c19
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp3.c21
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp4.c20
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp5.c30
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp6.c30
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp7.c37
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp8.c37
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp9.c38
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.target/arm/eabi1.c71
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.target/arm/g2.c2
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.target/arm/loop-autoinc.c18
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.target/arm/mmx-1.c2
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.target/arm/pr44999.c9
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.target/arm/pr46631.c16
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.target/arm/scd42-2.c2
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.target/arm/thumb2-cmpneg2add-1.c12
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.target/arm/thumb2-cmpneg2add-2.c12
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.target/bfin/loop-autoinc.c16
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.target/i386/align-main-1.c2
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.target/i386/align-main-2.c2
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.target/i386/incoming-10.c19
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.target/i386/incoming-11.c18
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.target/i386/incoming-12.c20
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.target/i386/incoming-13.c15
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.target/i386/incoming-14.c15
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.target/i386/incoming-15.c15
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.target/i386/incoming-6.c17
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.target/i386/incoming-7.c16
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.target/i386/incoming-8.c18
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.target/i386/incoming-9.c18
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.target/i386/max-stack-align.c14
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.target/i386/movbe-1.c18
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.target/i386/movbe-2.c19
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.target/i386/pr37843-4.c13
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.target/i386/sse-12.c2
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.target/i386/sse-13.c15
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.target/i386/sse-14.c17
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.target/i386/sse-22.c22
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.target/i386/sse-23.c47
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.target/i386/sse2-vec-2a.c4
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.target/x86_64/abi/callabi/func-2a.c27
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.target/x86_64/abi/callabi/func-2b.c13
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.target/x86_64/abi/callabi/func-indirect-2a.c17
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.target/x86_64/abi/callabi/func-indirect-2b.c24
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.target/x86_64/abi/callabi/vaarg-4a.c24
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.target/x86_64/abi/callabi/vaarg-4b.c31
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.target/x86_64/abi/callabi/vaarg-5a.c17
-rw-r--r--gcc-4.4.3/gcc/testsuite/gcc.target/x86_64/abi/callabi/vaarg-5b.c37
-rw-r--r--gcc-4.4.3/gcc/testsuite/lib/scanasm.exp37
-rw-r--r--gcc-4.4.3/gcc/testsuite/lib/target-supports.exp26
-rw-r--r--gcc-4.4.3/gcc/timevar.def1
-rw-r--r--gcc-4.4.3/gcc/toplev.c4
-rw-r--r--gcc-4.4.3/gcc/tree-dfa.c26
-rw-r--r--gcc-4.4.3/gcc/tree-flow.h6
-rw-r--r--gcc-4.4.3/gcc/tree-inline.c6
-rw-r--r--gcc-4.4.3/gcc/tree-pass.h3
-rw-r--r--gcc-4.4.3/gcc/tree-profile.c757
-rw-r--r--gcc-4.4.3/gcc/tree-sample-profile.c184
-rw-r--r--gcc-4.4.3/gcc/tree-sample-profile.h10
-rw-r--r--gcc-4.4.3/gcc/tree-ssa-alias.c32
-rw-r--r--gcc-4.4.3/gcc/tree-ssa-dce.c55
-rw-r--r--gcc-4.4.3/gcc/tree-ssa-loop-im.c4
-rw-r--r--gcc-4.4.3/gcc/tree-ssa-loop-ivopts.c404
-rw-r--r--gcc-4.4.3/gcc/tree-ssa-lrs.c8
-rw-r--r--gcc-4.4.3/gcc/tree-ssa-operands.c14
-rw-r--r--gcc-4.4.3/gcc/tree-ssa-pre.c1
-rw-r--r--gcc-4.4.3/gcc/tree-ssa-sccvn.c30
-rw-r--r--gcc-4.4.3/gcc/tree-ssa-uninit.c219
-rw-r--r--gcc-4.4.3/gcc/tree-ssa.c13
-rw-r--r--gcc-4.4.3/gcc/tree-stack-overlay.c1004
-rw-r--r--gcc-4.4.3/gcc/tree-stack-overlay.h27
-rw-r--r--gcc-4.4.3/gcc/tree-threadsafe-analyze.c556
-rw-r--r--gcc-4.4.3/gcc/tree-vrp.c2
-rw-r--r--gcc-4.4.3/gcc/unwind-dw2-fde-glibc.c4
-rw-r--r--gcc-4.4.3/gcc/value-prof.c709
-rw-r--r--gcc-4.4.3/gcc/value-prof.h16
-rw-r--r--gcc-4.4.3/gcc/varasm.c6
-rw-r--r--gcc-4.4.3/libgcc/Makefile.in18
-rw-r--r--gcc-4.4.3/libiberty/getpagesize.c1
-rw-r--r--gcc-4.4.3/libmudflap/Makefile.in10
-rwxr-xr-xgcc-4.4.3/libmudflap/configure48
-rw-r--r--gcc-4.4.3/libmudflap/configure.ac2
-rw-r--r--gcc-4.4.3/libstdc++-v3/include/backward/hashtable.h3
-rw-r--r--gcc-4.4.3/libstdc++-v3/include/bits/stl_algo.h7
-rw-r--r--gcc-4.4.3/libstdc++-v3/include/bits/stl_tree.h26
-rw-r--r--gcc-4.4.3/libstdc++-v3/include/ext/sso_string_base.h51
-rw-r--r--gcc-4.4.3/libstdc++-v3/include/ext/vstring.h4
-rw-r--r--gcc-4.4.3/libstdc++-v3/include/ext/vstring.tcc10
339 files changed, 21220 insertions, 2210 deletions
diff --git a/gcc-4.4.3/Makefile.in b/gcc-4.4.3/Makefile.in
index ada717f89..53a5146aa 100644
--- a/gcc-4.4.3/Makefile.in
+++ b/gcc-4.4.3/Makefile.in
@@ -305,9 +305,17 @@ WINDRES_FOR_BUILD = @WINDRES_FOR_BUILD@
BUILD_PREFIX = @BUILD_PREFIX@
BUILD_PREFIX_1 = @BUILD_PREFIX_1@
+# Some stuff don't compile with SSP
+enable_esp = @enable_esp@
+ifeq ($(enable_esp),yes)
+ESP_NOSSP_CFLAGS = -fno-stack-protector
+else
+ESP_NOSSP_CFLAGS=
+endif
+
# Flags to pass to stage2 and later makes. They are defined
# here so that they can be overridden by Makefile fragments.
-BOOT_CFLAGS= -g -O2
+BOOT_CFLAGS= -g -O2 $(ESP_NOSSP_CFLAGS)
BOOT_LDFLAGS=
BOOT_ADAFLAGS=-gnatpg -gnata
@@ -350,9 +358,9 @@ GNATMAKE = @GNATMAKE@
CFLAGS = @CFLAGS@
LDFLAGS = @LDFLAGS@
-LIBCFLAGS = $(CFLAGS)
+LIBCFLAGS = $(CFLAGS) $(ESP_NOSSP_CFLAGS)
CXXFLAGS = @CXXFLAGS@
-LIBCXXFLAGS = $(CXXFLAGS) -fno-implicit-templates
+LIBCXXFLAGS = $(CXXFLAGS) -fno-implicit-templates $(ESP_NOSSP_CFLAGS)
TFLAGS =
diff --git a/gcc-4.4.3/README.google b/gcc-4.4.3/README.google
index bfddb6db5..5c749f4ac 100644
--- a/gcc-4.4.3/README.google
+++ b/gcc-4.4.3/README.google
@@ -1501,7 +1501,7 @@ gcc/testsuite/g++.dg/debug/dwarf2/dwarf4-typedef.C
Fix problem in gcc where a local typedef in a member function could produce
an ICE in output_die. (b/2479745)
Owner: ccoutant
- Status: Not yet upstream
+ Status: Upstream in GCC 4.6 at r161217.
gcc/cp/cp-lang.c
gcc/gimple.c
@@ -2016,6 +2016,162 @@ gcc/simplify-got.c
Owner: jingyu
Status: google local
+gcc/cgraph.c
+gcc/cgraph.h
+gcc/value-prof.c
+ When deleting a cgraph_node, also remove it from the pid_map to
+ avoid accidentally using an invalid cgraph_node during value
+ profiling with stale profiles.
+ Owner: nvachhar
+ Status: not yet upstream
+
+gcc/Makefile.in
+gcc/common.opt
+gcc/coverage.c
+gcc/gcov-io.h
+gcc/libgcov.c
+gcc/params.def
+gcc/profile.c
+gcc/tree-profile.c
+gcc/value-prof.h
+ Add new FDO technique based on reuse distance measurement.
+ Not on by default in either plain, FDO or LIPO.
+ Use optional flag -fprofile-reusedist for profile generation.
+ Use optional flag -foptimize-locality for profile use.
+ There are dependencies to runtime libraries not included here.
+ Owner: rus
+ Status: Google local
+
+gcc/config/arm/arm.md
+gcc/config/arm/thumb2.md
+gcc/config/arm/constraints.md
+gcc/testsuite/lib/target-supports.exp
+gcc/testsuite/gcc.target/arm/thumb2-cmpneg2add-1.c
+gcc/testsuite/gcc.target/arm/thumb2-cmpneg2add-2.c
+ Add new peephole2 to change cmn to add for thumb2 if the immediate constant
+ is a small negative number.
+ Owner: carrot
+ Status: In GCC 4.6 at revision 161040 and part of 147812(target-supports.exp).
+
+gcc/dyn-ipa.c
+gcc/gcov-io.h
+gcc/libgcov.c
+ Implement lipo module-group sorting.
+ Owner: raksit
+ Status: not yet upstream
+
+gcc/dyn-ipa.c
+ Fix a bug in the previous submission above.
+ Owner: raksit
+ Status: not yet upstream
+
+gcc/config/arm/thumb2.md
+gcc/config/arm/constraints.md
+ Correct the thumb2_addsi_short pattern.
+ Owner: carrot
+ Status: In GCC 4.5 at revision 155054.
+
+gcc/doc/invoke.texi
+gcc/final.c
+gcc/common.opt
+gcc/params.def
+ New compiler option, -fcgraph-section, to emit call graph edge profile
+ counts in .note.callgraph.text sections. This information will allow
+ the linker to reconstruct the global call graph and do better function
+ layout. A new .note.callgraph.text section is created for each function.
+ This section lists every callee and the number of times it is called. The
+ params variable "note-cgraph-section-edge-threshold" can be used to
+ only list edges above a certain threshold.
+ Owner: tmsriram
+ Status: not yet upstream
+
+gcc/opts.c
+ Fix the way -Werror=coverage-mismatch is enabled by default so that
+ -Wno-error disables it properly.
+ Owner: nvachhar
+ Status: Not yet upstream
+
+gcc/ipa-inline.c
+ Upstream patch fixing a problem with improperly updated priorities
+ (badness) of callsites during inlining.
+ Owner: meheff
+ Status: Partial backport of GCC 4.6.0 upstream patch r158278.
+
+gcc/tree-ssa-loop-ivopts.c
+gcc/dbgcnt.def
+ Fix b2776888
+ Fix a problem in multiple exit handling
+ Owner: davidxl
+ Status: the second part will be in upstream (approved)
+ The first part is in a the sinking support which is not
+ accepted upstream
+
+gcc/config/arm/arm.c
+gcc/doc/tm.texi
+gcc/simplify-got.c
+gcc/target.h
+gcc/passes.c
+ Move the simplify-got pass after loop optimization.
+ Owner: carrot
+ Status: not yet upsteam.
+
+gcc/value-prof.c
+ Make check_ic_target more robust by checking for record size if an
+ indirect call site returns a record type and also check to ensure
+ the call site and target function have a matching number of
+ parameters.
+ Owner: nvachhar
+ Status: Not yet upstream.
+
+gcc/ipa-inline.c
+ Change detailed dump of inliner to more readable tree-based format.
+ Owner: meheff
+ Status: not yet upsteam.
+
+gcc/c-opts.c
+gcc/c.opt
+gcc/cp/call.c
+gcc/cp/cvt.c
+gcc/doc/invoke.texi
+gcc/testsuite/g++.dg/warn/Wnull-conversion-1.C
+gcc/testsuite/g++.dg/warn/Wnull-conversion-2.C
+ Change the option name for null conversion warning from -Wnull-conversion
+ to -Wconversion-null to match upstream GCC's option.
+ Owner: lcwu
+ Status: not yet upstream.
+
+gcc/Makefile.in
+gcc/c-opts.c
+gcc/doc/invoke.texi
+gcc/dyn-ipa.c
+gcc/ggc-page.c
+gcc/ggc.h
+gcc/params.def
+ Implement memory consumption based auto-cutoff of the number of
+ imported modules during profile-use.
+ Owner: raksit
+gcc/final.c
+ Enhance assembly debug dump to include control flow annotations.
+ Owner: davidxl
+ Status: not yet upstream
+
+gcc/config/arm/thumb2.md
+ Replace tst instruction with lsls for a single bit test.
+ Owner: carrot
+ Status: back port of upstream GCC 4.6.0 patches 161344, 161929, 161930.
+
+gcc/ipa-inline.c
+ Properly update all callsite priorities after each inlining decision.
+ Owner: meheff
+ Status: not yet upsteam.
+
+gcc/params.def
+ Lower the lipo maximum memory limit so that a couple of benchmarks that
+ did't build earlier on the compiler-team forge cluster (which apparently
+ has lower memory limits than public forge cluster) can build now.
+ Owner: raksit
+ Status: not yet upstream
+
config.sub
gcc/config.gcc
gcc/config/linux.h
@@ -2061,21 +2217,405 @@ gcc/config/arm/thumb2.md
Owner: jingyu
Status: Back port upstream patch r157942
+gcc/ipa-inline.c
+ Change inlining heuristic in a few ways:
+ (1) Change base priority to average growth per callsite.
+ (2) Clean out some crufty elements of priority formula.
+ (3) Add threshold parameter which enables inlining of high priority
+ callsites of functions not marked inline.
+ Owner: meheff
+ Status: not yet upsteam.
+
gcc/config/arm/arm.h
Add .note.GNU-stack annotation to all ARM targeted codes.
Owner: jingyu
Status: keep it local
-gcc/config/arm/thumb2.md
- Replace tst instruction with lsls for a single bit test.
+gcc/cp/pt.c
+gcc/testsuite/lib/scanasm.exp
+gcc/testsuite/g++.dg/debug/dwarf2/lineno-simple1.C
+gcc/testsuite/g++.dg/debug/dwarf2/pr44641.C
+ Fix debug locations of certain template instantiations
+ Owner: jyasskin
+ Status: backport of upstream r162349 and r162383, and a very small
+ piece of 147866.
+
+gcc/calls.c
+gcc/fortran/module.c
+gcc/ipa-struct-reorg.c
+ Fix spurious "may be used uninitialized" errors. This is required to
+ compile gcc with optimization enabled.
+ Owner: aaw
+ Status: google-local
+
+gcc/tree-ssa-uninit.c
+ Fix 2862386
+ Owner: davidxl
+ Status: not yet upstream
+
+gcc/cp/typeck2.c
+gcc/testsuite/g++.dg/init/pr42556.C
+ Drop empty CONSTRUCTOR when all of its elements are explicitly initialized.
Owner: carrot
- Status: back port of upstream GCC 4.6.0 patches 161344, 161929, 161930.
+ Status: Back port from upstream patch r158047.
+
+libstdc++-v3/include/bits/stl_algo.h
+libstdc++-v3/include/bits/stl_tree.h
+ For http://b/1731200, make sure that debug checks do not hide compilation
+ errors.
+ Owner: ppluzhnikov
+ Status: google-local
+
+gcc/c.opt
+gcc/doc/extend.texi
+gcc/doc/invoke.texi
+gcc/testsuite/g++.dg/warn/Wnonnull-1.C
+ Enable -Wnonnull check in C++.
+ Owner: lcwu
+ Status: not yet upstream
+
+gcc/caller-save.c
+gcc/ira.c
+gcc/postreload.c
+gcc/rtl.h
+ Fix long build time for MaoDefs.cc. b/2524357.
+ http://gcc.gnu.org/ml/gcc-cvs/2010-08/msg00135.html
+ Owner: martint
+ Status: in gcc 4.5
libiberty/getpagesize.c
Local work around for building C++ library for Android toolchain.
Owner: jingyu
Status: keep it local
+gcc/ipa-inline.c
+gcc/params.def
+gcc/tree-ssa-lrs.c
+ Improvements to inliner size estimation heuristics. Account for linker
+ garbage collection, and function prologue/epilogue/alignment size. Changes
+ to tree-ssa-lrs.c are due to "may be used uninitialized" warnings exposed by
+ the inlining heuristic changes.
+ Owner: meheff
+ Status: not yet upstream
+
+gcc/config/arm/arm.md
+gcc/config/arm/thumb2.md
+gcc/testsuite/gcc.target/arm/pr44999.c
+ Change "and r0, r0, 255" to uxtb in thumb2.
+ Owner: carrot
+ Status: back port from upstream GCC 4.6 patch r163184.
+
+gcc/cp/name-lookup.c
+gcc/testsuite/g++.dg/lookup/koenig5.C
+gcc/testsuite/g++.dg/lookup/koenig6.C
+gcc/testsuite/g++.dg/template/crash56.C
+gcc/testsuite/g++.old-deja/g++.ns/koenig5.C
+ Ignore non-functions during argument-dependent lookup.
+ http://gcc.gnu.org/bugzilla/show_bug.cgi?id=17365
+ http://gcc.gnu.org/viewcvs?view=revision&revision=153905
+ Owner: aaw
+ Status: backport of upstream rev. 153905
+
+gcc/tree-profile.c
+ Change prefix of -foptimize-locality runtime from __libopt__ to libopt__.
+ Owner: rus
+ Status: google-local
+
+gcc/value-prof.c
+ Disable the stringops value profile transformations when -foptimize-locality
+ is turned on.
+ Owner: rus
+ Status: google-local
+
+gcc/cp/call.c
+gcc/cp/class.c
+gcc/cp/cp-lang.c
+gcc/cp/cp-tree.h
+gcc/langhooks-def.h
+gcc/langhooks.c
+gcc/langhooks.h
+gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-50.C
+gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-51.C
+gcc/tree-threadsafe-analyze.c
+ Add support for allowing non-const but non-modifying methods to be
+ protected by reader locks.
+ Owner: lcwu
+ Status: not yet upstream
+
+gcc/c-common.c
+gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-52.C
+gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-53.C
+gcc/tree-threadsafe-analyze.c
+ Added support to allow point_to_guarded_by and point_to_guarded attributes
+ on smart/scoped pointers.
+ Owner: lcwu
+ Status: not yet upstream
+
+gcc/tree-profile.c
+ Calls to builtin functions must not be instrumented by the direct call
+ profiler. Check for DECL_BUILT_IN, in addition to the already present
+ DECL_IS_BUILTIN check.
+ Owner: raksit
+ Status: not yet upstream
+
+gcc/dyn-ipa.c
+ Reduce memory consumption during dynamic-call-graph-analysis of LIPO
+ profile collection run (upto 30x), by making use of hash set instead
+ of sparse array.
+ Owner: raksit
+ Status: not yet upstream
+
+gcc/params.def
+ Lower lipo profile-use maximum-memory threshold from 2.8G to 2.4G
+ Owner: raksit
+ Status: not yet upstream
+
+gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-56.C
+gcc/tree-threadsafe-analyze.c
+ Fix a bug in handling annotated member functions accessed through smart
+ pointer wrapped objects.
+ Owner: lcwu
+ Status: not yet upstream
+
+gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-57.C
+gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-58.C
+gcc/tree-threadsafe-analyze.c
+ Modify annotalysis so that a variable passed into a function for a
+ reference parameter is consider a use of this variable.
+ Owner: lcwu
+ Status: not yet upstream
+
+gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-54.C
+gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-55.C
+gcc/tree-threadsafe-analyze.c
+ Fix a bug in annotalysis' handling of the annotations that specify function
+ parameters as its lock arguments. We should not prepend the base object in
+ such cases.
+ Owner: lcwu
+ Status: not yet upstream
+
+libstdc++-v3/include/ext/sso_string_base.h
+libstdc++-v3/include/ext/vstring.h
+libstdc++-v3/include/ext/vstring.tcc
+ Remove unqualified lookups into dependent template base classes from STL
+ headers. These break clang. See http://b/2961693.
+ Owner: aaw
+ Status: not yet upstream
+
+gcc/cp/cp-tree.h
+gcc/cp/error.c
+gcc/cp/pt.c
+gcc/testsuite/g++.dg/template/defarg13.C
+gcc/testsuite/g++.dg/template/error39.C
+ Elide default arguments when printing templates in error messages.
+ http://b/2904171
+ Owner: aaw
+ Status: backport of uptream revisions 145566, 150223, and 149066.
+
+gcc/attribs.c
+gcc/c-common.c
+gcc/c-cppbuiltin.c
+gcc/testsuite/g++.dg/thread-ann/thread_annot_common.h
+gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-59.C
+gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-60.C
+gcc/tree-threadsafe-analyze.c
+ Add additional lock annotations/attributes to support (finer-grain)
+ escape hatches and allow annotalysis to understand some of tsan's dynamic
+ annotations.
+ Owner: lcwu
+ Status: not yet upstream
+
+gcc/gcc-4.4.3/libstdc++-v3/include/backward/hashtable.h
+ Intialize member fields of Hashtable_iterator in default constructor.
+ Owner: davidxl
+ Status: not yet upstream
+
+gcc/cp/cp-lang.c
+gcc/cp/cp-tree.h
+gcc/cp/error.c
+gcc/cp/parser.c
+gcc/cp/pt.c
+gcc/testsuite/g++.dg/other/crash-5.C
+gcc/testsuite/g++.dg/other/crash-7.C
+gcc/testsuite/g++.dg/other/crash-8.C
+ Don't elide default arguments for template names in debug info. Also,
+ simplify the implementation relative to http://cl/43521-p2 by storing
+ non-default argument counts during template construction. This reduces the
+ likelihood of undesired side-effects.
+ http://b/2987780
+ Owner: aaw
+ Status: backport of upstream revisions 148073 and 156351 (sans crash-6.C
+ which fails in unrelated code).
+
+gcc/config/arm/arm.c
+ Set inlining parameters to ARM-specific values.
+ Owner: meheff
+ Status: not yet upstream
+
+gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-61.C
+gcc/tree-threadsafe-analyze.c
+ Fix a bug in the handling of checking variables passed to a function by
+ reference. When the argument is an SSA name, we should simply grab the RHS of
+ its SSA DEF instead of calling get_canonical_lock_expr which does more than
+ what we need and would introduce infinite mutual-recursion in some cases.
+ Owner: lcwu
+ Status: not yet upstream
+
+gcc/l-ipo.c
+gcc/common.opt
+gcc/doc/invoke.texi
+ Add option -fripa-no-promote-always-inline-func
+ Owner: davidxl
+ Status: not yet upstream
+
+gcc/i386/i386.c
+gcc/testsuite/gcc.c-torture/execute/pr44575.c
+ When copying va_arg from a set of register save slots into a temporary, if
+ the container is bigger than type size, do the copying using smaller mode or
+ using memcpy.
+ Owner: eraman
+ Status: backport of upstream revision 161097
+
+gcc/cp/call.c
+gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-62.C
+ Fix an issue in the support that allows non-const but non-modifying methods
+ to be protected by reader locks (cl/43309-p2). The previous fix only handles
+ methods but not overloaded operators (e.g. operator[]).
+ Owner: lcwu
+
+gcc/l-ipo.c
+ fix bug in option -fripa-no-promote-always-inline-func
+ Owner: davidxl
+ Status: not yet upstream
+
+gcc/ipa-inline.c
+ Fix problem where inconsistent profile caused a divide by zero error
+ in the compiler
+ Owner: rlevin
+ Status: not yet upstream
+
+gcc/tree-ssa-alias.c
+gcc/tree-ssa-operands.c
+gcc/tree-ssa-loop-im.c
+gcc/testsuite/gcc.dg/tree-ssa/indirect-addr.c
+ Fix b/3034345: incorrect code generation with integer address
+ Owner: davidxl
+ Status: not yet stream (not needed)
+
+gcc/tree-inline.c
+ Fix b3052769
+ Owner: davidxl
+ Status: not yet upstream
+
+gcc/opts.c
+gcc/toplev.c
+gcc/testsuite/gcc.dg/pr43564.c
+gcc/testsuite/gcc.dg/nrv6.c
+ Fix b/3065307: internal compiler error in tree_nrv
+ Owner: eraman
+ Status: Upstream r157795. nrv6.c is a local test case.
+
+gcc/ChangeLog.ix86
+gcc/doc/md.texi
+gcc/genautomata.c
+gcc/rtl.def
+ Added bypass choice.
+ http://gcc.gnu.org/viewcvs?view=revision&revision=145155
+ Owner: asharif
+ Status: Upstream in ix86 branch r145155. Also in trunk.
+
+gcc/config.gcc
+gcc/config/i386/cpuid.h
+gcc/config/i386/i386-c.c
+gcc/config/i386/i386.c
+gcc/config/i386/i386.h
+gcc/config/i386/i386.md
+gcc/config/i386/i386.opt
+gcc/config/i386/lwpintrin.h
+gcc/config/i386/x86intrin.h
+gcc/doc/extend.texi
+gcc/doc/invoke.texi
+gcc/testsuite/gcc.target/i386/sse-12.c
+gcc/testsuite/gcc.target/i386/sse-13.c
+gcc/testsuite/gcc.target/i386/sse-14.c
+gcc/testsuite/gcc.target/i386/sse-22.c
+gcc/testsuite/gcc.target/i386/sse-23.c
+ Add support for LWP instructions of bulldozer microarchitecture.
+ Owner: eraman
+ Status: In upstream r153917 and r155217. Some local changes since patches
+ couldn't be cleanly applied.
+
+gcc/ChangeLog.ix86
+gcc/config/i386/cygming.h
+gcc/config/i386/i386-protos.h
+gcc/config/i386/i386.c
+gcc/config/i386/i386.h
+gcc/config/i386/i386.md
+gcc/config/i386/i386.opt
+gcc/config/i386/mingw32.h
+gcc/doc/invoke.texi
+gcc/testsuite/ChangeLog.ix86
+gcc/testsuite/gcc.target/x86_64/abi/callabi/func-2a.c
+gcc/testsuite/gcc.target/x86_64/abi/callabi/func-2b.c
+gcc/testsuite/gcc.target/x86_64/abi/callabi/func-indirect-2a.c
+gcc/testsuite/gcc.target/x86_64/abi/callabi/func-indirect-2b.c
+gcc/testsuite/gcc.target/x86_64/abi/callabi/vaarg-4a.c
+gcc/testsuite/gcc.target/x86_64/abi/callabi/vaarg-4b.c
+gcc/testsuite/gcc.target/x86_64/abi/callabi/vaarg-5a.c
+gcc/testsuite/gcc.target/x86_64/abi/callabi/vaarg-5b.c
+ Replace DEFAULT_ABI with ix86_abi. Add some tests that were upstream.
+ http://gcc.gnu.org/viewcvs?view=revision&revision=145157
+ Owner: asharif
+ Status: Upstream in ix86 branch r145157. Also in trunk.
+
+gcc/ChangeLog.ix86
+gcc/config/i386/i386-protos.h
+gcc/config/i386/i386.c
+ Rewrite of ix86_agi_dependent() function.
+ http://gcc.gnu.org/viewcvs?view=revision&revision=145236
+ Owner: asharif
+ Status: Upstream in ix86 branch r145236. Also in trunk.
+
+gcc/ChangeLog.ix86
+gcc/config/i386/i386.c
+ Move initialization of ix86_abi.
+ http://gcc.gnu.org/viewcvs?view=revision&revision=145450
+ Owner: asharif
+ Status: Upstream in ix86 branch r145450. Also in trunk.
+
+gcc/params.def
+ Change stack frame growth parameter to zero. With this change, the
+ stack frame growth is strictly limited during inlining by the
+ parameter large-stack-frame, which is set to 16K.
+ Owner: meheff
+ Status: Local patch
+
+gcc/testsuite/g++.dg/torture/pr45709-2.C
+gcc/testsuite/g++.dg/torture/pr45709.C
+gcc/tree-inline.c
+ Backport r164399 from upstream gcc-4_4-branch (b/3068369).
+ Owner: raksit
+ Status: In upstream branches 4.3 and onwards.
+
+gcc/Makefile.in
+ Backport fix for PR/40249. The bug causes unwanted inlining when
+ compiling crtstuff.c for PowerPC platforms. Symptom is segv on
+ program exit, due to register corruption caused by invalid _fini
+ function in crtbeginT.o.
+ * Makefile.in (CRTSTUFF_CFLAGS): Replace -fno-inline-functions
+ with -fno-inline.
+ http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40249
+ http://gcc.gnu.org/viewcvs?view=revision&revision=147907
+ Owner: simonb
+ Status: Backport upstream branch 4.5 r147907.
+
+gcc/params.def
+ Change stack frame growth parameter to zero. With this change, the
+ stack frame growth is strictly limited during inlining by the
+ parameter large-stack-frame, which is set to 16K.
+ Owner: meheff
+ Status: Local patch
+
gcc/testsuite/g++.dg/torture/pr45709-2.C
gcc/testsuite/g++.dg/torture/pr45709.C
gcc/tree-inline.c
@@ -2083,11 +2623,401 @@ gcc/tree-inline.c
Owner: raksit
Status: In upstream branches 4.3 and onwards.
+gcc/Makefile.in
+ Backport fix for PR/40249. The bug causes unwanted inlining when
+ compiling crtstuff.c for PowerPC platforms. Symptom is segv on
+ program exit, due to register corruption caused by invalid _fini
+ function in crtbeginT.o.
+ * Makefile.in (CRTSTUFF_CFLAGS): Replace -fno-inline-functions
+ with -fno-inline.
+ http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40249
+ http://gcc.gnu.org/viewcvs?view=revision&revision=147907
+ Owner: simonb
+ Status: Backport upstream branch 4.5 r147907.
+
+gcc/cp/call.c
+gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-65.C
+ Fix a bug in cl/43309-p2 that allows non-const but non-modifying
+ overload methods to be protected by reader locks. In the original
+ implementation, when iterating through all possible overload
+ candidate functions, we didn't consider the fact that if a candidate
+ is a builtin, cand->fn actually contains an identifier node instead
+ of a function decl node. The bug caused the compiler to seg-fault.
+ Owner: lcwu
+ Status: Not yet upstream
+
+gcc/tree-inline.c
+ Improve error message when failing to inline an always_inline function.
+ Owner: meheff
+ Status: Not yet upstream
+
+gcc/testsuite/gcc.dg/always_inline2.c
+gcc/testsuite/gcc.dg/always_inline3.c
+ Fix testsuite failures due to change in inlining failure error message
+ for always_inline functions.
+ Owner: meheff
+ Status: Not yet upstream
+
+gcc/ipa-inline.c
+gcc/params.def
+ Unify inlining priority as growth/frequency and add priority tie-breakers
+ to stabilize inlining decisions in the presence of incosequential
+ code changes.
+ Owner: meheff
+
+gcc/ipa-inline.c
+ Add missing semicolon to fix compilation error.
+ Owner: meheff
+ Status: Local patch
+
+gcc/tree-ssa-uninit.C
+gcc/testsuite/g++.db/uninit-pred-3_a.C
+gcc/testsuite/g++.db/uninit-pred-3_b.C
+ Uninitialized variable warning enhancement
+ Owner: davidxl
+ Status: in upstream 4.6
+
+libstdc++-v3/include/ext/sso_string_base.h
+ Use different macro to guard scribbling on dangling strings, so
+ string::operator[] fixit can be run separately from dangling
+ string fixit.
+ Owner: ppluzhnikov
+ Status: google-local patch
+
+gcc/tree-ssa.c
+gcc/tree-ssa-uninit.c
+gcc/tree-flow.h
+gcc/c-opts.c
+gcc/opts.c
+gcc/common.opt
+gcc/doc/invoke.texi
+ Implement -Wmaybe-uninitialized option to control may be uninitialized warning
+ Owner: davidxl
+ Status: Not yet upstream
+
+gcc/ChangeLog.ix86
+gcc/config.gcc
+gcc/config/i386/atom.md
+gcc/config/i386/i386-c.c
+gcc/config/i386/i386.c
+gcc/config/i386/i386.h
+gcc/config/i386/i386.md
+gcc/config/i386/sse.md
+ Add atom pipeline model, tuning and insn selection.
+ Owner: asharif
+ Status: Upstream in ix86 branch r145450, r145632. Also in trunk.
+
+gcc/value-prof.c
+ Disable the stringops value profile transformations when either
+ -fprofile-reusedist or -foptimize-locality is turned on.
+ Owner: rus
+ Status: google-local
+
+gcc/opts.c
+ Fix a bug in handling -Wmaybe-uninitialized
+ Owner: davidxl
+ Status: not yet upstream
+
+gcc/ipa-inline.c
+ Fix ARM build failures by eliminating use of sqrt in inlining priority
+ compression scheme and renaming a parameter.
+ Owner: meheff
+ Status: Local patch
+
+gcc/tree-ssa-operands.c
+ Fix b/3125704
+ Owner: davidxl
+ Status: not needed in upstream
+
+gcc/testsuite/gcc.dg/tree-ssa/alias_bug.c
+ Add new test case
+ Owner: davidxl
+ Status: local patch
+
+gcc/ipa-cp.c
+ Fix segfault in updating of jump functions of functions cloned during
+ interprocedural constant propagation.
+ Owner: meheff
+ Status: not needed upstream
+
+gcc/ipa-inline.c
+ Prevent inlining which results in recursive calls to functions marked
+ always_inline.
+ Owner: meheff
+ Status: not yet upstream
+
+gcc/config/i386/i386.c:
+ Change switch cases to 'if then else' to prevent 'duplicate case value' error
+ for 32 bit builds.
+ Owner: eraman
+ Status: In upstream at r155237.
+
+gcc/config/mips/linux64.h
+ Back port 4.6 patch to add Android linker to mips.
+ Owner: jingyu
+ Status: In upstream at r160824.
+
+gcc/ChangeLog.ix86
+gcc/config/i386/atom.md
+gcc/config/i386/i386-protos.h
+gcc/config/i386/i386.c
+gcc/config/i386/i386.md
+gcc/doc/invoke.texi
+ Added atom documentation. Also changed i386.md to prefer add over lea,
+ whenever possible for Atom target.
+ Owner: asharif
+ Status: In ix86 branch in r145727 and r146444. Also in trunk.
+
+gcc/cp/parser.c
+gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-66.C
+gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-67.C
+ Fix a bug that occurs when annotating a member function definition outside
+ the class with locks that are also members in the class. The compiler
+ couldn't bind the lock names when parsing the attributes and therefore
+ emitted bogus warnings. This fix tries to re-bind the lock names again after
+ the class context is in scope.
+ Owner: lcwu
+ Status: not yet upstream
+
+gcc/testsuite/g++.dg/ipa/ipa-cp-1.C
+ Add new test case
+ Owner: meheff
+ Status: not needed upstream
+
+gcc/ChangeLog.ix86
+gcc/config/i386/driver-i386.c
+ Check extended family and model for Intel processors. Support Intel Atom.
+ Owner: asharif
+ Status: In ix86 branch in r147737 and r166085. Also in trunk.
+
+gcc/config.gcc
+gcc/config/linux.h
+gcc/config/linux-android.h
+gcc/config/arm/linux-eabi.h
+ Back port 4.6 Android related patch to fix several uclinux target.
+ Owner: jingyu
+ Status: In upstream at r162315.
+
+gcc/config/i386/linux-unwind.h
+ Back port 4.6 Bionic patch to fix i386 build with Bionic.
+ Owner: jingyu
+ Status: In upstream at r163933.
+
+
+gcc/cp/pt.c
+gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-68.C
+gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-69.C
+ Fix a bug in our delayed name binding with nested template instantiation
+ by pushing into and pop out of a stack the names that require delay binding
+ when we start and finish a template instantiation.
+ Owner: lcwu
+
+gcc/unwind-dw2-fde-glibc.c
+ Back port upstream 4.6 patch to fix x86 Bionic build.
+ Owner: jingyu
+ Status: In upstream at 163970.
+
+gcc/ChangeLog.ix86
+gcc/config/i386/cpuid.h
+gcc/config/i386/i386.c
+gcc/config/i386/i386.h
+gcc/config/i386/i386.md
+gcc/config/i386/i386.opt
+gcc/doc/invoke.texi
+gcc/testsuite/ChangeLog.ix86
+gcc/testsuite/gcc.target/i386/movbe-1.c
+gcc/testsuite/gcc.target/i386/movbe-2.c
+gcc/config/i386/driver-i386.c
+ Added PTA_MOVBE to atom.
+ Status: In ix86 branch in r147774 and r149232. Also in trunk.
+ Owner: asharif
+
+gcc/config/i386/i386.c
+gcc/config/i386/i386.h
+gcc/testsuite/gcc.target/i386/incoming-10.c
+gcc/testsuite/gcc.target/i386/incoming-11.c
+gcc/testsuite/gcc.target/i386/incoming-12.c
+gcc/testsuite/gcc.target/i386/incoming-13.c
+gcc/testsuite/gcc.target/i386/incoming-14.c
+gcc/testsuite/gcc.target/i386/incoming-15.c
+gcc/testsuite/gcc.target/i386/incoming-6.c
+gcc/testsuite/gcc.target/i386/incoming-7.c
+gcc/testsuite/gcc.target/i386/incoming-8.c
+gcc/testsuite/gcc.target/i386/incoming-9.c
+gcc/testsuite/gcc.target/i386/pr37843-4.c
+ Changed stack boundary code. It may change stack alignment.
+ Added new tests.
+ http://gcc.gnu.org/viewcvs?view=revision&revision=153780
+ Status: In ix86 branch in r153780. Also in trunk.
+ Owner: asharif
+
+gcc/tree-dfa.c
+gcc/tree-flow.h
+gcc/tree-ssa-loop-ivopts.c
+gcc/testsuite/gcc.target/bfin/loop-autoinc.c
+ Enhancement of auto increment.
+ Owner: carrot
+ Status: back port from upstream GCC 4.5 r150588.
+
+gcc/common.opt
+gcc/doc/invoke.texi
+gcc/gcov-io.h
+gcc/libgcov.c
+gcc/params.def
+gcc/profile.c
+gcc/profile.h
+gcc/tree-profile.c
+ Add sampling to branch profiling with -fprofile-generate-sampling.
+ Owner: rus
+ Status: not yet upstream
+
+gcc/ChangeLog.ix86
+gcc/config/i386/atom.md
+gcc/config/i386/i386.md
+gcc/config/i386/ppro.md
+gcc/config/i386/sse.md
+gcc/testsuite/ChangeLog.ix86
+gcc/testsuite/gcc.target/i386/sse2-vec-2a.c
+gcc/config/i386/i386.c
+ Turn on X86_TUNE_INTER_UNIT_MOVES for m_ATOM.
+ Properly handle psrldq for march=atom.
+ http://gcc.gnu.org/viewcvs?view=revision&revision=156958
+ http://gcc.gnu.org/viewcvs?view=revision&revision=161214
+ Owner: asharif
+ Status: In ix86 branch in r156958 and r161214. Also in trunk.
+
+gcc/Makefile.in
+gcc/cfgexpand.c
+gcc/common.opt
+gcc/function.h
+gcc/opts.c
+gcc/passes.c
+gcc/testsuite/gcc.dg/overlay1.c
+gcc/testsuite/gcc.dg/overlay2.c
+gcc/testsuite/gcc.dg/overlay3.c
+gcc/testsuite/gcc.dg/overlay4.c
+gcc/toplev.c
+gcc/tree-pass.h
+gcc/tree-stack-overlay.c
+gcc/tree-stack-overlay.h
+ Add support for an early stack allocation guarded by
+ -fearly-stack-alloc flag.
+ Owner: eraman
+ Status: Not yet upstream.
+
+gcc/testsuite/gcc.target/arm/loop-autoinc.c
+ Add an arm test case for the auto increment patch.
+ Owner: carrot
+ Status: Google-local patch.
+
+gcc/ChangeLog.ix86
+gcc/config.gcc
+gcc/config/i386/ssemath.h
+gcc/doc/install.texi
+gcc/testsuite/ChangeLog.ix86
+gcc/testsuite/gcc.dg/torture/stackalign/stackalign.exp
+ Support --with-fpmath=sse for x86. This fixes: b/2070963.
+ http://gcc.gnu.org/viewcvs?view=revision&revision=163239
+ Owner: asharif
+ Status: In ix86 branch in r163239. Also in trunk.
+
+gcc/common.opt
+gcc/coverage.c
+gcc/coverage.h
+gcc/doc/invoke.texi
+gcc/gcc.c
+gcc/gcov-dump.c
+gcc/gcov-io.c
+gcc/gcov-io.h
+gcc/libgcov.c
+gcc/opts.c
+gcc/params.def
+gcc/pmu-profile.c
+gcc/tree-profile.c
+libgcc/Makefile.in
+ Add FDO support for collecting PMU profiles via -fpmu-profile-generate flag.
+ Owner: singhai
+ Status: Local patch
+
+gcc/Makefile.in
+gcc/configure.ac
+gcc/configure
+gcc/gcc.c
+ For http://b/2739909, pass appropriate rpath to linker by default.
+ Owner: ppluzhnikov
+ Status: Google-local patch.
+
+gcc/pmu-profile.c
+ For http://b/3203856, guard x86 specific code with #ifdef's in order
+ to fix a broken ARM build.
+ Owner: singhai
+ Status: google-local patch
+
+gcc/c-common.c
+gcc/testsuite/g++.dg/warn/nonnull2.C
+ Add support to check whether a nonnull attribute references 'this' pointer.
+ Owner: lcwu
+ Status: not yet upstream.
+
+gcc/tree-sample-profile.c
+gcc/tree-sample-profile.h
+gcc/coverage.h
+gcc/predict.c
+gcc/value-prof.c
+gcc/cgraphbuild.c
+ SampleFDO enhancement
+ Owner: dehao
+ Status: google-local patch
+
+
+gcc/tree-flow.h
+gcc/tree-ssa-dce.c
+gcc/tree-ssa-sccvn.c
+gcc/tree-ssa-pre.c
+ Fix b/3212290
+ Owner: davidxl
+ Status: not needed in upstream
+
gcc/config/arm/cortex-a9.md
Cortex A9 machine description enhancement.
Owner: carrot
Status: back ported from upstream GCC 4.5 r153779.
+gcc/cp/pt.c
+ Fix b/3199268 / PR46527: give templates more accurate source location.
+ Owner: jyasskin
+ Status: backported from upstream GCC r167104
+
+libstdc++-v3/include/bits/stl_algo.h
+ For http://b/3243119, const-correct operator().
+ Owner: ppluzhnikov
+ Status: google-local patch.
+
+gcc/dyn-ipa.c
+ Print function name in dynanic callgraph dump
+ Owner: davidxl
+ Status: to be in upstream
+
+libstdc++-v3/include/ext/sso_string_base.h
+ For http://b/3186945, apply upstream revision
+ http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=167528
+ to eliminate overlapping memcpy() on swap with self.
+ Owner: ppluzhnikov
+ Status: upstream change 167528
+
+gcc/cfgexpand.c:
+ Guard a early stack allocation specific change with flag_early_stack_alloc.
+ Owner: eraman
+ Status: not in upstream
+
+gcc/ipa-inline.c
+gcc/testsuite/gcc.dg/always_inline4.c
+ Prevent inlining which causes the impossible to resolve situation of
+ a cycle of always_inline functions in the call graph. This generalizes
+ cl/44847. See http://b/2969299.
+ Owner: meheff
+ Status: not yet upstream
+
gcc/config/arm/arm.md
Fix bug 3264814, which was caused by missing dependencies of a previous back
port.
@@ -2112,9 +3042,303 @@ gcc/testsuite/g++.dg/init/ref15.C
Owner: dougkwan
Status: in upstream.
+gcc/Makefile.in
+gcc/builtin-types.def
+gcc/builtins.def
+gcc/c-common.c
+gcc/common.opt
+gcc/mversn-dispatch.c
+gcc/passes.c
+gcc/timevar.def
+gcc/tree-pass.h
+gcc/cgraph.c
+gcc/cgraph.h
+gcc/ipa-inline.c
+gcc/testsuite/gcc.dg/torture/mversn1.c
+gcc/testsuite/gcc.dg/mversn2.c
+gcc/testsuite/gcc.dg/mversn3.c
+gcc/testsuite/gcc.dg/mversn4.c
+gcc/testsuite/gcc.dg/mversn4a.c
+gcc/testsuite/gcc.dg/mversn4.h
+gcc/testsuite/gcc.dg/mversn6.c
+gcc/testsuite/g++.dg/torture/mversn5.C
+gcc/testsuite/g++.dg/torture/mversn5a.C
+gcc/testsuite/g++.dg/torture/mversn5.h
+gcc/testsuite/gcc.dg/mversn7.c
+gcc/testsuite/g++.dg/mversn8.C
+gcc/testsuite/g++.dg/mversn9.C
+gcc/testsuite/g++.dg/mversn10.C
+gcc/testsuite/g++.dg/mversn10a.C
+gcc/testsuite/g++.dg/torture/mversn11.C
+gcc/testsuite/g++.dg/mversn12.C
+gcc/testsuite/g++.dg/tree-prof/mversn13.C
+gcc/testsuite/g++.dg/mversn14.C
+gcc/testsuite/g++.dg/mversn14a.C
+gcc/testsuite/g++.dg/tree-prof/mversn15.C
+gcc/testsuite/g++.dg/tree-prof/mversn15a.C
+
+ Add new function attribute "version_selector".
+ Functions are marked with attribute "version_selector" only if
+ they are run-time constants. Example of such functions would
+ be those that test if a particular feature is available on a
+ particular architecture. Support has been added to hoist such
+ functions to a constructor so that they are executed only once
+ and the result is saved in a global which is used in place of
+ the function call.
+
+
+ Add support for __builtin_dispatch to allow multiversioning.
+ A new builtin is added that allows calling different functions
+ based on a run-time test. If the run-time test function is
+ called "featureTest" and the two different function versions
+ are "foo" and "bar" then the call :
+ __builtin_dispatch (featureTest, (void *) foo, (void *) bar)
+ calls foo is the test returns >=1 and bar if it returns 0.
+ Also, the flag -fclone-hot-version-paths is supported which
+ clones hot call-graph paths to such versioned functions to
+ enable maximum optimization along these paths. This is
+ equivalent to having fat binaries but for only the hot regions.
+
+ Owner: tmsriram
+ Status: google local
+
+gcc/testsuite/gcc.dg/overlay5.c
+gcc/tree-stack-overlay.c
+ Improve stack variable coalescing heuristic with -fearly-stack-alloc.
+ Owner: eraman
+ Status: local
+
+gcc/coverage.c
+gcc/doc/gcov.texi
+gcc/doc/invoke.texi
+gcc/gcov-dump.c
+gcc/gcov-io.c
+gcc/gcov-io.h
+gcc/gcov.c
+gcc/pmu-profile.c
+ Add support for parsing and dislaying PMU profile information
+ in gcov tool. Add support for collecting branch mispredict PMU
+ info on Intel and AMD platforms.
+ Owner: singhai
+ Status: google-local patch
+
+gcc/mversn-dispatch.c
+ Fix a bug related to the return type when lowering __builtin_dispatch.
+ Owner: tmsriram
+ Status: google local
+
+gcc/calls.c
+gcc/config/arm/arm-protos.h
+gcc/config/arm/arm.c
+gcc/config/arm/arm.h
+gcc/config/arm/bpabi.h
+gcc/config/arm/t-arm-elf
+gcc/config/sparc/sparc.c
+gcc/doc/extend.texi
+gcc/doc/invoke.texi
+gcc/doc/tm.texi
+gcc/explow.c
+gcc/expr.h
+gcc/optabs.c
+gcc/target-def.h
+gcc/target.h
+gcc/targhooks.c
+gcc/targhooks.h
+gcc/testsuite/gcc.dg/builtin-apply2.c
+gcc/testsuite/gcc.target/arm/aapcs/aapcs.exp
+gcc/testsuite/gcc.target/arm/aapcs/abitest.h
+gcc/testsuite/gcc.target/arm/aapcs/vfp1.c
+gcc/testsuite/gcc.target/arm/aapcs/vfp10.c
+gcc/testsuite/gcc.target/arm/aapcs/vfp11.c
+gcc/testsuite/gcc.target/arm/aapcs/vfp12.c
+gcc/testsuite/gcc.target/arm/aapcs/vfp13.c
+gcc/testsuite/gcc.target/arm/aapcs/vfp14.c
+gcc/testsuite/gcc.target/arm/aapcs/vfp15.c
+gcc/testsuite/gcc.target/arm/aapcs/vfp16.c
+gcc/testsuite/gcc.target/arm/aapcs/vfp17.c
+gcc/testsuite/gcc.target/arm/aapcs/vfp2.c
+gcc/testsuite/gcc.target/arm/aapcs/vfp3.c
+gcc/testsuite/gcc.target/arm/aapcs/vfp4.c
+gcc/testsuite/gcc.target/arm/aapcs/vfp5.c
+gcc/testsuite/gcc.target/arm/aapcs/vfp6.c
+gcc/testsuite/gcc.target/arm/aapcs/vfp7.c
+gcc/testsuite/gcc.target/arm/aapcs/vfp8.c
+gcc/testsuite/gcc.target/arm/aapcs/vfp9.c
+gcc/testsuite/gcc.target/arm/eabi1.c
+gcc/testsuite/gcc.target/arm/mmx-1.c
+gcc/testsuite/lib/target-supports.exp
+ New ARM floating point abi -mfloat-abi=hard.
+ Owner: carrot
+ Status: back ported from upstream GCC 4.5 patches r150525, r150527, r150528,
+r150530, r150531 and r150536.
+
+gcc/Makefile.in
+gcc/common.opt
+gcc/coverage.c
+gcc/coverage.h
+gcc/doc/invoke.texi
+gcc/flags.h
+gcc/fold-const.c
+gcc/gcov-io.c
+gcc/gcov-io.h
+gcc/libgcov.c
+gcc/opts.c
+gcc/profile.c
+gcc/real.c
+gcc/real.h
+gcc/testsuite/gcc.dg/tree-prof/ffvpt-pro-1.c
+gcc/testsuite/gcc.dg/tree-prof/ffvpt-pro-2.c
+gcc/testsuite/gcc.dg/tree-prof/ffvpt-pro-3.c
+gcc/testsuite/gcc.dg/tree-prof/ffvpt-pro-4.c
+gcc/tree-profile.c
+gcc/tree-vrp.c
+gcc/value-prof.c
+gcc/value-prof.h
+ Implement floating point value profile transformation (fvpt). This
+ pass enables profiling of math library calls and the possibility to
+ replace calls where arguments are very common with precalculated
+ results. The pass -ffvpt is off by default.
+ Owner: martint
+ Status: local
+
+gcc/testsuite/gcc.dg/tree-prof/ffvpt-pro.h
+ Add missing header file for ffvpt-tests.
+ Owner: martint
+ Status: local
+
+gcc/config/arm/arm.c
+ Back port upstream patch disable BB-reordering for ARM target.
+ http://gcc.gnu.org/viewcvs?view=revision&revision=153018
+ Owner: dougkwan
+ Status: In upstream rev 153018.
+
+gcc/testsuite/gcc.target/i386/max-stack-align.c
+ Brought in a testcase from upstream for lp64.
+ Owner: asharif
+ Status: In upstream r168011.
+
+libstdc++-v3/include/ext/sso_string_base.h
+ For http://b/3314076, wipe "logically dangling" part of the string with
+ 0xCD pattern.
+ Owner: ppluzhnikov
+ Status: google-local
+
+gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-70.C
+gcc/tree-threadsafe-analyze.c
+ Fix a bug (assertion failure) when processing calls to virtual functions that
+ are annotated with lock or unlock function attributes.
+ Owner: lcwu
+ Status: not yet upstream.
+
+gcc/config/arm/arm.c
+gcc/config/arm/thumb2.md
+ Change the instructions to clobber cc version for thumb2 if possible.
+ Owner: carrot
+ Status: In upstream gcc 4.6 r160458 and r160664.
+
+gcc/c.opt
+gcc/cp/parser.c
+gcc/doc/invoke.texi
+gcc/testsuite/g++.dg/warn/Wself-assign-1.C
+gcc/testsuite/g++.dg/warn/Wself-assign-2.C
+gcc/testsuite/g++.dg/warn/Wself-assign-3.C
+gcc/testsuite/g++.dg/warn/Wself-assign-4.C
+gcc/testsuite/g++.dg/warn/Wself-assign-5.C
+gcc/testsuite/g++.dg/warn/Wself-assign-non-pod-1.C
+gcc/testsuite/g++.dg/warn/Wself-assign-non-pod-2.C
+gcc/testsuite/g++.dg/warn/Wself-assign-non-pod-3.C
+gcc/testsuite/g++.dg/warn/Wself-assign-non-pod-4.C
+gcc/testsuite/g++.dg/warn/Wself-assign-non-pod-5.C
+ Add a new flag -Wself-assign-non-pod to control whether to warn on
+ self-assignment of non-POD variables. The flag is disabled by default.
+ Owner: lcwu
+ Status: not yet upstream
+
+gcc/value-prof.c
+ Remove use of glibc-only function strchrnul().
+ Owner: martint
+ Status: local
+
+gcc/config/arm/arm.c
+gcc/testsuite/gcc.target/arm/pr46631.c
+ Reduce thumb2 instructions <commutative_op> Rd, Rn, Rd to 16bit instructions.
+ Owner: carrot
+ Status: backported from upstream GCC 4.6 r167595.
+
libstdc++-v3/config/locale/generic/c_locale.cc
libstdc++-v3/config/locale/generic/c_locale.h
libstdc++-v3/config/locale/generic/time_members.cc
Hanlde NULL return value of setlocale(), required by bionic.
Owner: jingyu
Status: local
+
+gcc/testsuite/lib/scanasm.exp
+ Backport upstream patch r164527. to fix broken tests on ARM.
+ http://gcc.gnu.org/viewcvs?view=revision&revision=164527
+ Owner: dougkwan
+ Status: in r164527
+
+gcc/testsuite/gcc.dg/tree-prof/ffvpt-pro-4.c
+ Fix compilation error on armv7l-linux-gnueabi.
+ Owner: dougkwan
+ Status: local
+
+gcc/testsuite/gcc.dg/uninit-13.c
+ Mark test as expected failure. The test failed because of incorrect line
+ number in warning. bug 3374774
+ Owner: dougkwan
+ Status: local
+
+gcc/testsuite/gcc.dg/tree-prof/ffvpt-pro-3.c
+ Handle signed NaN in testcase.
+ Owner: martint
+ Status: local
+
+gcc/testsuite/gcc.dg/mversn7.c
+ Supply a body to featureTest function to work on ARM target where inlining
+ is not as aggressive as x86.
+ Owner: tmsriram
+ Status: google local
+
+gcc/testsuite/gcc.target/arm/g2.c
+gcc/testsuite/gcc.target/arm/scd42-2.c
+gcc/testsuite/gcc.target/arm/mmx-1.c
+ Skip these tests when compiling for Thumb because they are specific to
+ ARM mode. http://gcc.gnu.org/ml/gcc-patches/2010-10/msg00134.html
+ Owner: jingyu
+
+gcc/testsuite/g++.dg/abi/forced.C
+ Skip test if target needs status wrapper. Test does not work if wrapped.
+ Owner: dougkwan
+ Status: local
+
+gcc/testsuite/gcc.dg/mversn7.c
+ Fix test to work with ARM target where inlining is not as aggressive as x86.
+ Owner: tmsriram
+ Status: local
+
+gcc/gcc-4.4.3/gcc/coverage.c
+gcc/gcc-4.4.3/gcc/gcov-io.c
+gcc-4.4.3/gcc/gcov-io.h
+gcc-4.4.3/gcc/libgcov.c
+gcc-4.4.3/gcc/tree-profile.c
+ Add support for applying profile-gen to Linux kernel. Refactoring the code
+ that dumps profile information for better code sharing b/w user mode and
+ kernel mode.
+ Owner: xur
+ Statis: local
+
+gcc/config/i386/linux.h
+gcc/config/i386/linux64.h
+ Always pass --32 or --64 to the assembler, depending on compilation mode.
+ Enables (attempt) to boostrap 32-bit compiler on 64-bit x86 Linux.
+ (Provided by H.J. Lu.)
+ Owner: cgd
+ Status: backported from GCC 4.5 revs 152865 and 157143.
+
+gcc/dwarf2out.c
+gcc/testsuite/g++.dg/debug/dwarf2/pr41063.C
+ Revert CL 33375 (b/1906960) and apply the upstream patch.
+ http://gcc.gnu.org/ml/gcc-patches/2009-08/msg01508.html
+ Owner: ccoutant
+ Status: backported from GCC 4.5 revs 151185 and 151187.
diff --git a/gcc-4.4.3/configure b/gcc-4.4.3/configure
index c23e2664f..280492393 100755
--- a/gcc-4.4.3/configure
+++ b/gcc-4.4.3/configure
@@ -272,7 +272,7 @@ PACKAGE_STRING=
PACKAGE_BUGREPORT=
ac_unique_file="move-if-change"
-ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS TOPLEVEL_CONFIGURE_ARGUMENTS build build_cpu build_vendor build_os build_noncanonical host_noncanonical target_noncanonical host host_cpu host_vendor host_os target target_cpu target_vendor target_os INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LN LN_S build_libsubdir build_subdir host_subdir target_subdir CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CXX CXXFLAGS ac_ct_CXX GNATBIND ac_ct_GNATBIND GNATMAKE ac_ct_GNATMAKE do_compare gmplibs gmpinc extra_mpfr_configure_flags ppllibs pplinc clooglibs clooginc stage1_languages DEBUG_PREFIX_CFLAGS_FOR_TARGET CFLAGS_FOR_TARGET CXXFLAGS_FOR_TARGET RPATH_ENVVAR GCC_SHLIB_SUBDIR tooldir build_tooldir CONFIGURE_GDB_TK GDB_TK INSTALL_GDB_TK build_configargs build_configdirs host_configargs configdirs target_configargs AR_FOR_BUILD AS_FOR_BUILD CC_FOR_BUILD CFLAGS_FOR_BUILD CXXFLAGS_FOR_BUILD CXX_FOR_BUILD DLLTOOL_FOR_BUILD GCJ_FOR_BUILD GFORTRAN_FOR_BUILD LDFLAGS_FOR_BUILD LD_FOR_BUILD NM_FOR_BUILD RANLIB_FOR_BUILD WINDMC_FOR_BUILD WINDRES_FOR_BUILD config_shell YACC BISON M4 LEX FLEX MAKEINFO EXPECT RUNTEST AR AS DLLTOOL LD LIPO NM RANLIB STRIP WINDRES WINDMC OBJCOPY OBJDUMP CC_FOR_TARGET CXX_FOR_TARGET GCC_FOR_TARGET GCJ_FOR_TARGET GFORTRAN_FOR_TARGET AR_FOR_TARGET AS_FOR_TARGET DLLTOOL_FOR_TARGET LD_FOR_TARGET LIPO_FOR_TARGET NM_FOR_TARGET OBJDUMP_FOR_TARGET RANLIB_FOR_TARGET STRIP_FOR_TARGET WINDRES_FOR_TARGET WINDMC_FOR_TARGET RAW_CXX_FOR_TARGET FLAGS_FOR_TARGET COMPILER_AS_FOR_TARGET COMPILER_LD_FOR_TARGET COMPILER_NM_FOR_TARGET MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT stage1_cflags stage1_checking stage2_werror_flag datarootdir docdir pdfdir htmldir LIBOBJS LTLIBOBJS'
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS TOPLEVEL_CONFIGURE_ARGUMENTS build build_cpu build_vendor build_os build_noncanonical host_noncanonical target_noncanonical host host_cpu host_vendor host_os target target_cpu target_vendor target_os INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LN LN_S build_libsubdir build_subdir host_subdir target_subdir enable_esp CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CXX CXXFLAGS ac_ct_CXX GNATBIND ac_ct_GNATBIND GNATMAKE ac_ct_GNATMAKE do_compare gmplibs gmpinc extra_mpfr_configure_flags ppllibs pplinc clooglibs clooginc stage1_languages DEBUG_PREFIX_CFLAGS_FOR_TARGET CFLAGS_FOR_TARGET CXXFLAGS_FOR_TARGET RPATH_ENVVAR GCC_SHLIB_SUBDIR tooldir build_tooldir CONFIGURE_GDB_TK GDB_TK INSTALL_GDB_TK build_configargs build_configdirs host_configargs configdirs target_configargs AR_FOR_BUILD AS_FOR_BUILD CC_FOR_BUILD CFLAGS_FOR_BUILD CXXFLAGS_FOR_BUILD CXX_FOR_BUILD DLLTOOL_FOR_BUILD GCJ_FOR_BUILD GFORTRAN_FOR_BUILD LDFLAGS_FOR_BUILD LD_FOR_BUILD NM_FOR_BUILD RANLIB_FOR_BUILD WINDMC_FOR_BUILD WINDRES_FOR_BUILD config_shell YACC BISON M4 LEX FLEX MAKEINFO EXPECT RUNTEST AR AS DLLTOOL LD LIPO NM RANLIB STRIP WINDRES WINDMC OBJCOPY OBJDUMP CC_FOR_TARGET CXX_FOR_TARGET GCC_FOR_TARGET GCJ_FOR_TARGET GFORTRAN_FOR_TARGET AR_FOR_TARGET AS_FOR_TARGET DLLTOOL_FOR_TARGET LD_FOR_TARGET LIPO_FOR_TARGET NM_FOR_TARGET OBJDUMP_FOR_TARGET RANLIB_FOR_TARGET STRIP_FOR_TARGET WINDRES_FOR_TARGET WINDMC_FOR_TARGET RAW_CXX_FOR_TARGET FLAGS_FOR_TARGET COMPILER_AS_FOR_TARGET COMPILER_LD_FOR_TARGET COMPILER_NM_FOR_TARGET MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT stage1_cflags stage1_checking stage2_werror_flag datarootdir docdir pdfdir htmldir LIBOBJS LTLIBOBJS'
ac_subst_files='serialization_dependencies host_makefile_frag target_makefile_frag alphaieee_frag ospace_frag'
ac_pwd=`pwd`
@@ -934,6 +934,11 @@ Optional Features:
--enable-FEATURE[=ARG] include FEATURE [ARG=yes]
--enable-gold use gold instead of ld
--enable-libada build libada directory
+ --enable-esp
+ Enable Stack protector, Position independent executable and
+ as default if we have suppot for it when compiling
+ and link with -z relro and -z now as default.
+ Linux targets supported i*86, x86_64, ppc*, sparc* and arm*
--enable-libssp build libssp directory
--disable-ppl-version-check disable check for PPL version
--disable-cloog-version-check disable check for CLooG version
@@ -2145,6 +2150,25 @@ if test "${ENABLE_LIBADA}" != "yes" ; then
noconfigdirs="$noconfigdirs gnattools"
fi
+# Check whether --enable-esp was given and target have the support.
+# Check whether --enable-esp or --disable-esp was given.
+if test "${enable_esp+set}" = set; then
+ enableval="$enable_esp"
+
+ case $target in
+ i?86*-*-linux* | x86_64*-*-linux* | ppc*-*-linux* | sparc*-*-linux* | arm*-*-linux*)
+ enable_esp=yes
+ ;;
+ *)
+ { { echo "$as_me:$LINENO: error: *** --enable-esp is not supported on this $target target." >&5
+echo "$as_me: error: *** --enable-esp is not supported on this $target target." >&2;}
+ { (exit 1); exit 1; }; }
+ ;;
+ esac
+
+fi;
+
+
# Check whether --enable-libssp or --disable-libssp was given.
if test "${enable_libssp+set}" = set; then
enableval="$enable_libssp"
@@ -12432,6 +12456,9 @@ case $build in
*) stage1_cflags="-g -J" ;;
esac ;;
esac
+if test x$enable_esp = xyes; then
+ stage1_cflags="$stage1_cflags -fno-stack-protector"
+fi
# This is aimed to mimic bootstrap with a non-GCC compiler to catch problems.
if test "$GCC" = yes; then
@@ -13235,6 +13262,7 @@ s,@build_libsubdir@,$build_libsubdir,;t t
s,@build_subdir@,$build_subdir,;t t
s,@host_subdir@,$host_subdir,;t t
s,@target_subdir@,$target_subdir,;t t
+s,@enable_esp@,$enable_esp,;t t
s,@CC@,$CC,;t t
s,@CFLAGS@,$CFLAGS,;t t
s,@LDFLAGS@,$LDFLAGS,;t t
diff --git a/gcc-4.4.3/configure.ac b/gcc-4.4.3/configure.ac
index 97e268f2f..40aea377e 100644
--- a/gcc-4.4.3/configure.ac
+++ b/gcc-4.4.3/configure.ac
@@ -383,6 +383,25 @@ if test "${ENABLE_LIBADA}" != "yes" ; then
noconfigdirs="$noconfigdirs gnattools"
fi
+# Check whether --enable-esp was given and target have the support.
+AC_ARG_ENABLE([esp],
+[ --enable-esp
+ Enable Stack protector, Position independent executable and
+ as default if we have suppot for it when compiling
+ and link with -z relro and -z now as default.
+ Linux targets supported i*86, x86_64, ppc*, sparc* and arm*],
+[
+ case $target in
+ i?86*-*-linux* | x86_64*-*-linux* | ppc*-*-linux* | sparc*-*-linux* | arm*-*-linux*)
+ enable_esp=yes
+ ;;
+ *)
+ AC_MSG_ERROR([*** --enable-esp is not supported on this $target target.])
+ ;;
+ esac
+])
+AC_SUBST([enable_esp])
+
AC_ARG_ENABLE(libssp,
[ --enable-libssp build libssp directory],
ENABLE_LIBSSP=$enableval,
@@ -2890,6 +2909,9 @@ case $build in
*) stage1_cflags="-g -J" ;;
esac ;;
esac
+if test x$enable_esp = xyes; then
+ stage1_cflags="$stage1_cflags -fno-stack-protector"
+fi
# This is aimed to mimic bootstrap with a non-GCC compiler to catch problems.
if test "$GCC" = yes; then
diff --git a/gcc-4.4.3/gcc/ChangeLog.ix86 b/gcc-4.4.3/gcc/ChangeLog.ix86
new file mode 100644
index 000000000..1f0288190
--- /dev/null
+++ b/gcc-4.4.3/gcc/ChangeLog.ix86
@@ -0,0 +1,274 @@
+2010-08-13 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backport from mainline
+ 2010-02-26 H.J. Lu <hongjiu.lu@intel.com>
+
+ * config.gcc: Support --with-fpmath=sse for x86.
+
+ * config/i386/ssemath.h: New.
+
+ * doc/install.texi (--with-fpmath=sse): Documented.
+
+2010-06-22 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backport from mainline
+ 2010-06-22 H.J. Lu <hongjiu.lu@intel.com>
+
+ * config/i386/i386.md (unit): Also check sseishft1.
+
+ 2010-06-21 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/44615
+ * config/i386/atom.md (atom_sseishft_2): Also check sseishft1.
+
+ * config/i386/i386.md (type): Add sseishft1
+
+ * config/i386/ppro_insn (ppro_insn): Also check sseishft1.
+ (ppro_insn_load): Likewise.
+ (ppro_insn_store): Likewise.
+ (ppro_insn_both): Likewise.
+
+ * config/i386/sse.md (*vec_extractv2di_1_rex64_avx): Replace
+ sseishft with sseishft1 for type.
+ (*vec_extractv2di_1_avx): Likewise.
+ (*vec_extractv2di_1_rex64): Replace sseishft with sseishft1 for
+ type. Remove atom_unit.
+ (*vec_extractv2di_1_sse2): Likewise.
+
+2010-02-22 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backport from mainline:
+ 2010-02-22 H.J. Lu <hongjiu.lu@intel.com>
+ * config/i386/i386.c (initial_ix86_tune_features): Turn on
+ X86_TUNE_INTER_UNIT_MOVES for m_ATOM.
+
+2009-10-30 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backport from mainline:
+ 2009-10-30 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/40838
+ * cfgexpand.c (expand_stack_alignment): Call update_stack_boundary
+ first. Move assert on stack_alignment_estimated just before
+ setting stack_realign_needed.
+ (gimple_expand_cfg): Initialize stack_alignment_estimated to 0.
+ Don't call update_stack_boundary.
+
+ * config/i386/i386.c (ix86_minimum_incoming_stack_boundary): New.
+ (verride_options): Don't check ix86_force_align_arg_pointer here.
+ (ix86_function_ok_for_sibcall): Use it.
+ (ix86_update_stack_boundary): Likewise.
+
+ * config/i386/i386.h (STACK_REALIGN_DEFAULT): Update comments.
+
+2009-05-21 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backport from mainline:
+ 2009-05-21 H.J. Lu <hongjiu.lu@intel.com>
+ Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/cpuid.h (bit_MOVBE): New.
+
+ * config/i386/driver-i386.c (host_detect_local_cpu): Check movbe.
+
+ * config/i386/i386.c (OPTION_MASK_ISA_MOVBE_SET): New.
+ (OPTION_MASK_ISA_MOVBE_UNSET): Likewise.
+ (ix86_handle_option): Handle OPT_mmovbe.
+ (ix86_target_string): Add -mmovbe.
+ (pta_flags): Add PTA_MOVBE.
+ (processor_alias_table): Add PTA_MOVBE to "atom".
+ (override_options): Handle PTA_MOVBE.
+
+ * config/i386/i386.h (TARGET_MOVBE): New.
+
+ * config/i386/i386.md (bswapsi2): Check TARGET_MOVBE.
+ (*bswapsi_movbe): New.
+ (*bswapdi_movbe): Likewise.
+ (bswapdi2): Renamed to ...
+ (*bswapdi_1): This.
+ (bswapdi2): New expander.
+
+ * config/i386/i386.opt (mmovbe): New.
+
+ * doc/invoke.texi: Document -mmovbe.
+
+2009-05-20 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backport from mainline:
+ 2009-05-20 H.J. Lu <hongjiu.lu@intel.com>
+
+ * config/i386/driver-i386.c (host_detect_local_cpu): Check
+ extended family and model for Intel processors. Support Intel
+ Atom.
+
+2009-04-20 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backport from mainline:
+ 2009-04-20 Joey Ye <joey.ye@intel.com>
+ Xuepeng Guo <xuepeng.guo@intel.com>
+ H.J. Lu <hongjiu.lu@intel.com>
+
+ * config/i386/atom.md: Add bypasses with ix86_dep_by_shift_count.
+
+ * config/i386/i386.c (LEA_SEARCH_THRESHOLD): New macro.
+ (IX86_LEA_PRIORITY): Likewise.
+ (distance_non_agu_define): New function.
+ (distance_agu_use): Likewise.
+ (ix86_lea_for_add_ok): Likewise.
+ (ix86_dep_by_shift_count): Likewise.
+
+ * config/i386/i386.md: Call ix86_lea_for_add_ok to decide we
+ should split for LEA.
+
+ * config/i386/i386-protos.h (ix86_lea_for_add_ok): Declare new
+ function.
+ (ix86_dep_by_shift_count): Likewise.
+
+2009-04-07 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backport from mainline:
+ 2009-04-07 H.J. Lu <hongjiu.lu@intel.com>
+
+ * doc/invoke.texi: Document Atom support.
+
+2009-04-06 H.J. Lu <hongjiu.lu@intel.com>
+
+ * config/i386/i386.md: Revert 2 accidental checkins.
+
+2009-04-06 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backport from mainline:
+ 2009-04-06 Joey Ye <joey.ye@intel.com>
+ Xuepeng Guo <xuepeng.guo@intel.com>
+ H.J. Lu <hongjiu.lu@intel.com>
+
+ Atom pipeline model, tuning and insn selection.
+ * config.gcc (atom): Add atom config options and target.
+
+ * config/i386/atom.md: New.
+
+ * config/i386/i386.c (atom_cost): New cost.
+ (m_ATOM): New macro flag.
+ (initial_ix86_tune_features): Set m_ATOM.
+ (x86_accumulate_outgoing_args): Likewise.
+ (x86_arch_always_fancy_math_387): Likewise.
+ (processor_target): Add Atom cost.
+ (cpu_names): Add Atom cpu name.
+ (override_options): Set Atom ISA.
+ (ix86_issue_rate): New case PROCESSOR_ATOM.
+ (ix86_adjust_cost): Likewise.
+
+ * config/i386/i386.h (TARGET_ATOM): New target macro.
+ (ix86_tune_indices): Add X86_TUNE_OPT_AGU.
+ (TARGET_OPT_AGU): New target option.
+ (target_cpu_default): Add TARGET_CPU_DEFAULT_atom.
+ (processor_type): Add PROCESSOR_ATOM.
+
+ * config/i386/i386.md (cpu): Add new value "atom".
+ (use_carry, movu): New attr.
+ (atom.md): Include atom.md.
+ (adddi3_carry_rex64): Set attr "use_carry".
+ (addqi3_carry): Likewise.
+ (addhi3_carry): Likewise.
+ (addsi3_carry): Likewise.
+ (*addsi3_carry_zext): Likewise.
+ (subdi3_carry_rex64): Likewise.
+ (subqi3_carry): Likewise.
+ (subhi3_carry): Likewise.
+ (subsi3_carry): Likewise.
+ (x86_movdicc_0_m1_rex64): Likewise.
+ (*x86_movdicc_0_m1_se): Likewise.
+ (x86_movsicc_0_m1): Likewise.
+ (*x86_movsicc_0_m1_se): Likewise.
+ (*adddi_1_rex64): Emit add insn as much as possible.
+ (*addsi_1): Likewise.
+ (return_internal): Set atom_unit.
+ (return_internal_long): Likewise.
+ (return_pop_internal): Likewise.
+ (*rcpsf2_sse): Set atom_sse_attr attr.
+ (*qrt<mode>2_sse): Likewise.
+
+2009-04-02 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backport from mainline:
+ 2009-04-02 H.J. Lu <hongjiu.lu@intel.com>
+
+ * config/i386/i386.c (ix86_abi): Move initialization to ...
+ (override_options): Here.
+
+2009-03-29 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backport from mainline:
+ 2009-03-29 H.J. Lu <hongjiu.lu@intel.com>
+
+ * config/i386/i386-protos.h (ix86_agi_dependent): New.
+
+ * config/i386/i386.c (ix86_agi_dependent): Rewrite.
+ (ix86_adjust_cost): Updated.
+
+2009-03-27 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backport from mainline:
+ 2009-03-27 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/39472
+ * config/i386/i386.c (ix86_abi): New.
+ (override_options): Handle -mabi=.
+ (ix86_function_arg_regno_p): Replace DEFAULT_ABI with
+ ix86_abi.
+ (ix86_call_abi_override): Likewise.
+ (init_cumulative_args): Likewise.
+ (function_arg_advance): Likewise.
+ (function_arg_64): Likewise.
+ (function_arg): Likewise.
+ (ix86_pass_by_reference): Likewise.
+ (ix86_function_value_regno_p): Likewise.
+ (ix86_build_builtin_va_list_abi): Likewise.
+ (setup_incoming_varargs_64): Likewise.
+ (is_va_list_char_pointer): Likewise.
+ (ix86_init_machine_status): Likewise.
+ (ix86_reg_parm_stack_space): Use enum calling_abi on
+ call_abi.
+ (ix86_function_type_abi): Return enum calling_abi. Rewrite
+ for 64bit. Replace DEFAULT_ABI with ix86_abi.
+ (ix86_function_abi): Make it static and return enum
+ calling_abi.
+ (ix86_cfun_abi): Return enum calling_abi. Replace DEFAULT_ABI
+ with ix86_abi.
+ (ix86_fn_abi_va_list): Updated.
+
+ * config/i386/i386.h (ix86_abi): New.
+ (STACK_BOUNDARY): Replace DEFAULT_ABI with ix86_abi.
+ (CONDITIONAL_REGISTER_USAGE): Likewise.
+ (CUMULATIVE_ARGS): Change call_abi type to enum calling_abi.
+ (machine_function): Likewise.
+
+ * config/i386/i386.md (untyped_call): Replace DEFAULT_ABI
+ with ix86_abi.
+ * config/i386/cygming.h (TARGET_64BIT_MS_ABI): Likewise.
+ (STACK_BOUNDARY): Likewise.
+ * config/i386/mingw32.h (EXTRA_OS_CPP_BUILTINS): Likewise.
+
+ * config/i386/i386.opt (mabi=): New.
+
+ * config/i386/i386-protos.h (ix86_cfun_abi): Changed to
+ return enum calling_abi.
+ (ix86_function_type_abi): Likewise.
+ (ix86_function_abi): Removed.
+
+2009-03-27 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backport from mainline:
+ 2009-03-27 Vladimir Makarov <vmakarov@redhat.com>
+
+ * genautomata.c: Add a new year to the copyright. Add a new
+ reference.
+ (struct insn_reserv_decl): Add comments for member bypass_list.
+ (find_bypass): Remove.
+ (insert_bypass): New.
+ (process_decls): Use insert_bypass.
+ (output_internal_insn_latency_func): Output all bypasses with the
+ same input insn in one switch case.
+
+ * rtl.def (define_bypass): Describe bypass choice.
+ * doc/md.texi (define_bypass): Ditto.
diff --git a/gcc-4.4.3/gcc/Makefile.in b/gcc-4.4.3/gcc/Makefile.in
index b506db902..974b016e1 100644
--- a/gcc-4.4.3/gcc/Makefile.in
+++ b/gcc-4.4.3/gcc/Makefile.in
@@ -555,6 +555,9 @@ objext = .o
exeext = @host_exeext@
build_exeext = @build_exeext@
+# Google-local http://b/2739909
+link_rpath_spec = @link_rpath_spec@
+
# Directory in which to put man pages.
mandir = @mandir@
man1dir = $(mandir)/man1
@@ -593,13 +596,24 @@ ifeq ($(inhibit_libc),true)
INHIBIT_LIBC_CFLAGS = -Dinhibit_libc
endif
+# We don't want __stack_chk_fail in crt* and libgcc2.a.
+# We don't want to compile crtbegin, crtend and crtbeginT with -fPIE.
+enable_esp = @enable_esp@
+ifeq ($(enable_esp),yes)
+ESP_NOPIE_CFLAGS = -fno-PIE
+ESP_NOSSP_CFLAGS = -fno-stack-protector
+else
+ESP_NOPIE_CFLAGS=
+ESP_NOSSP_CFLAGS=
+endif
+
# Options to use when compiling libgcc2.a.
#
LIBGCC2_DEBUG_CFLAGS = -g
LIBGCC2_CFLAGS = -O2 $(LIBGCC2_INCLUDES) $(GCC_CFLAGS) $(TARGET_LIBGCC2_CFLAGS) \
$(LIBGCC2_DEBUG_CFLAGS) $(GTHREAD_FLAGS) \
-DIN_LIBGCC2 -D__GCC_FLOAT_NOT_NEEDED \
- $(INHIBIT_LIBC_CFLAGS)
+ $(INHIBIT_LIBC_CFLAGS) $(ESP_NOSSP_CFLAGS)
# Additional options to use when compiling libgcc2.a.
# Some targets override this to -isystem include
@@ -610,9 +624,9 @@ TARGET_LIBGCC2_CFLAGS =
# Options to use when compiling crtbegin/end.
CRTSTUFF_CFLAGS = -O2 $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -g0 \
- -finhibit-size-directive -fno-inline-functions -fno-exceptions \
+ -finhibit-size-directive -fno-inline -fno-exceptions \
-fno-zero-initialized-in-bss -fno-toplevel-reorder -fno-tree-vectorize \
- $(INHIBIT_LIBC_CFLAGS)
+ $(INHIBIT_LIBC_CFLAGS) $(ESP_NOSSP_CFLAGS)
# Additional sources to handle exceptions; overridden by targets as needed.
LIB2ADDEH = $(srcdir)/unwind-dw2.c $(srcdir)/unwind-dw2-fde.c \
@@ -642,6 +656,12 @@ EXTRA_PROGRAMS = @extra_programs@
# The rules for compiling them should be in the t-* file for the machine.
EXTRA_PARTS = @extra_parts@
+# We add crtbeginTS.o to the EXTRA_PARTS list if enable_crtbeginTS = yes
+enable_crtbeginTS = @enable_crtbeginTS@
+ifeq ($(enable_crtbeginTS),yes)
+EXTRA_PARTS += crtbeginTS.o
+endif
+
# List of extra object files that should be compiled and linked with
# compiler proper (cc1, cc1obj, cc1plus).
EXTRA_OBJS = @extra_objs@
@@ -930,7 +950,7 @@ BUILD_LIBDEPS= $(BUILD_LIBIBERTY)
# How to link with both our special library facilities
# and the system's installed libraries.
LIBS = @LIBS@ $(CPPLIB) $(LIBINTL) $(LIBICONV) $(LIBIBERTY) $(LIBDECNUMBER)
-BACKENDLIBS = $(CLOOGLIBS) $(PPLLIBS) $(GMPLIBS) $(PLUGINLIBS)
+BACKENDLIBS = $(CLOOGLIBS) $(PPLLIBS) $(GMPLIBS) $(PLUGINLIBS) -lm
# Any system libraries needed just for GNAT.
SYSLIBS = @GNAT_LIBEXC@
@@ -1166,6 +1186,7 @@ OBJS-common = \
mcf.o \
mode-switching.o \
modulo-sched.o \
+ mversn-dispatch.o \
omega.o \
omp-low.o \
optabs.o \
@@ -1212,6 +1233,7 @@ OBJS-common = \
simplify-rtx.o \
sparseset.o \
sreal.o \
+ tree-stack-overlay.o \
stack-ptr-mod.o \
statistics.o \
stmt.o \
@@ -1368,13 +1390,14 @@ MOSTLYCLEANFILES = insn-flags.h insn-config.h insn-codes.h \
LIB2FUNCS_ST = _eprintf __gcc_bcmp
# Defined in libgcov.c, included only in gcov library
-LIBGCOV = _gcov _gcov_merge_add _gcov_merge_single _gcov_merge_delta \
- _gcov_fork _gcov_execl _gcov_execlp _gcov_execle \
+LIBGCOV = _gcov _gcov_merge_add _gcov_merge_single _gcov_merge_single_float \
+ _gcov_merge_delta _gcov_fork _gcov_execl _gcov_execlp _gcov_execle \
_gcov_execv _gcov_execvp _gcov_execve \
_gcov_interval_profiler _gcov_pow2_profiler _gcov_one_value_profiler \
- _gcov_indirect_call_profiler _gcov_direct_call_profiler \
- _gcov_average_profiler _gcov_ior_profiler _gcov_merge_ior _gcov_merge_dc \
- _gcov_merge_icall_topn _gcov_indirect_call_topn_profiler
+ _gcov_one_float_value_profiler _gcov_indirect_call_profiler \
+ _gcov_direct_call_profiler _gcov_average_profiler _gcov_ior_profiler \
+ _gcov_merge_ior _gcov_merge_dc _gcov_merge_icall_topn \
+ _gcov_indirect_call_topn_profiler _gcov_merge_reusedist
FPBIT_FUNCS = _pack_sf _unpack_sf _addsub_sf _mul_sf _div_sf \
_fpcmp_parts_sf _compare_sf _eq_sf _ne_sf _gt_sf _ge_sf \
@@ -1743,8 +1766,9 @@ libgcc.mvars: config.status Makefile $(LIB2ADD) $(LIB2ADD_ST) specs \
echo LIBGCC_SYNC = '$(LIBGCC_SYNC)' >> tmp-libgcc.mvars
echo LIBGCC_SYNC_CFLAGS = '$(LIBGCC_SYNC_CFLAGS)' >> tmp-libgcc.mvars
echo CRTSTUFF_CFLAGS = '$(CRTSTUFF_CFLAGS)' >> tmp-libgcc.mvars
- echo CRTSTUFF_T_CFLAGS = '$(CRTSTUFF_T_CFLAGS)' >> tmp-libgcc.mvars
+ echo CRTSTUFF_T_CFLAGS = '$(CRTSTUFF_T_CFLAGS) $(ESP_NOPIE_CFLAGS)' >> tmp-libgcc.mvars
echo CRTSTUFF_T_CFLAGS_S = '$(CRTSTUFF_T_CFLAGS_S)' >> tmp-libgcc.mvars
+ echo enable_crtbeginTS = '$(enable_crtbeginTS)' >> tmp-libgcc.mvars
mv tmp-libgcc.mvars libgcc.mvars
@@ -1778,12 +1802,14 @@ s-mlib: $(srcdir)/genmultilib Makefile
$(T)crtbegin.o: crtstuff.c $(GCC_PASSES) $(TCONFIG_H) auto-host.h \
gbl-ctors.h stmp-int-hdrs tsystem.h coretypes.h $(TM_H)
$(GCC_FOR_TARGET) $(CRTSTUFF_CFLAGS) $(CRTSTUFF_T_CFLAGS) \
+ $(ESP_NOPIE_CFLAGS) \
-c $(srcdir)/crtstuff.c -DCRT_BEGIN \
-o $(T)crtbegin$(objext)
$(T)crtend.o: crtstuff.c $(GCC_PASSES) $(TCONFIG_H) auto-host.h \
gbl-ctors.h stmp-int-hdrs tsystem.h coretypes.h $(TM_H)
$(GCC_FOR_TARGET) $(CRTSTUFF_CFLAGS) $(CRTSTUFF_T_CFLAGS) \
+ $(ESP_NOPIE_CFLAGS) \
-c $(srcdir)/crtstuff.c -DCRT_END \
-o $(T)crtend$(objext)
@@ -1804,9 +1830,19 @@ $(T)crtendS.o: crtstuff.c $(GCC_PASSES) $(TCONFIG_H) auto-host.h \
$(T)crtbeginT.o: crtstuff.c $(GCC_PASSES) $(TCONFIG_H) auto-host.h \
gbl-ctors.h stmp-int-hdrs tsystem.h coretypes.h $(TM_H)
$(GCC_FOR_TARGET) $(CRTSTUFF_CFLAGS) $(CRTSTUFF_T_CFLAGS) \
+ $(ESP_NOPIE_CFLAGS) \
-c $(srcdir)/crtstuff.c -DCRT_BEGIN -DCRTSTUFFT_O \
-o $(T)crtbeginT$(objext)
+# This is a version of crtbegin for -static -fPIE links if espf is enable.
+ifeq ($(enable_crtbeginTS),yes)
+$(T)crtbeginTS.o: crtstuff.c $(GCC_PASSES) $(TCONFIG_H) auto-host.h \
+ gbl-ctors.h stmp-int-hdrs tsystem.h coretypes.h $(TM_H)
+ $(GCC_FOR_TARGET) $(CRTSTUFF_CFLAGS) $(CRTSTUFF_T_CFLAGS_S) \
+ -c $(srcdir)/crtstuff.c -DCRT_BEGIN -DCRTSTUFFT_O -DCRTSTUFFS_O \
+ -o $(T)crtbeginTS$(objext)
+endif
+
# Compile the start modules crt0.o and mcrt0.o that are linked with
# every program
$(T)crt0.o: s-crt0 ; @true
@@ -1924,7 +1960,7 @@ c-opts.o : c-opts.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(TREE_H) $(C_PRAGMA_H) $(FLAGS_H) $(TOPLEV_H) langhooks.h \
$(TREE_INLINE_H) $(DIAGNOSTIC_H) intl.h debug.h $(C_COMMON_H) \
opts.h options.h $(MKDEPS_H) incpath.h cppdefault.h $(TARGET_H) \
- $(TM_P_H) $(VARRAY_H) $(FUNCTION_H)
+ $(TM_P_H) $(VARRAY_H) $(FUNCTION_H) $(PARAMS_H)
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) \
$< $(OUTPUT_OPTION) @TARGET_SYSTEM_ROOT_DEFINE@
@@ -1976,6 +2012,7 @@ DRIVER_DEFINES = \
-DDEFAULT_TARGET_MACHINE=\"$(target_noncanonical)\" \
-DSTANDARD_BINDIR_PREFIX=\"$(bindir)/\" \
-DTOOLDIR_BASE_PREFIX=\"$(libsubdir_to_prefix)$(prefix_to_exec_prefix)\" \
+ -DLINK_RPATH_SPEC="\" $(link_rpath_spec) \"" \
@RUNTIME_ROOT_PREFIX_DEFINE@ \
@TARGET_SYSTEM_ROOT_DEFINE@ \
$(VALGRIND_DRIVER_DEFINES) \
@@ -2727,6 +2764,11 @@ implicit-zee.o : implicit-zee.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RT
$(DF_H) $(TIMEVAR_H) tree-pass.h $(RECOG_H) $(EXPR_H) \
$(REGS_H) $(TREE_H) $(TM_P_H) insn-config.h $(INSN_ATTR_H) $(REAL_H) $(TOPLEV_H) \
$(TARGET_H) $(OPTABS_H) insn-codes.h rtlhooks-def.h $(PARAMS_H) $(CGRAPH_H)
+mversn-dispatch.o : mversn-dispatch.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+ $(TREE_H) langhooks.h $(TREE_INLINE_H) $(FLAGS_H) $(CGRAPH_H) intl.h \
+ $(DIAGNOSTIC_H) $(FIBHEAP_H) $(PARAMS_H) $(TIMEVAR_H) tree-pass.h \
+ $(HASHTAB_H) $(COVERAGE_H) $(GGC_H) $(TREE_FLOW_H) $(RTL_H) $(IPA_PROP_H) \
+ $(BASIC_BLOCK_H) $(TOPLEV_H) $(TREE_DUMP_H)
gcse.o : gcse.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
$(REGS_H) hard-reg-set.h $(FLAGS_H) $(REAL_H) insn-config.h $(GGC_H) \
$(RECOG_H) $(EXPR_H) $(BASIC_BLOCK_H) $(FUNCTION_H) output.h $(TOPLEV_H) \
@@ -2835,7 +2877,7 @@ cfgexpand.o : cfgexpand.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
$(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) $(FUNCTION_H) $(TIMEVAR_H) $(TM_H) \
coretypes.h $(TREE_DUMP_H) except.h langhooks.h tree-pass.h $(RTL_H) \
$(DIAGNOSTIC_H) $(TOPLEV_H) $(BASIC_BLOCK_H) $(FLAGS_H) debug.h $(PARAMS_H) \
- value-prof.h $(TREE_INLINE_H) $(TARGET_H)
+ value-prof.h $(TREE_INLINE_H) $(TARGET_H) tree-stack-overlay.h
cfgrtl.o : cfgrtl.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
$(FLAGS_H) insn-config.h $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h \
output.h $(TOPLEV_H) $(FUNCTION_H) except.h $(TM_P_H) $(INSN_ATTR_H) \
@@ -2942,6 +2984,11 @@ alias.o : alias.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
$(ALIAS_H) $(EMIT_RTL_H) $(GGC_H) $(FUNCTION_H) cselib.h $(TREE_H) $(TM_P_H) \
langhooks.h $(TARGET_H) gt-alias.h $(TIMEVAR_H) $(CGRAPH_H) \
$(SPLAY_TREE_H) $(VARRAY_H) $(IPA_TYPE_ESCAPE_H) $(DF_H) tree-pass.h
+tree-stack-overlay.o : tree-stack-overlay.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
+ $(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) $(FUNCTION_H) $(TIMEVAR_H) $(TM_H) \
+ coretypes.h $(TREE_DUMP_H) except.h langhooks.h tree-pass.h $(RTL_H) \
+ $(DIAGNOSTIC_H) $(TOPLEV_H) $(BASIC_BLOCK_H) $(FLAGS_H) debug.h $(PARAMS_H) \
+ $(TARGET_H) tree-stack-overlay.h gt-tree-stack-overlay.h $(GGC_H)
stack-ptr-mod.o : stack-ptr-mod.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TM_H) $(TREE_H) $(RTL_H) $(REGS_H) $(EXPR_H) tree-pass.h \
$(BASIC_BLOCK_H) $(FLAGS_H) output.h $(DF_H)
@@ -3114,7 +3161,7 @@ $(out_object_file): $(out_file) $(CONFIG_H) coretypes.h $(TM_H) $(TREE_H) \
output.h $(INSN_ATTR_H) $(SYSTEM_H) $(TOPLEV_H) $(TARGET_H) libfuncs.h \
$(TARGET_DEF_H) $(FUNCTION_H) $(SCHED_INT_H) $(TM_P_H) $(EXPR_H) \
langhooks.h $(GGC_H) $(OPTABS_H) $(REAL_H) tm-constrs.h $(GIMPLE_H)
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) \
+ $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(ESP_NOSSP_CFLAGS)\
$(out_file) $(OUTPUT_OPTION)
# Build auxiliary files that support ecoff format.
@@ -3366,6 +3413,7 @@ GTFILES = $(CPP_ID_DATA_H) $(srcdir)/input.h $(srcdir)/coretypes.h \
$(srcdir)/tree-phinodes.c \
$(srcdir)/ipa-reference.c $(srcdir)/tree-ssa-structalias.h \
$(srcdir)/tree-ssa-structalias.c $(srcdir)/tree-inline.c \
+ $(srcdir)/tree-stack-overlay.c \
@all_gtfiles@
# Compute the list of GT header files from the corresponding C sources,
@@ -4191,7 +4239,7 @@ PLUGIN_HEADERS = $(TREE_H) $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(host_xm_file_list) $(host_xm_include_list) $(xm_include_list) \
intl.h $(PLUGIN_VERSION_H) $(DIAGNOSTIC_H) $(C_COMMON_H) $(C_PRETTY_PRINT_H) \
tree-iterator.h $(PLUGIN_H) $(TREE_FLOW_H) langhooks.h incpath.h \
- tree-ssa-sccvn.h real.h output.h $(IPA_UTILS_H)
+ tree-ssa-sccvn.h real.h output.h $(IPA_UTILS_H) $(CFGLOOP_H)
# Install the headers needed to build a plugin.
install-plugin: installdirs lang.install-plugin
diff --git a/gcc-4.4.3/gcc/attribs.c b/gcc-4.4.3/gcc/attribs.c
index d8ac372e5..ad30d7971 100644
--- a/gcc-4.4.3/gcc/attribs.c
+++ b/gcc-4.4.3/gcc/attribs.c
@@ -541,6 +541,11 @@ is_lock_attribute_p (tree identifier)
if (is_lock_attribute_with_args (identifier)
|| is_attribute_p ("no_thread_safety_analysis", identifier)
+ || is_attribute_p ("ignore_reads_begin", identifier)
+ || is_attribute_p ("ignore_reads_end", identifier)
+ || is_attribute_p ("ignore_writes_begin", identifier)
+ || is_attribute_p ("ignore_writes_end", identifier)
+ || is_attribute_p ("unprotected_read", identifier)
|| is_attribute_p ("guarded", identifier)
|| is_attribute_p ("point_to_guarded", identifier)
|| is_attribute_p ("lockable", identifier)
diff --git a/gcc-4.4.3/gcc/builtin-types.def b/gcc-4.4.3/gcc/builtin-types.def
index 4676dd764..bf86ae797 100644
--- a/gcc-4.4.3/gcc/builtin-types.def
+++ b/gcc-4.4.3/gcc/builtin-types.def
@@ -473,3 +473,7 @@ DEF_FUNCTION_TYPE_VAR_5 (BT_FN_INT_INT_INT_INT_INT_INT_VAR,
DEF_POINTER_TYPE (BT_PTR_FN_VOID_VAR, BT_FN_VOID_VAR)
DEF_FUNCTION_TYPE_3 (BT_FN_PTR_PTR_FN_VOID_VAR_PTR_SIZE,
BT_PTR, BT_PTR_FN_VOID_VAR, BT_PTR, BT_SIZE)
+
+DEF_POINTER_TYPE (BT_PTR_FN_INT, BT_FN_INT)
+DEF_FUNCTION_TYPE_VAR_3 (BT_FN_INT_PTR_FN_INT_PTR_PTR_VAR,
+ BT_INT, BT_PTR_FN_INT, BT_PTR, BT_PTR)
diff --git a/gcc-4.4.3/gcc/builtins.def b/gcc-4.4.3/gcc/builtins.def
index 7a98c7639..16c3a6ee5 100644
--- a/gcc-4.4.3/gcc/builtins.def
+++ b/gcc-4.4.3/gcc/builtins.def
@@ -758,6 +758,9 @@ DEF_BUILTIN (BUILT_IN_EMUTLS_REGISTER_COMMON,
true, true, true, ATTR_NOTHROW_LIST, false,
!targetm.have_tls)
+/* Multiversioning builtin dispatch hook. */
+DEF_GCC_BUILTIN (BUILT_IN_DISPATCH, "dispatch", BT_FN_INT_PTR_FN_INT_PTR_PTR_VAR, ATTR_NULL)
+
/* Synchronization Primitives. */
#include "sync-builtins.def"
diff --git a/gcc-4.4.3/gcc/c-common.c b/gcc-4.4.3/gcc/c-common.c
index 03f4d3451..8f5db0d38 100644
--- a/gcc-4.4.3/gcc/c-common.c
+++ b/gcc-4.4.3/gcc/c-common.c
@@ -523,6 +523,7 @@ static tree check_case_value (tree);
static bool check_case_bounds (tree, tree, tree *, tree *);
static tree handle_packed_attribute (tree *, tree, tree, int, bool *);
+static tree handle_version_selector_attribute (tree *, tree, tree, int, bool *);
static tree handle_nocommon_attribute (tree *, tree, tree, int, bool *);
static tree handle_common_attribute (tree *, tree, tree, int, bool *);
static tree handle_noreturn_attribute (tree *, tree, tree, int, bool *);
@@ -775,6 +776,8 @@ const unsigned int num_c_common_reswords =
const struct attribute_spec c_common_attribute_table[] =
{
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
+ { "version_selector", 0, 0, true, false, false,
+ handle_version_selector_attribute },
{ "packed", 0, 0, false, false, false,
handle_packed_attribute },
{ "nocommon", 0, 0, true, false, false,
@@ -914,6 +917,16 @@ const struct attribute_spec c_common_attribute_table[] =
handle_lock_returned_attribute },
{ "no_thread_safety_analysis", 0, 0, true, false, false,
handle_no_thread_safety_analysis_attribute },
+ { "ignore_reads_begin", 0, 0, true, false, false,
+ handle_no_thread_safety_analysis_attribute },
+ { "ignore_reads_end", 0, 0, true, false, false,
+ handle_no_thread_safety_analysis_attribute },
+ { "ignore_writes_begin", 0, 0, true, false, false,
+ handle_no_thread_safety_analysis_attribute },
+ { "ignore_writes_end", 0, 0, true, false, false,
+ handle_no_thread_safety_analysis_attribute },
+ { "unprotected_read", 0, 0, true, false, false,
+ handle_no_thread_safety_analysis_attribute },
{ NULL, 0, 0, false, false, false, NULL }
};
@@ -5211,6 +5224,37 @@ handle_packed_attribute (tree *node, tree name, tree ARG_UNUSED (args),
return NULL_TREE;
}
+/* Handle a "version_selector attribute".
+ Functions are marked with attribute "version_selector" only if
+ they are run-time constants. Example of such functions would
+ be those that test if a particular feature is available on a
+ particular architecture. Such function must return a positive
+ integer. For two-way functions, those that test if a feature
+ is present or not must return 1 or 0 respectively. */
+
+static tree
+handle_version_selector_attribute (tree *node, tree name,
+ tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags),
+ bool *no_add_attrs)
+{
+ if (TREE_CODE (*node) == FUNCTION_DECL)
+ {
+ /* Check that the return type is integer. */
+ gcc_assert (TREE_CODE (TREE_TYPE (TREE_TYPE (*node)))
+ == INTEGER_TYPE);
+ if (dump_file)
+ fprintf (dump_file, "%s is a version_selector function\n",
+ IDENTIFIER_POINTER (DECL_NAME (*node)));
+ }
+ else
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+ return NULL_TREE;
+}
+
/* Handle a "nocommon" attribute; arguments as in
struct attribute_spec.handler. */
@@ -6696,7 +6740,7 @@ handle_nonnull_attribute (tree *node, tree ARG_UNUSED (name),
/* Argument list specified. Verify that each argument number references
a pointer argument. */
- for (attr_arg_num = 1; args; args = TREE_CHAIN (args))
+ for (attr_arg_num = 1; args; args = TREE_CHAIN (args), attr_arg_num++)
{
tree argument;
unsigned HOST_WIDE_INT arg_num = 0, ck_num;
@@ -6728,6 +6772,7 @@ handle_nonnull_attribute (tree *node, tree ARG_UNUSED (name),
return NULL_TREE;
}
+
if (TREE_CODE (TREE_VALUE (argument)) != POINTER_TYPE)
{
error ("nonnull argument references non-pointer operand (argument %lu, operand %lu)",
@@ -6735,6 +6780,11 @@ handle_nonnull_attribute (tree *node, tree ARG_UNUSED (name),
*no_add_attrs = true;
return NULL_TREE;
}
+
+ if (TREE_CODE (type) == METHOD_TYPE && arg_num == 1)
+ warning (OPT_Wattributes,
+ "nonnull argument references 'this' pointer (argument %lu, operand %lu)",
+ (unsigned long) attr_arg_num, (unsigned long) arg_num);
}
}
@@ -7374,14 +7424,9 @@ static tree
handle_point_to_guarded_by_attribute (tree *node, tree name, tree args,
int flags, bool *no_add_attrs)
{
- /* point_to_guarded_by attribute can only annotate a pointer. */
- if (!POINTER_TYPE_P (TREE_TYPE (*node)))
- {
- warning (OPT_Wattributes,
- "%qE attribute ignored for a non-pointer", name);
- *no_add_attrs = true;
- return NULL_TREE;
- }
+ /* We used to check if the point_to_guarded_by attribute is applied to
+ a pointer, but no longer do that as we now allow the attribute to
+ be applied to smart/scoped pointer objects. */
/* The rest of the handler is identical to the handler for
the guarded_by attr. */
@@ -7414,14 +7459,9 @@ static tree
handle_point_to_guarded_attribute (tree *node, tree name, tree args,
int flags, bool *no_add_attrs)
{
- /* point_to_guarded attribute can only annotate a pointer. */
- if (!POINTER_TYPE_P (TREE_TYPE (*node)))
- {
- warning (OPT_Wattributes,
- "%qE attribute ignored for a non-pointer", name);
- *no_add_attrs = true;
- return NULL_TREE;
- }
+ /* We used to check if the point_to_guarded attribute is applied to
+ a pointer, but no longer do that as we now allow the attribute to
+ be applied to smart/scoped pointer objects. */
/* The rest of the handler is identical to the handler for guarded attr. */
return handle_guarded_attribute (node, name, args, flags, no_add_attrs);
diff --git a/gcc-4.4.3/gcc/c-cppbuiltin.c b/gcc-4.4.3/gcc/c-cppbuiltin.c
index 974b257b1..0fda7993b 100644
--- a/gcc-4.4.3/gcc/c-cppbuiltin.c
+++ b/gcc-4.4.3/gcc/c-cppbuiltin.c
@@ -669,7 +669,10 @@ c_cpp_builtins (cpp_reader *pfile)
/* Define a macro indicating whether the thread safety attributes/analysis
is supported. */
if (warn_thread_safety)
- cpp_define (pfile, "__SUPPORT_TS_ANNOTATION__");
+ {
+ cpp_define (pfile, "__SUPPORT_TS_ANNOTATION__");
+ cpp_define (pfile, "__SUPPORT_DYN_ANNOTATION__");
+ }
/* Tell source code if the compiler makes sync_compare_and_swap
builtins available. */
diff --git a/gcc-4.4.3/gcc/c-opts.c b/gcc-4.4.3/gcc/c-opts.c
index c0262b93c..82290a8eb 100644
--- a/gcc-4.4.3/gcc/c-opts.c
+++ b/gcc-4.4.3/gcc/c-opts.c
@@ -41,6 +41,7 @@ along with GCC; see the file COPYING3. If not see
#include "target.h"
#include "tm_p.h"
#include "function.h"
+#include "params.h"
#ifndef DOLLARS_IN_IDENTIFIERS
# define DOLLARS_IN_IDENTIFIERS true
@@ -405,6 +406,7 @@ c_common_handle_option (size_t scode, const char *arg, int value)
warning about not using it without also specifying -O. */
if (warn_uninitialized != 1)
warn_uninitialized = (value ? 2 : 0);
+ warn_maybe_uninitialized = value;
if (!c_dialect_cxx ())
{
@@ -1096,9 +1098,9 @@ c_common_post_options (const char **pfilename)
warn_sign_conversion = (c_dialect_cxx ()) ? 0 : warn_conversion;
/* Enable warning for null conversion when -Wconversion is specified (unless
- disabled through -Wno-null-conversion). */
- if (warn_null_conversion == -1)
- warn_null_conversion = warn_conversion;
+ disabled through -Wno-conversion-null). */
+ if (warn_conversion_null == -1)
+ warn_conversion_null = warn_conversion;
/* Enable warning for converting real values to integral values
when -Wconversion is specified (unless disabled through
@@ -1229,6 +1231,28 @@ c_common_init (void)
return true;
}
+/* Return TRUE if the lipo maximum memory consumption limit is reached, and
+ we should not import any further auxiliary modules. Check after parsing
+ each module, the Ith module being the just parsed module. */
+static bool
+lipo_max_mem_reached (unsigned int i)
+{
+ if (L_IPO_COMP_MODE && PARAM_VALUE (PARAM_MAX_LIPO_MEMORY)
+ && i < (num_in_fnames - 1)
+ && ((ggc_total_allocated () >> 10)
+ > (size_t) PARAM_VALUE (PARAM_MAX_LIPO_MEMORY))) {
+ i++;
+ do {
+ inform (input_location, "Not importing %s: maximum memory "
+ "consumption reached", in_fnames[i]);
+ i++;
+ } while (i < num_in_fnames);
+ return true;
+ }
+ return false;
+}
+
+
/* Initialize the integrated preprocessor after debug output has been
initialized; loop over each input file. */
void
@@ -1270,6 +1294,12 @@ c_common_parse_file (int set_yydebug)
set_lipo_c_parsing_context (parse_in, i, verbose);
push_file_scope ();
c_parse_file ();
+ /* In lipo mode, processing too many auxiliary files will cause us
+ to hit memory limits, and cause thrashing -- prevent this by not
+ processing any further auxiliary modules if we reach a certain
+ memory limit. */
+ if (lipo_max_mem_reached (i))
+ num_in_fnames = i + 1;
finish_file ();
pop_file_scope ();
/* And end the main input file, if the debug writer wants it */
diff --git a/gcc-4.4.3/gcc/c.opt b/gcc-4.4.3/gcc/c.opt
index 0d6baf8b1..81610a95f 100644
--- a/gcc-4.4.3/gcc/c.opt
+++ b/gcc-4.4.3/gcc/c.opt
@@ -171,14 +171,18 @@ Wconversion
C ObjC C++ ObjC++ Var(warn_conversion) Warning
Warn for implicit type conversions that may change a value
-Wnull-conversion
-C ObjC C++ ObjC++ Var(warn_null_conversion) Init(-1) Warning
+Wconversion-null
+C++ ObjC++ Var(warn_conversion_null) Init(-1) Warning
Warn about peculiar, but valid, conversions from/to NULL
Wreal-conversion
C ObjC C++ ObjC++ Var(warn_real_conversion) Init(-1) Warning
Warn for implicit type conversions from real to integral values
+Wself-assign-non-pod
+C++ ObjC++ Var(warn_self_assign_non_pod) Init(0) Warning
+Warn when a variable of a non-POD type is assigned to itself
+
Wsign-conversion
C ObjC C++ ObjC++ Var(warn_sign_conversion) Init(-1)
Warn for implicit type conversions between signed and unsigned integers
@@ -345,7 +349,7 @@ C++ ObjC++ Var(warn_nonvdtor) Warning
Warn about non-virtual destructors
Wnonnull
-C ObjC Var(warn_nonnull) Warning
+C C++ ObjC ObjC++ Var(warn_nonnull) Warning
Warn about NULL being passed to argument slots marked as requiring non-NULL
Wnormalized=
diff --git a/gcc-4.4.3/gcc/caller-save.c b/gcc-4.4.3/gcc/caller-save.c
index 0c840c308..92e03f0c8 100644
--- a/gcc-4.4.3/gcc/caller-save.c
+++ b/gcc-4.4.3/gcc/caller-save.c
@@ -143,7 +143,7 @@ reg_save_code (int reg, enum machine_mode mode)
/* Update the register number and modes of the register
and memory operand. */
- SET_REGNO (test_reg, reg);
+ SET_REGNO_RAW (test_reg, reg);
PUT_MODE (test_reg, mode);
PUT_MODE (test_mem, mode);
diff --git a/gcc-4.4.3/gcc/calls.c b/gcc-4.4.3/gcc/calls.c
index 1cdc480cf..ff3ea9c35 100644
--- a/gcc-4.4.3/gcc/calls.c
+++ b/gcc-4.4.3/gcc/calls.c
@@ -2004,7 +2004,7 @@ expand_call (tree exp, rtx target, int ignore)
#ifdef REG_PARM_STACK_SPACE
/* Define the boundary of the register parm stack space that needs to be
saved, if any. */
- int low_to_save, high_to_save;
+ int low_to_save = 0, high_to_save = 0;
rtx save_area = 0; /* Place that it is saved */
#endif
@@ -3812,7 +3812,7 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
cse'ing of library calls could delete a call and leave the pop. */
NO_DEFER_POP;
valreg = (mem_value == 0 && outmode != VOIDmode
- ? hard_libcall_value (outmode) : NULL_RTX);
+ ? hard_libcall_value (outmode, orgfun) : NULL_RTX);
/* Stack must be properly aligned now. */
gcc_assert (!(stack_pointer_delta
diff --git a/gcc-4.4.3/gcc/cfgexpand.c b/gcc-4.4.3/gcc/cfgexpand.c
index d63701a7d..66acd3c75 100644
--- a/gcc-4.4.3/gcc/cfgexpand.c
+++ b/gcc-4.4.3/gcc/cfgexpand.c
@@ -42,7 +42,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-inline.h"
#include "value-prof.h"
#include "target.h"
-
+#include "tree-stack-overlay.h"
/* Return an expression tree corresponding to the RHS of GIMPLE
statement STMT. */
@@ -871,6 +871,21 @@ dump_stack_var_partition (void)
}
}
+static void
+sort_stack_vars (void)
+{
+ size_t si, n = stack_vars_num;
+
+ stack_vars_sorted = XNEWVEC (size_t, stack_vars_num);
+ for (si = 0; si < n; ++si)
+ stack_vars_sorted[si] = si;
+
+ if (n == 1)
+ return;
+
+ qsort (stack_vars_sorted, n, sizeof (size_t), stack_var_size_cmp);
+}
+
/* Assign rtl to DECL at frame offset OFFSET. */
static void
@@ -896,6 +911,34 @@ expand_one_stack_var_at (tree decl, HOST_WIDE_INT offset)
set_mem_attributes (x, decl, true);
SET_DECL_RTL (decl, x);
+ if (flag_early_stack_alloc)
+ {
+ /* If this decl is synthesized by stack_overlay pass, copy the RTL
+ to the original DECLs and remove this decl from BLOCK_VARS to
+ generate proper debug info. */
+ VEC(tree,gc) *orig_vars = get_original_stack_vars (decl);
+ if (VEC_length(tree,orig_vars))
+ {
+ tree t, outer_block = DECL_INITIAL (current_function_decl);
+ int ix=0;
+ /* Set RTL to original variables. */
+ for (ix = 0; VEC_iterate(tree,orig_vars,ix,t); ix++)
+ SET_DECL_RTL (t, x);
+ /* Remove decl from BLOCK_VARS. */
+ t = BLOCK_VARS (outer_block);
+ if (t == decl)
+ BLOCK_VARS (outer_block) = TREE_CHAIN (t);
+ else
+ {
+ for (; t ; t = TREE_CHAIN (t))
+ if (TREE_CHAIN (t) == decl)
+ {
+ TREE_CHAIN (t) = TREE_CHAIN (decl);
+ break;
+ }
+ }
+ }
+ }
}
/* A subroutine of expand_used_vars. Give each partition representative
@@ -1045,6 +1088,11 @@ defer_stack_allocation (tree var, bool toplevel)
if (flag_stack_protect)
return true;
+ /* If stack protection is not required and variable coalescing happens
+ in an earlier pass, no need to defer allocation. */
+ if (flag_early_stack_alloc)
+ return false;
+
/* Variables in the outermost scope automatically conflict with
every other variable. The only reason to want to defer them
at all is that, after sorting, we can more efficiently pack
@@ -1064,6 +1112,7 @@ defer_stack_allocation (tree var, bool toplevel)
return true;
}
+
/* A subroutine of expand_used_vars. Expand one variable according to
its flavor. Variables to be placed on the stack are not actually
expanded yet, merely recorded.
@@ -1282,12 +1331,25 @@ stack_protect_decl_phase (tree decl)
else
ret = (bits & SPCT_HAS_LARGE_CHAR_ARRAY) != 0;
- if (ret)
+ if (!flag_early_stack_alloc && ret)
has_protected_decls = true;
return ret;
}
+static bool
+need_stack_protection (void)
+{
+ size_t i, n = stack_vars_num;
+
+ if (!flag_stack_protect)
+ return false;
+ for (i = 0; i < n; ++i)
+ if (stack_protect_decl_phase (stack_vars[i].decl))
+ return true;
+ return false;
+}
+
/* Two helper routines that check for phase 1 and phase 2. These are used
as callbacks for expand_stack_vars. */
@@ -1475,35 +1537,37 @@ expand_used_vars (void)
for (; t; t = next)
{
tree var = TREE_VALUE (t);
- bool expand_now = false;
+ bool expand_now = flag_early_stack_alloc;
next = TREE_CHAIN (t);
-
- /* We didn't set a block for static or extern because it's hard
- to tell the difference between a global variable (re)declared
- in a local scope, and one that's really declared there to
- begin with. And it doesn't really matter much, since we're
- not giving them stack space. Expand them now. */
- if (TREE_STATIC (var) || DECL_EXTERNAL (var))
- expand_now = true;
-
- /* Any variable that could have been hoisted into an SSA_NAME
- will have been propagated anywhere the optimizers chose,
- i.e. not confined to their original block. Allocate them
- as if they were defined in the outermost scope. */
- else if (is_gimple_reg (var))
- expand_now = true;
-
- /* If the variable is not associated with any block, then it
- was created by the optimizers, and could be live anywhere
- in the function. */
- else if (TREE_USED (var))
- expand_now = true;
-
- /* Finally, mark all variables on the list as used. We'll use
- this in a moment when we expand those associated with scopes. */
- TREE_USED (var) = 1;
-
+ if (!flag_early_stack_alloc)
+ {
+ /* We didn't set a block for static or extern because it's hard
+ to tell the difference between a global variable (re)declared
+ in a local scope, and one that's really declared there to
+ begin with. And it doesn't really matter much, since we're
+ not giving them stack space. Expand them now. */
+ if (TREE_STATIC (var) || DECL_EXTERNAL (var))
+ expand_now = true;
+
+ /* Any variable that could have been hoisted into an SSA_NAME
+ will have been propagated anywhere the optimizers chose,
+ i.e. not confined to their original block. Allocate them
+ as if they were defined in the outermost scope. */
+ else if (is_gimple_reg (var))
+ expand_now = true;
+
+ /* If the variable is not associated with any block, then it
+ was created by the optimizers, and could be live anywhere
+ in the function. */
+ else if (TREE_USED (var))
+ expand_now = true;
+
+ /* Finally, mark all variables on the list as used. We'll use
+ this in a moment when we expand those associated with scopes. */
+ TREE_USED (var) = 1;
+
+ }
if (expand_now)
{
expand_one_var (var, true, true);
@@ -1525,11 +1589,14 @@ expand_used_vars (void)
ggc_free (t);
}
- /* At this point, all variables within the block tree with TREE_USED
- set are actually used by the optimized function. Lay them out. */
- expand_used_vars_for_block (outer_block, true);
+ if (flag_early_stack_alloc)
+ has_protected_decls = need_stack_protection ();
+ else
+ /* At this point, all variables within the block tree with TREE_USED
+ set are actually used by the optimized function. Lay them out. */
+ expand_used_vars_for_block (outer_block, true);
- if (stack_vars_num > 0)
+ if (!flag_early_stack_alloc && stack_vars_num > 0)
{
/* Due to the way alias sets work, no variables with non-conflicting
alias sets may be assigned the same address. Add conflicts to
@@ -1558,6 +1625,8 @@ expand_used_vars (void)
/* Assign rtl to each variable based on these partitions. */
if (stack_vars_num > 0)
{
+ if (flag_early_stack_alloc)
+ sort_stack_vars ();
/* Reorder decls to be protected by iterating over the variables
array multiple times, and allocating out of each phase in turn. */
/* ??? We could probably integrate this into the qsort we did
@@ -2245,8 +2314,18 @@ expand_stack_alignment (void)
|| crtl->has_nonlocal_goto)
crtl->need_drap = true;
- gcc_assert (crtl->stack_alignment_needed
- <= crtl->stack_alignment_estimated);
+ /* Call update_stack_boundary here again to update incoming stack
+ boundary. It may set incoming stack alignment to a different
+ value after RTL expansion. TARGET_FUNCTION_OK_FOR_SIBCALL may
+ use the minimum incoming stack alignment to check if it is OK
+ to perform sibcall optimization since sibcall optimization will
+ only align the outgoing stack to incoming stack boundary. */
+ if (targetm.calls.update_stack_boundary)
+ targetm.calls.update_stack_boundary ();
+
+ /* The incoming stack frame has to be aligned at least at
+ parm_stack_boundary. */
+ gcc_assert (crtl->parm_stack_boundary <= INCOMING_STACK_BOUNDARY);
/* Update crtl->stack_alignment_estimated and use it later to align
stack. We check PREFERRED_STACK_BOUNDARY if there may be non-call
@@ -2262,6 +2341,9 @@ expand_stack_alignment (void)
if (preferred_stack_boundary > crtl->stack_alignment_needed)
crtl->stack_alignment_needed = preferred_stack_boundary;
+ gcc_assert (crtl->stack_alignment_needed
+ <= crtl->stack_alignment_estimated);
+
crtl->stack_realign_needed
= INCOMING_STACK_BOUNDARY < crtl->stack_alignment_estimated;
crtl->stack_realign_tried = crtl->stack_realign_needed;
@@ -2333,7 +2415,7 @@ gimple_expand_cfg (void)
targetm.expand_to_rtl_hook ();
crtl->stack_alignment_needed = STACK_BOUNDARY;
crtl->max_used_stack_slot_alignment = STACK_BOUNDARY;
- crtl->stack_alignment_estimated = STACK_BOUNDARY;
+ crtl->stack_alignment_estimated = 0;
crtl->preferred_stack_boundary = STACK_BOUNDARY;
cfun->cfg->max_jumptable_ents = 0;
@@ -2368,23 +2450,6 @@ gimple_expand_cfg (void)
if (crtl->stack_protect_guard)
stack_protect_prologue ();
- /* Update stack boundary if needed. */
- if (SUPPORTS_STACK_ALIGNMENT)
- {
- /* Call update_stack_boundary here to update incoming stack
- boundary before TARGET_FUNCTION_OK_FOR_SIBCALL is called.
- TARGET_FUNCTION_OK_FOR_SIBCALL needs to know the accurate
- incoming stack alignment to check if it is OK to perform
- sibcall optimization since sibcall optimization will only
- align the outgoing stack to incoming stack boundary. */
- if (targetm.calls.update_stack_boundary)
- targetm.calls.update_stack_boundary ();
-
- /* The incoming stack frame has to be aligned at least at
- parm_stack_boundary. */
- gcc_assert (crtl->parm_stack_boundary <= INCOMING_STACK_BOUNDARY);
- }
-
/* Register rtl specific functions for cfg. */
rtl_register_cfg_hooks ();
diff --git a/gcc-4.4.3/gcc/cgraph.c b/gcc-4.4.3/gcc/cgraph.c
index 96b4662cd..77e1bd0fd 100644
--- a/gcc-4.4.3/gcc/cgraph.c
+++ b/gcc-4.4.3/gcc/cgraph.c
@@ -440,7 +440,7 @@ cgraph_create_node (void)
if (cgraph_nodes)
cgraph_nodes->previous = node;
node->previous = NULL;
- node->global.estimated_growth = INT_MIN;
+ node->global.estimated_average_growth = INT_MIN;
cgraph_nodes = node;
cgraph_n_nodes++;
return node;
@@ -1005,6 +1005,7 @@ cgraph_remove_node (struct cgraph_node *node)
cgraph_call_node_removal_hooks (node);
cgraph_node_remove_callers (node);
cgraph_node_remove_callees (node);
+ cgraph_remove_pid (node);
/* Incremental inlining access removed nodes stored in the postorder list.
*/
@@ -1118,6 +1119,15 @@ cgraph_mark_needed_node (struct cgraph_node *node)
cgraph_mark_reachable_node (node);
}
+/* Indicate that the address of the function represented by the node
+ has been taken. */
+
+void
+cgraph_mark_address_taken (struct cgraph_node *node)
+{
+ node->address_taken = 1;
+}
+
/* Return local info for the compiled function. */
struct cgraph_local_info *
@@ -1756,4 +1766,25 @@ dump_vcg_cgraph (FILE *fp, int min_count, bool weighted)
free (include_node);
}
+/* Return true if NODE is a hot function. */
+
+bool
+hot_function_p (struct cgraph_node *node)
+{
+ struct cgraph_edge *edge;
+
+ if (node->local.inline_summary.self_hot_insns > 0)
+ return true;
+
+ for (edge = node->callees; edge; edge = edge->next_callee)
+ if (cgraph_maybe_hot_edge_p (edge))
+ return true;
+
+ for (edge = node->callers; edge; edge = edge->next_caller)
+ if (cgraph_maybe_hot_edge_p (edge))
+ return true;
+
+ return false;
+}
+
#include "gt-cgraph.h"
diff --git a/gcc-4.4.3/gcc/cgraph.h b/gcc-4.4.3/gcc/cgraph.h
index 2df9d0821..f83ba05b2 100644
--- a/gcc-4.4.3/gcc/cgraph.h
+++ b/gcc-4.4.3/gcc/cgraph.h
@@ -111,8 +111,9 @@ struct cgraph_global_info GTY(())
/* Estimated size of the function after inlining. */
int insns;
- /* Estimated growth after inlining. INT_MIN if not computed. */
- int estimated_growth;
+ /* Estimated average per-callsite growth after inlining all calls to
+ this function. INT_MIN if not computed. */
+ int estimated_average_growth;
/* Set iff the function has been inlined at least once. */
bool inlined;
@@ -176,6 +177,8 @@ struct cgraph_node GTY((chain_next ("%h.next"), chain_prev ("%h.previous")))
/* Set when function must be output - it is externally visible
or its address is taken. */
unsigned needed : 1;
+ /* Set when the address of the function has been taken. */
+ unsigned address_taken : 1;
/* Set when decl is an abstract function pointed to by the
ABSTRACT_DECL_ORIGIN of a reachable function. */
unsigned abstract_and_needed : 1;
@@ -357,12 +360,15 @@ void cgraph_add_new_function (tree, bool);
void dump_vcg_cgraph (FILE *, int, bool);
+bool hot_function_p (struct cgraph_node *);
+
/* In cgraphunit.c */
void cgraph_finalize_function (tree, bool);
void cgraph_mark_if_needed (tree);
void cgraph_finalize_compilation_unit (void);
void cgraph_optimize (void);
void cgraph_mark_needed_node (struct cgraph_node *);
+void cgraph_mark_address_taken (struct cgraph_node *);
void cgraph_mark_reachable_node (struct cgraph_node *);
bool cgraph_inline_p (struct cgraph_edge *, const char **reason);
bool cgraph_preserve_function_body_p (tree);
@@ -536,6 +542,8 @@ void dump_hot_components (FILE *);
void verify_hot_components (void);
bool cgraph_gate_ipa_early_inlining (void);
+void cgraph_remove_pid (struct cgraph_node *);
+
/* Create a new static variable of type TYPE. */
tree add_new_static_var (tree type);
diff --git a/gcc-4.4.3/gcc/cgraphbuild.c b/gcc-4.4.3/gcc/cgraphbuild.c
index fb9c1611a..c412f5680 100644
--- a/gcc-4.4.3/gcc/cgraphbuild.c
+++ b/gcc-4.4.3/gcc/cgraphbuild.c
@@ -34,6 +34,7 @@ along with GCC; see the file COPYING3. If not see
#include "gcov-io.h"
#include "coverage.h"
#include "tree-pass.h"
+#include "tree-sample-profile.h"
/* Walk tree and record all calls and references to functions/variables.
Called via walk_tree: TP is pointer to tree to be examined. */
@@ -61,7 +62,10 @@ record_reference (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
functions reachable unconditionally. */
decl = TREE_OPERAND (*tp, 0);
if (TREE_CODE (decl) == FUNCTION_DECL)
- cgraph_mark_needed_node (cgraph_node (decl));
+ {
+ cgraph_mark_needed_node (cgraph_node (decl));
+ cgraph_mark_address_taken (cgraph_node (decl));
+ }
break;
default:
@@ -162,9 +166,31 @@ add_fake_indirect_call_edges (struct cgraph_node *node)
= get_coverage_counts_no_warn (DECL_STRUCT_FUNCTION (node->decl),
GCOV_COUNTER_ICALL_TOPNV, &n_counts);
- if (!ic_counts)
+ if (!ic_counts && !flag_sample_profile)
return;
+ /* For sample profile, we find the th indirect callees by its names. */
+ if (flag_sample_profile)
+ {
+ struct sample_indirect_call *ic =
+ sp_get_indirect_calls (cgraph_node_name (node));
+ if (!ic)
+ return;
+ for (i = 0; i < ic->num_values; i++)
+ {
+ struct cgraph_node *callee = find_func_by_name (ic->targets[i]);
+ if (callee)
+ {
+ struct cgraph_edge *e;
+ tree decl = callee->decl;
+ e = cgraph_create_edge (node, cgraph_real_node (decl), NULL,
+ ic->count[i], 0, 0);
+ e->indirect_call = 1;
+ }
+ }
+ return;
+ }
+
gcc_assert ((n_counts % GCOV_ICALL_TOPN_NCOUNTS) == 0);
/* After the early_inline_1 before value profile transformation,
diff --git a/gcc-4.4.3/gcc/common.opt b/gcc-4.4.3/gcc/common.opt
index 7f0f4e97d..3280c7330 100644
--- a/gcc-4.4.3/gcc/common.opt
+++ b/gcc-4.4.3/gcc/common.opt
@@ -249,6 +249,10 @@ Wuninitialized
Common Var(warn_uninitialized) Warning
Warn about uninitialized automatic variables
+Wmaybe-uninitialized
+Common Var(warn_maybe_uninitialized) Warning
+Warn about maybe uninitialized automatic variables
+
Wunreachable-code
Common Var(warn_notreached) Warning
Warn about code that will never be executed
@@ -421,6 +425,10 @@ fcaller-saves
Common Report Var(flag_caller_saves) Optimization
Save registers around function calls
+fcgraph-section
+Common Report Var(flag_cgraph_section) Init(0)
+Generate .note.callgraph.text sections listing callees and edge counts.
+
fcheck-data-deps
Common Report Var(flag_check_data_deps)
Compare the results of several data dependence analyzers.
@@ -515,6 +523,14 @@ fdwarf2-cfi-asm
Common Report Var(flag_dwarf2_cfi_asm) Init(HAVE_GAS_CFI_DIRECTIVE)
Enable CFI tables via GAS assembler directives.
+fprofile-reusedist
+Common Report Var(flag_profile_reusedist)
+Profile generation for memory reuse distance.
+
+foptimize-locality
+Common Report Var(flag_optimize_locality)
+Optimization based on improving memory reference locality.
+
fripa
Common Report Var(flag_dyn_ipa)
Perform Dynamic Inter-Procedural Analysis.
@@ -527,6 +543,12 @@ fripa-disallow-opt-mismatch
Common Report Var(flag_ripa_disallow_opt_mismatch)
Don't import an auxiliary module if the command line options mismatch with the primary module
+fripa-no-promote-always-inline-func
+Common Report Var(flag_ripa_no_promote_always_inline) Init(0)
+Don't promote always inline static functions assuming they
+will be inlined and no copy is needed.
+
+
fripa-verbose
Common Report Var(flag_ripa_verbose)
Enable verbose informational messages for LIPO compilation
@@ -535,6 +557,10 @@ fearly-inlining
Common Report Var(flag_early_inlining) Init(1) Optimization
Perform early inlining
+fearly-stack-alloc
+Common Report Var(flag_early_stack_alloc)
+Make stack coalescing decisions earlier
+
feliminate-dwarf2-dups
Common Report Var(flag_eliminate_dwarf2_dups)
Perform DWARF2 duplicate elimination
@@ -979,6 +1005,10 @@ fprofile-generate=
Common Joined RejectNegative
Enable common options for generating profile info for profile feedback directed optimizations, and set -fprofile-dir=
+fprofile-generate-sampling
+Common Var(flag_profile_generate_sampling)
+Turn on instrumentation sampling with -fprofile-generate with rate set by --param profile-generate-sampling-rate or environment variable GCOV_SAMPLING_RATE
+
fprofile-use
Common Var(flag_profile_use)
Enable common options for performing profile feedback directed optimizations
@@ -1044,6 +1074,14 @@ frounding-math
Common Report Var(flag_rounding_math) Optimization
Disable optimizations that assume default FP rounding behavior
+fpmu-profile-generate=
+Common Joined RejectNegative Var(flag_pmu_profile_generate)
+-fpmu-profile-generate=[load-latency] Generate pmu profile for cache misses. Currently only pfmon based load latency profiling is supported on Intel/PEBS and AMD/IBS platforms.
+
+fpmu-profile-use=
+Common Joined RejectNegative Var(flag_pmu_profile_use)
+-fpmu-profile-use=[load-latency] Use pmu profile data while optimizing. Currently only perfmon based load latency profiling is supported on Intel/PEBS and AMD/IBS platforms.
+
fsample-profile
Common Report Var(flag_sample_profile) Optimization
Use sample profile information for branch probabilities. The default sample
@@ -1479,6 +1517,15 @@ fvpt
Common Report Var(flag_value_profile_transformations) Optimization
Use expression value profiles in optimizations
+ffvpt
+Common Report Var(flag_float_value_profile_transformations) Optimization
+Enable floating point optimizations based on value profiles. Required
+both for profile generation and use.
+
+ffvpt-functions=
+Common Joined
+-ffvpt-functions=<function>[,<function>,...]|all List functions to optimize.
+
fweb
Common Report Var(flag_web) Init(2) Optimization
Construct webs and split unrelated uses of single variable
@@ -1487,6 +1534,10 @@ ftree-builtin-call-dce
Common Report Var(flag_tree_builtin_call_dce) Init(0) Optimization
Enable conditional dead code elimination for builtin calls
+fclone-hot-version-paths
+Common Report Var(flag_clone_hot_version_paths) Init(0)
+Enable cloning and hoisting of hot multiversioned paths
+
fwhole-program
Common Report Var(flag_whole_program) Init(0) Optimization
Perform whole program optimizations
diff --git a/gcc-4.4.3/gcc/config.gcc b/gcc-4.4.3/gcc/config.gcc
index 1a5315bce..4aed6f30e 100644
--- a/gcc-4.4.3/gcc/config.gcc
+++ b/gcc-4.4.3/gcc/config.gcc
@@ -300,7 +300,7 @@ i[34567]86-*-*)
pmmintrin.h tmmintrin.h ammintrin.h smmintrin.h
nmmintrin.h bmmintrin.h mmintrin-common.h
wmmintrin.h immintrin.h x86intrin.h avxintrin.h
- cross-stdarg.h"
+ cross-stdarg.h lwpintrin.h"
;;
x86_64-*-*)
cpu_type=i386
@@ -310,7 +310,7 @@ x86_64-*-*)
pmmintrin.h tmmintrin.h ammintrin.h smmintrin.h
nmmintrin.h bmmintrin.h mmintrin-common.h
wmmintrin.h immintrin.h x86intrin.h avxintrin.h
- cross-stdarg.h"
+ cross-stdarg.h lwpintrin.h"
need_64bit_hwint=yes
;;
ia64-*-*)
@@ -407,6 +407,9 @@ case ${target} in
;;
esac
+# Common C libraries.
+tm_defines="$tm_defines LIBC_GLIBC=1 LIBC_UCLIBC=2 LIBC_BIONIC=3"
+
# Common parts for widely ported systems.
case ${target} in
*-*-darwin*)
@@ -498,8 +501,6 @@ case ${target} in
*-*-gnu*)
tmake_file="$tmake_file t-gnu";;
esac
- # Common C libraries.
- tm_defines="$tm_defines LIBC_GLIBC=1 LIBC_UCLIBC=2 LIBC_BIONIC=3"
# glibc / uclibc / bionic switch.
# uclibc and bionic aren't usable for GNU/Hurd and neither for GNU/k*BSD.
case $target in
@@ -1117,7 +1118,7 @@ i[34567]86-*-linux* | i[34567]86-*-kfreebsd*-gnu | i[34567]86-*-knetbsd*-gnu | i
tmake_file="${tmake_file} i386/t-linux64"
need_64bit_hwint=yes
case X"${with_cpu}" in
- Xgeneric|Xcore2|Xnocona|Xx86-64|Xamdfam10|Xbarcelona|Xk8|Xopteron|Xathlon64|Xathlon-fx)
+ Xgeneric|Xatom|Xcore2|Xnocona|Xx86-64|Xamdfam10|Xbarcelona|Xk8|Xopteron|Xathlon64|Xathlon-fx)
;;
X)
if test x$with_cpu_64 = x; then
@@ -1126,7 +1127,7 @@ i[34567]86-*-linux* | i[34567]86-*-kfreebsd*-gnu | i[34567]86-*-knetbsd*-gnu | i
;;
*)
echo "Unsupported CPU used in --with-cpu=$with_cpu, supported values:" 1>&2
- echo "generic core2 nocona x86-64 amdfam10 barcelona k8 opteron athlon64 athlon-fx" 1>&2
+ echo "generic atom core2 nocona x86-64 amdfam10 barcelona k8 opteron athlon64 athlon-fx" 1>&2
exit 1
;;
esac
@@ -1237,7 +1238,7 @@ i[34567]86-*-solaris2*)
# libgcc/configure.ac instead.
need_64bit_hwint=yes
case X"${with_cpu}" in
- Xgeneric|Xcore2|Xnocona|Xx86-64|Xamdfam10|Xbarcelona|Xk8|Xopteron|Xathlon64|Xathlon-fx)
+ Xgeneric|Xatom|Xcore2|Xnocona|Xx86-64|Xamdfam10|Xbarcelona|Xk8|Xopteron|Xathlon64|Xathlon-fx)
;;
X)
if test x$with_cpu_64 = x; then
@@ -1246,7 +1247,7 @@ i[34567]86-*-solaris2*)
;;
*)
echo "Unsupported CPU used in --with-cpu=$with_cpu, supported values:" 1>&2
- echo "generic core2 nocona x86-64 amdfam10 barcelona k8 opteron athlon64 athlon-fx" 1>&2
+ echo "generic atom core2 nocona x86-64 amdfam10 barcelona k8 opteron athlon64 athlon-fx" 1>&2
exit 1
;;
esac
@@ -2624,6 +2625,27 @@ if test x$with_cpu = x ; then
esac
fi
+# Support --with-fpmath.
+if test x$with_fpmath != x; then
+ case ${target} in
+ i[34567]86-*-* | x86_64-*-*)
+ case ${with_fpmath} in
+ sse)
+ tm_file="${tm_file} i386/ssemath.h"
+ ;;
+ *)
+ echo "Invalid --with-fpmath=$with_fpmath" 1>&2
+ exit 1
+ ;;
+ esac
+ ;;
+ *)
+ echo "--with-fpmath isn't supported for $target." 1>&2
+ exit 1
+ ;;
+ esac
+fi
+
# Similarly for --with-schedule.
if test x$with_schedule = x; then
case ${target} in
@@ -2847,7 +2869,7 @@ case "${target}" in
esac
# OK
;;
- "" | amdfam10 | barcelona | k8 | opteron | athlon64 | athlon-fx | nocona | core2 | generic)
+ "" | amdfam10 | barcelona | k8 | opteron | athlon64 | athlon-fx | nocona | core2 | atom | generic)
# OK
;;
*)
diff --git a/gcc-4.4.3/gcc/config.in b/gcc-4.4.3/gcc/config.in
index 2c49621e8..a3a297ce9 100644
--- a/gcc-4.4.3/gcc/config.in
+++ b/gcc-4.4.3/gcc/config.in
@@ -46,6 +46,12 @@
#endif
+/* Define to 1 to enable crtbeginTS.o. */
+#ifndef USED_FOR_TARGET
+#undef ENABLE_CRTBEGINTS
+#endif
+
+
/* Define to 1 to specify that we are using the BID decimal floating point
format instead of DPD */
#ifndef USED_FOR_TARGET
@@ -65,6 +71,12 @@
#endif
+/* Define to 1 to enable esp. */
+#ifndef USED_FOR_TARGET
+#undef ENABLE_ESP
+#endif
+
+
/* Define to 1 to enable fixed-point arithmetic extension to C. */
#ifndef USED_FOR_TARGET
#undef ENABLE_FIXED_POINT
diff --git a/gcc-4.4.3/gcc/config/arm/arm-protos.h b/gcc-4.4.3/gcc/config/arm/arm-protos.h
index 8d03141e4..ee0a34393 100644
--- a/gcc-4.4.3/gcc/config/arm/arm-protos.h
+++ b/gcc-4.4.3/gcc/config/arm/arm-protos.h
@@ -154,13 +154,15 @@ extern bool arm_output_addr_const_extra (FILE *, rtx);
#if defined TREE_CODE
extern rtx arm_function_arg (CUMULATIVE_ARGS *, enum machine_mode, tree, int);
+extern void arm_function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode,
+ tree, bool);
extern void arm_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree);
extern bool arm_pad_arg_upward (enum machine_mode, const_tree);
extern bool arm_pad_reg_upward (enum machine_mode, tree, int);
extern bool arm_needs_doubleword_align (enum machine_mode, tree);
-extern rtx arm_function_value(const_tree, const_tree);
#endif
extern int arm_apply_result_size (void);
+extern rtx aapcs_libcall_value (enum machine_mode);
#endif /* RTX_CODE */
diff --git a/gcc-4.4.3/gcc/config/arm/arm.c b/gcc-4.4.3/gcc/config/arm/arm.c
index 2e2317b50..80bd3af3a 100644
--- a/gcc-4.4.3/gcc/config/arm/arm.c
+++ b/gcc-4.4.3/gcc/config/arm/arm.c
@@ -43,6 +43,7 @@
#include "optabs.h"
#include "toplev.h"
#include "recog.h"
+#include "cgraph.h"
#include "ggc.h"
#include "except.h"
#include "c-pragma.h"
@@ -54,6 +55,7 @@
#include "langhooks.h"
#include "df.h"
#include "libfuncs.h"
+#include "params.h"
/* Forward definitions of types. */
typedef struct minipool_node Mnode;
@@ -111,6 +113,7 @@ static unsigned long arm_compute_save_reg_mask (void);
static unsigned long arm_isr_value (tree);
static unsigned long arm_compute_func_type (void);
static tree arm_handle_fndecl_attribute (tree *, tree, tree, int, bool *);
+static tree arm_handle_pcs_attribute (tree *, tree, tree, int, bool *);
static tree arm_handle_isr_attribute (tree *, tree, tree, int, bool *);
#if TARGET_DLLIMPORT_DECL_ATTRIBUTES
static tree arm_handle_notshared_attribute (tree *, tree, tree, int, bool *);
@@ -124,6 +127,10 @@ static int arm_adjust_cost (rtx, rtx, rtx, int);
static int count_insns_for_constant (HOST_WIDE_INT, int);
static int arm_get_strip_length (int);
static bool arm_function_ok_for_sibcall (tree, tree);
+static bool arm_return_in_memory (const_tree, const_tree);
+static rtx arm_function_value (const_tree, const_tree, bool);
+static rtx arm_libcall_value (enum machine_mode, rtx);
+
static void arm_internal_label (FILE *, const char *, unsigned long);
static void arm_output_mi_thunk (FILE *, tree, HOST_WIDE_INT, HOST_WIDE_INT,
tree);
@@ -150,6 +157,9 @@ static void emit_constant_insn (rtx cond, rtx pattern);
static rtx emit_set_insn (rtx, rtx);
static int arm_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,
tree, bool);
+static rtx aapcs_allocate_return_reg (enum machine_mode, const_tree,
+ const_tree);
+static int aapcs_select_return_coproc (const_tree, const_tree);
#ifdef OBJECT_FORMAT_ELF
static void arm_elf_asm_constructor (rtx, int) ATTRIBUTE_UNUSED;
@@ -203,8 +213,8 @@ static rtx arm_pic_static_addr (rtx orig, rtx reg);
static rtx arm_get_pic_reg (void);
static void arm_clear_pic_reg (void);
static bool arm_can_simplify_got_access (int, int);
-static rtx arm_loaded_global_var (rtx, rtx *);
-static void arm_load_global_address (rtx, rtx, rtx, rtx);
+static rtx arm_loaded_global_var (rtx, rtx *, rtx *);
+static void arm_load_global_address (rtx, rtx, rtx, rtx, rtx);
/* Initialize the GCC target structure. */
@@ -264,6 +274,12 @@ static void arm_load_global_address (rtx, rtx, rtx, rtx);
#undef TARGET_FUNCTION_OK_FOR_SIBCALL
#define TARGET_FUNCTION_OK_FOR_SIBCALL arm_function_ok_for_sibcall
+#undef TARGET_FUNCTION_VALUE
+#define TARGET_FUNCTION_VALUE arm_function_value
+
+#undef TARGET_LIBCALL_VALUE
+#define TARGET_LIBCALL_VALUE arm_libcall_value
+
#undef TARGET_ASM_OUTPUT_MI_THUNK
#define TARGET_ASM_OUTPUT_MI_THUNK arm_output_mi_thunk
#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
@@ -621,6 +637,8 @@ static int after_arm_reorg = 0;
/* The maximum number of insns to be used when loading a constant. */
static int arm_constant_limit = 3;
+static enum arm_pcs arm_pcs_default;
+
/* For an explanation of these variables, see final_prescan_insn below. */
int arm_ccfsm_state;
/* arm_current_cc is also used for Thumb-2 cond_exec blocks. */
@@ -1536,9 +1554,6 @@ arm_override_options (void)
else
arm_float_abi = TARGET_DEFAULT_FLOAT_ABI;
- if (arm_float_abi == ARM_FLOAT_ABI_HARD && TARGET_VFP)
- sorry ("-mfloat-abi=hard and VFP");
-
/* FPA and iWMMXt are incompatible because the insn encodings overlap.
VFP and iWMMXt can theoretically coexist, but it's unlikely such silicon
will ever exist. GCC makes no attempt to support this combination. */
@@ -1553,6 +1568,28 @@ arm_override_options (void)
if (TARGET_SOFT_FLOAT)
arm_fpu_arch = FPUTYPE_NONE;
+ if (TARGET_AAPCS_BASED)
+ {
+ if (arm_abi == ARM_ABI_IWMMXT)
+ arm_pcs_default = ARM_PCS_AAPCS_IWMMXT;
+ else if (arm_float_abi == ARM_FLOAT_ABI_HARD
+ && TARGET_HARD_FLOAT
+ && TARGET_VFP)
+ arm_pcs_default = ARM_PCS_AAPCS_VFP;
+ else
+ arm_pcs_default = ARM_PCS_AAPCS;
+ }
+ else
+ {
+ if (arm_float_abi == ARM_FLOAT_ABI_HARD && TARGET_VFP)
+ sorry ("-mfloat-abi=hard and VFP");
+
+ if (arm_abi == ARM_ABI_APCS)
+ arm_pcs_default = ARM_PCS_APCS;
+ else
+ arm_pcs_default = ARM_PCS_ATPCS;
+ }
+
/* For arm2/3 there is no need to do any scheduling if there is only
a floating point emulator, or we are doing software floating-point. */
if ((TARGET_SOFT_FLOAT
@@ -1682,6 +1719,16 @@ arm_override_options (void)
max_insns_skipped = 3;
}
+ /* Hot/Cold partitioning is not currently supported, since we can't
+ handle literal pool placement in that case. */
+ if (flag_reorder_blocks_and_partition)
+ {
+ inform (input_location,
+ "-freorder-blocks-and-partition not supported on this architecture");
+ flag_reorder_blocks_and_partition = 0;
+ flag_reorder_blocks = 1;
+ }
+
/* Ideally we would want to use CFI directives to generate
debug info. However this also creates the .eh_frame
section, so disable them until GAS can handle
@@ -1689,6 +1736,21 @@ arm_override_options (void)
if (TARGET_AAPCS_BASED)
flag_dwarf2_cfi_asm = 0;
+ if (!PARAM_SET_P (PARAM_INLINE_CALL_COST))
+ set_param_value ("inline-call-cost", 2);
+
+ if (!PARAM_SET_P (PARAM_INLINE_FUNCTION_SIZE_ADJUSTMENT))
+ set_param_value ("inline-function-size-adjustment", 3);
+
+ if (!PARAM_SET_P (PARAM_INLINE_ADDRESS_TAKEN_FUNCTION_EMIT_PROBABILITY))
+ set_param_value ("inline-address-taken-function-emit-probability", 100);
+
+ if (!PARAM_SET_P (PARAM_INLINE_ADDRESS_NOT_TAKEN_FUNCTION_EMIT_PROBABILITY))
+ set_param_value ("inline-address-not-taken-function-emit-probability", 100);
+
+ if (!PARAM_SET_P (PARAM_INLINE_PRIORITY_THRESHOLD))
+ set_param_value ("inline-priority-threshold", 0);
+
/* Register global variables with the garbage collector. */
arm_add_gc_roots ();
}
@@ -2911,14 +2973,19 @@ arm_canonicalize_comparison (enum rtx_code code, enum machine_mode mode,
/* Define how to find the value returned by a function. */
-rtx
-arm_function_value(const_tree type, const_tree func ATTRIBUTE_UNUSED)
+static rtx
+arm_function_value(const_tree type, const_tree func,
+ bool outgoing ATTRIBUTE_UNUSED)
{
enum machine_mode mode;
int unsignedp ATTRIBUTE_UNUSED;
rtx r ATTRIBUTE_UNUSED;
mode = TYPE_MODE (type);
+
+ if (TARGET_AAPCS_BASED)
+ return aapcs_allocate_return_reg (mode, type, func);
+
/* Promote integer types. */
if (INTEGRAL_TYPE_P (type))
PROMOTE_FUNCTION_MODE (mode, unsignedp, type);
@@ -2935,7 +3002,87 @@ arm_function_value(const_tree type, const_tree func ATTRIBUTE_UNUSED)
}
}
- return LIBCALL_VALUE(mode);
+ return LIBCALL_VALUE (mode);
+}
+
+static int
+libcall_eq (const void *p1, const void *p2)
+{
+ return rtx_equal_p ((const_rtx) p1, (const_rtx) p2);
+}
+
+static hashval_t
+libcall_hash (const void *p1)
+{
+ return hash_rtx ((const_rtx) p1, VOIDmode, NULL, NULL, FALSE);
+}
+
+static void
+add_libcall (htab_t htab, rtx libcall)
+{
+ *htab_find_slot (htab, libcall, INSERT) = libcall;
+}
+
+static bool
+arm_libcall_uses_aapcs_base (rtx libcall)
+{
+ static bool init_done = false;
+ static htab_t libcall_htab;
+
+ if (!init_done)
+ {
+ init_done = true;
+
+ libcall_htab = htab_create (31, libcall_hash, libcall_eq,
+ NULL);
+ add_libcall (libcall_htab,
+ convert_optab_libfunc (sfloat_optab, SFmode, SImode));
+ add_libcall (libcall_htab,
+ convert_optab_libfunc (sfloat_optab, DFmode, SImode));
+ add_libcall (libcall_htab,
+ convert_optab_libfunc (sfloat_optab, SFmode, DImode));
+ add_libcall (libcall_htab,
+ convert_optab_libfunc (sfloat_optab, DFmode, DImode));
+
+ add_libcall (libcall_htab,
+ convert_optab_libfunc (ufloat_optab, SFmode, SImode));
+ add_libcall (libcall_htab,
+ convert_optab_libfunc (ufloat_optab, DFmode, SImode));
+ add_libcall (libcall_htab,
+ convert_optab_libfunc (ufloat_optab, SFmode, DImode));
+ add_libcall (libcall_htab,
+ convert_optab_libfunc (ufloat_optab, DFmode, DImode));
+
+ /* add_libcall (libcall_htab,
+ convert_optab_libfunc (sext_optab, SFmode, HFmode));
+ add_libcall (libcall_htab,
+ convert_optab_libfunc (trunc_optab, HFmode, SFmode)); */
+ add_libcall (libcall_htab,
+ convert_optab_libfunc (sfix_optab, DImode, DFmode));
+ add_libcall (libcall_htab,
+ convert_optab_libfunc (ufix_optab, DImode, DFmode));
+ add_libcall (libcall_htab,
+ convert_optab_libfunc (sfix_optab, DImode, SFmode));
+ add_libcall (libcall_htab,
+ convert_optab_libfunc (ufix_optab, DImode, SFmode));
+ }
+
+ return libcall && htab_find (libcall_htab, libcall) != NULL;
+}
+
+rtx
+arm_libcall_value (enum machine_mode mode, rtx libcall)
+{
+ if (TARGET_AAPCS_BASED && arm_pcs_default != ARM_PCS_AAPCS
+ && GET_MODE_CLASS (mode) == MODE_FLOAT)
+ {
+ /* The following libcalls return their result in integer registers,
+ even though they return a floating point value. */
+ if (arm_libcall_uses_aapcs_base (libcall))
+ return gen_rtx_REG (mode, ARG_REGISTER(1));
+ }
+
+ return LIBCALL_VALUE (mode);
}
/* Determine the amount of memory needed to store the possible return
@@ -2945,10 +3092,12 @@ arm_apply_result_size (void)
{
int size = 16;
- if (TARGET_ARM)
+ if (TARGET_32BIT)
{
if (TARGET_HARD_FLOAT_ABI)
{
+ if (TARGET_VFP)
+ size += 32;
if (TARGET_FPA)
size += 12;
if (TARGET_MAVERICK)
@@ -2961,27 +3110,56 @@ arm_apply_result_size (void)
return size;
}
-/* Decide whether a type should be returned in memory (true)
- or in a register (false). This is called as the target hook
- TARGET_RETURN_IN_MEMORY. */
+/* Decide whether TYPE should be returned in memory (true)
+ or in a register (false). FNTYPE is the type of the function making
+ the call. */
static bool
-arm_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
+arm_return_in_memory (const_tree type, const_tree fntype)
{
HOST_WIDE_INT size;
- size = int_size_in_bytes (type);
+ size = int_size_in_bytes (type); /* Negative if not fixed size. */
+
+ if (TARGET_AAPCS_BASED)
+ {
+ /* Simple, non-aggregate types (ie not including vectors and
+ complex) are always returned in a register (or registers).
+ We don't care about which register here, so we can short-cut
+ some of the detail. */
+ if (!AGGREGATE_TYPE_P (type)
+ && TREE_CODE (type) != VECTOR_TYPE
+ && TREE_CODE (type) != COMPLEX_TYPE)
+ return false;
+
+ /* Any return value that is no larger than one word can be
+ returned in r0. */
+ if (((unsigned HOST_WIDE_INT) size) <= UNITS_PER_WORD)
+ return false;
+
+ /* Check any available co-processors to see if they accept the
+ type as a register candidate (VFP, for example, can return
+ some aggregates in consecutive registers). These aren't
+ available if the call is variadic. */
+ if (aapcs_select_return_coproc (type, fntype) >= 0)
+ return false;
+
+ /* Vector values should be returned using ARM registers, not
+ memory (unless they're over 16 bytes, which will break since
+ we only have four call-clobbered registers to play with). */
+ if (TREE_CODE (type) == VECTOR_TYPE)
+ return (size < 0 || size > (4 * UNITS_PER_WORD));
+
+ /* The rest go in memory. */
+ return true;
+ }
- /* Vector values should be returned using ARM registers, not memory (unless
- they're over 16 bytes, which will break since we only have four
- call-clobbered registers to play with). */
if (TREE_CODE (type) == VECTOR_TYPE)
return (size < 0 || size > (4 * UNITS_PER_WORD));
if (!AGGREGATE_TYPE_P (type) &&
- !(TARGET_AAPCS_BASED && TREE_CODE (type) == COMPLEX_TYPE))
- /* All simple types are returned in registers.
- For AAPCS, complex types are treated the same as aggregates. */
- return 0;
+ (TREE_CODE (type) != VECTOR_TYPE))
+ /* All simple types are returned in registers. */
+ return false;
if (arm_abi != ARM_ABI_APCS)
{
@@ -2998,7 +3176,7 @@ arm_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
the aggregate is either huge or of variable size, and in either case
we will want to return it via memory and not in a register. */
if (size < 0 || size > UNITS_PER_WORD)
- return 1;
+ return true;
if (TREE_CODE (type) == RECORD_TYPE)
{
@@ -3018,18 +3196,18 @@ arm_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
continue;
if (field == NULL)
- return 0; /* An empty structure. Allowed by an extension to ANSI C. */
+ return false; /* An empty structure. Allowed by an extension to ANSI C. */
/* Check that the first field is valid for returning in a register. */
/* ... Floats are not allowed */
if (FLOAT_TYPE_P (TREE_TYPE (field)))
- return 1;
+ return true;
/* ... Aggregates that are not themselves valid for returning in
a register are not allowed. */
if (arm_return_in_memory (TREE_TYPE (field), NULL_TREE))
- return 1;
+ return true;
/* Now check the remaining fields, if any. Only bitfields are allowed,
since they are not addressable. */
@@ -3041,10 +3219,10 @@ arm_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
continue;
if (!DECL_BIT_FIELD_TYPE (field))
- return 1;
+ return true;
}
- return 0;
+ return false;
}
if (TREE_CODE (type) == UNION_TYPE)
@@ -3061,18 +3239,18 @@ arm_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
continue;
if (FLOAT_TYPE_P (TREE_TYPE (field)))
- return 1;
+ return true;
if (arm_return_in_memory (TREE_TYPE (field), NULL_TREE))
- return 1;
+ return true;
}
- return 0;
+ return false;
}
#endif /* not ARM_WINCE */
/* Return all other types in memory. */
- return 1;
+ return false;
}
/* Indicate whether or not words of a double are in big-endian order. */
@@ -3097,14 +3275,752 @@ arm_float_words_big_endian (void)
return 1;
}
+const struct pcs_attribute_arg
+{
+ const char *arg;
+ enum arm_pcs value;
+} pcs_attribute_args[] =
+ {
+ {"aapcs", ARM_PCS_AAPCS},
+ {"aapcs-vfp", ARM_PCS_AAPCS_VFP},
+#if 0
+ /* We could recognize these, but changes would be needed elsewhere
+ * to implement them. */
+ {"aapcs-iwmmxt", ARM_PCS_AAPCS_IWMMXT},
+ {"atpcs", ARM_PCS_ATPCS},
+ {"apcs", ARM_PCS_APCS},
+#endif
+ {NULL, ARM_PCS_UNKNOWN}
+ };
+
+static enum arm_pcs
+arm_pcs_from_attribute (tree attr)
+{
+ const struct pcs_attribute_arg *ptr;
+ const char *arg;
+
+ /* Get the value of the argument. */
+ if (TREE_VALUE (attr) == NULL_TREE
+ || TREE_CODE (TREE_VALUE (attr)) != STRING_CST)
+ return ARM_PCS_UNKNOWN;
+
+ arg = TREE_STRING_POINTER (TREE_VALUE (attr));
+
+ /* Check it against the list of known arguments. */
+ for (ptr = pcs_attribute_args; ptr->arg != NULL; ptr++)
+ if (streq (arg, ptr->arg))
+ return ptr->value;
+
+ /* An unrecognized interrupt type. */
+ return ARM_PCS_UNKNOWN;
+}
+
+/* Get the PCS variant to use for this call. TYPE is the function's type
+ specification, DECL is the specific declartion. DECL may be null if
+ the call could be indirect or if this is a library call. */
+static enum arm_pcs
+arm_get_pcs_model (const_tree type, const_tree decl)
+{
+ bool user_convention = false;
+ enum arm_pcs user_pcs = arm_pcs_default;
+ tree attr;
+
+ gcc_assert (type);
+
+ attr = lookup_attribute ("pcs", TYPE_ATTRIBUTES (type));
+ if (attr)
+ {
+ user_pcs = arm_pcs_from_attribute (TREE_VALUE (attr));
+ user_convention = true;
+ }
+
+ if (TARGET_AAPCS_BASED)
+ {
+ /* Detect varargs functions. These always use the base rules
+ (no argument is ever a candidate for a co-processor
+ register). */
+ bool base_rules = (TYPE_ARG_TYPES (type) != 0
+ && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (type)))
+ != void_type_node));
+
+ if (user_convention)
+ {
+ if (user_pcs > ARM_PCS_AAPCS_LOCAL)
+ sorry ("Non-AAPCS derived PCS variant");
+ else if (base_rules && user_pcs != ARM_PCS_AAPCS)
+ error ("Variadic functions must use the base AAPCS variant");
+ }
+
+ if (base_rules)
+ return ARM_PCS_AAPCS;
+ else if (user_convention)
+ return user_pcs;
+ else if (decl && flag_unit_at_a_time)
+ {
+ /* Local functions never leak outside this compilation unit,
+ so we are free to use whatever conventions are
+ appropriate. */
+ /* FIXME: remove CONST_CAST_TREE when cgraph is constified. */
+ struct cgraph_local_info *i = cgraph_local_info (CONST_CAST_TREE(decl));
+ if (i && i->local)
+ return ARM_PCS_AAPCS_LOCAL;
+ }
+ }
+ else if (user_convention && user_pcs != arm_pcs_default)
+ sorry ("PCS variant");
+
+ /* For everything else we use the target's default. */
+ return arm_pcs_default;
+}
+
+
+static void
+aapcs_vfp_cum_init (CUMULATIVE_ARGS *pcum ATTRIBUTE_UNUSED,
+ const_tree fntype ATTRIBUTE_UNUSED,
+ rtx libcall ATTRIBUTE_UNUSED,
+ const_tree fndecl ATTRIBUTE_UNUSED)
+{
+ /* Record the unallocated VFP registers. */
+ pcum->aapcs_vfp_regs_free = (1 << NUM_VFP_ARG_REGS) - 1;
+ pcum->aapcs_vfp_reg_alloc = 0;
+}
+
+/* Walk down the type tree of TYPE counting consecutive base elements.
+ If *MODEP is VOIDmode, then set it to the first valid floating point
+ type. If a non-floating point type is found, or if a floating point
+ type that doesn't match a non-VOIDmode *MODEP is found, then return -1,
+ otherwise return the count in the sub-tree. */
+static int
+aapcs_vfp_sub_candidate (const_tree type, enum machine_mode *modep)
+{
+ enum machine_mode mode;
+ HOST_WIDE_INT size;
+
+ switch (TREE_CODE (type))
+ {
+ case REAL_TYPE:
+ mode = TYPE_MODE (type);
+ if (mode != DFmode && mode != SFmode)
+ return -1;
+
+ if (*modep == VOIDmode)
+ *modep = mode;
+
+ if (*modep == mode)
+ return 1;
+
+ break;
+
+ case COMPLEX_TYPE:
+ mode = TYPE_MODE (TREE_TYPE (type));
+ if (mode != DFmode && mode != SFmode)
+ return -1;
+
+ if (*modep == VOIDmode)
+ *modep = mode;
+
+ if (*modep == mode)
+ return 2;
+
+ break;
+
+ case VECTOR_TYPE:
+ /* Use V2SImode and V4SImode as representatives of all 64-bit
+ and 128-bit vector types, whether or not those modes are
+ supported with the present options. */
+ size = int_size_in_bytes (type);
+ switch (size)
+ {
+ case 8:
+ mode = V2SImode;
+ break;
+ case 16:
+ mode = V4SImode;
+ break;
+ default:
+ return -1;
+ }
+
+ if (*modep == VOIDmode)
+ *modep = mode;
+
+ /* Vector modes are considered to be opaque: two vectors are
+ equivalent for the purposes of being homogeneous aggregates
+ if they are the same size. */
+ if (*modep == mode)
+ return 1;
+
+ break;
+
+ case ARRAY_TYPE:
+ {
+ int count;
+ tree index = TYPE_DOMAIN (type);
+
+ /* Can't handle incomplete types. */
+ if (!COMPLETE_TYPE_P(type))
+ return -1;
+
+ count = aapcs_vfp_sub_candidate (TREE_TYPE (type), modep);
+ if (count == -1
+ || !index
+ || !TYPE_MAX_VALUE (index)
+ || !host_integerp (TYPE_MAX_VALUE (index), 1)
+ || !TYPE_MIN_VALUE (index)
+ || !host_integerp (TYPE_MIN_VALUE (index), 1)
+ || count < 0)
+ return -1;
+
+ count *= (1 + tree_low_cst (TYPE_MAX_VALUE (index), 1)
+ - tree_low_cst (TYPE_MIN_VALUE (index), 1));
+
+ /* There must be no padding. */
+ if (!host_integerp (TYPE_SIZE (type), 1)
+ || (tree_low_cst (TYPE_SIZE (type), 1)
+ != count * GET_MODE_BITSIZE (*modep)))
+ return -1;
+
+ return count;
+ }
+
+ case RECORD_TYPE:
+ {
+ int count = 0;
+ int sub_count;
+ tree field;
+
+ /* Can't handle incomplete types. */
+ if (!COMPLETE_TYPE_P(type))
+ return -1;
+
+ for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+ {
+ if (TREE_CODE (field) != FIELD_DECL)
+ continue;
+
+ sub_count = aapcs_vfp_sub_candidate (TREE_TYPE (field), modep);
+ if (sub_count < 0)
+ return -1;
+ count += sub_count;
+ }
+
+ /* There must be no padding. */
+ if (!host_integerp (TYPE_SIZE (type), 1)
+ || (tree_low_cst (TYPE_SIZE (type), 1)
+ != count * GET_MODE_BITSIZE (*modep)))
+ return -1;
+
+ return count;
+ }
+
+ case UNION_TYPE:
+ case QUAL_UNION_TYPE:
+ {
+ /* These aren't very interesting except in a degenerate case. */
+ int count = 0;
+ int sub_count;
+ tree field;
+
+ /* Can't handle incomplete types. */
+ if (!COMPLETE_TYPE_P(type))
+ return -1;
+
+ for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+ {
+ if (TREE_CODE (field) != FIELD_DECL)
+ continue;
+
+ sub_count = aapcs_vfp_sub_candidate (TREE_TYPE (field), modep);
+ if (sub_count < 0)
+ return -1;
+ count = count > sub_count ? count : sub_count;
+ }
+
+ /* There must be no padding. */
+ if (!host_integerp (TYPE_SIZE (type), 1)
+ || (tree_low_cst (TYPE_SIZE (type), 1)
+ != count * GET_MODE_BITSIZE (*modep)))
+ return -1;
+
+ return count;
+ }
+
+ default:
+ break;
+ }
+
+ return -1;
+}
+
+static bool
+aapcs_vfp_is_call_or_return_candidate (enum machine_mode mode, const_tree type,
+ int *base_mode,
+ int *count)
+{
+ if (GET_MODE_CLASS (mode) == MODE_FLOAT
+ || GET_MODE_CLASS (mode) == MODE_VECTOR_INT
+ || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT)
+ {
+ *count = 1;
+ *base_mode = mode;
+ return true;
+ }
+ else if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT)
+ {
+ *count = 2;
+ *base_mode = (mode == DCmode ? DFmode : SFmode);
+ return true;
+ }
+ else if (type && (mode == BLKmode || TREE_CODE (type) == VECTOR_TYPE))
+ {
+ enum machine_mode aggregate_mode = VOIDmode;
+ int ag_count = aapcs_vfp_sub_candidate (type, &aggregate_mode);
+
+ if (ag_count > 0 && ag_count <= 4)
+ {
+ *count = ag_count;
+ *base_mode = aggregate_mode;
+ return true;
+ }
+ }
+ return false;
+}
+
+static bool
+aapcs_vfp_is_return_candidate (enum arm_pcs pcs_variant,
+ enum machine_mode mode, const_tree type)
+{
+ int count ATTRIBUTE_UNUSED;
+ int ag_mode ATTRIBUTE_UNUSED;
+
+ if (!(pcs_variant == ARM_PCS_AAPCS_VFP
+ || (pcs_variant == ARM_PCS_AAPCS_LOCAL
+ && TARGET_32BIT && TARGET_VFP && TARGET_HARD_FLOAT)))
+ return false;
+ return aapcs_vfp_is_call_or_return_candidate (mode, type, &ag_mode, &count);
+}
+
+static bool
+aapcs_vfp_is_call_candidate (CUMULATIVE_ARGS *pcum, enum machine_mode mode,
+ const_tree type)
+{
+ if (!(pcum->pcs_variant == ARM_PCS_AAPCS_VFP
+ || (pcum->pcs_variant == ARM_PCS_AAPCS_LOCAL
+ && TARGET_32BIT && TARGET_VFP && TARGET_HARD_FLOAT)))
+ return false;
+ return aapcs_vfp_is_call_or_return_candidate (mode, type,
+ &pcum->aapcs_vfp_rmode,
+ &pcum->aapcs_vfp_rcount);
+}
+
+static bool
+aapcs_vfp_allocate (CUMULATIVE_ARGS *pcum, enum machine_mode mode,
+ const_tree type ATTRIBUTE_UNUSED)
+{
+ int shift = GET_MODE_SIZE (pcum->aapcs_vfp_rmode) / GET_MODE_SIZE (SFmode);
+ unsigned mask = (1 << (shift * pcum->aapcs_vfp_rcount)) - 1;
+ int regno;
+
+ for (regno = 0; regno < NUM_VFP_ARG_REGS; regno += shift)
+ if (((pcum->aapcs_vfp_regs_free >> regno) & mask) == mask)
+ {
+ pcum->aapcs_vfp_reg_alloc = mask << regno;
+ if (mode == BLKmode || (mode == TImode && !TARGET_NEON))
+ {
+ int i;
+ int rcount = pcum->aapcs_vfp_rcount;
+ int rshift = shift;
+ enum machine_mode rmode = pcum->aapcs_vfp_rmode;
+ rtx par;
+ if (!TARGET_NEON)
+ {
+ /* Avoid using unsupported vector modes. */
+ if (rmode == V2SImode)
+ rmode = DImode;
+ else if (rmode == V4SImode)
+ {
+ rmode = DImode;
+ rcount *= 2;
+ rshift /= 2;
+ }
+ }
+ par = gen_rtx_PARALLEL (mode, rtvec_alloc (rcount));
+ for (i = 0; i < rcount; i++)
+ {
+ rtx tmp = gen_rtx_REG (rmode,
+ FIRST_VFP_REGNUM + regno + i * rshift);
+ tmp = gen_rtx_EXPR_LIST
+ (VOIDmode, tmp,
+ GEN_INT (i * GET_MODE_SIZE (rmode)));
+ XVECEXP (par, 0, i) = tmp;
+ }
+
+ pcum->aapcs_reg = par;
+ }
+ else
+ pcum->aapcs_reg = gen_rtx_REG (mode, FIRST_VFP_REGNUM + regno);
+ return true;
+ }
+ return false;
+}
+
+static rtx
+aapcs_vfp_allocate_return_reg (enum arm_pcs pcs_variant ATTRIBUTE_UNUSED,
+ enum machine_mode mode,
+ const_tree type ATTRIBUTE_UNUSED)
+{
+ if (!(pcs_variant == ARM_PCS_AAPCS_VFP
+ || (pcs_variant == ARM_PCS_AAPCS_LOCAL
+ && TARGET_32BIT && TARGET_VFP && TARGET_HARD_FLOAT)))
+ return false;
+ if (mode == BLKmode || (mode == TImode && !TARGET_NEON))
+ {
+ int count;
+ int ag_mode;
+ int i;
+ rtx par;
+ int shift;
+
+ aapcs_vfp_is_call_or_return_candidate (mode, type, &ag_mode, &count);
+
+ if (!TARGET_NEON)
+ {
+ if (ag_mode == V2SImode)
+ ag_mode = DImode;
+ else if (ag_mode == V4SImode)
+ {
+ ag_mode = DImode;
+ count *= 2;
+ }
+ }
+ shift = GET_MODE_SIZE(ag_mode) / GET_MODE_SIZE(SFmode);
+ par = gen_rtx_PARALLEL (mode, rtvec_alloc (count));
+ for (i = 0; i < count; i++)
+ {
+ rtx tmp = gen_rtx_REG (ag_mode, FIRST_VFP_REGNUM + i * shift);
+ tmp = gen_rtx_EXPR_LIST (VOIDmode, tmp,
+ GEN_INT (i * GET_MODE_SIZE (ag_mode)));
+ XVECEXP (par, 0, i) = tmp;
+ }
+
+ return par;
+ }
+
+ return gen_rtx_REG (mode, FIRST_VFP_REGNUM);
+}
+
+static void
+aapcs_vfp_advance (CUMULATIVE_ARGS *pcum ATTRIBUTE_UNUSED,
+ enum machine_mode mode ATTRIBUTE_UNUSED,
+ const_tree type ATTRIBUTE_UNUSED)
+{
+ pcum->aapcs_vfp_regs_free &= ~pcum->aapcs_vfp_reg_alloc;
+ pcum->aapcs_vfp_reg_alloc = 0;
+ return;
+}
+
+#define AAPCS_CP(X) \
+ { \
+ aapcs_ ## X ## _cum_init, \
+ aapcs_ ## X ## _is_call_candidate, \
+ aapcs_ ## X ## _allocate, \
+ aapcs_ ## X ## _is_return_candidate, \
+ aapcs_ ## X ## _allocate_return_reg, \
+ aapcs_ ## X ## _advance \
+ }
+
+/* Table of co-processors that can be used to pass arguments in
+ registers. Idealy no arugment should be a candidate for more than
+ one co-processor table entry, but the table is processed in order
+ and stops after the first match. If that entry then fails to put
+ the argument into a co-processor register, the argument will go on
+ the stack. */
+static struct
+{
+ /* Initialize co-processor related state in CUMULATIVE_ARGS structure. */
+ void (*cum_init) (CUMULATIVE_ARGS *, const_tree, rtx, const_tree);
+
+ /* Return true if an argument of mode MODE (or type TYPE if MODE is
+ BLKmode) is a candidate for this co-processor's registers; this
+ function should ignore any position-dependent state in
+ CUMULATIVE_ARGS and only use call-type dependent information. */
+ bool (*is_call_candidate) (CUMULATIVE_ARGS *, enum machine_mode, const_tree);
+
+ /* Return true if the argument does get a co-processor register; it
+ should set aapcs_reg to an RTX of the register allocated as is
+ required for a return from FUNCTION_ARG. */
+ bool (*allocate) (CUMULATIVE_ARGS *, enum machine_mode, const_tree);
+
+ /* Return true if a result of mode MODE (or type TYPE if MODE is
+ BLKmode) is can be returned in this co-processor's registers. */
+ bool (*is_return_candidate) (enum arm_pcs, enum machine_mode, const_tree);
+
+ /* Allocate and return an RTX element to hold the return type of a
+ call, this routine must not fail and will only be called if
+ is_return_candidate returned true with the same parameters. */
+ rtx (*allocate_return_reg) (enum arm_pcs, enum machine_mode, const_tree);
+
+ /* Finish processing this argument and prepare to start processing
+ the next one. */
+ void (*advance) (CUMULATIVE_ARGS *, enum machine_mode, const_tree);
+} aapcs_cp_arg_layout[ARM_NUM_COPROC_SLOTS] =
+ {
+ AAPCS_CP(vfp)
+ };
+
+#undef AAPCS_CP
+
+static int
+aapcs_select_call_coproc (CUMULATIVE_ARGS *pcum, enum machine_mode mode,
+ tree type)
+{
+ int i;
+
+ for (i = 0; i < ARM_NUM_COPROC_SLOTS; i++)
+ if (aapcs_cp_arg_layout[i].is_call_candidate (pcum, mode, type))
+ return i;
+
+ return -1;
+}
+
+static int
+aapcs_select_return_coproc (const_tree type, const_tree fntype)
+{
+ /* We aren't passed a decl, so we can't check that a call is local.
+ However, it isn't clear that that would be a win anyway, since it
+ might limit some tail-calling opportunities. */
+ enum arm_pcs pcs_variant;
+
+ if (fntype)
+ {
+ const_tree fndecl = NULL_TREE;
+ if (TREE_CODE (fntype) == FUNCTION_DECL)
+ {
+ fndecl = fntype;
+ fntype = TREE_TYPE (fntype);
+ }
+
+ pcs_variant = arm_get_pcs_model (fntype, fndecl);
+ }
+ else
+ pcs_variant = arm_pcs_default;
+
+ if (pcs_variant != ARM_PCS_AAPCS)
+ {
+ int i;
+
+ for (i = 0; i < ARM_NUM_COPROC_SLOTS; i++)
+ if (aapcs_cp_arg_layout[i].is_return_candidate (pcs_variant,
+ TYPE_MODE (type),
+ type))
+ return i;
+ }
+ return -1;
+}
+
+static rtx
+aapcs_allocate_return_reg (enum machine_mode mode, const_tree type,
+ const_tree fntype)
+{
+ /* We aren't passed a decl, so we can't check that a call is local.
+ However, it isn't clear that that would be a win anyway, since it
+ might limit some tail-calling opportunities. */
+ enum arm_pcs pcs_variant;
+ int unsignedp ATTRIBUTE_UNUSED;
+
+ if (fntype)
+ {
+ const_tree fndecl = NULL_TREE;
+
+ if (TREE_CODE (fntype) == FUNCTION_DECL)
+ {
+ fndecl = fntype;
+ fntype = TREE_TYPE (fntype);
+ }
+
+ pcs_variant = arm_get_pcs_model (fntype, fndecl);
+ }
+ else
+ pcs_variant = arm_pcs_default;
+
+ /* Promote integer types. */
+ if (type && INTEGRAL_TYPE_P (type))
+ PROMOTE_FUNCTION_MODE (mode, unsignedp, type);
+
+ if (pcs_variant != ARM_PCS_AAPCS)
+ {
+ int i;
+
+ for (i = 0; i < ARM_NUM_COPROC_SLOTS; i++)
+ if (aapcs_cp_arg_layout[i].is_return_candidate (pcs_variant, mode,
+ type))
+ return aapcs_cp_arg_layout[i].allocate_return_reg (pcs_variant,
+ mode, type);
+ }
+
+ /* Promotes small structs returned in a register to full-word size
+ for big-endian AAPCS. */
+ if (type && arm_return_in_msb (type))
+ {
+ HOST_WIDE_INT size = int_size_in_bytes (type);
+ if (size % UNITS_PER_WORD != 0)
+ {
+ size += UNITS_PER_WORD - size % UNITS_PER_WORD;
+ mode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0);
+ }
+ }
+
+ return gen_rtx_REG (mode, R0_REGNUM);
+}
+
+rtx
+aapcs_libcall_value (enum machine_mode mode)
+{
+ return aapcs_allocate_return_reg (mode, NULL_TREE, NULL_TREE);
+}
+
+/* Lay out a function argument using the AAPCS rules. The rule
+ numbers referred to here are those in the AAPCS. */
+static void
+aapcs_layout_arg (CUMULATIVE_ARGS *pcum, enum machine_mode mode,
+ tree type, int named)
+{
+ int nregs, nregs2;
+ int ncrn;
+
+ /* We only need to do this once per argument. */
+ if (pcum->aapcs_arg_processed)
+ return;
+
+ pcum->aapcs_arg_processed = true;
+
+ /* Special case: if named is false then we are handling an incoming
+ anonymous argument which is on the stack. */
+ if (!named)
+ return;
+
+ /* Is this a potential co-processor register candidate? */
+ if (pcum->pcs_variant != ARM_PCS_AAPCS)
+ {
+ int slot = aapcs_select_call_coproc (pcum, mode, type);
+ pcum->aapcs_cprc_slot = slot;
+
+ /* We don't have to apply any of the rules from part B of the
+ preparation phase, these are handled elsewhere in the
+ compiler. */
+
+ if (slot >= 0)
+ {
+ /* A Co-processor register candidate goes either in its own
+ class of registers or on the stack. */
+ if (!pcum->aapcs_cprc_failed[slot])
+ {
+ /* C1.cp - Try to allocate the argument to co-processor
+ registers. */
+ if (aapcs_cp_arg_layout[slot].allocate (pcum, mode, type))
+ return;
+
+ /* C2.cp - Put the argument on the stack and note that we
+ can't assign any more candidates in this slot. We also
+ need to note that we have allocated stack space, so that
+ we won't later try to split a non-cprc candidate between
+ core registers and the stack. */
+ pcum->aapcs_cprc_failed[slot] = true;
+ pcum->can_split = false;
+ }
+
+ /* We didn't get a register, so this argument goes on the
+ stack. */
+ gcc_assert (pcum->can_split == false);
+ return;
+ }
+ }
+
+ /* C3 - For double-word aligned arguments, round the NCRN up to the
+ next even number. */
+ ncrn = pcum->aapcs_ncrn;
+ if ((ncrn & 1) && arm_needs_doubleword_align (mode, type))
+ ncrn++;
+
+ nregs = ARM_NUM_REGS2(mode, type);
+
+ /* Sigh, this test should really assert that nregs > 0, but a GCC
+ extension allows empty structs and then gives them empty size; it
+ then allows such a structure to be passed by value. For some of
+ the code below we have to pretend that such an argument has
+ non-zero size so that we 'locate' it correctly either in
+ registers or on the stack. */
+ gcc_assert (nregs >= 0);
+
+ nregs2 = nregs ? nregs : 1;
+
+ /* C4 - Argument fits entirely in core registers. */
+ if (ncrn + nregs2 <= NUM_ARG_REGS)
+ {
+ pcum->aapcs_reg = gen_rtx_REG (mode, ncrn);
+ pcum->aapcs_next_ncrn = ncrn + nregs;
+ return;
+ }
+
+ /* C5 - Some core registers left and there are no arguments already
+ on the stack: split this argument between the remaining core
+ registers and the stack. */
+ if (ncrn < NUM_ARG_REGS && pcum->can_split)
+ {
+ pcum->aapcs_reg = gen_rtx_REG (mode, ncrn);
+ pcum->aapcs_next_ncrn = NUM_ARG_REGS;
+ pcum->aapcs_partial = (NUM_ARG_REGS - ncrn) * UNITS_PER_WORD;
+ return;
+ }
+
+ /* C6 - NCRN is set to 4. */
+ pcum->aapcs_next_ncrn = NUM_ARG_REGS;
+
+ /* C7,C8 - arugment goes on the stack. We have nothing to do here. */
+ return;
+}
+
/* Initialize a variable CUM of type CUMULATIVE_ARGS
for a call to a function whose data type is FNTYPE.
For a library call, FNTYPE is NULL. */
void
arm_init_cumulative_args (CUMULATIVE_ARGS *pcum, tree fntype,
- rtx libname ATTRIBUTE_UNUSED,
+ rtx libname,
tree fndecl ATTRIBUTE_UNUSED)
{
+ /* Long call handling. */
+ if (fntype)
+ pcum->pcs_variant = arm_get_pcs_model (fntype, fndecl);
+ else
+ pcum->pcs_variant = arm_pcs_default;
+
+ if (pcum->pcs_variant <= ARM_PCS_AAPCS_LOCAL)
+ {
+ if (arm_libcall_uses_aapcs_base (libname))
+ pcum->pcs_variant = ARM_PCS_AAPCS;
+
+ pcum->aapcs_ncrn = pcum->aapcs_next_ncrn = 0;
+ pcum->aapcs_reg = NULL_RTX;
+ pcum->aapcs_partial = 0;
+ pcum->aapcs_arg_processed = false;
+ pcum->aapcs_cprc_slot = -1;
+ pcum->can_split = true;
+
+ if (pcum->pcs_variant != ARM_PCS_AAPCS)
+ {
+ int i;
+
+ for (i = 0; i < ARM_NUM_COPROC_SLOTS; i++)
+ {
+ pcum->aapcs_cprc_failed[i] = false;
+ aapcs_cp_arg_layout[i].cum_init (pcum, fntype, libname, fndecl);
+ }
+ }
+ return;
+ }
+
+ /* Legacy ABIs */
+
/* On the ARM, the offset starts at 0. */
pcum->nregs = 0;
pcum->iwmmxt_nregs = 0;
@@ -3158,6 +4074,17 @@ arm_function_arg (CUMULATIVE_ARGS *pcum, enum machine_mode mode,
{
int nregs;
+ /* Handle the special case quickly. Pick an arbitrary value for op2 of
+ a call insn (op3 of a call_value insn). */
+ if (mode == VOIDmode)
+ return const0_rtx;
+
+ if (pcum->pcs_variant <= ARM_PCS_AAPCS_LOCAL)
+ {
+ aapcs_layout_arg (pcum, mode, type, named);
+ return pcum->aapcs_reg;
+ }
+
/* Varargs vectors are treated the same as long long.
named_count avoids having to change the way arm handles 'named' */
if (TARGET_IWMMXT_ABI
@@ -3199,10 +4126,16 @@ arm_function_arg (CUMULATIVE_ARGS *pcum, enum machine_mode mode,
static int
arm_arg_partial_bytes (CUMULATIVE_ARGS *pcum, enum machine_mode mode,
- tree type, bool named ATTRIBUTE_UNUSED)
+ tree type, bool named)
{
int nregs = pcum->nregs;
+ if (pcum->pcs_variant <= ARM_PCS_AAPCS_LOCAL)
+ {
+ aapcs_layout_arg (pcum, mode, type, named);
+ return pcum->aapcs_partial;
+ }
+
if (TARGET_IWMMXT_ABI && arm_vector_mode_supported_p (mode))
return 0;
@@ -3214,6 +4147,39 @@ arm_arg_partial_bytes (CUMULATIVE_ARGS *pcum, enum machine_mode mode,
return 0;
}
+void
+arm_function_arg_advance (CUMULATIVE_ARGS *pcum, enum machine_mode mode,
+ tree type, bool named)
+{
+ if (pcum->pcs_variant <= ARM_PCS_AAPCS_LOCAL)
+ {
+ aapcs_layout_arg (pcum, mode, type, named);
+
+ if (pcum->aapcs_cprc_slot >= 0)
+ {
+ aapcs_cp_arg_layout[pcum->aapcs_cprc_slot].advance (pcum, mode,
+ type);
+ pcum->aapcs_cprc_slot = -1;
+ }
+
+ /* Generic stuff. */
+ pcum->aapcs_arg_processed = false;
+ pcum->aapcs_ncrn = pcum->aapcs_next_ncrn;
+ pcum->aapcs_reg = NULL_RTX;
+ pcum->aapcs_partial = 0;
+ }
+ else
+ {
+ pcum->nargs += 1;
+ if (arm_vector_mode_supported_p (mode)
+ && pcum->named_count > pcum->nargs
+ && TARGET_IWMMXT_ABI)
+ pcum->iwmmxt_nregs += 1;
+ else
+ pcum->nregs += ARM_NUM_REGS2 (mode, type);
+ }
+}
+
/* Variable sized types are passed by reference. This is a GCC
extension to the ARM ABI. */
@@ -3264,6 +4230,8 @@ const struct attribute_spec arm_attribute_table[] =
/* Whereas these functions are always known to reside within the 26 bit
addressing range. */
{ "short_call", 0, 0, false, true, true, NULL },
+ /* Specify the procedure call conventions for a function. */
+ { "pcs", 1, 1, false, true, true, arm_handle_pcs_attribute },
/* Interrupt Service Routines have special prologue and epilogue requirements. */
{ "isr", 0, 1, false, false, false, arm_handle_isr_attribute },
{ "interrupt", 0, 1, false, false, false, arm_handle_isr_attribute },
@@ -3366,6 +4334,20 @@ arm_handle_isr_attribute (tree *node, tree name, tree args, int flags,
return NULL_TREE;
}
+/* Handle a "pcs" attribute; arguments as in struct
+ attribute_spec.handler. */
+static tree
+arm_handle_pcs_attribute (tree *node ATTRIBUTE_UNUSED, tree name, tree args,
+ int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+{
+ if (arm_pcs_from_attribute (args) == ARM_PCS_UNKNOWN)
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+ return NULL_TREE;
+}
+
#if TARGET_DLLIMPORT_DECL_ATTRIBUTES
/* Handle the "notshared" attribute. This attribute is another way of
requesting hidden visibility. ARM's compiler supports
@@ -3527,7 +4509,7 @@ arm_is_long_call_p (tree decl)
/* Return nonzero if it is ok to make a tail-call to DECL. */
static bool
-arm_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
+arm_function_ok_for_sibcall (tree decl, tree exp)
{
unsigned long func_type;
@@ -3560,6 +4542,21 @@ arm_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
if (IS_INTERRUPT (func_type))
return false;
+ if (!VOID_TYPE_P (TREE_TYPE (DECL_RESULT (cfun->decl))))
+ {
+ /* Check that the return value locations are the same. For
+ example that we aren't returning a value from the sibling in
+ a VFP register but then need to transfer it to a core
+ register. */
+ rtx a, b;
+
+ a = arm_function_value (TREE_TYPE (exp), decl, false);
+ b = arm_function_value (TREE_TYPE (DECL_RESULT (cfun->decl)),
+ cfun->decl, false);
+ if (!rtx_equal_p (a, b))
+ return false;
+ }
+
/* Never tailcall if function may be called with a misaligned SP. */
if (IS_STACKALIGN (func_type))
return false;
@@ -9995,6 +10992,82 @@ note_invalid_constants (rtx insn, HOST_WIDE_INT address, int do_pushes)
return result;
}
+/* Convert instructions to their cc-clobbering variant if possible, since
+ that allows us to use smaller encodings. */
+
+static void
+thumb2_reorg (void)
+{
+ basic_block bb;
+ regset_head live;
+
+ INIT_REG_SET (&live);
+
+ /* We are freeing block_for_insn in the toplev to keep compatibility
+ with old MDEP_REORGS that are not CFG based. Recompute it now. */
+ compute_bb_for_insn ();
+ df_analyze ();
+
+ FOR_EACH_BB (bb)
+ {
+ rtx insn;
+
+ COPY_REG_SET (&live, DF_LR_OUT (bb));
+ df_simulate_initialize_backwards (bb, &live);
+ FOR_BB_INSNS_REVERSE (bb, insn)
+ {
+ if (NONJUMP_INSN_P (insn)
+ && !REGNO_REG_SET_P (&live, CC_REGNUM))
+ {
+ rtx pat = PATTERN (insn);
+ if (GET_CODE (pat) == SET
+ && low_register_operand (XEXP (pat, 0), SImode)
+ && thumb_16bit_operator (XEXP (pat, 1), SImode)
+ && low_register_operand (XEXP (XEXP (pat, 1), 0), SImode)
+ && low_register_operand (XEXP (XEXP (pat, 1), 1), SImode))
+ {
+ rtx dst = XEXP (pat, 0);
+ rtx src = XEXP (pat, 1);
+ rtx op0 = XEXP (src, 0);
+ rtx op1 = (GET_RTX_CLASS (GET_CODE (src)) == RTX_COMM_ARITH
+ ? XEXP (src, 1) : NULL);
+
+ if (rtx_equal_p (dst, op0)
+ || GET_CODE (src) == PLUS || GET_CODE (src) == MINUS)
+ {
+ rtx ccreg = gen_rtx_REG (CCmode, CC_REGNUM);
+ rtx clobber = gen_rtx_CLOBBER (VOIDmode, ccreg);
+ rtvec vec = gen_rtvec (2, pat, clobber);
+ PATTERN (insn) = gen_rtx_PARALLEL (VOIDmode, vec);
+ INSN_CODE (insn) = -1;
+ }
+ /* We can also handle a commutative operation where the
+ second operand matches the destination. */
+ else if (op1 && rtx_equal_p (dst, op1))
+ {
+ rtx ccreg = gen_rtx_REG (CCmode, CC_REGNUM);
+ rtx clobber = gen_rtx_CLOBBER (VOIDmode, ccreg);
+ rtvec vec;
+
+ src = copy_rtx (src);
+ XEXP (src, 0) = op1;
+ XEXP (src, 1) = op0;
+ pat = gen_rtx_SET (VOIDmode, dst, src);
+ vec = gen_rtvec (2, pat, clobber);
+ PATTERN (insn) = gen_rtx_PARALLEL (VOIDmode, vec);
+ INSN_CODE (insn) = -1;
+ }
+ }
+ }
+
+ if (NONDEBUG_INSN_P (insn))
+ df_simulate_one_insn_backwards (bb, insn, &live);
+ }
+ }
+
+ CLEAR_REG_SET (&live);
+}
+
/* Gcc puts the pool in the wrong place for ARM, since we can only
load addresses a limited distance around the pc. We do some
special munging to move the constant pool values to the correct
@@ -10006,6 +11079,9 @@ arm_reorg (void)
HOST_WIDE_INT address = 0;
Mfix * fix;
+ if (TARGET_THUMB2)
+ thumb2_reorg ();
+
minipool_fix_head = minipool_fix_tail = NULL;
/* The first insn must always be a note, or the code below won't
@@ -18823,19 +19899,24 @@ arm_output_load_gr (rtx *operands)
that way. */
static void
-arm_setup_incoming_varargs (CUMULATIVE_ARGS *cum,
+arm_setup_incoming_varargs (CUMULATIVE_ARGS *pcum,
enum machine_mode mode,
tree type,
int *pretend_size,
int second_time ATTRIBUTE_UNUSED)
{
- int nregs = cum->nregs;
- if (nregs & 1
- && ARM_DOUBLEWORD_ALIGN
- && arm_needs_doubleword_align (mode, type))
- nregs++;
+ int nregs;
cfun->machine->uses_anonymous_args = 1;
+ if (pcum->pcs_variant <= ARM_PCS_AAPCS_LOCAL)
+ {
+ nregs = pcum->aapcs_ncrn;
+ if ((nregs & 1) && arm_needs_doubleword_align (mode, type))
+ nregs++;
+ }
+ else
+ nregs = pcum->nregs;
+
if (nregs < NUM_ARG_REGS)
*pretend_size = (NUM_ARG_REGS - nregs) * UNITS_PER_WORD;
}
@@ -19219,9 +20300,10 @@ arm_vector_mode_supported_p (enum machine_mode mode)
|| mode == V16QImode || mode == V4SFmode || mode == V2DImode))
return true;
- if ((mode == V2SImode)
- || (mode == V4HImode)
- || (mode == V8QImode))
+ if ((TARGET_NEON || TARGET_IWMMXT)
+ && ((mode == V2SImode)
+ || (mode == V4HImode)
+ || (mode == V8QImode)))
return true;
return false;
@@ -19967,9 +21049,9 @@ arm_can_simplify_got_access (int n_symbol, int n_access)
}
/* Detect if INSN loads a global address. If so returns the symbol and
- stores the register contains the offset of GOT entry into OFFSET_REG. */
+ sets the corresponding OFFSET_REG and OFFSET_INSN. */
rtx
-arm_loaded_global_var (rtx insn, rtx * offset_reg)
+arm_loaded_global_var (rtx insn, rtx * offset_reg, rtx * offset_insn)
{
rtx set = single_set (insn);
rtx pic_reg = cfun->machine->pic_reg;
@@ -20014,6 +21096,7 @@ arm_loaded_global_var (rtx insn, rtx * offset_reg)
return NULL_RTX;
*offset_reg = op1;
+ *offset_insn = def_insn;
return RTVEC_ELT (XVEC (src, 0), 0);
}
@@ -20026,9 +21109,9 @@ arm_loaded_global_var (rtx insn, rtx * offset_reg)
LOAD_INSN is the original insn which loads the address from GOT. */
void
arm_load_global_address (rtx symbol, rtx offset_reg,
- rtx address_reg, rtx load_insn)
+ rtx address_reg, rtx load_insn, rtx offset_insn)
{
- rtx offset, got_prel;
+ rtx offset, got_prel, new_insn;
rtx labelno = GEN_INT (pic_labelno++);
rtx l1 = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, labelno), UNSPEC_PIC_LABEL);
rtx set = single_set (load_insn);
@@ -20044,22 +21127,22 @@ arm_load_global_address (rtx symbol, rtx offset_reg,
UNSPEC_GOT_PREL_SYM);
got_prel = gen_rtx_CONST (Pmode, got_prel);
if (TARGET_32BIT)
- emit_insn_before (gen_pic_load_addr_32bit (offset_reg, got_prel),
- load_insn);
+ new_insn = emit_insn_after (gen_pic_load_addr_32bit (offset_reg, got_prel),
+ offset_insn);
else
- emit_insn_before (gen_pic_load_addr_thumb1 (offset_reg, got_prel),
- load_insn);
+ new_insn = emit_insn_after (gen_pic_load_addr_thumb1 (offset_reg, got_prel),
+ offset_insn);
/* The second insn:
(SET offset_reg (PLUS offset_reg pc_rtx)) */
if (TARGET_ARM)
- emit_insn_before (gen_pic_add_dot_plus_eight (offset_reg, offset_reg,
- labelno),
- load_insn);
- else
- emit_insn_before (gen_pic_add_dot_plus_four (offset_reg, offset_reg,
+ emit_insn_after (gen_pic_add_dot_plus_eight (offset_reg, offset_reg,
labelno),
- load_insn);
+ new_insn);
+ else
+ emit_insn_after (gen_pic_add_dot_plus_four (offset_reg, offset_reg,
+ labelno),
+ new_insn);
/* The last insn to access the GOT entry:
(SET address_reg (MEM offset_reg))
diff --git a/gcc-4.4.3/gcc/config/arm/arm.h b/gcc-4.4.3/gcc/config/arm/arm.h
index a413dd323..1189914f6 100644
--- a/gcc-4.4.3/gcc/config/arm/arm.h
+++ b/gcc-4.4.3/gcc/config/arm/arm.h
@@ -880,6 +880,9 @@ extern int arm_structure_size_boundary;
/* The number of (integer) argument register available. */
#define NUM_ARG_REGS 4
+/* And similarly for the VFP. */
+#define NUM_VFP_ARG_REGS 16
+
/* Return the register number of the N'th (integer) argument. */
#define ARG_REGISTER(N) (N - 1)
@@ -1494,9 +1497,10 @@ do { \
/* Define how to find the value returned by a library function
assuming the value has mode MODE. */
-#define LIBCALL_VALUE(MODE) \
- (TARGET_32BIT && TARGET_HARD_FLOAT_ABI && TARGET_FPA \
- && GET_MODE_CLASS (MODE) == MODE_FLOAT \
+#define LIBCALL_VALUE(MODE) \
+ (TARGET_AAPCS_BASED ? aapcs_libcall_value (MODE) \
+ : (TARGET_32BIT && TARGET_HARD_FLOAT_ABI && TARGET_FPA \
+ && GET_MODE_CLASS (MODE) == MODE_FLOAT) \
? gen_rtx_REG (MODE, FIRST_FPA_REGNUM) \
: TARGET_32BIT && TARGET_HARD_FLOAT_ABI && TARGET_MAVERICK \
&& GET_MODE_CLASS (MODE) == MODE_FLOAT \
@@ -1505,22 +1509,16 @@ do { \
? gen_rtx_REG (MODE, FIRST_IWMMXT_REGNUM) \
: gen_rtx_REG (MODE, ARG_REGISTER (1)))
-/* Define how to find the value returned by a function.
- VALTYPE is the data type of the value (as a tree).
- If the precise function being called is known, FUNC is its FUNCTION_DECL;
- otherwise, FUNC is 0. */
-#define FUNCTION_VALUE(VALTYPE, FUNC) \
- arm_function_value (VALTYPE, FUNC);
-
-/* 1 if N is a possible register number for a function value.
- On the ARM, only r0 and f0 can return results. */
-/* On a Cirrus chip, mvf0 can return results. */
-#define FUNCTION_VALUE_REGNO_P(REGNO) \
- ((REGNO) == ARG_REGISTER (1) \
- || (TARGET_32BIT && ((REGNO) == FIRST_CIRRUS_FP_REGNUM) \
- && TARGET_HARD_FLOAT_ABI && TARGET_MAVERICK) \
- || ((REGNO) == FIRST_IWMMXT_REGNUM && TARGET_IWMMXT_ABI) \
- || (TARGET_32BIT && ((REGNO) == FIRST_FPA_REGNUM) \
+/* 1 if REGNO is a possible register number for a function value. */
+#define FUNCTION_VALUE_REGNO_P(REGNO) \
+ ((REGNO) == ARG_REGISTER (1) \
+ || (TARGET_AAPCS_BASED && TARGET_32BIT \
+ && TARGET_VFP && TARGET_HARD_FLOAT \
+ && (REGNO) == FIRST_VFP_REGNUM) \
+ || (TARGET_32BIT && ((REGNO) == FIRST_CIRRUS_FP_REGNUM) \
+ && TARGET_HARD_FLOAT_ABI && TARGET_MAVERICK) \
+ || ((REGNO) == FIRST_IWMMXT_REGNUM && TARGET_IWMMXT_ABI) \
+ || (TARGET_32BIT && ((REGNO) == FIRST_FPA_REGNUM) \
&& TARGET_HARD_FLOAT_ABI && TARGET_FPA))
/* Amount of memory needed for an untyped call to save all possible return
@@ -1620,9 +1618,27 @@ machine_function;
that is in text_section. */
extern GTY(()) rtx thumb_call_via_label[14];
+/* The number of potential ways of assigning to a co-processor. */
+#define ARM_NUM_COPROC_SLOTS 1
+
+/* Enumeration of procedure calling standard variants. We don't really
+ support all of these yet. */
+enum arm_pcs
+{
+ ARM_PCS_AAPCS, /* Base standard AAPCS. */
+ ARM_PCS_AAPCS_VFP, /* Use VFP registers for floating point values. */
+ ARM_PCS_AAPCS_IWMMXT, /* Use iWMMXT registers for vectors. */
+ /* This must be the last AAPCS variant. */
+ ARM_PCS_AAPCS_LOCAL, /* Private call within this compilation unit. */
+ ARM_PCS_ATPCS, /* ATPCS. */
+ ARM_PCS_APCS, /* APCS (legacy Linux etc). */
+ ARM_PCS_UNKNOWN
+};
+
+/* We can't define this inside a generator file because it needs enum
+ machine_mode. */
/* A C type for declaring a variable that is used as the first argument of
- `FUNCTION_ARG' and other related values. For some target machines, the
- type `int' suffices and can hold the number of bytes of argument so far. */
+ `FUNCTION_ARG' and other related values. */
typedef struct
{
/* This is the number of registers of arguments scanned so far. */
@@ -1631,7 +1647,30 @@ typedef struct
int iwmmxt_nregs;
int named_count;
int nargs;
- int can_split;
+ /* Which procedure call variant to use for this call. */
+ enum arm_pcs pcs_variant;
+
+ /* AAPCS related state tracking. */
+ int aapcs_arg_processed; /* No need to lay out this argument again. */
+ int aapcs_cprc_slot; /* Index of co-processor rules to handle
+ this argument, or -1 if using core
+ registers. */
+ int aapcs_ncrn;
+ int aapcs_next_ncrn;
+ rtx aapcs_reg; /* Register assigned to this argument. */
+ int aapcs_partial; /* How many bytes are passed in regs (if
+ split between core regs and stack.
+ Zero otherwise. */
+ int aapcs_cprc_failed[ARM_NUM_COPROC_SLOTS];
+ int can_split; /* Argument can be split between core regs
+ and the stack. */
+ /* Private data for tracking VFP register allocation */
+ unsigned aapcs_vfp_regs_free;
+ unsigned aapcs_vfp_reg_alloc;
+ int aapcs_vfp_rcount;
+ /* Can't include insn-modes.h because this header is needed before we
+ generate it. */
+ int /* enum machine_mode */ aapcs_vfp_rmode;
} CUMULATIVE_ARGS;
/* Define where to put the arguments to a function.
@@ -1677,13 +1716,7 @@ typedef struct
of mode MODE and data type TYPE.
(TYPE is null for libcalls where that information may not be available.) */
#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
- (CUM).nargs += 1; \
- if (arm_vector_mode_supported_p (MODE) \
- && (CUM).named_count > (CUM).nargs \
- && TARGET_IWMMXT_ABI) \
- (CUM).iwmmxt_nregs += 1; \
- else \
- (CUM).nregs += ARM_NUM_REGS2 (MODE, TYPE)
+ arm_function_arg_advance (&(CUM), (MODE), (TYPE), (NAMED))
/* If defined, a C expression that gives the alignment boundary, in bits, of an
argument with the specified mode and type. If it is not defined,
@@ -1695,9 +1728,11 @@ typedef struct
/* 1 if N is a possible register number for function argument passing.
On the ARM, r0-r3 are used to pass args. */
-#define FUNCTION_ARG_REGNO_P(REGNO) \
- (IN_RANGE ((REGNO), 0, 3) \
- || (TARGET_IWMMXT_ABI \
+#define FUNCTION_ARG_REGNO_P(REGNO) \
+ (IN_RANGE ((REGNO), 0, 3) \
+ || (TARGET_AAPCS_BASED && TARGET_VFP && TARGET_HARD_FLOAT \
+ && IN_RANGE ((REGNO), FIRST_VFP_REGNUM, FIRST_VFP_REGNUM + 15)) \
+ || (TARGET_IWMMXT_ABI \
&& IN_RANGE ((REGNO), FIRST_IWMMXT_REGNUM, FIRST_IWMMXT_REGNUM + 9)))
diff --git a/gcc-4.4.3/gcc/config/arm/arm.md b/gcc-4.4.3/gcc/config/arm/arm.md
index e9de45efd..ea16f1c31 100644
--- a/gcc-4.4.3/gcc/config/arm/arm.md
+++ b/gcc-4.4.3/gcc/config/arm/arm.md
@@ -743,14 +743,14 @@
[(set (reg:CC CC_REGNUM)
(compare:CC
(match_operand:SI 1 "s_register_operand" "r,r")
- (match_operand:SI 2 "arm_addimm_operand" "I,L")))
+ (match_operand:SI 2 "arm_addimm_operand" "L,I")))
(set (match_operand:SI 0 "s_register_operand" "=r,r")
(plus:SI (match_dup 1)
- (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
+ (match_operand:SI 3 "arm_addimm_operand" "I,L")))]
"TARGET_32BIT && INTVAL (operands[2]) == -INTVAL (operands[3])"
"@
- sub%.\\t%0, %1, %2
- add%.\\t%0, %1, #%n2"
+ add%.\\t%0, %1, %3
+ sub%.\\t%0, %1, #%n3"
[(set_attr "conds" "set")]
)
@@ -1907,9 +1907,17 @@
{
if (GET_CODE (operands[2]) == CONST_INT)
{
- arm_split_constant (AND, SImode, NULL_RTX,
- INTVAL (operands[2]), operands[0],
- operands[1], optimize && can_create_pseudo_p ());
+ if (INTVAL (operands[2]) == 255 && arm_arch6)
+ {
+ operands[1] = convert_to_mode (QImode, operands[1], 1);
+ emit_insn (gen_thumb2_zero_extendqisi2_v6 (operands[0],
+ operands[1]));
+ }
+ else
+ arm_split_constant (AND, SImode, NULL_RTX,
+ INTVAL (operands[2]), operands[0],
+ operands[1],
+ optimize && can_create_pseudo_p ());
DONE;
}
diff --git a/gcc-4.4.3/gcc/config/arm/bpabi.h b/gcc-4.4.3/gcc/config/arm/bpabi.h
index 4d2974e32..4b37dcf63 100644
--- a/gcc-4.4.3/gcc/config/arm/bpabi.h
+++ b/gcc-4.4.3/gcc/config/arm/bpabi.h
@@ -90,16 +90,22 @@
#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (muldi3, lmul)
#endif
#ifdef L_fixdfdi
-#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (fixdfdi, d2lz)
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (fixdfdi, d2lz) \
+ extern DWtype __fixdfdi (DFtype) __attribute__((pcs("aapcs"))); \
+ extern UDWtype __fixunsdfdi (DFtype) __asm__("__aeabi_d2ulz") __attribute__((pcs("aapcs")));
#endif
#ifdef L_fixunsdfdi
-#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (fixunsdfdi, d2ulz)
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (fixunsdfdi, d2ulz) \
+ extern UDWtype __fixunsdfdi (DFtype) __attribute__((pcs("aapcs")));
#endif
#ifdef L_fixsfdi
-#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (fixsfdi, f2lz)
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (fixsfdi, f2lz) \
+ extern DWtype __fixsfdi (SFtype) __attribute__((pcs("aapcs"))); \
+ extern UDWtype __fixunssfdi (SFtype) __asm__("__aeabi_f2ulz") __attribute__((pcs("aapcs")));
#endif
#ifdef L_fixunssfdi
-#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (fixunssfdi, f2ulz)
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (fixunssfdi, f2ulz) \
+ extern UDWtype __fixunssfdi (SFtype) __attribute__((pcs("aapcs")));
#endif
#ifdef L_floatdidf
#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (floatdidf, l2d)
diff --git a/gcc-4.4.3/gcc/config/arm/constraints.md b/gcc-4.4.3/gcc/config/arm/constraints.md
index d14dafd2b..8cab39a66 100644
--- a/gcc-4.4.3/gcc/config/arm/constraints.md
+++ b/gcc-4.4.3/gcc/config/arm/constraints.md
@@ -31,6 +31,7 @@
;; The following multi-letter normal constraints have been used:
;; in ARM/Thumb-2 state: Da, Db, Dc, Dn, Dl, DL, Dv
;; in Thumb-1 state: Pa, Pb
+;; in Thumb-2 state: Ps, Pt, Pw, Px
;; The following memory constraints have been used:
;; in ARM/Thumb-2 state: Q, Ut, Uv, Uy, Un, Us
@@ -149,6 +150,26 @@
(match_test "TARGET_THUMB1 && ival >= -262 && ival <= 262
&& (ival > 255 || ival < -255)")))
+(define_constraint "Ps"
+ "@internal In Thumb-2 state a constant in the range -255 to +255"
+ (and (match_code "const_int")
+ (match_test "TARGET_THUMB2 && ival >= -255 && ival <= 255")))
+
+(define_constraint "Pt"
+ "@internal In Thumb-2 state a constant in the range -7 to +7"
+ (and (match_code "const_int")
+ (match_test "TARGET_THUMB2 && ival >= -7 && ival <= 7")))
+
+(define_constraint "Pw"
+ "@internal In Thumb-2 state a constant in the range -255 to -1"
+ (and (match_code "const_int")
+ (match_test "TARGET_THUMB2 && ival >= -255 && ival <= -1")))
+
+(define_constraint "Px"
+ "@internal In Thumb-2 state a constant in the range -7 to -1"
+ (and (match_code "const_int")
+ (match_test "TARGET_THUMB2 && ival >= -7 && ival <= -1")))
+
(define_constraint "G"
"In ARM/Thumb-2 state a valid FPA immediate constant."
(and (match_code "const_double")
diff --git a/gcc-4.4.3/gcc/config/arm/linux-eabi.h b/gcc-4.4.3/gcc/config/arm/linux-eabi.h
index 6dd44436a..2ca881890 100644
--- a/gcc-4.4.3/gcc/config/arm/linux-eabi.h
+++ b/gcc-4.4.3/gcc/config/arm/linux-eabi.h
@@ -27,6 +27,7 @@
{ \
TARGET_BPABI_CPP_BUILTINS(); \
LINUX_TARGET_OS_CPP_BUILTINS(); \
+ ANDROID_TARGET_OS_CPP_BUILTINS(); \
} \
while (false)
diff --git a/gcc-4.4.3/gcc/config/arm/t-arm-elf b/gcc-4.4.3/gcc/config/arm/t-arm-elf
index 9f6068258..5b812b750 100644
--- a/gcc-4.4.3/gcc/config/arm/t-arm-elf
+++ b/gcc-4.4.3/gcc/config/arm/t-arm-elf
@@ -32,6 +32,13 @@ MULTILIB_OPTIONS += $(MLOPT_armv7a)
MULTILIB_DIRNAMES += $(MLDIR_armv7a)
MULTILIB_MATCHES += $(MLMATCH_armv7a)
+# Not quite true. We can support hard-vfp calling in Thumb2, but how do we
+# express that here? Also, we really need architecture v5e or later
+# (mcrr etc).
+MULTILIB_OPTIONS += mfloat-abi=hard
+MULTILIB_DIRNAMES += fpu
+MULTILIB_EXCEPTIONS += *mthumb/*mfloat-abi=hard*
+
# MULTILIB_OPTIONS += mcpu=ep9312
# MULTILIB_DIRNAMES += ep9312
# MULTILIB_EXCEPTIONS += *mthumb/*mcpu=ep9312*
diff --git a/gcc-4.4.3/gcc/config/arm/thumb2.md b/gcc-4.4.3/gcc/config/arm/thumb2.md
index 2243172e6..6e03e8b21 100644
--- a/gcc-4.4.3/gcc/config/arm/thumb2.md
+++ b/gcc-4.4.3/gcc/config/arm/thumb2.md
@@ -943,7 +943,7 @@
(set_attr "neg_pool_range" "*,250")]
)
-(define_insn "*thumb2_zero_extendqisi2_v6"
+(define_insn "thumb2_zero_extendqisi2_v6"
[(set (match_operand:SI 0 "s_register_operand" "=r,r")
(zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
"TARGET_THUMB2 && arm_arch6"
@@ -1006,29 +1006,6 @@
}"
)
-;; Peepholes and insns for 16-bit flag clobbering instructions.
-;; The conditional forms of these instructions do not clobber CC.
-;; However by the time peepholes are run it is probably too late to do
-;; anything useful with this information.
-(define_peephole2
- [(set (match_operand:SI 0 "low_register_operand" "")
- (match_operator:SI 3 "thumb_16bit_operator"
- [(match_operand:SI 1 "low_register_operand" "")
- (match_operand:SI 2 "low_register_operand" "")]))]
- "TARGET_THUMB2
- && (rtx_equal_p(operands[0], operands[1])
- || GET_CODE(operands[3]) == PLUS
- || GET_CODE(operands[3]) == MINUS)
- && peep2_regno_dead_p(0, CC_REGNUM)"
- [(parallel
- [(set (match_dup 0)
- (match_op_dup 3
- [(match_dup 1)
- (match_dup 2)]))
- (clobber (reg:CC CC_REGNUM))])]
- ""
-)
-
(define_insn "*thumb2_alusi3_short"
[(set (match_operand:SI 0 "s_register_operand" "=l")
(match_operator:SI 3 "thumb_16bit_operator"
@@ -1124,9 +1101,9 @@
)
(define_insn "*thumb2_addsi_short"
- [(set (match_operand:SI 0 "low_register_operand" "=l")
- (plus:SI (match_operand:SI 1 "low_register_operand" "l")
- (match_operand:SI 2 "low_reg_or_int_operand" "lIL")))
+ [(set (match_operand:SI 0 "low_register_operand" "=l,l")
+ (plus:SI (match_operand:SI 1 "low_register_operand" "l,0")
+ (match_operand:SI 2 "low_reg_or_int_operand" "lPt,Ps")))
(clobber (reg:CC CC_REGNUM))]
"TARGET_THUMB2 && reload_completed"
"*
@@ -1178,6 +1155,32 @@
(set_attr "length" "2")]
)
+(define_peephole2
+ [(set (match_operand:CC 0 "cc_register" "")
+ (compare:CC (match_operand:SI 1 "low_register_operand" "")
+ (match_operand:SI 2 "const_int_operand" "")))]
+ "TARGET_THUMB2
+ && peep2_reg_dead_p (1, operands[1])
+ && satisfies_constraint_Pw (operands[2])"
+ [(parallel
+ [(set (match_dup 0) (compare:CC (match_dup 1) (match_dup 2)))
+ (set (match_dup 1) (plus:SI (match_dup 1) (match_dup 3)))])]
+ "operands[3] = GEN_INT (- INTVAL (operands[2]));"
+)
+
+(define_peephole2
+ [(match_scratch:SI 3 "l")
+ (set (match_operand:CC 0 "cc_register" "")
+ (compare:CC (match_operand:SI 1 "low_register_operand" "")
+ (match_operand:SI 2 "const_int_operand" "")))]
+ "TARGET_THUMB2
+ && satisfies_constraint_Px (operands[2])"
+ [(parallel
+ [(set (match_dup 0) (compare:CC (match_dup 1) (match_dup 2)))
+ (set (match_dup 3) (plus:SI (match_dup 1) (match_dup 4)))])]
+ "operands[4] = GEN_INT (- INTVAL (operands[2]));"
+)
+
(define_insn "*thumb2_cbz"
[(set (pc) (if_then_else
(eq (match_operand:SI 0 "s_register_operand" "l,?r")
diff --git a/gcc-4.4.3/gcc/config/i386/atom.md b/gcc-4.4.3/gcc/config/i386/atom.md
new file mode 100644
index 000000000..1664269ba
--- /dev/null
+++ b/gcc-4.4.3/gcc/config/i386/atom.md
@@ -0,0 +1,796 @@
+;; Atom Scheduling
+;; Copyright (C) 2009 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/>.
+;;
+;; Atom is an in-order core with two integer pipelines.
+
+
+(define_attr "atom_unit" "sishuf,simul,jeu,complex,other"
+ (const_string "other"))
+
+(define_attr "atom_sse_attr" "rcp,movdup,lfence,fence,prefetch,sqrt,mxcsr,other"
+ (const_string "other"))
+
+(define_automaton "atom")
+
+;; Atom has two ports: port 0 and port 1 connecting to all execution units
+(define_cpu_unit "atom-port-0,atom-port-1" "atom")
+
+;; EU: Execution Unit
+;; Atom EUs are connected by port 0 or port 1.
+
+(define_cpu_unit "atom-eu-0, atom-eu-1,
+ atom-imul-1, atom-imul-2, atom-imul-3, atom-imul-4"
+ "atom")
+
+;; Some EUs have duplicated copied and can be accessed via either
+;; port 0 or port 1
+;; (define_reservation "atom-port-either" "(atom-port-0 | atom-port-1)")
+
+;;; Some instructions is dual-pipe execution, need both ports
+;;; Complex multi-op macro-instructoins need both ports and all EUs
+(define_reservation "atom-port-dual" "(atom-port-0 + atom-port-1)")
+(define_reservation "atom-all-eu" "(atom-eu-0 + atom-eu-1 +
+ atom-imul-1 + atom-imul-2 + atom-imul-3 +
+ atom-imul-4)")
+
+;;; Most of simple instructions have 1 cycle latency. Some of them
+;;; issue in port 0, some in port 0 and some in either port.
+(define_reservation "atom-simple-0" "(atom-port-0 + atom-eu-0)")
+(define_reservation "atom-simple-1" "(atom-port-1 + atom-eu-1)")
+(define_reservation "atom-simple-either" "(atom-simple-0 | atom-simple-1)")
+
+;;; Some insn issues in port 0 with 3 cycle latency and 1 cycle tput
+(define_reservation "atom-eu-0-3-1" "(atom-port-0 + atom-eu-0, nothing*2)")
+
+;;; fmul insn can have 4 or 5 cycles latency
+(define_reservation "atom-fmul-5c" "(atom-port-0 + atom-eu-0), nothing*4")
+(define_reservation "atom-fmul-4c" "(atom-port-0 + atom-eu-0), nothing*3")
+
+;;; fadd can has 5 cycles latency depends on instruction forms
+(define_reservation "atom-fadd-5c" "(atom-port-1 + atom-eu-1), nothing*5")
+
+;;; imul insn has 5 cycles latency
+(define_reservation "atom-imul-32"
+ "atom-imul-1, atom-imul-2, atom-imul-3, atom-imul-4,
+ atom-port-0")
+;;; imul instruction excludes other non-FP instructions.
+(exclusion_set "atom-eu-0, atom-eu-1"
+ "atom-imul-1, atom-imul-2, atom-imul-3, atom-imul-4")
+
+;;; dual-execution instructions can have 1,2,4,5 cycles latency depends on
+;;; instruction forms
+(define_reservation "atom-dual-1c" "(atom-port-dual + atom-eu-0 + atom-eu-1)")
+(define_reservation "atom-dual-2c"
+ "(atom-port-dual + atom-eu-0 + atom-eu-1, nothing)")
+(define_reservation "atom-dual-5c"
+ "(atom-port-dual + atom-eu-0 + atom-eu-1, nothing*4)")
+
+;;; Complex macro-instruction has variants of latency, and uses both ports.
+(define_reservation "atom-complex" "(atom-port-dual + atom-all-eu)")
+
+(define_insn_reservation "atom_other" 9
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "other")
+ (eq_attr "atom_unit" "!jeu")))
+ "atom-complex, atom-all-eu*8")
+
+;; return has type "other" with atom_unit "jeu"
+(define_insn_reservation "atom_other_2" 1
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "other")
+ (eq_attr "atom_unit" "jeu")))
+ "atom-dual-1c")
+
+(define_insn_reservation "atom_multi" 9
+ (and (eq_attr "cpu" "atom")
+ (eq_attr "type" "multi"))
+ "atom-complex, atom-all-eu*8")
+
+;; Normal alu insns without carry
+(define_insn_reservation "atom_alu" 1
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "alu")
+ (and (eq_attr "memory" "none")
+ (eq_attr "use_carry" "0"))))
+ "atom-simple-either")
+
+;; Normal alu insns without carry
+(define_insn_reservation "atom_alu_mem" 1
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "alu")
+ (and (eq_attr "memory" "!none")
+ (eq_attr "use_carry" "0"))))
+ "atom-simple-either")
+
+;; Alu insn consuming CF, such as add/sbb
+(define_insn_reservation "atom_alu_carry" 1
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "alu")
+ (and (eq_attr "memory" "none")
+ (eq_attr "use_carry" "1"))))
+ "atom-simple-either")
+
+;; Alu insn consuming CF, such as add/sbb
+(define_insn_reservation "atom_alu_carry_mem" 1
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "alu")
+ (and (eq_attr "memory" "!none")
+ (eq_attr "use_carry" "1"))))
+ "atom-simple-either")
+
+(define_insn_reservation "atom_alu1" 1
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "alu1")
+ (eq_attr "memory" "none")))
+ "atom-simple-either")
+
+(define_insn_reservation "atom_alu1_mem" 1
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "alu1")
+ (eq_attr "memory" "!none")))
+ "atom-simple-either")
+
+(define_insn_reservation "atom_negnot" 1
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "negnot")
+ (eq_attr "memory" "none")))
+ "atom-simple-either")
+
+(define_insn_reservation "atom_negnot_mem" 1
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "negnot")
+ (eq_attr "memory" "!none")))
+ "atom-simple-either")
+
+(define_insn_reservation "atom_imov" 1
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "imov")
+ (eq_attr "memory" "none")))
+ "atom-simple-either")
+
+(define_insn_reservation "atom_imov_mem" 1
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "imov")
+ (eq_attr "memory" "!none")))
+ "atom-simple-either")
+
+;; 16<-16, 32<-32
+(define_insn_reservation "atom_imovx" 1
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "imovx")
+ (and (eq_attr "memory" "none")
+ (ior (and (match_operand:HI 0 "register_operand")
+ (match_operand:HI 1 "general_operand"))
+ (and (match_operand:SI 0 "register_operand")
+ (match_operand:SI 1 "general_operand"))))))
+ "atom-simple-either")
+
+;; 16<-16, 32<-32, mem
+(define_insn_reservation "atom_imovx_mem" 1
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "imovx")
+ (and (eq_attr "memory" "!none")
+ (ior (and (match_operand:HI 0 "register_operand")
+ (match_operand:HI 1 "general_operand"))
+ (and (match_operand:SI 0 "register_operand")
+ (match_operand:SI 1 "general_operand"))))))
+ "atom-simple-either")
+
+;; 32<-16, 32<-8, 64<-16, 64<-8, 64<-32, 8<-8
+(define_insn_reservation "atom_imovx_2" 1
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "imovx")
+ (and (eq_attr "memory" "none")
+ (ior (match_operand:QI 0 "register_operand")
+ (ior (and (match_operand:SI 0 "register_operand")
+ (not (match_operand:SI 1 "general_operand")))
+ (match_operand:DI 0 "register_operand"))))))
+ "atom-simple-0")
+
+;; 32<-16, 32<-8, 64<-16, 64<-8, 64<-32, 8<-8, mem
+(define_insn_reservation "atom_imovx_2_mem" 1
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "imovx")
+ (and (eq_attr "memory" "!none")
+ (ior (match_operand:QI 0 "register_operand")
+ (ior (and (match_operand:SI 0 "register_operand")
+ (not (match_operand:SI 1 "general_operand")))
+ (match_operand:DI 0 "register_operand"))))))
+ "atom-simple-0")
+
+;; 16<-8
+(define_insn_reservation "atom_imovx_3" 3
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "imovx")
+ (and (match_operand:HI 0 "register_operand")
+ (match_operand:QI 1 "general_operand"))))
+ "atom-complex, atom-all-eu*2")
+
+(define_insn_reservation "atom_lea" 1
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "lea")
+ (eq_attr "mode" "!HI")))
+ "atom-simple-either")
+
+;; lea 16bit address is complex insn
+(define_insn_reservation "atom_lea_2" 2
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "lea")
+ (eq_attr "mode" "HI")))
+ "atom-complex, atom-all-eu")
+
+(define_insn_reservation "atom_incdec" 1
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "incdec")
+ (eq_attr "memory" "none")))
+ "atom-simple-either")
+
+(define_insn_reservation "atom_incdec_mem" 1
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "incdec")
+ (eq_attr "memory" "!none")))
+ "atom-simple-either")
+
+;; simple shift instruction use SHIFT eu, none memory
+(define_insn_reservation "atom_ishift" 1
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "ishift")
+ (and (eq_attr "memory" "none") (eq_attr "prefix_0f" "0"))))
+ "atom-simple-0")
+
+;; simple shift instruction use SHIFT eu, memory
+(define_insn_reservation "atom_ishift_mem" 1
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "ishift")
+ (and (eq_attr "memory" "!none") (eq_attr "prefix_0f" "0"))))
+ "atom-simple-0")
+
+;; DF shift (prefixed with 0f) is complex insn with latency of 7 cycles
+(define_insn_reservation "atom_ishift_3" 7
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "ishift")
+ (eq_attr "prefix_0f" "1")))
+ "atom-complex, atom-all-eu*6")
+
+(define_insn_reservation "atom_ishift1" 1
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "ishift1")
+ (eq_attr "memory" "none")))
+ "atom-simple-0")
+
+(define_insn_reservation "atom_ishift1_mem" 1
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "ishift1")
+ (eq_attr "memory" "!none")))
+ "atom-simple-0")
+
+(define_insn_reservation "atom_rotate" 1
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "rotate")
+ (eq_attr "memory" "none")))
+ "atom-simple-0")
+
+(define_insn_reservation "atom_rotate_mem" 1
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "rotate")
+ (eq_attr "memory" "!none")))
+ "atom-simple-0")
+
+(define_insn_reservation "atom_rotate1" 1
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "rotate1")
+ (eq_attr "memory" "none")))
+ "atom-simple-0")
+
+(define_insn_reservation "atom_rotate1_mem" 1
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "rotate1")
+ (eq_attr "memory" "!none")))
+ "atom-simple-0")
+
+(define_insn_reservation "atom_imul" 5
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "imul")
+ (and (eq_attr "memory" "none") (eq_attr "mode" "SI"))))
+ "atom-imul-32")
+
+(define_insn_reservation "atom_imul_mem" 5
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "imul")
+ (and (eq_attr "memory" "!none") (eq_attr "mode" "SI"))))
+ "atom-imul-32")
+
+;; latency set to 10 as common 64x64 imul
+(define_insn_reservation "atom_imul_3" 10
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "imul")
+ (eq_attr "mode" "!SI")))
+ "atom-complex, atom-all-eu*9")
+
+(define_insn_reservation "atom_idiv" 65
+ (and (eq_attr "cpu" "atom")
+ (eq_attr "type" "idiv"))
+ "atom-complex, atom-all-eu*32, nothing*32")
+
+(define_insn_reservation "atom_icmp" 1
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "icmp")
+ (eq_attr "memory" "none")))
+ "atom-simple-either")
+
+(define_insn_reservation "atom_icmp_mem" 1
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "icmp")
+ (eq_attr "memory" "!none")))
+ "atom-simple-either")
+
+(define_insn_reservation "atom_test" 1
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "test")
+ (eq_attr "memory" "none")))
+ "atom-simple-either")
+
+(define_insn_reservation "atom_test_mem" 1
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "test")
+ (eq_attr "memory" "!none")))
+ "atom-simple-either")
+
+(define_insn_reservation "atom_ibr" 1
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "ibr")
+ (eq_attr "memory" "!load")))
+ "atom-simple-1")
+
+;; complex if jump target is from address
+(define_insn_reservation "atom_ibr_2" 2
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "ibr")
+ (eq_attr "memory" "load")))
+ "atom-complex, atom-all-eu")
+
+(define_insn_reservation "atom_setcc" 1
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "setcc")
+ (eq_attr "memory" "!store")))
+ "atom-simple-either")
+
+;; 2 cycles complex if target is in memory
+(define_insn_reservation "atom_setcc_2" 2
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "setcc")
+ (eq_attr "memory" "store")))
+ "atom-complex, atom-all-eu")
+
+(define_insn_reservation "atom_icmov" 1
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "icmov")
+ (eq_attr "memory" "none")))
+ "atom-simple-either")
+
+(define_insn_reservation "atom_icmov_mem" 1
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "icmov")
+ (eq_attr "memory" "!none")))
+ "atom-simple-either")
+
+;; UCODE if segreg, ignored
+(define_insn_reservation "atom_push" 2
+ (and (eq_attr "cpu" "atom")
+ (eq_attr "type" "push"))
+ "atom-dual-2c")
+
+;; pop r64 is 1 cycle. UCODE if segreg, ignored
+(define_insn_reservation "atom_pop" 1
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "pop")
+ (eq_attr "mode" "DI")))
+ "atom-dual-1c")
+
+;; pop non-r64 is 2 cycles. UCODE if segreg, ignored
+(define_insn_reservation "atom_pop_2" 2
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "pop")
+ (eq_attr "mode" "!DI")))
+ "atom-dual-2c")
+
+;; UCODE if segreg, ignored
+(define_insn_reservation "atom_call" 1
+ (and (eq_attr "cpu" "atom")
+ (eq_attr "type" "call"))
+ "atom-dual-1c")
+
+(define_insn_reservation "atom_callv" 1
+ (and (eq_attr "cpu" "atom")
+ (eq_attr "type" "callv"))
+ "atom-dual-1c")
+
+(define_insn_reservation "atom_leave" 3
+ (and (eq_attr "cpu" "atom")
+ (eq_attr "type" "leave"))
+ "atom-complex, atom-all-eu*2")
+
+(define_insn_reservation "atom_str" 3
+ (and (eq_attr "cpu" "atom")
+ (eq_attr "type" "str"))
+ "atom-complex, atom-all-eu*2")
+
+(define_insn_reservation "atom_sselog" 1
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "sselog")
+ (eq_attr "memory" "none")))
+ "atom-simple-either")
+
+(define_insn_reservation "atom_sselog_mem" 1
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "sselog")
+ (eq_attr "memory" "!none")))
+ "atom-simple-either")
+
+(define_insn_reservation "atom_sselog1" 1
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "sselog1")
+ (eq_attr "memory" "none")))
+ "atom-simple-0")
+
+(define_insn_reservation "atom_sselog1_mem" 1
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "sselog1")
+ (eq_attr "memory" "!none")))
+ "atom-simple-0")
+
+;; not pmad, not psad
+(define_insn_reservation "atom_sseiadd" 1
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "sseiadd")
+ (and (not (match_operand:V2DI 0 "register_operand"))
+ (and (eq_attr "atom_unit" "!simul")
+ (eq_attr "atom_unit" "!complex")))))
+ "atom-simple-either")
+
+;; pmad, psad and 64
+(define_insn_reservation "atom_sseiadd_2" 4
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "sseiadd")
+ (and (not (match_operand:V2DI 0 "register_operand"))
+ (and (eq_attr "atom_unit" "simul" )
+ (eq_attr "mode" "DI")))))
+ "atom-fmul-4c")
+
+;; pmad, psad and 128
+(define_insn_reservation "atom_sseiadd_3" 5
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "sseiadd")
+ (and (not (match_operand:V2DI 0 "register_operand"))
+ (and (eq_attr "atom_unit" "simul" )
+ (eq_attr "mode" "TI")))))
+ "atom-fmul-5c")
+
+;; if paddq(64 bit op), phadd/phsub
+(define_insn_reservation "atom_sseiadd_4" 6
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "sseiadd")
+ (ior (match_operand:V2DI 0 "register_operand")
+ (eq_attr "atom_unit" "complex"))))
+ "atom-complex, atom-all-eu*5")
+
+;; if immediate op.
+(define_insn_reservation "atom_sseishft" 1
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "sseishft")
+ (and (eq_attr "atom_unit" "!sishuf")
+ (match_operand 2 "immediate_operand"))))
+ "atom-simple-either")
+
+;; if palignr or psrldq
+(define_insn_reservation "atom_sseishft_2" 1
+ (and (eq_attr "cpu" "atom")
+ (ior (eq_attr "type" "sseishft1")
+ (and (eq_attr "type" "sseishft")
+ (and (eq_attr "atom_unit" "sishuf")
+ (match_operand 2 "immediate_operand")))))
+ "atom-simple-0")
+
+;; if reg/mem op
+(define_insn_reservation "atom_sseishft_3" 2
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "sseishft")
+ (not (match_operand 2 "immediate_operand"))))
+ "atom-complex, atom-all-eu")
+
+(define_insn_reservation "atom_sseimul" 1
+ (and (eq_attr "cpu" "atom")
+ (eq_attr "type" "sseimul"))
+ "atom-simple-0")
+
+;; rcpss or rsqrtss
+(define_insn_reservation "atom_sse" 4
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "sse")
+ (and (eq_attr "atom_sse_attr" "rcp") (eq_attr "mode" "SF"))))
+ "atom-fmul-4c")
+
+;; movshdup, movsldup. Suggest to type sseishft
+(define_insn_reservation "atom_sse_2" 1
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "sse")
+ (eq_attr "atom_sse_attr" "movdup")))
+ "atom-simple-0")
+
+;; lfence
+(define_insn_reservation "atom_sse_3" 1
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "sse")
+ (eq_attr "atom_sse_attr" "lfence")))
+ "atom-simple-either")
+
+;; sfence,clflush,mfence, prefetch
+(define_insn_reservation "atom_sse_4" 1
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "sse")
+ (ior (eq_attr "atom_sse_attr" "fence")
+ (eq_attr "atom_sse_attr" "prefetch"))))
+ "atom-simple-0")
+
+;; rcpps, rsqrtss, sqrt, ldmxcsr
+(define_insn_reservation "atom_sse_5" 7
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "sse")
+ (ior (ior (eq_attr "atom_sse_attr" "sqrt")
+ (eq_attr "atom_sse_attr" "mxcsr"))
+ (and (eq_attr "atom_sse_attr" "rcp")
+ (eq_attr "mode" "V4SF")))))
+ "atom-complex, atom-all-eu*6")
+
+;; xmm->xmm
+(define_insn_reservation "atom_ssemov" 1
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "ssemov")
+ (and (match_operand 0 "register_operand" "xy") (match_operand 1 "register_operand" "xy"))))
+ "atom-simple-either")
+
+;; reg->xmm
+(define_insn_reservation "atom_ssemov_2" 1
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "ssemov")
+ (and (match_operand 0 "register_operand" "xy") (match_operand 1 "register_operand" "r"))))
+ "atom-simple-0")
+
+;; xmm->reg
+(define_insn_reservation "atom_ssemov_3" 3
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "ssemov")
+ (and (match_operand 0 "register_operand" "r") (match_operand 1 "register_operand" "xy"))))
+ "atom-eu-0-3-1")
+
+;; mov mem
+(define_insn_reservation "atom_ssemov_4" 1
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "ssemov")
+ (and (eq_attr "movu" "0") (eq_attr "memory" "!none"))))
+ "atom-simple-0")
+
+;; movu mem
+(define_insn_reservation "atom_ssemov_5" 2
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "ssemov")
+ (ior (eq_attr "movu" "1") (eq_attr "memory" "!none"))))
+ "atom-complex, atom-all-eu")
+
+;; no memory simple
+(define_insn_reservation "atom_sseadd" 5
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "sseadd")
+ (and (eq_attr "memory" "none")
+ (and (eq_attr "mode" "!V2DF")
+ (eq_attr "atom_unit" "!complex")))))
+ "atom-fadd-5c")
+
+;; memory simple
+(define_insn_reservation "atom_sseadd_mem" 5
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "sseadd")
+ (and (eq_attr "memory" "!none")
+ (and (eq_attr "mode" "!V2DF")
+ (eq_attr "atom_unit" "!complex")))))
+ "atom-dual-5c")
+
+;; maxps, minps, *pd, hadd, hsub
+(define_insn_reservation "atom_sseadd_3" 8
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "sseadd")
+ (ior (eq_attr "mode" "V2DF") (eq_attr "atom_unit" "complex"))))
+ "atom-complex, atom-all-eu*7")
+
+;; Except dppd/dpps
+(define_insn_reservation "atom_ssemul" 5
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "ssemul")
+ (eq_attr "mode" "!SF")))
+ "atom-fmul-5c")
+
+;; Except dppd/dpps, 4 cycle if mulss
+(define_insn_reservation "atom_ssemul_2" 4
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "ssemul")
+ (eq_attr "mode" "SF")))
+ "atom-fmul-4c")
+
+(define_insn_reservation "atom_ssecmp" 1
+ (and (eq_attr "cpu" "atom")
+ (eq_attr "type" "ssecmp"))
+ "atom-simple-either")
+
+(define_insn_reservation "atom_ssecomi" 10
+ (and (eq_attr "cpu" "atom")
+ (eq_attr "type" "ssecomi"))
+ "atom-complex, atom-all-eu*9")
+
+;; no memory and cvtpi2ps, cvtps2pi, cvttps2pi
+(define_insn_reservation "atom_ssecvt" 5
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "ssecvt")
+ (ior (and (match_operand:V2SI 0 "register_operand")
+ (match_operand:V4SF 1 "register_operand"))
+ (and (match_operand:V4SF 0 "register_operand")
+ (match_operand:V2SI 1 "register_operand")))))
+ "atom-fadd-5c")
+
+;; memory and cvtpi2ps, cvtps2pi, cvttps2pi
+(define_insn_reservation "atom_ssecvt_2" 5
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "ssecvt")
+ (ior (and (match_operand:V2SI 0 "register_operand")
+ (match_operand:V4SF 1 "memory_operand"))
+ (and (match_operand:V4SF 0 "register_operand")
+ (match_operand:V2SI 1 "memory_operand")))))
+ "atom-dual-5c")
+
+;; otherwise. 7 cycles average for cvtss2sd
+(define_insn_reservation "atom_ssecvt_3" 7
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "ssecvt")
+ (not (ior (and (match_operand:V2SI 0 "register_operand")
+ (match_operand:V4SF 1 "nonimmediate_operand"))
+ (and (match_operand:V4SF 0 "register_operand")
+ (match_operand:V2SI 1 "nonimmediate_operand"))))))
+ "atom-complex, atom-all-eu*6")
+
+;; memory and cvtsi2sd
+(define_insn_reservation "atom_sseicvt" 5
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "sseicvt")
+ (and (match_operand:V2DF 0 "register_operand")
+ (match_operand:SI 1 "memory_operand"))))
+ "atom-dual-5c")
+
+;; otherwise. 8 cycles average for cvtsd2si
+(define_insn_reservation "atom_sseicvt_2" 8
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "sseicvt")
+ (not (and (match_operand:V2DF 0 "register_operand")
+ (match_operand:SI 1 "memory_operand")))))
+ "atom-complex, atom-all-eu*7")
+
+(define_insn_reservation "atom_ssediv" 62
+ (and (eq_attr "cpu" "atom")
+ (eq_attr "type" "ssediv"))
+ "atom-complex, atom-all-eu*12, nothing*49")
+
+;; simple for fmov
+(define_insn_reservation "atom_fmov" 1
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "fmov")
+ (eq_attr "memory" "none")))
+ "atom-simple-either")
+
+;; simple for fmov
+(define_insn_reservation "atom_fmov_mem" 1
+ (and (eq_attr "cpu" "atom")
+ (and (eq_attr "type" "fmov")
+ (eq_attr "memory" "!none")))
+ "atom-simple-either")
+
+;; Define bypass here
+
+;; There will be no stall from lea to non-mem EX insns
+(define_bypass 0 "atom_lea"
+ "atom_alu_carry,
+ atom_alu,atom_alu1,atom_negnot,atom_imov,atom_imovx,
+ atom_incdec, atom_setcc, atom_icmov, atom_pop")
+
+(define_bypass 0 "atom_lea"
+ "atom_alu_mem, atom_alu_carry_mem, atom_alu1_mem,
+ atom_imovx_mem, atom_imovx_2_mem,
+ atom_imov_mem, atom_icmov_mem, atom_fmov_mem"
+ "!ix86_agi_dependent")
+
+;; There will be 3 cycles stall from EX insns to AGAN insns LEA
+(define_bypass 4 "atom_alu_carry,
+ atom_alu,atom_alu1,atom_negnot,atom_imov,atom_imovx,
+ atom_incdec,atom_ishift,atom_ishift1,atom_rotate,
+ atom_rotate1, atom_setcc, atom_icmov, atom_pop,
+ atom_alu_mem, atom_alu_carry_mem, atom_alu1_mem,
+ atom_imovx_mem, atom_imovx_2_mem,
+ atom_imov_mem, atom_icmov_mem, atom_fmov_mem"
+ "atom_lea")
+
+;; There will be 3 cycles stall from EX insns to insns need addr calculation
+(define_bypass 4 "atom_alu_carry,
+ atom_alu,atom_alu1,atom_negnot,atom_imov,atom_imovx,
+ atom_incdec,atom_ishift,atom_ishift1,atom_rotate,
+ atom_rotate1, atom_setcc, atom_icmov, atom_pop,
+ atom_imovx_mem, atom_imovx_2_mem,
+ atom_alu_mem, atom_alu_carry_mem, atom_alu1_mem,
+ atom_imov_mem, atom_icmov_mem, atom_fmov_mem"
+ "atom_alu_mem, atom_alu_carry_mem, atom_alu1_mem,
+ atom_negnot_mem, atom_imov_mem, atom_incdec_mem,
+ atom_imovx_mem, atom_imovx_2_mem,
+ atom_imul_mem, atom_icmp_mem,
+ atom_test_mem, atom_icmov_mem, atom_sselog_mem,
+ atom_sselog1_mem, atom_fmov_mem, atom_sseadd_mem,
+ atom_ishift_mem, atom_ishift1_mem,
+ atom_rotate_mem, atom_rotate1_mem"
+ "ix86_agi_dependent")
+
+;; Stall from imul to lea is 8 cycles.
+(define_bypass 9 "atom_imul, atom_imul_mem" "atom_lea")
+
+;; Stall from imul to memory address is 8 cycles.
+(define_bypass 9 "atom_imul, atom_imul_mem"
+ "atom_alu_mem, atom_alu_carry_mem, atom_alu1_mem,
+ atom_negnot_mem, atom_imov_mem, atom_incdec_mem,
+ atom_ishift_mem, atom_ishift1_mem, atom_rotate_mem,
+ atom_rotate1_mem, atom_imul_mem, atom_icmp_mem,
+ atom_test_mem, atom_icmov_mem, atom_sselog_mem,
+ atom_sselog1_mem, atom_fmov_mem, atom_sseadd_mem"
+ "ix86_agi_dependent")
+
+;; There will be 0 cycle stall from cmp/test to jcc
+
+;; There will be 1 cycle stall from flag producer to cmov and adc/sbb
+(define_bypass 2 "atom_icmp, atom_test, atom_alu, atom_alu_carry,
+ atom_alu1, atom_negnot, atom_incdec, atom_ishift,
+ atom_ishift1, atom_rotate, atom_rotate1"
+ "atom_icmov, atom_alu_carry")
+
+;; lea to shift count stall is 2 cycles
+(define_bypass 3 "atom_lea"
+ "atom_ishift, atom_ishift1, atom_rotate, atom_rotate1,
+ atom_ishift_mem, atom_ishift1_mem,
+ atom_rotate_mem, atom_rotate1_mem"
+ "ix86_dep_by_shift_count")
+
+;; lea to shift source stall is 1 cycle
+(define_bypass 2 "atom_lea"
+ "atom_ishift, atom_ishift1, atom_rotate, atom_rotate1"
+ "!ix86_dep_by_shift_count")
+
+;; non-lea to shift count stall is 1 cycle
+(define_bypass 2 "atom_alu_carry,
+ atom_alu,atom_alu1,atom_negnot,atom_imov,atom_imovx,
+ atom_incdec,atom_ishift,atom_ishift1,atom_rotate,
+ atom_rotate1, atom_setcc, atom_icmov, atom_pop,
+ atom_alu_mem, atom_alu_carry_mem, atom_alu1_mem,
+ atom_imovx_mem, atom_imovx_2_mem,
+ atom_imov_mem, atom_icmov_mem, atom_fmov_mem"
+ "atom_ishift, atom_ishift1, atom_rotate, atom_rotate1,
+ atom_ishift_mem, atom_ishift1_mem,
+ atom_rotate_mem, atom_rotate1_mem"
+ "ix86_dep_by_shift_count")
diff --git a/gcc-4.4.3/gcc/config/i386/cpuid.h b/gcc-4.4.3/gcc/config/i386/cpuid.h
index b5258652e..003c202f0 100644
--- a/gcc-4.4.3/gcc/config/i386/cpuid.h
+++ b/gcc-4.4.3/gcc/config/i386/cpuid.h
@@ -29,6 +29,7 @@
#define bit_CMPXCHG16B (1 << 13)
#define bit_SSE4_1 (1 << 19)
#define bit_SSE4_2 (1 << 20)
+#define bit_MOVBE (1 << 22)
#define bit_POPCNT (1 << 23)
#define bit_AES (1 << 25)
#define bit_XSAVE (1 << 26)
@@ -46,6 +47,7 @@
/* Extended Features */
/* %ecx */
#define bit_LAHF_LM (1 << 0)
+#define bit_LWP (1 << 15)
#define bit_SSE4a (1 << 6)
#define bit_SSE5 (1 << 11)
diff --git a/gcc-4.4.3/gcc/config/i386/cygming.h b/gcc-4.4.3/gcc/config/i386/cygming.h
index 4f508a776..39650b107 100644
--- a/gcc-4.4.3/gcc/config/i386/cygming.h
+++ b/gcc-4.4.3/gcc/config/i386/cygming.h
@@ -34,7 +34,7 @@ along with GCC; see the file COPYING3. If not see
#endif
#undef TARGET_64BIT_MS_ABI
-#define TARGET_64BIT_MS_ABI (!cfun ? DEFAULT_ABI == MS_ABI : TARGET_64BIT && cfun->machine->call_abi == MS_ABI)
+#define TARGET_64BIT_MS_ABI (!cfun ? ix86_abi == MS_ABI : TARGET_64BIT && cfun->machine->call_abi == MS_ABI)
#undef DEFAULT_ABI
#define DEFAULT_ABI (TARGET_64BIT ? MS_ABI : SYSV_ABI)
@@ -202,7 +202,7 @@ do { \
#define CHECK_STACK_LIMIT 4000
#undef STACK_BOUNDARY
-#define STACK_BOUNDARY (DEFAULT_ABI == MS_ABI ? 128 : BITS_PER_WORD)
+#define STACK_BOUNDARY (ix86_abi == MS_ABI ? 128 : BITS_PER_WORD)
/* By default, target has a 80387, uses IEEE compatible arithmetic,
returns float values in the 387 and needs stack probes.
diff --git a/gcc-4.4.3/gcc/config/i386/driver-i386.c b/gcc-4.4.3/gcc/config/i386/driver-i386.c
index 9aa33d27c..c506b2bc3 100644
--- a/gcc-4.4.3/gcc/config/i386/driver-i386.c
+++ b/gcc-4.4.3/gcc/config/i386/driver-i386.c
@@ -378,6 +378,7 @@ const char *host_detect_local_cpu (int argc, const char **argv)
/* Extended features */
unsigned int has_lahf_lm = 0, has_sse4a = 0;
unsigned int has_longmode = 0, has_3dnowp = 0, has_3dnow = 0;
+ unsigned int has_movbe = 0;
unsigned int has_sse4_1 = 0, has_sse4_2 = 0;
unsigned int has_popcnt = 0, has_aes = 0, has_avx = 0;
unsigned int has_pclmul = 0;
@@ -398,9 +399,22 @@ const char *host_detect_local_cpu (int argc, const char **argv)
__cpuid (1, eax, ebx, ecx, edx);
- /* We don't care for extended family. */
model = (eax >> 4) & 0x0f;
family = (eax >> 8) & 0x0f;
+ if (vendor == SIG_INTEL)
+ {
+ unsigned int extended_model, extended_family;
+
+ extended_model = (eax >> 12) & 0xf0;
+ extended_family = (eax >> 20) & 0xff;
+ if (family == 0x0f)
+ {
+ family += extended_family;
+ model += extended_model;
+ }
+ else if (family == 0x06)
+ model += extended_model;
+ }
has_sse3 = ecx & bit_SSE3;
has_ssse3 = ecx & bit_SSSE3;
@@ -408,6 +422,7 @@ const char *host_detect_local_cpu (int argc, const char **argv)
has_sse4_2 = ecx & bit_SSE4_2;
has_avx = ecx & bit_AVX;
has_cmpxchg16b = ecx & bit_CMPXCHG16B;
+ has_movbe = ecx & bit_MOVBE;
has_popcnt = ecx & bit_POPCNT;
has_aes = ecx & bit_AES;
has_pclmul = ecx & bit_PCLMUL;
@@ -505,8 +520,8 @@ const char *host_detect_local_cpu (int argc, const char **argv)
break;
case PROCESSOR_PENTIUMPRO:
if (has_longmode)
- /* It is Core 2 Duo. */
- cpu = "core2";
+ /* It is Core 2 or Atom. */
+ cpu = (model == 28 || model == 38) ? "atom" : "core2";
else if (arch)
{
if (has_sse3)
@@ -597,6 +612,8 @@ const char *host_detect_local_cpu (int argc, const char **argv)
options = concat (options, "-mcx16 ", NULL);
if (has_lahf_lm)
options = concat (options, "-msahf ", NULL);
+ if (has_movbe)
+ options = concat (options, "-mmovbe", NULL);
if (has_aes)
options = concat (options, "-maes ", NULL);
if (has_pclmul)
diff --git a/gcc-4.4.3/gcc/config/i386/i386-c.c b/gcc-4.4.3/gcc/config/i386/i386-c.c
index 3d17c104e..1bb394542 100644
--- a/gcc-4.4.3/gcc/config/i386/i386-c.c
+++ b/gcc-4.4.3/gcc/config/i386/i386-c.c
@@ -119,6 +119,10 @@ ix86_target_macros_internal (int isa_flag,
def_or_undef (parse_in, "__core2");
def_or_undef (parse_in, "__core2__");
break;
+ case PROCESSOR_ATOM:
+ def_or_undef (parse_in, "__atom");
+ def_or_undef (parse_in, "__atom__");
+ break;
/* use PROCESSOR_max to not set/unset the arch macro. */
case PROCESSOR_max:
break;
@@ -187,6 +191,9 @@ ix86_target_macros_internal (int isa_flag,
case PROCESSOR_CORE2:
def_or_undef (parse_in, "__tune_core2__");
break;
+ case PROCESSOR_ATOM:
+ def_or_undef (parse_in, "__tune_atom__");
+ break;
case PROCESSOR_GENERIC32:
case PROCESSOR_GENERIC64:
break;
@@ -225,6 +232,8 @@ ix86_target_macros_internal (int isa_flag,
def_or_undef (parse_in, "__SSE4A__");
if (isa_flag & OPTION_MASK_ISA_SSE5)
def_or_undef (parse_in, "__SSE5__");
+ if (isa_flag & OPTION_MASK_ISA_LWP)
+ def_or_undef (parse_in, "__LWP__");
if ((fpmath & FPMATH_SSE) && (isa_flag & OPTION_MASK_ISA_SSE))
def_or_undef (parse_in, "__SSE_MATH__");
if ((fpmath & FPMATH_SSE) && (isa_flag & OPTION_MASK_ISA_SSE2))
diff --git a/gcc-4.4.3/gcc/config/i386/i386-protos.h b/gcc-4.4.3/gcc/config/i386/i386-protos.h
index 4b0e2c01c..96e01ea49 100644
--- a/gcc-4.4.3/gcc/config/i386/i386-protos.h
+++ b/gcc-4.4.3/gcc/config/i386/i386-protos.h
@@ -86,6 +86,9 @@ extern void ix86_fixup_binary_operands_no_copy (enum rtx_code,
extern void ix86_expand_binary_operator (enum rtx_code,
enum machine_mode, rtx[]);
extern int ix86_binary_operator_ok (enum rtx_code, enum machine_mode, rtx[]);
+extern bool ix86_lea_for_add_ok (enum rtx_code, rtx, rtx[]);
+extern bool ix86_dep_by_shift_count (const_rtx set_insn, const_rtx use_insn);
+extern bool ix86_agi_dependent (rtx set_insn, rtx use_insn);
extern void ix86_expand_unary_operator (enum rtx_code, enum machine_mode,
rtx[]);
extern rtx ix86_build_const_vector (enum machine_mode, bool, rtx);
@@ -140,9 +143,8 @@ extern int ix86_function_arg_boundary (enum machine_mode, tree);
extern bool ix86_sol10_return_in_memory (const_tree,const_tree);
extern rtx ix86_force_to_memory (enum machine_mode, rtx);
extern void ix86_free_from_memory (enum machine_mode);
-extern int ix86_cfun_abi (void);
-extern int ix86_function_abi (const_tree);
-extern int ix86_function_type_abi (const_tree);
+extern enum calling_abi ix86_cfun_abi (void);
+extern enum calling_abi ix86_function_type_abi (const_tree);
extern void ix86_call_abi_override (const_tree);
extern tree ix86_fn_abi_va_list (tree);
extern tree ix86_canonical_va_list_type (tree);
diff --git a/gcc-4.4.3/gcc/config/i386/i386.c b/gcc-4.4.3/gcc/config/i386/i386.c
index 350b214ed..fa148be65 100644
--- a/gcc-4.4.3/gcc/config/i386/i386.c
+++ b/gcc-4.4.3/gcc/config/i386/i386.c
@@ -1036,6 +1036,79 @@ struct processor_costs core2_cost = {
1, /* cond_not_taken_branch_cost. */
};
+static const
+struct processor_costs atom_cost = {
+ COSTS_N_INSNS (1), /* cost of an add instruction */
+ COSTS_N_INSNS (1) + 1, /* cost of a lea instruction */
+ COSTS_N_INSNS (1), /* variable shift costs */
+ COSTS_N_INSNS (1), /* constant shift costs */
+ {COSTS_N_INSNS (3), /* cost of starting multiply for QI */
+ COSTS_N_INSNS (4), /* HI */
+ COSTS_N_INSNS (3), /* SI */
+ COSTS_N_INSNS (4), /* DI */
+ COSTS_N_INSNS (2)}, /* other */
+ 0, /* cost of multiply per each bit set */
+ {COSTS_N_INSNS (18), /* cost of a divide/mod for QI */
+ COSTS_N_INSNS (26), /* HI */
+ COSTS_N_INSNS (42), /* SI */
+ COSTS_N_INSNS (74), /* DI */
+ COSTS_N_INSNS (74)}, /* other */
+ COSTS_N_INSNS (1), /* cost of movsx */
+ COSTS_N_INSNS (1), /* cost of movzx */
+ 8, /* "large" insn */
+ 17, /* MOVE_RATIO */
+ 2, /* cost for loading QImode using movzbl */
+ {4, 4, 4}, /* cost of loading integer registers
+ in QImode, HImode and SImode.
+ Relative to reg-reg move (2). */
+ {4, 4, 4}, /* cost of storing integer registers */
+ 4, /* cost of reg,reg fld/fst */
+ {12, 12, 12}, /* cost of loading fp registers
+ in SFmode, DFmode and XFmode */
+ {6, 6, 8}, /* cost of storing fp registers
+ in SFmode, DFmode and XFmode */
+ 2, /* cost of moving MMX register */
+ {8, 8}, /* cost of loading MMX registers
+ in SImode and DImode */
+ {8, 8}, /* cost of storing MMX registers
+ in SImode and DImode */
+ 2, /* cost of moving SSE register */
+ {8, 8, 8}, /* cost of loading SSE registers
+ in SImode, DImode and TImode */
+ {8, 8, 8}, /* cost of storing SSE registers
+ in SImode, DImode and TImode */
+ 5, /* MMX or SSE register to integer */
+ 32, /* size of l1 cache. */
+ 256, /* size of l2 cache. */
+ 64, /* size of prefetch block */
+ 6, /* number of parallel prefetches */
+ 3, /* Branch cost */
+ COSTS_N_INSNS (8), /* cost of FADD and FSUB insns. */
+ COSTS_N_INSNS (8), /* cost of FMUL instruction. */
+ COSTS_N_INSNS (20), /* cost of FDIV instruction. */
+ COSTS_N_INSNS (8), /* cost of FABS instruction. */
+ COSTS_N_INSNS (8), /* cost of FCHS instruction. */
+ COSTS_N_INSNS (40), /* cost of FSQRT instruction. */
+ {{libcall, {{11, loop}, {-1, rep_prefix_4_byte}}},
+ {libcall, {{32, loop}, {64, rep_prefix_4_byte},
+ {8192, rep_prefix_8_byte}, {-1, libcall}}}},
+ {{libcall, {{8, loop}, {15, unrolled_loop},
+ {2048, rep_prefix_4_byte}, {-1, libcall}}},
+ {libcall, {{24, loop}, {32, unrolled_loop},
+ {8192, rep_prefix_8_byte}, {-1, libcall}}}},
+ 1, /* scalar_stmt_cost. */
+ 1, /* scalar load_cost. */
+ 1, /* scalar_store_cost. */
+ 1, /* vec_stmt_cost. */
+ 1, /* vec_to_scalar_cost. */
+ 1, /* scalar_to_vec_cost. */
+ 1, /* vec_align_load_cost. */
+ 2, /* vec_unalign_load_cost. */
+ 1, /* vec_store_cost. */
+ 3, /* cond_taken_branch_cost. */
+ 1, /* cond_not_taken_branch_cost. */
+};
+
/* Generic64 should produce code tuned for Nocona and K8. */
static const
struct processor_costs generic64_cost = {
@@ -1194,6 +1267,7 @@ const struct processor_costs *ix86_cost = &pentium_cost;
#define m_PENT4 (1<<PROCESSOR_PENTIUM4)
#define m_NOCONA (1<<PROCESSOR_NOCONA)
#define m_CORE2 (1<<PROCESSOR_CORE2)
+#define m_ATOM (1<<PROCESSOR_ATOM)
#define m_GEODE (1<<PROCESSOR_GEODE)
#define m_K6 (1<<PROCESSOR_K6)
@@ -1231,10 +1305,11 @@ static unsigned int initial_ix86_tune_features[X86_TUNE_LAST] = {
m_486 | m_PENT,
/* X86_TUNE_UNROLL_STRLEN */
- m_486 | m_PENT | m_PPRO | m_AMD_MULTIPLE | m_K6 | m_CORE2 | m_GENERIC,
+ m_486 | m_PENT | m_ATOM | m_PPRO | m_AMD_MULTIPLE | m_K6
+ | m_CORE2 | m_GENERIC,
/* X86_TUNE_DEEP_BRANCH_PREDICTION */
- m_PPRO | m_K6_GEODE | m_AMD_MULTIPLE | m_PENT4 | m_GENERIC,
+ m_ATOM | m_PPRO | m_K6_GEODE | m_AMD_MULTIPLE | m_PENT4 | m_GENERIC,
/* X86_TUNE_BRANCH_PREDICTION_HINTS: Branch hints were put in P4 based
on simulation result. But after P4 was made, no performance benefit
@@ -1246,12 +1321,12 @@ static unsigned int initial_ix86_tune_features[X86_TUNE_LAST] = {
~m_386,
/* X86_TUNE_USE_SAHF */
- m_PPRO | m_K6_GEODE | m_K8 | m_AMDFAM10 | m_PENT4
+ m_ATOM | m_PPRO | m_K6_GEODE | m_K8 | m_AMDFAM10 | m_PENT4
| m_NOCONA | m_CORE2 | m_GENERIC,
/* X86_TUNE_MOVX: Enable to zero extend integer registers to avoid
partial dependencies. */
- m_AMD_MULTIPLE | m_PPRO | m_PENT4 | m_NOCONA
+ m_AMD_MULTIPLE | m_ATOM | m_PPRO | m_PENT4 | m_NOCONA
| m_CORE2 | m_GENERIC | m_GEODE /* m_386 | m_K6 */,
/* X86_TUNE_PARTIAL_REG_STALL: We probably ought to watch for partial
@@ -1271,13 +1346,13 @@ static unsigned int initial_ix86_tune_features[X86_TUNE_LAST] = {
m_386 | m_486 | m_K6_GEODE,
/* X86_TUNE_USE_SIMODE_FIOP */
- ~(m_PPRO | m_AMD_MULTIPLE | m_PENT | m_CORE2 | m_GENERIC),
+ ~(m_PPRO | m_AMD_MULTIPLE | m_PENT | m_ATOM | m_CORE2 | m_GENERIC),
/* X86_TUNE_USE_MOV0 */
m_K6,
/* X86_TUNE_USE_CLTD */
- ~(m_PENT | m_K6 | m_CORE2 | m_GENERIC),
+ ~(m_PENT | m_ATOM | m_K6 | m_CORE2 | m_GENERIC),
/* X86_TUNE_USE_XCHGB: Use xchgb %rh,%rl instead of rolw/rorw $8,rx. */
m_PENT4,
@@ -1292,8 +1367,8 @@ static unsigned int initial_ix86_tune_features[X86_TUNE_LAST] = {
~(m_PENT | m_PPRO),
/* X86_TUNE_PROMOTE_QIMODE */
- m_K6_GEODE | m_PENT | m_386 | m_486 | m_AMD_MULTIPLE | m_CORE2
- | m_GENERIC /* | m_PENT4 ? */,
+ m_K6_GEODE | m_PENT | m_ATOM | m_386 | m_486 | m_AMD_MULTIPLE
+ | m_CORE2 | m_GENERIC /* | m_PENT4 ? */,
/* X86_TUNE_FAST_PREFIX */
~(m_PENT | m_486 | m_386),
@@ -1317,26 +1392,28 @@ static unsigned int initial_ix86_tune_features[X86_TUNE_LAST] = {
m_PPRO,
/* X86_TUNE_ADD_ESP_4: Enable if add/sub is preferred over 1/2 push/pop. */
- m_AMD_MULTIPLE | m_K6_GEODE | m_PENT4 | m_NOCONA | m_CORE2 | m_GENERIC,
+ m_ATOM | m_AMD_MULTIPLE | m_K6_GEODE | m_PENT4 | m_NOCONA
+ | m_CORE2 | m_GENERIC,
/* X86_TUNE_ADD_ESP_8 */
- m_AMD_MULTIPLE | m_PPRO | m_K6_GEODE | m_386
+ m_AMD_MULTIPLE | m_ATOM | m_PPRO | m_K6_GEODE | m_386
| m_486 | m_PENT4 | m_NOCONA | m_CORE2 | m_GENERIC,
/* X86_TUNE_SUB_ESP_4 */
- m_AMD_MULTIPLE | m_PPRO | m_PENT4 | m_NOCONA | m_CORE2 | m_GENERIC,
+ m_AMD_MULTIPLE | m_ATOM | m_PPRO | m_PENT4 | m_NOCONA | m_CORE2
+ | m_GENERIC,
/* X86_TUNE_SUB_ESP_8 */
- m_AMD_MULTIPLE | m_PPRO | m_386 | m_486
+ m_AMD_MULTIPLE | m_ATOM | m_PPRO | m_386 | m_486
| m_PENT4 | m_NOCONA | m_CORE2 | m_GENERIC,
/* X86_TUNE_INTEGER_DFMODE_MOVES: Enable if integer moves are preferred
for DFmode copies */
- ~(m_AMD_MULTIPLE | m_PENT4 | m_NOCONA | m_PPRO | m_CORE2
+ ~(m_AMD_MULTIPLE | m_ATOM | m_PENT4 | m_NOCONA | m_PPRO | m_CORE2
| m_GENERIC | m_GEODE),
/* X86_TUNE_PARTIAL_REG_DEPENDENCY */
- m_AMD_MULTIPLE | m_PENT4 | m_NOCONA | m_CORE2 | m_GENERIC,
+ m_AMD_MULTIPLE | m_ATOM | m_PENT4 | m_NOCONA | m_CORE2 | m_GENERIC,
/* X86_TUNE_SSE_PARTIAL_REG_DEPENDENCY: In the Generic model we have a
conflict here in between PPro/Pentium4 based chips that thread 128bit
@@ -1347,7 +1424,8 @@ static unsigned int initial_ix86_tune_features[X86_TUNE_LAST] = {
shows that disabling this option on P4 brings over 20% SPECfp regression,
while enabling it on K8 brings roughly 2.4% regression that can be partly
masked by careful scheduling of moves. */
- m_PENT4 | m_NOCONA | m_PPRO | m_CORE2 | m_GENERIC | m_AMDFAM10,
+ m_ATOM | m_PENT4 | m_NOCONA | m_PPRO | m_CORE2 | m_GENERIC
+ | m_AMDFAM10,
/* X86_TUNE_SSE_UNALIGNED_MOVE_OPTIMAL */
m_AMDFAM10,
@@ -1365,13 +1443,13 @@ static unsigned int initial_ix86_tune_features[X86_TUNE_LAST] = {
m_PPRO | m_PENT4 | m_NOCONA,
/* X86_TUNE_MEMORY_MISMATCH_STALL */
- m_AMD_MULTIPLE | m_PENT4 | m_NOCONA | m_CORE2 | m_GENERIC,
+ m_AMD_MULTIPLE | m_ATOM | m_PENT4 | m_NOCONA | m_CORE2 | m_GENERIC,
/* X86_TUNE_PROLOGUE_USING_MOVE */
- m_ATHLON_K8 | m_PPRO | m_CORE2 | m_GENERIC,
+ m_ATHLON_K8 | m_ATOM | m_PPRO | m_CORE2 | m_GENERIC,
/* X86_TUNE_EPILOGUE_USING_MOVE */
- m_ATHLON_K8 | m_PPRO | m_CORE2 | m_GENERIC,
+ m_ATHLON_K8 | m_ATOM | m_PPRO | m_CORE2 | m_GENERIC,
/* X86_TUNE_SHIFT1 */
~m_486,
@@ -1387,22 +1465,25 @@ static unsigned int initial_ix86_tune_features[X86_TUNE_LAST] = {
/* X86_TUNE_FOUR_JUMP_LIMIT: Some CPU cores are not able to predict more
than 4 branch instructions in the 16 byte window. */
- m_PPRO | m_AMD_MULTIPLE | m_PENT4 | m_NOCONA | m_CORE2 | m_GENERIC,
+ m_ATOM | m_PPRO | m_AMD_MULTIPLE | m_PENT4 | m_NOCONA | m_CORE2
+ | m_GENERIC,
/* X86_TUNE_SCHEDULE */
- m_PPRO | m_AMD_MULTIPLE | m_K6_GEODE | m_PENT | m_CORE2 | m_GENERIC,
+ m_PPRO | m_AMD_MULTIPLE | m_K6_GEODE | m_PENT | m_ATOM | m_CORE2
+ | m_GENERIC,
/* X86_TUNE_USE_BT */
- m_AMD_MULTIPLE | m_CORE2 | m_GENERIC,
+ m_AMD_MULTIPLE | m_ATOM | m_CORE2 | m_GENERIC,
/* X86_TUNE_USE_INCDEC */
- ~(m_PENT4 | m_NOCONA | m_GENERIC),
+ ~(m_PENT4 | m_NOCONA | m_GENERIC | m_ATOM),
/* X86_TUNE_PAD_RETURNS */
m_AMD_MULTIPLE | m_CORE2 | m_GENERIC,
/* X86_TUNE_EXT_80387_CONSTANTS */
- m_K6_GEODE | m_ATHLON_K8 | m_PENT4 | m_NOCONA | m_PPRO | m_CORE2 | m_GENERIC,
+ m_K6_GEODE | m_ATHLON_K8 | m_ATOM | m_PENT4 | m_NOCONA | m_PPRO
+ | m_CORE2 | m_GENERIC,
/* X86_TUNE_SHORTEN_X87_SSE */
~m_K8,
@@ -1447,6 +1528,10 @@ static unsigned int initial_ix86_tune_features[X86_TUNE_LAST] = {
with a subsequent conditional jump instruction into a single
compare-and-branch uop. */
m_CORE2,
+
+ /* X86_TUNE_OPT_AGU: Optimize for Address Generation Unit. This flag
+ will impact LEA instruction selection. */
+ m_ATOM,
};
/* Feature tests against the various architecture variations. */
@@ -1472,10 +1557,11 @@ static unsigned int initial_ix86_arch_features[X86_ARCH_LAST] = {
};
static const unsigned int x86_accumulate_outgoing_args
- = m_AMD_MULTIPLE | m_PENT4 | m_NOCONA | m_PPRO | m_CORE2 | m_GENERIC;
+ = m_AMD_MULTIPLE | m_ATOM | m_PENT4 | m_NOCONA | m_PPRO | m_CORE2
+ | m_GENERIC;
static const unsigned int x86_arch_always_fancy_math_387
- = m_PENT | m_PPRO | m_AMD_MULTIPLE | m_PENT4
+ = m_PENT | m_ATOM | m_PPRO | m_AMD_MULTIPLE | m_PENT4
| m_NOCONA | m_CORE2 | m_GENERIC;
static enum stringop_alg stringop_alg = no_stringop;
@@ -1743,6 +1829,9 @@ static unsigned int ix86_default_incoming_stack_boundary;
/* Alignment for incoming stack boundary in bits. */
unsigned int ix86_incoming_stack_boundary;
+/* The abi used by target. */
+enum calling_abi ix86_abi;
+
/* Values 1-5: see jump.c */
int ix86_branch_cost;
@@ -1818,6 +1907,9 @@ static bool ix86_valid_target_attribute_p (tree, tree, tree, int);
static bool ix86_valid_target_attribute_inner_p (tree, char *[]);
static bool ix86_can_inline_p (tree, tree);
static void ix86_set_current_function (tree);
+static unsigned int ix86_minimum_incoming_stack_boundary (bool);
+
+static enum calling_abi ix86_function_abi (const_tree);
/* The svr4 ABI for the i386 says that records and unions are returned
@@ -1868,6 +1960,8 @@ static int ix86_isa_flags_explicit;
(OPTION_MASK_ISA_SSE4A | OPTION_MASK_ISA_SSE3_SET)
#define OPTION_MASK_ISA_SSE5_SET \
(OPTION_MASK_ISA_SSE5 | OPTION_MASK_ISA_SSE4A_SET)
+#define OPTION_MASK_ISA_LWP_SET \
+ OPTION_MASK_ISA_LWP
/* AES and PCLMUL need SSE2 because they use xmm registers */
#define OPTION_MASK_ISA_AES_SET \
@@ -1877,9 +1971,11 @@ static int ix86_isa_flags_explicit;
#define OPTION_MASK_ISA_ABM_SET \
(OPTION_MASK_ISA_ABM | OPTION_MASK_ISA_POPCNT)
+
#define OPTION_MASK_ISA_POPCNT_SET OPTION_MASK_ISA_POPCNT
#define OPTION_MASK_ISA_CX16_SET OPTION_MASK_ISA_CX16
#define OPTION_MASK_ISA_SAHF_SET OPTION_MASK_ISA_SAHF
+#define OPTION_MASK_ISA_MOVBE_SET OPTION_MASK_ISA_MOVBE
/* Define a set of ISAs which aren't available when a given ISA is
disabled. MMX and SSE ISAs are handled separately. */
@@ -1915,12 +2011,14 @@ static int ix86_isa_flags_explicit;
#define OPTION_MASK_ISA_SSE4A_UNSET \
(OPTION_MASK_ISA_SSE4A | OPTION_MASK_ISA_SSE5_UNSET)
#define OPTION_MASK_ISA_SSE5_UNSET OPTION_MASK_ISA_SSE5
+#define OPTION_MASK_ISA_LWP_UNSET OPTION_MASK_ISA_LWP
#define OPTION_MASK_ISA_AES_UNSET OPTION_MASK_ISA_AES
#define OPTION_MASK_ISA_PCLMUL_UNSET OPTION_MASK_ISA_PCLMUL
#define OPTION_MASK_ISA_ABM_UNSET OPTION_MASK_ISA_ABM
#define OPTION_MASK_ISA_POPCNT_UNSET OPTION_MASK_ISA_POPCNT
#define OPTION_MASK_ISA_CX16_UNSET OPTION_MASK_ISA_CX16
#define OPTION_MASK_ISA_SAHF_UNSET OPTION_MASK_ISA_SAHF
+#define OPTION_MASK_ISA_MOVBE_UNSET OPTION_MASK_ISA_MOVBE
/* Vectorization library interface and handlers. */
tree (*ix86_veclib_handler)(enum built_in_function, tree, tree) = NULL;
@@ -1953,7 +2051,8 @@ static const struct ptt processor_target_table[PROCESSOR_max] =
{&core2_cost, 16, 10, 16, 10, 16},
{&generic32_cost, 16, 7, 16, 7, 16},
{&generic64_cost, 16, 10, 16, 10, 16},
- {&amdfam10_cost, 32, 24, 32, 7, 32}
+ {&amdfam10_cost, 32, 24, 32, 7, 32},
+ {&atom_cost, 16, 7, 16, 7, 16}
};
static const char *const cpu_names[TARGET_CPU_DEFAULT_max] =
@@ -1971,6 +2070,7 @@ static const char *const cpu_names[TARGET_CPU_DEFAULT_max] =
"prescott",
"nocona",
"core2",
+ "atom",
"geode",
"k6",
"k6-2",
@@ -2157,6 +2257,19 @@ ix86_handle_option (size_t code, const char *arg ATTRIBUTE_UNUSED, int value)
}
return true;
+ case OPT_mlwp:
+ if (value)
+ {
+ ix86_isa_flags |= OPTION_MASK_ISA_LWP_SET;
+ ix86_isa_flags_explicit |= OPTION_MASK_ISA_LWP_SET;
+ }
+ else
+ {
+ ix86_isa_flags &= ~OPTION_MASK_ISA_LWP_UNSET;
+ ix86_isa_flags_explicit |= OPTION_MASK_ISA_LWP_UNSET;
+ }
+ return true;
+
case OPT_mabm:
if (value)
{
@@ -2209,6 +2322,19 @@ ix86_handle_option (size_t code, const char *arg ATTRIBUTE_UNUSED, int value)
}
return true;
+ case OPT_mmovbe:
+ if (value)
+ {
+ ix86_isa_flags |= OPTION_MASK_ISA_MOVBE_SET;
+ ix86_isa_flags_explicit |= OPTION_MASK_ISA_MOVBE_SET;
+ }
+ else
+ {
+ ix86_isa_flags &= ~OPTION_MASK_ISA_MOVBE_UNSET;
+ ix86_isa_flags_explicit |= OPTION_MASK_ISA_MOVBE_UNSET;
+ }
+ return true;
+
case OPT_maes:
if (value)
{
@@ -2259,6 +2385,7 @@ ix86_target_string (int isa, int flags, const char *arch, const char *tune,
{
{ "-m64", OPTION_MASK_ISA_64BIT },
{ "-msse5", OPTION_MASK_ISA_SSE5 },
+ { "-mlwp", OPTION_MASK_ISA_LWP },
{ "-msse4a", OPTION_MASK_ISA_SSE4A },
{ "-msse4.2", OPTION_MASK_ISA_SSE4_2 },
{ "-msse4.1", OPTION_MASK_ISA_SSE4_1 },
@@ -2271,6 +2398,7 @@ ix86_target_string (int isa, int flags, const char *arch, const char *tune,
{ "-mmmx", OPTION_MASK_ISA_MMX },
{ "-mabm", OPTION_MASK_ISA_ABM },
{ "-mpopcnt", OPTION_MASK_ISA_POPCNT },
+ { "-mmovbe", OPTION_MASK_ISA_MOVBE },
{ "-maes", OPTION_MASK_ISA_AES },
{ "-mpclmul", OPTION_MASK_ISA_PCLMUL },
};
@@ -2488,7 +2616,9 @@ override_options (bool main_args_p)
PTA_AES = 1 << 17,
PTA_PCLMUL = 1 << 18,
PTA_AVX = 1 << 19,
- PTA_FMA = 1 << 20
+ PTA_FMA = 1 << 20,
+ PTA_LWP = 1 << 21,
+ PTA_MOVBE = 1 << 22
};
static struct pta
@@ -2530,6 +2660,9 @@ override_options (bool main_args_p)
{"core2", PROCESSOR_CORE2, CPU_CORE2,
PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3
| PTA_SSSE3 | PTA_CX16},
+ {"atom", PROCESSOR_ATOM, CPU_ATOM,
+ PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3
+ | PTA_SSSE3 | PTA_CX16 | PTA_MOVBE},
{"geode", PROCESSOR_GEODE, CPU_GEODE,
PTA_MMX | PTA_3DNOW | PTA_3DNOW_A |PTA_PREFETCH_SSE},
{"k6", PROCESSOR_K6, CPU_K6, PTA_MMX},
@@ -2717,6 +2850,20 @@ override_options (bool main_args_p)
error ("bad value (%s) for %sarch=%s %s",
ix86_arch_string, prefix, suffix, sw);
+ /* Validate -mabi= value. */
+ if (ix86_abi_string)
+ {
+ if (strcmp (ix86_abi_string, "sysv") == 0)
+ ix86_abi = SYSV_ABI;
+ else if (strcmp (ix86_abi_string, "ms") == 0)
+ ix86_abi = MS_ABI;
+ else
+ error ("unknown ABI (%s) for %sabi=%s %s",
+ ix86_abi_string, prefix, suffix, sw);
+ }
+ else
+ ix86_abi = DEFAULT_ABI;
+
if (ix86_cmodel_string != 0)
{
if (!strcmp (ix86_cmodel_string, "small"))
@@ -2817,6 +2964,9 @@ override_options (bool main_args_p)
if (processor_alias_table[i].flags & PTA_SSE5
&& !(ix86_isa_flags_explicit & OPTION_MASK_ISA_SSE5))
ix86_isa_flags |= OPTION_MASK_ISA_SSE5;
+ if (processor_alias_table[i].flags & PTA_LWP
+ && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_LWP))
+ ix86_isa_flags |= OPTION_MASK_ISA_LWP;
if (processor_alias_table[i].flags & PTA_ABM
&& !(ix86_isa_flags_explicit & OPTION_MASK_ISA_ABM))
ix86_isa_flags |= OPTION_MASK_ISA_ABM;
@@ -2829,6 +2979,9 @@ override_options (bool main_args_p)
if (!(TARGET_64BIT && (processor_alias_table[i].flags & PTA_NO_SAHF))
&& !(ix86_isa_flags_explicit & OPTION_MASK_ISA_SAHF))
ix86_isa_flags |= OPTION_MASK_ISA_SAHF;
+ if (processor_alias_table[i].flags & PTA_MOVBE
+ && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_MOVBE))
+ ix86_isa_flags |= OPTION_MASK_ISA_MOVBE;
if (processor_alias_table[i].flags & PTA_AES
&& !(ix86_isa_flags_explicit & OPTION_MASK_ISA_AES))
ix86_isa_flags |= OPTION_MASK_ISA_AES;
@@ -3092,12 +3245,10 @@ override_options (bool main_args_p)
if (ix86_force_align_arg_pointer == -1)
ix86_force_align_arg_pointer = STACK_REALIGN_DEFAULT;
+ ix86_default_incoming_stack_boundary = PREFERRED_STACK_BOUNDARY;
+
/* Validate -mincoming-stack-boundary= value or default it to
MIN_STACK_BOUNDARY/PREFERRED_STACK_BOUNDARY. */
- if (ix86_force_align_arg_pointer)
- ix86_default_incoming_stack_boundary = MIN_STACK_BOUNDARY;
- else
- ix86_default_incoming_stack_boundary = PREFERRED_STACK_BOUNDARY;
ix86_incoming_stack_boundary = ix86_default_incoming_stack_boundary;
if (ix86_incoming_stack_boundary_string)
{
@@ -3503,6 +3654,7 @@ ix86_valid_target_attribute_inner_p (tree args, char *p_strings[])
IX86_ATTR_ISA ("sse4a", OPT_msse4a),
IX86_ATTR_ISA ("sse5", OPT_msse5),
IX86_ATTR_ISA ("ssse3", OPT_mssse3),
+ IX86_ATTR_ISA ("lwp", OPT_mlwp),
/* string options */
IX86_ATTR_STR ("arch=", IX86_FUNCTION_SPECIFIC_ARCH),
@@ -4147,7 +4299,8 @@ ix86_function_ok_for_sibcall (tree decl, tree exp)
/* If we need to align the outgoing stack, then sibcalling would
unalign the stack, which may break the called function. */
- if (ix86_incoming_stack_boundary < PREFERRED_STACK_BOUNDARY)
+ if (ix86_minimum_incoming_stack_boundary (true)
+ < PREFERRED_STACK_BOUNDARY)
return false;
if (decl)
@@ -4608,14 +4761,14 @@ ix86_function_arg_regno_p (int regno)
default ABI. */
/* RAX is used as hidden argument to va_arg functions. */
- if (DEFAULT_ABI == SYSV_ABI && regno == AX_REG)
+ if (ix86_abi == SYSV_ABI && regno == AX_REG)
return true;
- if (DEFAULT_ABI == MS_ABI)
+ if (ix86_abi == MS_ABI)
parm_regs = x86_64_ms_abi_int_parameter_registers;
else
parm_regs = x86_64_int_parameter_registers;
- for (i = 0; i < (DEFAULT_ABI == MS_ABI ? X64_REGPARM_MAX
+ for (i = 0; i < (ix86_abi == MS_ABI ? X64_REGPARM_MAX
: X86_64_REGPARM_MAX); i++)
if (regno == parm_regs[i])
return true;
@@ -4643,7 +4796,7 @@ ix86_must_pass_in_stack (enum machine_mode mode, const_tree type)
int
ix86_reg_parm_stack_space (const_tree fndecl)
{
- int call_abi = SYSV_ABI;
+ enum calling_abi call_abi = SYSV_ABI;
if (fndecl != NULL_TREE && TREE_CODE (fndecl) == FUNCTION_DECL)
call_abi = ix86_function_abi (fndecl);
else
@@ -4655,37 +4808,39 @@ ix86_reg_parm_stack_space (const_tree fndecl)
/* Returns value SYSV_ABI, MS_ABI dependent on fntype, specifying the
call abi used. */
-int
+enum calling_abi
ix86_function_type_abi (const_tree fntype)
{
if (TARGET_64BIT && fntype != NULL)
{
- int abi;
- if (DEFAULT_ABI == SYSV_ABI)
- abi = lookup_attribute ("ms_abi", TYPE_ATTRIBUTES (fntype)) ? MS_ABI : SYSV_ABI;
- else
- abi = lookup_attribute ("sysv_abi", TYPE_ATTRIBUTES (fntype)) ? SYSV_ABI : MS_ABI;
-
+ enum calling_abi abi = ix86_abi;
+ if (abi == SYSV_ABI)
+ {
+ if (lookup_attribute ("ms_abi", TYPE_ATTRIBUTES (fntype)))
+ abi = MS_ABI;
+ }
+ else if (lookup_attribute ("sysv_abi", TYPE_ATTRIBUTES (fntype)))
+ abi = SYSV_ABI;
return abi;
}
- return DEFAULT_ABI;
+ return ix86_abi;
}
-int
+static enum calling_abi
ix86_function_abi (const_tree fndecl)
{
if (! fndecl)
- return DEFAULT_ABI;
+ return ix86_abi;
return ix86_function_type_abi (TREE_TYPE (fndecl));
}
/* Returns value SYSV_ABI, MS_ABI dependent on cfun, specifying the
call abi used. */
-int
+enum calling_abi
ix86_cfun_abi (void)
{
if (! cfun || ! TARGET_64BIT)
- return DEFAULT_ABI;
+ return ix86_abi;
return cfun->machine->call_abi;
}
@@ -4699,7 +4854,7 @@ void
ix86_call_abi_override (const_tree fndecl)
{
if (fndecl == NULL_TREE)
- cfun->machine->call_abi = DEFAULT_ABI;
+ cfun->machine->call_abi = ix86_abi;
else
cfun->machine->call_abi = ix86_function_type_abi (TREE_TYPE (fndecl));
}
@@ -4740,8 +4895,8 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, /* Argument info to initialize */
cum->nregs = ix86_regparm;
if (TARGET_64BIT)
{
- if (cum->call_abi != DEFAULT_ABI)
- cum->nregs = DEFAULT_ABI != SYSV_ABI ? X86_64_REGPARM_MAX
+ if (cum->call_abi != ix86_abi)
+ cum->nregs = ix86_abi != SYSV_ABI ? X86_64_REGPARM_MAX
: X64_REGPARM_MAX;
}
if (TARGET_SSE)
@@ -4749,8 +4904,8 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, /* Argument info to initialize */
cum->sse_nregs = SSE_REGPARM_MAX;
if (TARGET_64BIT)
{
- if (cum->call_abi != DEFAULT_ABI)
- cum->sse_nregs = DEFAULT_ABI != SYSV_ABI ? X86_64_SSE_REGPARM_MAX
+ if (cum->call_abi != ix86_abi)
+ cum->sse_nregs = ix86_abi != SYSV_ABI ? X86_64_SSE_REGPARM_MAX
: X64_SSE_REGPARM_MAX;
}
}
@@ -5716,7 +5871,7 @@ function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
if (type)
mode = type_natural_mode (type, NULL);
- if (TARGET_64BIT && (cum ? cum->call_abi : DEFAULT_ABI) == MS_ABI)
+ if (TARGET_64BIT && (cum ? cum->call_abi : ix86_abi) == MS_ABI)
function_arg_advance_ms_64 (cum, bytes, words);
else if (TARGET_64BIT)
function_arg_advance_64 (cum, mode, type, words, named);
@@ -5862,9 +6017,9 @@ function_arg_64 (CUMULATIVE_ARGS *cum, enum machine_mode mode,
if (mode == VOIDmode)
return GEN_INT (cum->maybe_vaarg
? (cum->sse_nregs < 0
- ? (cum->call_abi == DEFAULT_ABI
+ ? (cum->call_abi == ix86_abi
? SSE_REGPARM_MAX
- : (DEFAULT_ABI != SYSV_ABI ? X86_64_SSE_REGPARM_MAX
+ : (ix86_abi != SYSV_ABI ? X86_64_SSE_REGPARM_MAX
: X64_SSE_REGPARM_MAX))
: cum->sse_regno)
: -1);
@@ -5958,7 +6113,7 @@ function_arg (CUMULATIVE_ARGS *cum, enum machine_mode omode,
if (type && TREE_CODE (type) == VECTOR_TYPE)
mode = type_natural_mode (type, cum);
- if (TARGET_64BIT && (cum ? cum->call_abi : DEFAULT_ABI) == MS_ABI)
+ if (TARGET_64BIT && (cum ? cum->call_abi : ix86_abi) == MS_ABI)
return function_arg_ms_64 (cum, mode, omode, named, bytes);
else if (TARGET_64BIT)
return function_arg_64 (cum, mode, omode, type, named);
@@ -5978,7 +6133,7 @@ ix86_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
const_tree type, bool named ATTRIBUTE_UNUSED)
{
/* See Windows x64 Software Convention. */
- if (TARGET_64BIT && (cum ? cum->call_abi : DEFAULT_ABI) == MS_ABI)
+ if (TARGET_64BIT && (cum ? cum->call_abi : ix86_abi) == MS_ABI)
{
int msize = (int) GET_MODE_SIZE (mode);
if (type)
@@ -6118,7 +6273,7 @@ ix86_function_value_regno_p (int regno)
/* TODO: The function should depend on current function ABI but
builtins.c would need updating then. Therefore we use the
default ABI. */
- if (TARGET_64BIT && DEFAULT_ABI == MS_ABI)
+ if (TARGET_64BIT && ix86_abi == MS_ABI)
return false;
return TARGET_FLOAT_RETURNS_IN_80387;
@@ -6514,13 +6669,13 @@ ix86_build_builtin_va_list_abi (enum calling_abi abi)
static tree
ix86_build_builtin_va_list (void)
{
- tree ret = ix86_build_builtin_va_list_abi (DEFAULT_ABI);
+ tree ret = ix86_build_builtin_va_list_abi (ix86_abi);
/* Initialize abi specific va_list builtin types. */
if (TARGET_64BIT)
{
tree t;
- if (DEFAULT_ABI == MS_ABI)
+ if (ix86_abi == MS_ABI)
{
t = ix86_build_builtin_va_list_abi (SYSV_ABI);
if (TREE_CODE (t) != RECORD_TYPE)
@@ -6534,7 +6689,7 @@ ix86_build_builtin_va_list (void)
t = build_variant_type_copy (t);
sysv_va_list_type_node = t;
}
- if (DEFAULT_ABI != MS_ABI)
+ if (ix86_abi != MS_ABI)
{
t = ix86_build_builtin_va_list_abi (MS_ABI);
if (TREE_CODE (t) != RECORD_TYPE)
@@ -6567,8 +6722,8 @@ setup_incoming_varargs_64 (CUMULATIVE_ARGS *cum)
int i;
int regparm = ix86_regparm;
- if (cum->call_abi != DEFAULT_ABI)
- regparm = DEFAULT_ABI != SYSV_ABI ? X86_64_REGPARM_MAX : X64_REGPARM_MAX;
+ if (cum->call_abi != ix86_abi)
+ regparm = ix86_abi != SYSV_ABI ? X86_64_REGPARM_MAX : X64_REGPARM_MAX;
/* GPR size of varargs save area. */
if (cfun->va_list_gpr_size)
@@ -6721,7 +6876,7 @@ is_va_list_char_pointer (tree type)
return true;
canonic = ix86_canonical_va_list_type (type);
return (canonic == ms_va_list_type_node
- || (DEFAULT_ABI == MS_ABI && canonic == va_list_type_node));
+ || (ix86_abi == MS_ABI && canonic == va_list_type_node));
}
/* Implement va_start. */
@@ -6965,7 +7120,7 @@ ix86_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p,
}
if (need_temp)
{
- int i;
+ int i, prev_size = 0;
tree temp = create_tmp_var (type, "va_arg_tmp");
/* addr = &temp; */
@@ -6977,13 +7132,29 @@ ix86_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p,
rtx slot = XVECEXP (container, 0, i);
rtx reg = XEXP (slot, 0);
enum machine_mode mode = GET_MODE (reg);
- tree piece_type = lang_hooks.types.type_for_mode (mode, 1);
- tree addr_type = build_pointer_type (piece_type);
- tree daddr_type = build_pointer_type_for_mode (piece_type,
- ptr_mode, true);
+ tree piece_type;
+ tree addr_type;
+ tree daddr_type;
tree src_addr, src;
int src_offset;
tree dest_addr, dest;
+ int cur_size = GET_MODE_SIZE (mode);
+
+ if (prev_size + cur_size > size)
+ {
+ cur_size = size - prev_size;
+ mode = mode_for_size (cur_size * BITS_PER_UNIT, MODE_INT, 1);
+ if (mode == BLKmode)
+ mode = QImode;
+ }
+ piece_type = lang_hooks.types.type_for_mode (mode, 1);
+ if (mode == GET_MODE (reg))
+ addr_type = build_pointer_type (piece_type);
+ else
+ addr_type = build_pointer_type_for_mode (piece_type, ptr_mode,
+ true);
+ daddr_type = build_pointer_type_for_mode (piece_type, ptr_mode,
+ true);
if (SSE_REGNO_P (REGNO (reg)))
{
@@ -6998,14 +7169,26 @@ ix86_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p,
src_addr = fold_convert (addr_type, src_addr);
src_addr = fold_build2 (POINTER_PLUS_EXPR, addr_type, src_addr,
size_int (src_offset));
- src = build_va_arg_indirect_ref (src_addr);
dest_addr = fold_convert (daddr_type, addr);
dest_addr = fold_build2 (POINTER_PLUS_EXPR, daddr_type, dest_addr,
size_int (INTVAL (XEXP (slot, 1))));
- dest = build_va_arg_indirect_ref (dest_addr);
+ if (cur_size == GET_MODE_SIZE (mode))
+ {
+ src = build_va_arg_indirect_ref (src_addr);
+ dest = build_va_arg_indirect_ref (dest_addr);
- gimplify_assign (dest, src, pre_p);
+ gimplify_assign (dest, src, pre_p);
+ }
+ else
+ {
+ tree copy
+ = build_call_expr (implicit_built_in_decls[BUILT_IN_MEMCPY],
+ 3, dest_addr, src_addr,
+ size_int (cur_size));
+ gimplify_and_add (copy, pre_p);
+ }
+ prev_size += cur_size;
}
}
@@ -8088,37 +8271,58 @@ find_drap_reg (void)
}
}
-/* Update incoming stack boundary and estimated stack alignment. */
+/* Return minimum incoming stack alignment. */
-static void
-ix86_update_stack_boundary (void)
+static unsigned int
+ix86_minimum_incoming_stack_boundary (bool sibcall)
{
+ unsigned int incoming_stack_boundary;
+
/* Prefer the one specified at command line. */
- ix86_incoming_stack_boundary
- = (ix86_user_incoming_stack_boundary
- ? ix86_user_incoming_stack_boundary
- : ix86_default_incoming_stack_boundary);
+ if (ix86_user_incoming_stack_boundary)
+ incoming_stack_boundary = ix86_user_incoming_stack_boundary;
+ /* In 32bit, use MIN_STACK_BOUNDARY for incoming stack boundary
+ if -mstackrealign is used, it isn't used for sibcall check and
+ estimated stack alignment is 128bit. */
+ else if (!sibcall
+ && !TARGET_64BIT
+ && ix86_force_align_arg_pointer
+ && crtl->stack_alignment_estimated == 128)
+ incoming_stack_boundary = MIN_STACK_BOUNDARY;
+ else
+ incoming_stack_boundary = ix86_default_incoming_stack_boundary;
/* Incoming stack alignment can be changed on individual functions
via force_align_arg_pointer attribute. We use the smallest
incoming stack boundary. */
- if (ix86_incoming_stack_boundary > MIN_STACK_BOUNDARY
+ if (incoming_stack_boundary > MIN_STACK_BOUNDARY
&& lookup_attribute (ix86_force_align_arg_pointer_string,
TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))))
- ix86_incoming_stack_boundary = MIN_STACK_BOUNDARY;
+ incoming_stack_boundary = MIN_STACK_BOUNDARY;
/* The incoming stack frame has to be aligned at least at
parm_stack_boundary. */
- if (ix86_incoming_stack_boundary < crtl->parm_stack_boundary)
- ix86_incoming_stack_boundary = crtl->parm_stack_boundary;
+ if (incoming_stack_boundary < crtl->parm_stack_boundary)
+ incoming_stack_boundary = crtl->parm_stack_boundary;
/* Stack at entrance of main is aligned by runtime. We use the
smallest incoming stack boundary. */
- if (ix86_incoming_stack_boundary > MAIN_STACK_BOUNDARY
+ if (incoming_stack_boundary > MAIN_STACK_BOUNDARY
&& DECL_NAME (current_function_decl)
&& MAIN_NAME_P (DECL_NAME (current_function_decl))
&& DECL_FILE_SCOPE_P (current_function_decl))
- ix86_incoming_stack_boundary = MAIN_STACK_BOUNDARY;
+ incoming_stack_boundary = MAIN_STACK_BOUNDARY;
+
+ return incoming_stack_boundary;
+}
+
+/* Update incoming stack boundary and estimated stack alignment. */
+
+static void
+ix86_update_stack_boundary (void)
+{
+ ix86_incoming_stack_boundary
+ = ix86_minimum_incoming_stack_boundary (false);
/* x86_64 vararg needs 16byte stack alignment for register save
area. */
@@ -13228,6 +13432,316 @@ ix86_expand_unary_operator (enum rtx_code code, enum machine_mode mode,
emit_move_insn (operands[0], dst);
}
+#define LEA_SEARCH_THRESHOLD 12
+
+/* Search backward for non-agu definition of register number REGNO1
+ or register number REGNO2 in INSN's basic block until
+ 1. Pass LEA_SEARCH_THRESHOLD instructions, or
+ 2. Reach BB boundary, or
+ 3. Reach agu definition.
+ Returns the distance between the non-agu definition point and INSN.
+ If no definition point, returns -1. */
+
+static int
+distance_non_agu_define (unsigned int regno1, unsigned int regno2,
+ rtx insn)
+{
+ basic_block bb = BLOCK_FOR_INSN (insn);
+ int distance = 0;
+ df_ref *def_rec;
+ enum attr_type insn_type;
+
+ if (insn != BB_HEAD (bb))
+ {
+ rtx prev = PREV_INSN (insn);
+ while (prev && distance < LEA_SEARCH_THRESHOLD)
+ {
+ if (INSN_P (prev))
+ {
+ distance++;
+ for (def_rec = DF_INSN_DEFS (prev); *def_rec; def_rec++)
+ if (DF_REF_TYPE (*def_rec) == DF_REF_REG_DEF
+ && !DF_REF_IS_ARTIFICIAL (*def_rec)
+ && (regno1 == DF_REF_REGNO (*def_rec)
+ || regno2 == DF_REF_REGNO (*def_rec)))
+ {
+ insn_type = get_attr_type (prev);
+ if (insn_type != TYPE_LEA)
+ goto done;
+ }
+ }
+ if (prev == BB_HEAD (bb))
+ break;
+ prev = PREV_INSN (prev);
+ }
+ }
+
+ if (distance < LEA_SEARCH_THRESHOLD)
+ {
+ edge e;
+ edge_iterator ei;
+ bool simple_loop = false;
+
+ FOR_EACH_EDGE (e, ei, bb->preds)
+ if (e->src == bb)
+ {
+ simple_loop = true;
+ break;
+ }
+
+ if (simple_loop)
+ {
+ rtx prev = BB_END (bb);
+ while (prev
+ && prev != insn
+ && distance < LEA_SEARCH_THRESHOLD)
+ {
+ if (INSN_P (prev))
+ {
+ distance++;
+ for (def_rec = DF_INSN_DEFS (prev); *def_rec; def_rec++)
+ if (DF_REF_TYPE (*def_rec) == DF_REF_REG_DEF
+ && !DF_REF_IS_ARTIFICIAL (*def_rec)
+ && (regno1 == DF_REF_REGNO (*def_rec)
+ || regno2 == DF_REF_REGNO (*def_rec)))
+ {
+ insn_type = get_attr_type (prev);
+ if (insn_type != TYPE_LEA)
+ goto done;
+ }
+ }
+ prev = PREV_INSN (prev);
+ }
+ }
+ }
+
+ distance = -1;
+
+done:
+ /* get_attr_type may modify recog data. We want to make sure
+ that recog data is valid for instruction INSN, on which
+ distance_non_agu_define is called. INSN is unchanged here. */
+ extract_insn_cached (insn);
+ return distance;
+}
+
+/* Return the distance between INSN and the next insn that uses
+ register number REGNO0 in memory address. Return -1 if no such
+ a use is found within LEA_SEARCH_THRESHOLD or REGNO0 is set. */
+
+static int
+distance_agu_use (unsigned int regno0, rtx insn)
+{
+ basic_block bb = BLOCK_FOR_INSN (insn);
+ int distance = 0;
+ df_ref *def_rec;
+ df_ref *use_rec;
+
+ if (insn != BB_END (bb))
+ {
+ rtx next = NEXT_INSN (insn);
+ while (next && distance < LEA_SEARCH_THRESHOLD)
+ {
+ if (INSN_P (next))
+ {
+ distance++;
+
+ for (use_rec = DF_INSN_USES (next); *use_rec; use_rec++)
+ if ((DF_REF_TYPE (*use_rec) == DF_REF_REG_MEM_LOAD
+ || DF_REF_TYPE (*use_rec) == DF_REF_REG_MEM_STORE)
+ && regno0 == DF_REF_REGNO (*use_rec))
+ {
+ /* Return DISTANCE if OP0 is used in memory
+ address in NEXT. */
+ return distance;
+ }
+
+ for (def_rec = DF_INSN_DEFS (next); *def_rec; def_rec++)
+ if (DF_REF_TYPE (*def_rec) == DF_REF_REG_DEF
+ && !DF_REF_IS_ARTIFICIAL (*def_rec)
+ && regno0 == DF_REF_REGNO (*def_rec))
+ {
+ /* Return -1 if OP0 is set in NEXT. */
+ return -1;
+ }
+ }
+ if (next == BB_END (bb))
+ break;
+ next = NEXT_INSN (next);
+ }
+ }
+
+ if (distance < LEA_SEARCH_THRESHOLD)
+ {
+ edge e;
+ edge_iterator ei;
+ bool simple_loop = false;
+
+ FOR_EACH_EDGE (e, ei, bb->succs)
+ if (e->dest == bb)
+ {
+ simple_loop = true;
+ break;
+ }
+
+ if (simple_loop)
+ {
+ rtx next = BB_HEAD (bb);
+ while (next
+ && next != insn
+ && distance < LEA_SEARCH_THRESHOLD)
+ {
+ if (INSN_P (next))
+ {
+ distance++;
+
+ for (use_rec = DF_INSN_USES (next); *use_rec; use_rec++)
+ if ((DF_REF_TYPE (*use_rec) == DF_REF_REG_MEM_LOAD
+ || DF_REF_TYPE (*use_rec) == DF_REF_REG_MEM_STORE)
+ && regno0 == DF_REF_REGNO (*use_rec))
+ {
+ /* Return DISTANCE if OP0 is used in memory
+ address in NEXT. */
+ return distance;
+ }
+
+ for (def_rec = DF_INSN_DEFS (next); *def_rec; def_rec++)
+ if (DF_REF_TYPE (*def_rec) == DF_REF_REG_DEF
+ && !DF_REF_IS_ARTIFICIAL (*def_rec)
+ && regno0 == DF_REF_REGNO (*def_rec))
+ {
+ /* Return -1 if OP0 is set in NEXT. */
+ return -1;
+ }
+
+ }
+ next = NEXT_INSN (next);
+ }
+ }
+ }
+
+ return -1;
+}
+
+/* Define this macro to tune LEA priority vs ADD, it take effect when
+ there is a dilemma of choicing LEA or ADD
+ Negative value: ADD is more preferred than LEA
+ Zero: Netrual
+ Positive value: LEA is more preferred than ADD*/
+#define IX86_LEA_PRIORITY 2
+
+/* Return true if it is ok to optimize an ADD operation to LEA
+ operation to avoid flag register consumation. For the processors
+ like ATOM, if the destination register of LEA holds an actual
+ address which will be used soon, LEA is better and otherwise ADD
+ is better. */
+
+bool
+ix86_lea_for_add_ok (enum rtx_code code ATTRIBUTE_UNUSED,
+ rtx insn, rtx operands[])
+{
+ unsigned int regno0 = true_regnum (operands[0]);
+ unsigned int regno1 = true_regnum (operands[1]);
+ unsigned int regno2;
+
+ if (!TARGET_OPT_AGU || optimize_function_for_size_p (cfun))
+ return regno0 != regno1;
+
+ regno2 = true_regnum (operands[2]);
+
+ /* If a = b + c, (a!=b && a!=c), must use lea form. */
+ if (regno0 != regno1 && regno0 != regno2)
+ return true;
+ else
+ {
+ int dist_define, dist_use;
+ dist_define = distance_non_agu_define (regno1, regno2, insn);
+ if (dist_define <= 0)
+ return true;
+
+ /* If this insn has both backward non-agu dependence and forward
+ agu dependence, the one with short distance take effect. */
+ dist_use = distance_agu_use (regno0, insn);
+ if (dist_use <= 0
+ || (dist_define + IX86_LEA_PRIORITY) < dist_use)
+ return false;
+
+ return true;
+ }
+}
+
+/* Return true if destination reg of SET_BODY is shift count of
+ USE_BODY. */
+
+static bool
+ix86_dep_by_shift_count_body (const_rtx set_body, const_rtx use_body)
+{
+ rtx set_dest;
+ rtx shift_rtx;
+ int i;
+
+ /* Retrieve destination of SET_BODY. */
+ switch (GET_CODE (set_body))
+ {
+ case SET:
+ set_dest = SET_DEST (set_body);
+ if (!set_dest || !REG_P (set_dest))
+ return false;
+ break;
+ case PARALLEL:
+ for (i = XVECLEN (set_body, 0) - 1; i >= 0; i--)
+ if (ix86_dep_by_shift_count_body (XVECEXP (set_body, 0, i),
+ use_body))
+ return true;
+ default:
+ return false;
+ break;
+ }
+
+ /* Retrieve shift count of USE_BODY. */
+ switch (GET_CODE (use_body))
+ {
+ case SET:
+ shift_rtx = XEXP (use_body, 1);
+ break;
+ case PARALLEL:
+ for (i = XVECLEN (use_body, 0) - 1; i >= 0; i--)
+ if (ix86_dep_by_shift_count_body (set_body,
+ XVECEXP (use_body, 0, i)))
+ return true;
+ default:
+ return false;
+ break;
+ }
+
+ if (shift_rtx
+ && (GET_CODE (shift_rtx) == ASHIFT
+ || GET_CODE (shift_rtx) == LSHIFTRT
+ || GET_CODE (shift_rtx) == ASHIFTRT
+ || GET_CODE (shift_rtx) == ROTATE
+ || GET_CODE (shift_rtx) == ROTATERT))
+ {
+ rtx shift_count = XEXP (shift_rtx, 1);
+
+ /* Return true if shift count is dest of SET_BODY. */
+ if (REG_P (shift_count)
+ && true_regnum (set_dest) == true_regnum (shift_count))
+ return true;
+ }
+
+ return false;
+}
+
+/* Return true if destination reg of SET_INSN is shift count of
+ USE_INSN. */
+
+bool
+ix86_dep_by_shift_count (const_rtx set_insn, const_rtx use_insn)
+{
+ return ix86_dep_by_shift_count_body (PATTERN (set_insn),
+ PATTERN (use_insn));
+}
+
/* Return TRUE or FALSE depending on whether the unary operator meets the
appropriate constraints. */
@@ -19084,7 +19598,7 @@ ix86_init_machine_status (void)
f = GGC_CNEW (struct machine_function);
f->use_fast_prologue_epilogue_nregs = -1;
f->tls_descriptor_call_expanded_p = 0;
- f->call_abi = DEFAULT_ABI;
+ f->call_abi = ix86_abi;
return f;
}
@@ -19345,6 +19859,7 @@ ix86_issue_rate (void)
switch (ix86_tune)
{
case PROCESSOR_PENTIUM:
+ case PROCESSOR_ATOM:
case PROCESSOR_K6:
return 2;
@@ -19411,41 +19926,21 @@ ix86_flags_dependent (rtx insn, rtx dep_insn, enum attr_type insn_type)
return 1;
}
-/* A subroutine of ix86_adjust_cost -- return true iff INSN has a memory
- address with operands set by DEP_INSN. */
+/* Return true iff USE_INSN has a memory address with operands set by
+ SET_INSN. */
-static int
-ix86_agi_dependent (rtx insn, rtx dep_insn, enum attr_type insn_type)
+bool
+ix86_agi_dependent (rtx set_insn, rtx use_insn)
{
- rtx addr;
-
- if (insn_type == TYPE_LEA
- && TARGET_PENTIUM)
- {
- addr = PATTERN (insn);
-
- if (GET_CODE (addr) == PARALLEL)
- addr = XVECEXP (addr, 0, 0);
-
- gcc_assert (GET_CODE (addr) == SET);
-
- addr = SET_SRC (addr);
- }
- else
- {
- int i;
- extract_insn_cached (insn);
- for (i = recog_data.n_operands - 1; i >= 0; --i)
- if (MEM_P (recog_data.operand[i]))
- {
- addr = XEXP (recog_data.operand[i], 0);
- goto found;
- }
- return 0;
- found:;
- }
-
- return modified_in_p (addr, dep_insn);
+ int i;
+ extract_insn_cached (use_insn);
+ for (i = recog_data.n_operands - 1; i >= 0; --i)
+ if (MEM_P (recog_data.operand[i]))
+ {
+ rtx addr = XEXP (recog_data.operand[i], 0);
+ return modified_in_p (addr, set_insn) != 0;
+ }
+ return false;
}
static int
@@ -19473,7 +19968,20 @@ ix86_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
{
case PROCESSOR_PENTIUM:
/* Address Generation Interlock adds a cycle of latency. */
- if (ix86_agi_dependent (insn, dep_insn, insn_type))
+ if (insn_type == TYPE_LEA)
+ {
+ rtx addr = PATTERN (insn);
+
+ if (GET_CODE (addr) == PARALLEL)
+ addr = XVECEXP (addr, 0, 0);
+
+ gcc_assert (GET_CODE (addr) == SET);
+
+ addr = SET_SRC (addr);
+ if (modified_in_p (addr, dep_insn))
+ cost += 1;
+ }
+ else if (ix86_agi_dependent (dep_insn, insn))
cost += 1;
/* ??? Compares pair with jump/setcc. */
@@ -19483,7 +19991,7 @@ ix86_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
/* Floating point stores require value to be ready one cycle earlier. */
if (insn_type == TYPE_FMOV
&& get_attr_memory (insn) == MEMORY_STORE
- && !ix86_agi_dependent (insn, dep_insn, insn_type))
+ && !ix86_agi_dependent (dep_insn, insn))
cost += 1;
break;
@@ -19506,7 +20014,7 @@ ix86_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
in parallel with previous instruction in case
previous instruction is not needed to compute the address. */
if ((memory == MEMORY_LOAD || memory == MEMORY_BOTH)
- && !ix86_agi_dependent (insn, dep_insn, insn_type))
+ && !ix86_agi_dependent (dep_insn, insn))
{
/* Claim moves to take one cycle, as core can issue one load
at time and the next load can start cycle later. */
@@ -19535,7 +20043,7 @@ ix86_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
in parallel with previous instruction in case
previous instruction is not needed to compute the address. */
if ((memory == MEMORY_LOAD || memory == MEMORY_BOTH)
- && !ix86_agi_dependent (insn, dep_insn, insn_type))
+ && !ix86_agi_dependent (dep_insn, insn))
{
/* Claim moves to take one cycle, as core can issue one load
at time and the next load can start cycle later. */
@@ -19552,6 +20060,7 @@ ix86_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
case PROCESSOR_ATHLON:
case PROCESSOR_K8:
case PROCESSOR_AMDFAM10:
+ case PROCESSOR_ATOM:
case PROCESSOR_GENERIC32:
case PROCESSOR_GENERIC64:
memory = get_attr_memory (insn);
@@ -19560,7 +20069,7 @@ ix86_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
in parallel with previous instruction in case
previous instruction is not needed to compute the address. */
if ((memory == MEMORY_LOAD || memory == MEMORY_BOTH)
- && !ix86_agi_dependent (insn, dep_insn, insn_type))
+ && !ix86_agi_dependent (dep_insn, insn))
{
enum attr_unit unit = get_attr_unit (insn);
int loadcost = 3;
@@ -20815,6 +21324,14 @@ enum ix86_builtins
IX86_BUILTIN_PCOMFALSEQ,
IX86_BUILTIN_PCOMTRUEQ,
+ /* LWP instructions. */
+ IX86_BUILTIN_LLWPCB,
+ IX86_BUILTIN_SLWPCB,
+ IX86_BUILTIN_LWPVAL32,
+ IX86_BUILTIN_LWPVAL64,
+ IX86_BUILTIN_LWPINS32,
+ IX86_BUILTIN_LWPINS64,
+
IX86_BUILTIN_MAX
};
@@ -20998,6 +21515,8 @@ enum ix86_special_builtin_type
{
SPECIAL_FTYPE_UNKNOWN,
VOID_FTYPE_VOID,
+ VOID_FTYPE_PVOID,
+ PVOID_FTYPE_VOID,
V32QI_FTYPE_PCCHAR,
V16QI_FTYPE_PCCHAR,
V8SF_FTYPE_PCV4SF,
@@ -21027,7 +21546,13 @@ enum ix86_special_builtin_type
VOID_FTYPE_PV8SF_V8SF_V8SF,
VOID_FTYPE_PV4DF_V4DF_V4DF,
VOID_FTYPE_PV4SF_V4SF_V4SF,
- VOID_FTYPE_PV2DF_V2DF_V2DF
+ VOID_FTYPE_PV2DF_V2DF_V2DF,
+ VOID_FTYPE_USHORT_UINT_USHORT,
+ VOID_FTYPE_UINT_UINT_UINT,
+ VOID_FTYPE_UINT64_UINT_UINT,
+ UCHAR_FTYPE_USHORT_UINT_USHORT,
+ UCHAR_FTYPE_UINT_UINT_UINT,
+ UCHAR_FTYPE_UINT64_UINT_UINT
};
/* Builtin types */
@@ -21266,6 +21791,14 @@ static const struct builtin_description bdesc_special_args[] =
{ OPTION_MASK_ISA_AVX, CODE_FOR_avx_maskstoreps, "__builtin_ia32_maskstoreps", IX86_BUILTIN_MASKSTOREPS, UNKNOWN, (int) VOID_FTYPE_PV4SF_V4SF_V4SF },
{ OPTION_MASK_ISA_AVX, CODE_FOR_avx_maskstorepd256, "__builtin_ia32_maskstorepd256", IX86_BUILTIN_MASKSTOREPD256, UNKNOWN, (int) VOID_FTYPE_PV4DF_V4DF_V4DF },
{ OPTION_MASK_ISA_AVX, CODE_FOR_avx_maskstoreps256, "__builtin_ia32_maskstoreps256", IX86_BUILTIN_MASKSTOREPS256, UNKNOWN, (int) VOID_FTYPE_PV8SF_V8SF_V8SF },
+
+ { OPTION_MASK_ISA_LWP, CODE_FOR_lwp_llwpcb, "__builtin_ia32_llwpcb", IX86_BUILTIN_LLWPCB, UNKNOWN, (int) VOID_FTYPE_PVOID },
+ { OPTION_MASK_ISA_LWP, CODE_FOR_lwp_slwpcb, "__builtin_ia32_slwpcb", IX86_BUILTIN_SLWPCB, UNKNOWN, (int) PVOID_FTYPE_VOID },
+ { OPTION_MASK_ISA_LWP, CODE_FOR_lwp_lwpvalsi3, "__builtin_ia32_lwpval32", IX86_BUILTIN_LWPVAL32, UNKNOWN, (int) VOID_FTYPE_UINT_UINT_UINT },
+ { OPTION_MASK_ISA_LWP, CODE_FOR_lwp_lwpvaldi3, "__builtin_ia32_lwpval64", IX86_BUILTIN_LWPVAL64, UNKNOWN, (int) VOID_FTYPE_UINT64_UINT_UINT },
+ { OPTION_MASK_ISA_LWP, CODE_FOR_lwp_lwpinssi3, "__builtin_ia32_lwpins32", IX86_BUILTIN_LWPINS32, UNKNOWN, (int) UCHAR_FTYPE_UINT_UINT_UINT },
+ { OPTION_MASK_ISA_LWP, CODE_FOR_lwp_lwpinsdi3, "__builtin_ia32_lwpins64", IX86_BUILTIN_LWPINS64, UNKNOWN, (int) UCHAR_FTYPE_UINT64_UINT_UINT },
+
};
/* Builtins with variable number of arguments. */
@@ -22255,6 +22788,7 @@ ix86_init_mmx_sse_builtins (void)
NULL_TREE);
tree unsigned_ftype_void
= build_function_type (unsigned_type_node, void_list_node);
+
tree v2si_ftype_v4sf
= build_function_type_list (V2SI_type_node, V4SF_type_node, NULL_TREE);
/* Loads/stores. */
@@ -22915,6 +23449,56 @@ ix86_init_mmx_sse_builtins (void)
= build_function_type_list (V2DF_type_node,
V2DF_type_node, V2DI_type_node, NULL_TREE);
+ /* LWP instructions. */
+
+ tree pvoid_ftype_void
+ = build_function_type (ptr_type_node, void_list_node);
+
+ tree void_ftype_pvoid
+ = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
+
+ tree void_ftype_ushort_unsigned_ushort
+ = build_function_type_list (void_type_node,
+ short_unsigned_type_node,
+ unsigned_type_node,
+ short_unsigned_type_node,
+ NULL_TREE);
+
+ tree void_ftype_unsigned_unsigned_unsigned
+ = build_function_type_list (void_type_node,
+ unsigned_type_node,
+ unsigned_type_node,
+ unsigned_type_node,
+ NULL_TREE);
+
+ tree void_ftype_uint64_unsigned_unsigned
+ = build_function_type_list (void_type_node,
+ long_long_unsigned_type_node,
+ unsigned_type_node,
+ unsigned_type_node,
+ NULL_TREE);
+
+ tree uchar_ftype_ushort_unsigned_ushort
+ = build_function_type_list (unsigned_char_type_node,
+ short_unsigned_type_node,
+ unsigned_type_node,
+ short_unsigned_type_node,
+ NULL_TREE);
+
+ tree uchar_ftype_unsigned_unsigned_unsigned
+ = build_function_type_list (unsigned_char_type_node,
+ unsigned_type_node,
+ unsigned_type_node,
+ unsigned_type_node,
+ NULL_TREE);
+
+ tree uchar_ftype_uint64_unsigned_unsigned
+ = build_function_type_list (unsigned_char_type_node,
+ long_long_unsigned_type_node,
+ unsigned_type_node,
+ unsigned_type_node,
+ NULL_TREE);
+
tree ftype;
/* Add all special builtins with variable number of operands. */
@@ -23022,6 +23606,31 @@ ix86_init_mmx_sse_builtins (void)
case VOID_FTYPE_PV2DF_V2DF_V2DF:
type = void_ftype_pv2df_v2df_v2df;
break;
+ case VOID_FTYPE_USHORT_UINT_USHORT:
+ type = void_ftype_ushort_unsigned_ushort;
+ break;
+ case VOID_FTYPE_UINT_UINT_UINT:
+ type = void_ftype_unsigned_unsigned_unsigned;
+ break;
+ case VOID_FTYPE_UINT64_UINT_UINT:
+ type = void_ftype_uint64_unsigned_unsigned;
+ break;
+ case VOID_FTYPE_PVOID:
+ type = void_ftype_pvoid;
+ break;
+ case PVOID_FTYPE_VOID:
+ type = pvoid_ftype_void;
+ break;
+ case UCHAR_FTYPE_USHORT_UINT_USHORT:
+ type = uchar_ftype_ushort_unsigned_ushort;
+ break;
+ case UCHAR_FTYPE_UINT_UINT_UINT:
+ type = uchar_ftype_unsigned_unsigned_unsigned;
+ break;
+ case UCHAR_FTYPE_UINT64_UINT_UINT:
+ type = uchar_ftype_uint64_unsigned_unsigned;
+ break;
+
default:
gcc_unreachable ();
}
@@ -24803,7 +25412,7 @@ ix86_expand_special_args_builtin (const struct builtin_description *d,
{
rtx op;
enum machine_mode mode;
- } args[2];
+ } args[3];
enum insn_code icode = d->icode;
bool last_arg_constant = false;
const struct insn_data *insn_p = &insn_data[icode];
@@ -24824,6 +25433,7 @@ ix86_expand_special_args_builtin (const struct builtin_description *d,
case V4DF_FTYPE_PCV2DF:
case V4DF_FTYPE_PCDOUBLE:
case V2DF_FTYPE_PCDOUBLE:
+ case VOID_FTYPE_PVOID:
nargs = 1;
klass = load;
memory = 0;
@@ -24867,6 +25477,15 @@ ix86_expand_special_args_builtin (const struct builtin_description *d,
/* Reserve memory operand for target. */
memory = ARRAY_SIZE (args);
break;
+ case VOID_FTYPE_UINT_UINT_UINT:
+ case VOID_FTYPE_UINT64_UINT_UINT:
+ case UCHAR_FTYPE_UINT_UINT_UINT:
+ case UCHAR_FTYPE_UINT64_UINT_UINT:
+ nargs = 3;
+ klass = load;
+ memory = ARRAY_SIZE (args);
+ last_arg_constant = true;
+ break;
default:
gcc_unreachable ();
}
@@ -24903,12 +25522,16 @@ ix86_expand_special_args_builtin (const struct builtin_description *d,
if (last_arg_constant && (i + 1) == nargs)
{
if (!match)
- switch (icode)
- {
- default:
+ {
+ if (icode == CODE_FOR_lwp_lwpvalsi3
+ || icode == CODE_FOR_lwp_lwpinssi3
+ || icode == CODE_FOR_lwp_lwpvaldi3
+ || icode == CODE_FOR_lwp_lwpinsdi3)
+ error ("the last argument must be a 32-bit immediate");
+ else
error ("the last argument must be an 8-bit immediate");
- return const0_rtx;
- }
+ return const0_rtx;
+ }
}
else
{
@@ -24943,6 +25566,9 @@ ix86_expand_special_args_builtin (const struct builtin_description *d,
case 2:
pat = GEN_FCN (icode) (target, args[0].op, args[1].op);
break;
+ case 3:
+ pat = GEN_FCN (icode) (target, args[0].op, args[1].op, args[2].op);
+ break;
default:
gcc_unreachable ();
}
@@ -25240,6 +25866,23 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
return target;
}
+ case IX86_BUILTIN_LLWPCB:
+ arg0 = CALL_EXPR_ARG (exp, 0);
+ op0 = expand_normal (arg0);
+ icode = CODE_FOR_lwp_llwpcb;
+ if (! (*insn_data[icode].operand[0].predicate) (op0, Pmode))
+ op0 = copy_to_mode_reg (Pmode, op0);
+ emit_insn (gen_lwp_llwpcb (op0));
+ return 0;
+
+ case IX86_BUILTIN_SLWPCB:
+ icode = CODE_FOR_lwp_slwpcb;
+ if (!target
+ || ! (*insn_data[icode].operand[0].predicate) (target, Pmode))
+ target = gen_reg_rtx (Pmode);
+ emit_insn (gen_lwp_slwpcb (target));
+ return target;
+
default:
break;
}
@@ -29840,14 +30483,11 @@ x86_builtin_vectorization_cost (bool runtime_test)
tree
ix86_fn_abi_va_list (tree fndecl)
{
- int abi;
-
if (!TARGET_64BIT)
return va_list_type_node;
gcc_assert (fndecl != NULL_TREE);
- abi = ix86_function_abi ((const_tree) fndecl);
- if (abi == MS_ABI)
+ if (ix86_function_abi ((const_tree) fndecl) == MS_ABI)
return ms_va_list_type_node;
else
return sysv_va_list_type_node;
diff --git a/gcc-4.4.3/gcc/config/i386/i386.h b/gcc-4.4.3/gcc/config/i386/i386.h
index abdc7d019..e9014b79a 100644
--- a/gcc-4.4.3/gcc/config/i386/i386.h
+++ b/gcc-4.4.3/gcc/config/i386/i386.h
@@ -55,10 +55,12 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#define TARGET_FMA OPTION_ISA_FMA
#define TARGET_SSE4A OPTION_ISA_SSE4A
#define TARGET_SSE5 OPTION_ISA_SSE5
+#define TARGET_LWP OPTION_ISA_LWP
#define TARGET_ROUND OPTION_ISA_ROUND
#define TARGET_ABM OPTION_ISA_ABM
#define TARGET_POPCNT OPTION_ISA_POPCNT
#define TARGET_SAHF OPTION_ISA_SAHF
+#define TARGET_MOVBE OPTION_ISA_MOVBE
#define TARGET_AES OPTION_ISA_AES
#define TARGET_PCLMUL OPTION_ISA_PCLMUL
#define TARGET_CMPXCHG16B OPTION_ISA_CX16
@@ -236,6 +238,7 @@ extern const struct processor_costs ix86_size_cost;
#define TARGET_GENERIC64 (ix86_tune == PROCESSOR_GENERIC64)
#define TARGET_GENERIC (TARGET_GENERIC32 || TARGET_GENERIC64)
#define TARGET_AMDFAM10 (ix86_tune == PROCESSOR_AMDFAM10)
+#define TARGET_ATOM (ix86_tune == PROCESSOR_ATOM)
/* Feature tests against the various tunings. */
enum ix86_tune_indices {
@@ -300,6 +303,7 @@ enum ix86_tune_indices {
X86_TUNE_USE_VECTOR_FP_CONVERTS,
X86_TUNE_USE_VECTOR_CONVERTS,
X86_TUNE_FUSE_CMP_AND_BRANCH,
+ X86_TUNE_OPT_AGU,
X86_TUNE_LAST
};
@@ -387,6 +391,7 @@ extern unsigned char ix86_tune_features[X86_TUNE_LAST];
ix86_tune_features[X86_TUNE_USE_VECTOR_CONVERTS]
#define TARGET_FUSE_CMP_AND_BRANCH \
ix86_tune_features[X86_TUNE_FUSE_CMP_AND_BRANCH]
+#define TARGET_OPT_AGU ix86_tune_features[X86_TUNE_OPT_AGU]
/* Feature tests against the various architecture variations. */
enum ix86_arch_indices {
@@ -470,7 +475,10 @@ enum calling_abi
MS_ABI = 1
};
-/* The default abi form used by target. */
+/* The abi used by target. */
+extern enum calling_abi ix86_abi;
+
+/* The default abi used by target. */
#define DEFAULT_ABI SYSV_ABI
/* Subtargets may reset this to 1 in order to enable 96-bit long double
@@ -569,6 +577,7 @@ enum target_cpu_default
TARGET_CPU_DEFAULT_prescott,
TARGET_CPU_DEFAULT_nocona,
TARGET_CPU_DEFAULT_core2,
+ TARGET_CPU_DEFAULT_atom,
TARGET_CPU_DEFAULT_geode,
TARGET_CPU_DEFAULT_k6,
@@ -658,7 +667,7 @@ enum target_cpu_default
/* Boundary (in *bits*) on which stack pointer should be aligned. */
#define STACK_BOUNDARY \
- (TARGET_64BIT && DEFAULT_ABI == MS_ABI ? 128 : BITS_PER_WORD)
+ (TARGET_64BIT && ix86_abi == MS_ABI ? 128 : BITS_PER_WORD)
/* Stack boundary of the main function guaranteed by OS. */
#define MAIN_STACK_BOUNDARY (TARGET_64BIT ? 128 : 32)
@@ -679,9 +688,7 @@ enum target_cpu_default
generate an alternate prologue and epilogue that realigns the
runtime stack if nessary. This supports mixing codes that keep a
4-byte aligned stack, as specified by i386 psABI, with codes that
- need a 16-byte aligned stack, as required by SSE instructions. If
- STACK_REALIGN_DEFAULT is 1 and PREFERRED_STACK_BOUNDARY_DEFAULT is
- 128, stacks for all functions may be realigned. */
+ need a 16-byte aligned stack, as required by SSE instructions. */
#define STACK_REALIGN_DEFAULT 0
/* Boundary (in *bits*) on which the incoming stack is aligned. */
@@ -1584,7 +1591,7 @@ typedef struct ix86_args {
int maybe_vaarg; /* true for calls to possibly vardic fncts. */
int float_in_sse; /* 1 if in 32-bit mode SFmode (2 for DFmode) should
be passed in SSE registers. Otherwise 0. */
- int call_abi; /* Set to SYSV_ABI for sysv abi. Otherwise
+ enum calling_abi call_abi; /* Set to SYSV_ABI for sysv abi. Otherwise
MS_ABI for ms abi. */
} CUMULATIVE_ARGS;
@@ -2230,6 +2237,7 @@ enum processor_type
PROCESSOR_GENERIC32,
PROCESSOR_GENERIC64,
PROCESSOR_AMDFAM10,
+ PROCESSOR_ATOM,
PROCESSOR_max
};
@@ -2410,7 +2418,7 @@ struct machine_function GTY(())
int tls_descriptor_call_expanded_p;
/* This value is used for amd64 targets and specifies the current abi
to be used. MS_ABI means ms abi. Otherwise SYSV_ABI means sysv abi. */
- int call_abi;
+ enum calling_abi call_abi;
struct machine_cfa_state cfa;
};
#endif
diff --git a/gcc-4.4.3/gcc/config/i386/i386.md b/gcc-4.4.3/gcc/config/i386/i386.md
index 22c891c49..bbe915112 100644
--- a/gcc-4.4.3/gcc/config/i386/i386.md
+++ b/gcc-4.4.3/gcc/config/i386/i386.md
@@ -227,6 +227,11 @@
(UNSPECV_CLD 15)
(UNSPECV_VZEROALL 16)
(UNSPECV_VZEROUPPER 17)
+ (UNSPECV_VSWAPMOV 18)
+ (UNSPECV_LLWP_INTRINSIC 19)
+ (UNSPECV_SLWP_INTRINSIC 20)
+ (UNSPECV_LWPVAL_INTRINSIC 21)
+ (UNSPECV_LWPINS_INTRINSIC 22)
])
;; Constants to represent pcomtrue/pcomfalse variants
@@ -315,7 +320,7 @@
;; Processor type.
-(define_attr "cpu" "none,pentium,pentiumpro,geode,k6,athlon,k8,core2,
+(define_attr "cpu" "none,pentium,pentiumpro,geode,k6,athlon,k8,core2,atom,
generic64,amdfam10"
(const (symbol_ref "ix86_schedule")))
@@ -329,9 +334,9 @@
push,pop,call,callv,leave,
str,bitmanip,
fmov,fop,fsgn,fmul,fdiv,fpspc,fcmov,fcmp,fxch,fistp,fisttp,frndint,
- sselog,sselog1,sseiadd,sseiadd1,sseishft,sseimul,
+ sselog,sselog1,sseiadd,sseiadd1,sseishft,sseishft1,sseimul,
sse,ssemov,sseadd,ssemul,ssecmp,ssecomi,ssecvt,ssecvt1,sseicvt,ssediv,sseins,
- ssemuladd,sse4arg,
+ ssemuladd,sse4arg,lwp,
mmx,mmxmov,mmxadd,mmxmul,mmxcmp,mmxcvt,mmxshft"
(const_string "other"))
@@ -344,7 +349,7 @@
(define_attr "unit" "integer,i387,sse,mmx,unknown"
(cond [(eq_attr "type" "fmov,fop,fsgn,fmul,fdiv,fpspc,fcmov,fcmp,fxch,fistp,fisttp,frndint")
(const_string "i387")
- (eq_attr "type" "sselog,sselog1,sseiadd,sseiadd1,sseishft,sseimul,
+ (eq_attr "type" "sselog,sselog1,sseiadd,sseiadd1,sseishft,sseishft1,sseimul,
sse,ssemov,sseadd,ssemul,ssecmp,ssecomi,ssecvt,
ssecvt1,sseicvt,ssediv,sseins,ssemuladd,sse4arg")
(const_string "sse")
@@ -524,7 +529,7 @@
;; if the instruction is complex.
(define_attr "memory" "none,load,store,both,unknown"
- (cond [(eq_attr "type" "other,multi,str")
+ (cond [(eq_attr "type" "other,multi,str,lwp")
(const_string "unknown")
(eq_attr "type" "lea,fcmov,fpspc")
(const_string "none")
@@ -611,6 +616,12 @@
(define_attr "i387_cw" "trunc,floor,ceil,mask_pm,uninitialized,any"
(const_string "any"))
+;; Define attribute to classify add/sub insns that consumes carry flag (CF)
+(define_attr "use_carry" "0,1" (const_string "0"))
+
+;; Define attribute to indicate unaligned ssemov insns
+(define_attr "movu" "0,1" (const_string "0"))
+
;; Describe a user's asm statement.
(define_asm_attributes
[(set_attr "length" "128")
@@ -673,6 +684,9 @@
;; Single word integer modes without QImode.
(define_mode_iterator SWI248 [HI SI (DI "TARGET_64BIT")])
+;; Single word integer modes without QImode and HImode.
+(define_mode_iterator SWI48 [SI (DI "TARGET_64BIT")])
+
;; Instruction suffix for integer modes.
(define_mode_attr imodesuffix [(QI "b") (HI "w") (SI "l") (DI "q")])
@@ -726,6 +740,7 @@
(include "k6.md")
(include "athlon.md")
(include "geode.md")
+(include "atom.md")
;; Operand and operator predicates and constraints
@@ -5789,6 +5804,7 @@
"TARGET_64BIT && ix86_binary_operator_ok (PLUS, DImode, operands)"
"adc{q}\t{%2, %0|%0, %2}"
[(set_attr "type" "alu")
+ (set_attr "use_carry" "1")
(set_attr "pent_pair" "pu")
(set_attr "mode" "DI")])
@@ -5863,6 +5879,7 @@
"ix86_binary_operator_ok (PLUS, QImode, operands)"
"adc{b}\t{%2, %0|%0, %2}"
[(set_attr "type" "alu")
+ (set_attr "use_carry" "1")
(set_attr "pent_pair" "pu")
(set_attr "mode" "QI")])
@@ -5875,6 +5892,7 @@
"ix86_binary_operator_ok (PLUS, HImode, operands)"
"adc{w}\t{%2, %0|%0, %2}"
[(set_attr "type" "alu")
+ (set_attr "use_carry" "1")
(set_attr "pent_pair" "pu")
(set_attr "mode" "HI")])
@@ -5887,6 +5905,7 @@
"ix86_binary_operator_ok (PLUS, SImode, operands)"
"adc{l}\t{%2, %0|%0, %2}"
[(set_attr "type" "alu")
+ (set_attr "use_carry" "1")
(set_attr "pent_pair" "pu")
(set_attr "mode" "SI")])
@@ -5900,6 +5919,7 @@
"TARGET_64BIT && ix86_binary_operator_ok (PLUS, SImode, operands)"
"adc{l}\t{%2, %k0|%k0, %2}"
[(set_attr "type" "alu")
+ (set_attr "use_carry" "1")
(set_attr "pent_pair" "pu")
(set_attr "mode" "SI")])
@@ -6129,9 +6149,9 @@
(set_attr "mode" "SI")])
(define_insn "*adddi_1_rex64"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=r,rm,r")
- (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0,r")
- (match_operand:DI 2 "x86_64_general_operand" "rme,re,le")))
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=r,rm,r,r")
+ (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0,r,r")
+ (match_operand:DI 2 "x86_64_general_operand" "rme,re,0,le")))
(clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && ix86_binary_operator_ok (PLUS, DImode, operands)"
{
@@ -6152,6 +6172,10 @@
}
default:
+ /* Use add as much as possible to replace lea for AGU optimization. */
+ if (which_alternative == 2 && TARGET_OPT_AGU)
+ return "add{q}\t{%1, %0|%0, %1}";
+
gcc_assert (rtx_equal_p (operands[0], operands[1]));
/* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
@@ -6170,8 +6194,11 @@
}
}
[(set (attr "type")
- (cond [(eq_attr "alternative" "2")
+ (cond [(and (eq_attr "alternative" "2")
+ (eq (symbol_ref "TARGET_OPT_AGU") (const_int 0)))
(const_string "lea")
+ (eq_attr "alternative" "3")
+ (const_string "lea")
; Current assemblers are broken and do not allow @GOTOFF in
; ought but a memory context.
(match_operand:DI 2 "pic_symbolic_operand" "")
@@ -6188,8 +6215,8 @@
(plus:DI (match_operand:DI 1 "register_operand" "")
(match_operand:DI 2 "x86_64_nonmemory_operand" "")))
(clobber (reg:CC FLAGS_REG))]
- "TARGET_64BIT && reload_completed
- && true_regnum (operands[0]) != true_regnum (operands[1])"
+ "TARGET_64BIT && reload_completed
+ && ix86_lea_for_add_ok (PLUS, insn, operands)"
[(set (match_dup 0)
(plus:DI (match_dup 1)
(match_dup 2)))]
@@ -6393,9 +6420,9 @@
(define_insn "*addsi_1"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=r,rm,r")
- (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,r")
- (match_operand:SI 2 "general_operand" "g,ri,li")))
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=r,rm,r,r")
+ (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,r,r")
+ (match_operand:SI 2 "general_operand" "g,ri,0,li")))
(clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (PLUS, SImode, operands)"
{
@@ -6416,6 +6443,10 @@
}
default:
+ /* Use add as much as possible to replace lea for AGU optimization. */
+ if (which_alternative == 2 && TARGET_OPT_AGU)
+ return "add{l}\t{%1, %0|%0, %1}";
+
gcc_assert (rtx_equal_p (operands[0], operands[1]));
/* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
@@ -6432,7 +6463,10 @@
}
}
[(set (attr "type")
- (cond [(eq_attr "alternative" "2")
+ (cond [(and (eq_attr "alternative" "2")
+ (eq (symbol_ref "TARGET_OPT_AGU") (const_int 0)))
+ (const_string "lea")
+ (eq_attr "alternative" "3")
(const_string "lea")
; Current assemblers are broken and do not allow @GOTOFF in
; ought but a memory context.
@@ -6450,8 +6484,7 @@
(plus (match_operand 1 "register_operand" "")
(match_operand 2 "nonmemory_operand" "")))
(clobber (reg:CC FLAGS_REG))]
- "reload_completed
- && true_regnum (operands[0]) != true_regnum (operands[1])"
+ "reload_completed && ix86_lea_for_add_ok (PLUS, insn, operands)"
[(const_int 0)]
{
rtx pat;
@@ -7552,6 +7585,7 @@
"TARGET_64BIT && ix86_binary_operator_ok (MINUS, DImode, operands)"
"sbb{q}\t{%2, %0|%0, %2}"
[(set_attr "type" "alu")
+ (set_attr "use_carry" "1")
(set_attr "pent_pair" "pu")
(set_attr "mode" "DI")])
@@ -7600,6 +7634,7 @@
"ix86_binary_operator_ok (MINUS, QImode, operands)"
"sbb{b}\t{%2, %0|%0, %2}"
[(set_attr "type" "alu")
+ (set_attr "use_carry" "1")
(set_attr "pent_pair" "pu")
(set_attr "mode" "QI")])
@@ -7612,6 +7647,7 @@
"ix86_binary_operator_ok (MINUS, HImode, operands)"
"sbb{w}\t{%2, %0|%0, %2}"
[(set_attr "type" "alu")
+ (set_attr "use_carry" "1")
(set_attr "pent_pair" "pu")
(set_attr "mode" "HI")])
@@ -7624,6 +7660,7 @@
"ix86_binary_operator_ok (MINUS, SImode, operands)"
"sbb{l}\t{%2, %0|%0, %2}"
[(set_attr "type" "alu")
+ (set_attr "use_carry" "1")
(set_attr "pent_pair" "pu")
(set_attr "mode" "SI")])
@@ -15162,7 +15199,7 @@
? gen_rtx_REG (XCmode, FIRST_FLOAT_REG) : NULL),
operands[0], const0_rtx,
GEN_INT ((TARGET_64BIT
- ? (DEFAULT_ABI == SYSV_ABI
+ ? (ix86_abi == SYSV_ABI
? X86_64_SSE_REGPARM_MAX
: X64_SSE_REGPARM_MAX)
: X86_32_SSE_REGPARM_MAX)
@@ -15242,6 +15279,7 @@
"reload_completed"
"ret"
[(set_attr "length" "1")
+ (set_attr "atom_unit" "jeu")
(set_attr "length_immediate" "0")
(set_attr "modrm" "0")])
@@ -15254,6 +15292,7 @@
"reload_completed"
"rep\;ret"
[(set_attr "length" "1")
+ (set_attr "atom_unit" "jeu")
(set_attr "length_immediate" "0")
(set_attr "prefix_rep" "1")
(set_attr "modrm" "0")])
@@ -15264,6 +15303,7 @@
"reload_completed"
"ret\t%0"
[(set_attr "length" "3")
+ (set_attr "atom_unit" "jeu")
(set_attr "length_immediate" "2")
(set_attr "modrm" "0")])
@@ -15612,7 +15652,7 @@
(bswap:SI (match_operand:SI 1 "register_operand" "")))]
""
{
- if (!TARGET_BSWAP)
+ if (!(TARGET_BSWAP || TARGET_MOVBE))
{
rtx x = operands[0];
@@ -15624,6 +15664,21 @@
}
})
+(define_insn "*bswapsi_movbe"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,m")
+ (bswap:SI (match_operand:SI 1 "nonimmediate_operand" "0,m,r")))]
+ "TARGET_MOVBE && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+ "@
+ bswap\t%0
+ movbe\t{%1, %0|%0, %1}
+ movbe\t{%1, %0|%0, %1}"
+ [(set_attr "type" "*,imov,imov")
+ (set_attr "modrm" "*,1,1")
+ (set_attr "prefix_0f" "1")
+ (set_attr "prefix_extra" "*,1,1")
+ (set_attr "length" "2,*,*")
+ (set_attr "mode" "SI")])
+
(define_insn "*bswapsi_1"
[(set (match_operand:SI 0 "register_operand" "=r")
(bswap:SI (match_operand:SI 1 "register_operand" "0")))]
@@ -15652,7 +15707,29 @@
[(set_attr "length" "4")
(set_attr "mode" "HI")])
-(define_insn "bswapdi2"
+(define_expand "bswapdi2"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (bswap:DI (match_operand:DI 1 "register_operand" "")))]
+ "TARGET_64BIT"
+ "")
+
+(define_insn "*bswapdi_movbe"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m")
+ (bswap:DI (match_operand:DI 1 "nonimmediate_operand" "0,m,r")))]
+ "TARGET_64BIT && TARGET_MOVBE
+ && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+ "@
+ bswap\t%0
+ movbe\t{%1, %0|%0, %1}
+ movbe\t{%1, %0|%0, %1}"
+ [(set_attr "type" "*,imov,imov")
+ (set_attr "modrm" "*,1,1")
+ (set_attr "prefix_0f" "1")
+ (set_attr "prefix_extra" "*,1,1")
+ (set_attr "length" "3,*,*")
+ (set_attr "mode" "DI")])
+
+(define_insn "*bswapdi_1"
[(set (match_operand:DI 0 "register_operand" "=r")
(bswap:DI (match_operand:DI 1 "register_operand" "0")))]
"TARGET_64BIT"
@@ -16380,6 +16457,7 @@
"TARGET_SSE_MATH"
"%vrcpss\t{%1, %d0|%d0, %1}"
[(set_attr "type" "sse")
+ (set_attr "atom_sse_attr" "rcp")
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "SF")])
@@ -16731,6 +16809,7 @@
"TARGET_SSE_MATH"
"%vrsqrtss\t{%1, %d0|%d0, %1}"
[(set_attr "type" "sse")
+ (set_attr "atom_sse_attr" "rcp")
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "SF")])
@@ -16751,6 +16830,7 @@
"SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH"
"%vsqrts<ssemodefsuffix>\t{%1, %d0|%d0, %1}"
[(set_attr "type" "sse")
+ (set_attr "atom_sse_attr" "sqrt")
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "<MODE>")
(set_attr "athlon_decode" "*")
@@ -19807,6 +19887,7 @@
; Since we don't have the proper number of operands for an alu insn,
; fill in all the blanks.
[(set_attr "type" "alu")
+ (set_attr "use_carry" "1")
(set_attr "pent_pair" "pu")
(set_attr "memory" "none")
(set_attr "imm_disp" "false")
@@ -19822,6 +19903,7 @@
""
"sbb{q}\t%0, %0"
[(set_attr "type" "alu")
+ (set_attr "use_carry" "1")
(set_attr "pent_pair" "pu")
(set_attr "memory" "none")
(set_attr "imm_disp" "false")
@@ -19865,6 +19947,7 @@
; Since we don't have the proper number of operands for an alu insn,
; fill in all the blanks.
[(set_attr "type" "alu")
+ (set_attr "use_carry" "1")
(set_attr "pent_pair" "pu")
(set_attr "memory" "none")
(set_attr "imm_disp" "false")
@@ -19880,6 +19963,7 @@
""
"sbb{l}\t%0, %0"
[(set_attr "type" "alu")
+ (set_attr "use_carry" "1")
(set_attr "pent_pair" "pu")
(set_attr "memory" "none")
(set_attr "imm_disp" "false")
@@ -20212,7 +20296,8 @@
}
}
[(set (attr "type")
- (cond [(eq_attr "alternative" "0")
+ (cond [(and (eq_attr "alternative" "0")
+ (eq (symbol_ref "TARGET_OPT_AGU") (const_int 0)))
(const_string "alu")
(match_operand:SI 2 "const0_operand" "")
(const_string "imov")
@@ -20255,7 +20340,8 @@
}
}
[(set (attr "type")
- (cond [(eq_attr "alternative" "0")
+ (cond [(and (eq_attr "alternative" "0")
+ (eq (symbol_ref "TARGET_OPT_AGU") (const_int 0)))
(const_string "alu")
(match_operand:DI 2 "const0_operand" "")
(const_string "imov")
@@ -21753,6 +21839,7 @@
return patterns[locality];
}
[(set_attr "type" "sse")
+ (set_attr "atom_sse_attr" "prefetch")
(set_attr "memory" "none")])
(define_insn "*prefetch_sse_rex"
@@ -21771,6 +21858,7 @@
return patterns[locality];
}
[(set_attr "type" "sse")
+ (set_attr "atom_sse_attr" "prefetch")
(set_attr "memory" "none")])
(define_insn "*prefetch_3dnow"
@@ -21972,6 +22060,93 @@
(set_attr "prefix_extra" "1")
(set_attr "mode" "DI")])
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; LWP instructions
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(define_expand "lwp_llwpcb"
+ [(unspec_volatile [(match_operand 0 "register_operand" "r")]
+ UNSPECV_LLWP_INTRINSIC)]
+ "TARGET_LWP"
+ "")
+
+(define_insn "*lwp_llwpcb<mode>1"
+ [(unspec_volatile [(match_operand:P 0 "register_operand" "r")]
+ UNSPECV_LLWP_INTRINSIC)]
+ "TARGET_LWP"
+ "llwpcb\t%0"
+ [(set_attr "type" "lwp")
+ (set_attr "mode" "<MODE>")
+ (set_attr "length" "5")])
+
+(define_expand "lwp_slwpcb"
+ [(set (match_operand 0 "register_operand" "=r")
+ (unspec_volatile [(const_int 0)] UNSPECV_SLWP_INTRINSIC))]
+ "TARGET_LWP"
+ {
+ if (TARGET_64BIT)
+ emit_insn (gen_lwp_slwpcbdi (operands[0]));
+ else
+ emit_insn (gen_lwp_slwpcbsi (operands[0]));
+ DONE;
+ })
+
+(define_insn "lwp_slwpcb<mode>"
+ [(set (match_operand:P 0 "register_operand" "=r")
+ (unspec_volatile:P [(const_int 0)] UNSPECV_SLWP_INTRINSIC))]
+ "TARGET_LWP"
+ "slwpcb\t%0"
+ [(set_attr "type" "lwp")
+ (set_attr "mode" "<MODE>")
+ (set_attr "length" "5")])
+
+(define_expand "lwp_lwpval<mode>3"
+ [(unspec_volatile [(match_operand:SWI48 1 "register_operand" "r")
+ (match_operand:SI 2 "nonimmediate_operand" "rm")
+ (match_operand:SI 3 "const_int_operand" "i")]
+ UNSPECV_LWPVAL_INTRINSIC)]
+ "TARGET_LWP"
+ "/* Avoid unused variable warning. */
+ (void) operand0;")
+
+(define_insn "*lwp_lwpval<mode>3_1"
+ [(unspec_volatile [(match_operand:SWI48 0 "register_operand" "r")
+ (match_operand:SI 1 "nonimmediate_operand" "rm")
+ (match_operand:SI 2 "const_int_operand" "i")]
+ UNSPECV_LWPVAL_INTRINSIC)]
+ "TARGET_LWP"
+ "lwpval\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "lwp")
+ (set_attr "mode" "<MODE>")
+ (set (attr "length")
+ (symbol_ref "ix86_attr_length_address_default (insn) + 9"))])
+
+(define_expand "lwp_lwpins<mode>3"
+ [(set (reg:CCC FLAGS_REG)
+ (unspec_volatile:CCC [(match_operand:SWI48 1 "register_operand" "r")
+ (match_operand:SI 2 "nonimmediate_operand" "rm")
+ (match_operand:SI 3 "const_int_operand" "i")]
+ UNSPECV_LWPINS_INTRINSIC))
+ (set (match_operand:QI 0 "nonimmediate_operand" "=qm")
+ (eq:QI (reg:CCC FLAGS_REG) (const_int 0)))]
+ "TARGET_LWP"
+ "")
+
+(define_insn "*lwp_lwpins<mode>3_1"
+ [(set (reg:CCC FLAGS_REG)
+ (unspec_volatile:CCC [(match_operand:SWI48 0 "register_operand" "r")
+ (match_operand:SI 1 "nonimmediate_operand" "rm")
+ (match_operand:SI 2 "const_int_operand" "i")]
+ UNSPECV_LWPINS_INTRINSIC))]
+ "TARGET_LWP"
+ "lwpins\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "lwp")
+ (set_attr "mode" "<MODE>")
+ (set (attr "length")
+ (symbol_ref "ix86_attr_length_address_default (insn) + 9"))])
+
(include "mmx.md")
(include "sse.md")
(include "sync.md")
diff --git a/gcc-4.4.3/gcc/config/i386/i386.opt b/gcc-4.4.3/gcc/config/i386/i386.opt
index 05727be7b..c2562e48d 100644
--- a/gcc-4.4.3/gcc/config/i386/i386.opt
+++ b/gcc-4.4.3/gcc/config/i386/i386.opt
@@ -232,6 +232,10 @@ mtune=
Target RejectNegative Joined Var(ix86_tune_string)
Schedule code for given CPU
+mabi=
+Target RejectNegative Joined Var(ix86_abi_string)
+Generate code that conforms to the given ABI
+
mveclibabi=
Target RejectNegative Joined Var(ix86_veclibabi_string)
Vector library ABI to use
@@ -323,6 +327,10 @@ msse5
Target Report Mask(ISA_SSE5) Var(ix86_isa_flags) VarExists Save
Support SSE5 built-in functions and code generation
+mlwp
+Target Report Mask(ISA_LWP) Var(ix86_isa_flags) VarExists Save
+Support LWP built-in functions and code generation
+
mabm
Target Report Mask(ISA_ABM) Var(ix86_isa_flags) VarExists Save
Support code generation of Advanced Bit Manipulation (ABM) instructions.
@@ -339,6 +347,10 @@ msahf
Target Report Mask(ISA_SAHF) Var(ix86_isa_flags) VarExists Save
Support code generation of sahf instruction in 64bit x86-64 code.
+mmovbe
+Target Report Mask(ISA_MOVBE) Var(ix86_isa_flags) VarExists Save
+Support code generation of movbe instruction.
+
maes
Target Report Mask(ISA_AES) Var(ix86_isa_flags) VarExists Save
Support AES built-in functions and code generation
diff --git a/gcc-4.4.3/gcc/config/i386/linux-unwind.h b/gcc-4.4.3/gcc/config/i386/linux-unwind.h
index 89f238a6e..d73f354ba 100644
--- a/gcc-4.4.3/gcc/config/i386/linux-unwind.h
+++ b/gcc-4.4.3/gcc/config/i386/linux-unwind.h
@@ -106,7 +106,7 @@ x86_64_fallback_frame_state (struct _Unwind_Context *context,
signal-turned-exceptions for them. There's also no configure-run for
the target, so we can't check on (e.g.) HAVE_SYS_UCONTEXT_H. Using the
target libc version macro should be enough. */
-#if !(__GLIBC__ == 2 && __GLIBC_MINOR__ == 0)
+#if defined __GLIBC__ && !(__GLIBC__ == 2 && __GLIBC_MINOR__ == 0)
#include <signal.h>
#include <sys/ucontext.h>
diff --git a/gcc-4.4.3/gcc/config/i386/linux.h b/gcc-4.4.3/gcc/config/i386/linux.h
index 4f19b20ea..f3a98c26a 100644
--- a/gcc-4.4.3/gcc/config/i386/linux.h
+++ b/gcc-4.4.3/gcc/config/i386/linux.h
@@ -107,7 +107,7 @@ along with GCC; see the file COPYING3. If not see
#undef ASM_SPEC
#define ASM_SPEC \
- "%{v:-V} %{Qy:} %{!Qn:-Qy} %{n} %{T} %{Ym,*} %{Yd,*} %{Wa,*:%*} \
+ "%{v:-V} %{Qy:} %{!Qn:-Qy} %{n} %{T} %{Ym,*} %{Yd,*} %{Wa,*:%*} --32 \
%{!mno-sse2avx:%{mavx:-msse2avx}} %{msse2avx:%{!mavx:-msse2avx}}"
/* These may be provided by config/linux-grtev2.h. */
diff --git a/gcc-4.4.3/gcc/config/i386/linux64.h b/gcc-4.4.3/gcc/config/i386/linux64.h
index 9fe1d0aca..17d972cfb 100644
--- a/gcc-4.4.3/gcc/config/i386/linux64.h
+++ b/gcc-4.4.3/gcc/config/i386/linux64.h
@@ -64,11 +64,6 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#define GLIBC_DYNAMIC_LINKER32 RUNTIME_ROOT_PREFIX "/lib/ld-linux.so.2"
#define GLIBC_DYNAMIC_LINKER64 RUNTIME_ROOT_PREFIX "/lib64/ld-linux-x86-64.so.2"
-#undef ASM_SPEC
-#define ASM_SPEC "%{v:-V} %{Qy:} %{!Qn:-Qy} %{n} %{T} %{Ym,*} %{Yd,*} \
- %{Wa,*:%*} %{m32:--32} %{m64:--64} \
- %{!mno-sse2avx:%{mavx:-msse2avx}} %{msse2avx:%{!mavx:-msse2avx}}"
-
#if TARGET_64BIT_DEFAULT
#define SPEC_32 "m32"
#define SPEC_64 "!m32"
@@ -77,6 +72,11 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#define SPEC_64 "m64"
#endif
+#undef ASM_SPEC
+#define ASM_SPEC "%{v:-V} %{Qy:} %{!Qn:-Qy} %{n} %{T} %{Ym,*} %{Yd,*} \
+ %{Wa,*:%*} %{" SPEC_32 ":--32} %{" SPEC_64 ":--64} \
+ %{!mno-sse2avx:%{mavx:-msse2avx}} %{msse2avx:%{!mavx:-msse2avx}}"
+
#undef LINK_SPEC
#define LINK_SPEC "%{" SPEC_64 ":-m elf_x86_64} %{" SPEC_32 ":-m elf_i386} \
%{shared:-shared} \
diff --git a/gcc-4.4.3/gcc/config/i386/lwpintrin.h b/gcc-4.4.3/gcc/config/i386/lwpintrin.h
new file mode 100644
index 000000000..954b039e5
--- /dev/null
+++ b/gcc-4.4.3/gcc/config/i386/lwpintrin.h
@@ -0,0 +1,100 @@
+/* Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ GCC is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _X86INTRIN_H_INCLUDED
+# error "Never use <lwpintrin.h> directly; include <x86intrin.h> instead."
+#endif
+
+#ifndef _LWPINTRIN_H_INCLUDED
+#define _LWPINTRIN_H_INCLUDED
+
+#ifndef __LWP__
+# error "LWP instruction set not enabled"
+#else
+
+extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+__llwpcb (void *pcbAddress)
+{
+ __builtin_ia32_llwpcb (pcbAddress);
+}
+
+extern __inline void * __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+__slwpcb (void)
+{
+ return __builtin_ia32_slwpcb ();
+}
+
+#ifdef __OPTIMIZE__
+extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+__lwpval32 (unsigned int data2, unsigned int data1, unsigned int flags)
+{
+ __builtin_ia32_lwpval32 (data2, data1, flags);
+}
+
+#ifdef __x86_64__
+extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+__lwpval64 (unsigned long long data2, unsigned int data1, unsigned int flags)
+{
+ __builtin_ia32_lwpval64 (data2, data1, flags);
+}
+#endif
+#else
+#define __lwpval32(D2, D1, F) \
+ (__builtin_ia32_lwpval32 ((unsigned int) (D2), (unsigned int) (D1), \
+ (unsigned int) (F)))
+#ifdef __x86_64__
+#define __lwpval64(D2, D1, F) \
+ (__builtin_ia32_lwpval64 ((unsigned long long) (D2), (unsigned int) (D1), \
+ (unsigned int) (F)))
+#endif
+#endif
+
+
+#ifdef __OPTIMIZE__
+extern __inline unsigned char __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+__lwpins32 (unsigned int data2, unsigned int data1, unsigned int flags)
+{
+ return __builtin_ia32_lwpins32 (data2, data1, flags);
+}
+
+#ifdef __x86_64__
+extern __inline unsigned char __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+__lwpins64 (unsigned long long data2, unsigned int data1, unsigned int flags)
+{
+ return __builtin_ia32_lwpins64 (data2, data1, flags);
+}
+#endif
+#else
+#define __lwpins32(D2, D1, F) \
+ (__builtin_ia32_lwpins32 ((unsigned int) (D2), (unsigned int) (D1), \
+ (unsigned int) (F)))
+#ifdef __x86_64__
+#define __lwpins64(D2, D1, F) \
+ (__builtin_ia32_lwpins64 ((unsigned long long) (D2), (unsigned int) (D1), \
+ (unsigned int) (F)))
+#endif
+#endif
+
+#endif /* __LWP__ */
+
+#endif /* _LWPINTRIN_H_INCLUDED */
diff --git a/gcc-4.4.3/gcc/config/i386/mingw32.h b/gcc-4.4.3/gcc/config/i386/mingw32.h
index f3fbe8c58..746d7d105 100644
--- a/gcc-4.4.3/gcc/config/i386/mingw32.h
+++ b/gcc-4.4.3/gcc/config/i386/mingw32.h
@@ -38,7 +38,7 @@ along with GCC; see the file COPYING3. If not see
builtin_define_std ("WINNT"); \
builtin_define_with_int_value ("_INTEGRAL_MAX_BITS", \
TYPE_PRECISION (intmax_type_node));\
- if (TARGET_64BIT && DEFAULT_ABI == MS_ABI) \
+ if (TARGET_64BIT && ix86_abi == MS_ABI) \
{ \
builtin_define ("__MINGW64__"); \
builtin_define_std ("WIN64"); \
diff --git a/gcc-4.4.3/gcc/config/i386/ppro.md b/gcc-4.4.3/gcc/config/i386/ppro.md
index 5e163d829..20f457ab1 100644
--- a/gcc-4.4.3/gcc/config/i386/ppro.md
+++ b/gcc-4.4.3/gcc/config/i386/ppro.md
@@ -731,7 +731,7 @@
(define_insn_reservation "ppro_insn" 1
(and (eq_attr "cpu" "pentiumpro")
(and (eq_attr "memory" "none,unknown")
- (eq_attr "type" "alu,alu1,negnot,incdec,icmp,test,setcc,icmov,push,pop,fxch,sseiadd,sseishft,sseimul,mmx,mmxadd,mmxcmp")))
+ (eq_attr "type" "alu,alu1,negnot,incdec,icmp,test,setcc,icmov,push,pop,fxch,sseiadd,sseishft,sseishft1,sseimul,mmx,mmxadd,mmxcmp")))
"decodern,(p0|p1)")
;; read-modify and register-memory instructions have 2 or three uops,
@@ -739,13 +739,13 @@
(define_insn_reservation "ppro_insn_load" 3
(and (eq_attr "cpu" "pentiumpro")
(and (eq_attr "memory" "load")
- (eq_attr "type" "alu,alu1,negnot,incdec,icmp,test,setcc,icmov,push,pop,fxch,sseiadd,sseishft,sseimul,mmx,mmxadd,mmxcmp")))
+ (eq_attr "type" "alu,alu1,negnot,incdec,icmp,test,setcc,icmov,push,pop,fxch,sseiadd,sseishft,sseishft1,sseimul,mmx,mmxadd,mmxcmp")))
"decoder0,p2+(p0|p1)")
(define_insn_reservation "ppro_insn_store" 1
(and (eq_attr "cpu" "pentiumpro")
(and (eq_attr "memory" "store")
- (eq_attr "type" "alu,alu1,negnot,incdec,icmp,test,setcc,icmov,push,pop,fxch,sseiadd,sseishft,sseimul,mmx,mmxadd,mmxcmp")))
+ (eq_attr "type" "alu,alu1,negnot,incdec,icmp,test,setcc,icmov,push,pop,fxch,sseiadd,sseishft,sseishft1,sseimul,mmx,mmxadd,mmxcmp")))
"decoder0,(p0|p1),p4+p3")
;; read-modify-store instructions produce 4 uops so they have to be
@@ -753,6 +753,6 @@
(define_insn_reservation "ppro_insn_both" 4
(and (eq_attr "cpu" "pentiumpro")
(and (eq_attr "memory" "both")
- (eq_attr "type" "alu,alu1,negnot,incdec,icmp,test,setcc,icmov,push,pop,fxch,sseiadd,sseishft,sseimul,mmx,mmxadd,mmxcmp")))
+ (eq_attr "type" "alu,alu1,negnot,incdec,icmp,test,setcc,icmov,push,pop,fxch,sseiadd,sseishft,sseishft1,sseimul,mmx,mmxadd,mmxcmp")))
"decoder0,p2+(p0|p1),p4+p3")
diff --git a/gcc-4.4.3/gcc/config/i386/sse.md b/gcc-4.4.3/gcc/config/i386/sse.md
index ea5fb3440..cae9eed3b 100644
--- a/gcc-4.4.3/gcc/config/i386/sse.md
+++ b/gcc-4.4.3/gcc/config/i386/sse.md
@@ -342,6 +342,7 @@
&& !(MEM_P (operands[0]) && MEM_P (operands[1]))"
"vmovup<avxmodesuffixf2c>\t{%1, %0|%0, %1}"
[(set_attr "type" "ssemov")
+ (set_attr "movu" "1")
(set_attr "prefix" "vex")
(set_attr "mode" "<MODE>")])
@@ -367,6 +368,7 @@
&& !(MEM_P (operands[0]) && MEM_P (operands[1]))"
"movup<ssemodesuffixf2c>\t{%1, %0|%0, %1}"
[(set_attr "type" "ssemov")
+ (set_attr "movu" "1")
(set_attr "mode" "<MODE>")])
(define_insn "avx_movdqu<avxmodesuffix>"
@@ -377,6 +379,7 @@
"TARGET_AVX && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
"vmovdqu\t{%1, %0|%0, %1}"
[(set_attr "type" "ssemov")
+ (set_attr "movu" "1")
(set_attr "prefix" "vex")
(set_attr "mode" "<avxvecmode>")])
@@ -387,6 +390,7 @@
"TARGET_SSE2 && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
"movdqu\t{%1, %0|%0, %1}"
[(set_attr "type" "ssemov")
+ (set_attr "movu" "1")
(set_attr "prefix_data16" "1")
(set_attr "mode" "TI")])
@@ -428,7 +432,7 @@
UNSPEC_MOVNT))]
"TARGET_SSE2"
"movntdq\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssecvt")
+ [(set_attr "type" "ssemov")
(set_attr "prefix_data16" "1")
(set_attr "mode" "TI")])
@@ -438,7 +442,7 @@
UNSPEC_MOVNT))]
"TARGET_SSE2"
"movnti\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssecvt")
+ [(set_attr "type" "ssemov")
(set_attr "mode" "V2DF")])
(define_insn "avx_lddqu<avxmodesuffix>"
@@ -449,6 +453,7 @@
"TARGET_AVX"
"vlddqu\t{%1, %0|%0, %1}"
[(set_attr "type" "ssecvt")
+ (set_attr "movu" "1")
(set_attr "prefix" "vex")
(set_attr "mode" "<avxvecmode>")])
@@ -458,7 +463,8 @@
UNSPEC_LDDQU))]
"TARGET_SSE3"
"lddqu\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssecvt")
+ [(set_attr "type" "ssemov")
+ (set_attr "movu" "1")
(set_attr "prefix_rep" "1")
(set_attr "mode" "TI")])
@@ -765,6 +771,7 @@
"TARGET_SSE"
"%vrcpps\t{%1, %0|%0, %1}"
[(set_attr "type" "sse")
+ (set_attr "atom_sse_attr" "rcp")
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "V4SF")])
@@ -791,6 +798,7 @@
"TARGET_SSE"
"rcpss\t{%1, %0|%0, %1}"
[(set_attr "type" "sse")
+ (set_attr "atom_sse_attr" "rcp")
(set_attr "mode" "SF")])
(define_expand "sqrtv8sf2"
@@ -836,6 +844,7 @@
"TARGET_SSE"
"%vsqrtps\t{%1, %0|%0, %1}"
[(set_attr "type" "sse")
+ (set_attr "atom_sse_attr" "sqrt")
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "V4SF")])
@@ -880,6 +889,7 @@
"SSE_VEC_FLOAT_MODE_P (<MODE>mode)"
"sqrts<ssemodesuffixf2c>\t{%1, %0|%0, %1}"
[(set_attr "type" "sse")
+ (set_attr "atom_sse_attr" "sqrt")
(set_attr "mode" "<ssescalarmode>")])
(define_expand "rsqrtv8sf2"
@@ -1043,7 +1053,7 @@
(const_int 1)))]
"SSE_VEC_FLOAT_MODE_P (<MODE>mode)"
"<maxminfprefix>s<ssemodesuffixf2c>\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")
+ [(set_attr "type" "sseadd")
(set_attr "mode" "<ssescalarmode>")])
;; These versions of the min/max patterns implement exactly the operations
@@ -1179,6 +1189,7 @@
"TARGET_SSE3"
"addsubpd\t{%2, %0|%0, %2}"
[(set_attr "type" "sseadd")
+ (set_attr "atom_unit" "complex")
(set_attr "mode" "V2DF")])
(define_insn "avx_h<plusminus_insn>v4df3"
@@ -1302,6 +1313,7 @@
"TARGET_SSE3"
"h<plusminus_mnemonic>ps\t{%2, %0|%0, %2}"
[(set_attr "type" "sseadd")
+ (set_attr "atom_unit" "complex")
(set_attr "prefix_rep" "1")
(set_attr "mode" "V4SF")])
@@ -5069,6 +5081,7 @@
"TARGET_SSE2 && ix86_binary_operator_ok (MULT, V8HImode, operands)"
"pmaddwd\t{%2, %0|%0, %2}"
[(set_attr "type" "sseiadd")
+ (set_attr "atom_unit" "simul")
(set_attr "prefix_data16" "1")
(set_attr "mode" "TI")])
@@ -7018,7 +7031,7 @@
vpsrldq\t{$8, %1, %0|%0, %1, 8}
vmovq\t{%H1, %0|%0, %H1}
vmov{q}\t{%H1, %0|%0, %H1}"
- [(set_attr "type" "ssemov,sseishft,ssemov,imov")
+ [(set_attr "type" "ssemov,sseishft1,ssemov,imov")
(set_attr "memory" "*,none,*,*")
(set_attr "prefix" "vex")
(set_attr "mode" "V2SF,TI,TI,DI")])
@@ -7034,7 +7047,7 @@
psrldq\t{$8, %0|%0, 8}
movq\t{%H1, %0|%0, %H1}
mov{q}\t{%H1, %0|%0, %H1}"
- [(set_attr "type" "ssemov,sseishft,ssemov,imov")
+ [(set_attr "type" "ssemov,sseishft1,ssemov,imov")
(set_attr "memory" "*,none,*,*")
(set_attr "mode" "V2SF,TI,TI,DI")])
@@ -7050,7 +7063,7 @@
vmovhps\t{%1, %0|%0, %1}
vpsrldq\t{$8, %1, %0|%0, %1, 8}
vmovq\t{%H1, %0|%0, %H1}"
- [(set_attr "type" "ssemov,sseishft,ssemov")
+ [(set_attr "type" "ssemov,sseishft1,ssemov")
(set_attr "memory" "*,none,*")
(set_attr "prefix" "vex")
(set_attr "mode" "V2SF,TI,TI")])
@@ -7066,7 +7079,7 @@
movhps\t{%1, %0|%0, %1}
psrldq\t{$8, %0|%0, 8}
movq\t{%H1, %0|%0, %H1}"
- [(set_attr "type" "ssemov,sseishft,ssemov")
+ [(set_attr "type" "ssemov,sseishft1,ssemov")
(set_attr "memory" "*,none,*")
(set_attr "mode" "V2SF,TI,TI")])
@@ -7624,6 +7637,7 @@
"TARGET_SSE2"
"psadbw\t{%2, %0|%0, %2}"
[(set_attr "type" "sseiadd")
+ (set_attr "atom_unit" "simul")
(set_attr "prefix_data16" "1")
(set_attr "mode" "TI")])
@@ -7645,7 +7659,7 @@
UNSPEC_MOVMSK))]
"SSE_VEC_FLOAT_MODE_P (<MODE>mode)"
"%vmovmskp<ssemodesuffixf2c>\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssecvt")
+ [(set_attr "type" "ssemov")
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "<MODE>")])
@@ -7655,7 +7669,7 @@
UNSPEC_MOVMSK))]
"TARGET_SSE2"
"%vpmovmskb\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssecvt")
+ [(set_attr "type" "ssemov")
(set_attr "prefix_data16" "1")
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "SI")])
@@ -7678,7 +7692,7 @@
"TARGET_SSE2 && !TARGET_64BIT"
;; @@@ check ordering of operands in intel/nonintel syntax
"%vmaskmovdqu\t{%2, %1|%1, %2}"
- [(set_attr "type" "ssecvt")
+ [(set_attr "type" "ssemov")
(set_attr "prefix_data16" "1")
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "TI")])
@@ -7692,7 +7706,7 @@
"TARGET_SSE2 && TARGET_64BIT"
;; @@@ check ordering of operands in intel/nonintel syntax
"%vmaskmovdqu\t{%2, %1|%1, %2}"
- [(set_attr "type" "ssecvt")
+ [(set_attr "type" "ssemov")
(set_attr "prefix_data16" "1")
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "TI")])
@@ -7703,6 +7717,7 @@
"TARGET_SSE"
"%vldmxcsr\t%0"
[(set_attr "type" "sse")
+ (set_attr "atom_sse_attr" "mxcsr")
(set_attr "prefix" "maybe_vex")
(set_attr "memory" "load")])
@@ -7712,6 +7727,7 @@
"TARGET_SSE"
"%vstmxcsr\t%0"
[(set_attr "type" "sse")
+ (set_attr "atom_sse_attr" "mxcsr")
(set_attr "prefix" "maybe_vex")
(set_attr "memory" "store")])
@@ -7730,6 +7746,7 @@
"TARGET_SSE || TARGET_3DNOW_A"
"sfence"
[(set_attr "type" "sse")
+ (set_attr "atom_sse_attr" "fence")
(set_attr "memory" "unknown")])
(define_insn "sse2_clflush"
@@ -7738,6 +7755,7 @@
"TARGET_SSE2"
"clflush\t%a0"
[(set_attr "type" "sse")
+ (set_attr "atom_sse_attr" "fence")
(set_attr "memory" "unknown")])
(define_expand "sse2_mfence"
@@ -7755,6 +7773,7 @@
"TARGET_64BIT || TARGET_SSE2"
"mfence"
[(set_attr "type" "sse")
+ (set_attr "atom_sse_attr" "fence")
(set_attr "memory" "unknown")])
(define_expand "sse2_lfence"
@@ -7772,6 +7791,7 @@
"TARGET_SSE2"
"lfence"
[(set_attr "type" "sse")
+ (set_attr "atom_sse_attr" "lfence")
(set_attr "memory" "unknown")])
(define_insn "sse3_mwait"
@@ -7895,6 +7915,7 @@
"TARGET_SSSE3"
"phaddw\t{%2, %0|%0, %2}"
[(set_attr "type" "sseiadd")
+ (set_attr "atom_unit" "complex")
(set_attr "prefix_data16" "1")
(set_attr "prefix_extra" "1")
(set_attr "mode" "TI")])
@@ -7923,6 +7944,7 @@
"TARGET_SSSE3"
"phaddw\t{%2, %0|%0, %2}"
[(set_attr "type" "sseiadd")
+ (set_attr "atom_unit" "complex")
(set_attr "prefix_extra" "1")
(set_attr "mode" "DI")])
@@ -7977,6 +7999,7 @@
"TARGET_SSSE3"
"phaddd\t{%2, %0|%0, %2}"
[(set_attr "type" "sseiadd")
+ (set_attr "atom_unit" "complex")
(set_attr "prefix_data16" "1")
(set_attr "prefix_extra" "1")
(set_attr "mode" "TI")])
@@ -7997,6 +8020,7 @@
"TARGET_SSSE3"
"phaddd\t{%2, %0|%0, %2}"
[(set_attr "type" "sseiadd")
+ (set_attr "atom_unit" "complex")
(set_attr "prefix_extra" "1")
(set_attr "mode" "DI")])
@@ -8083,6 +8107,7 @@
"TARGET_SSSE3"
"phaddsw\t{%2, %0|%0, %2}"
[(set_attr "type" "sseiadd")
+ (set_attr "atom_unit" "complex")
(set_attr "prefix_data16" "1")
(set_attr "prefix_extra" "1")
(set_attr "mode" "TI")])
@@ -8111,6 +8136,7 @@
"TARGET_SSSE3"
"phaddsw\t{%2, %0|%0, %2}"
[(set_attr "type" "sseiadd")
+ (set_attr "atom_unit" "complex")
(set_attr "prefix_extra" "1")
(set_attr "mode" "DI")])
@@ -8197,6 +8223,7 @@
"TARGET_SSSE3"
"phsubw\t{%2, %0|%0, %2}"
[(set_attr "type" "sseiadd")
+ (set_attr "atom_unit" "complex")
(set_attr "prefix_data16" "1")
(set_attr "prefix_extra" "1")
(set_attr "mode" "TI")])
@@ -8225,6 +8252,7 @@
"TARGET_SSSE3"
"phsubw\t{%2, %0|%0, %2}"
[(set_attr "type" "sseiadd")
+ (set_attr "atom_unit" "complex")
(set_attr "prefix_extra" "1")
(set_attr "mode" "DI")])
@@ -8279,6 +8307,7 @@
"TARGET_SSSE3"
"phsubd\t{%2, %0|%0, %2}"
[(set_attr "type" "sseiadd")
+ (set_attr "atom_unit" "complex")
(set_attr "prefix_data16" "1")
(set_attr "prefix_extra" "1")
(set_attr "mode" "TI")])
@@ -8299,6 +8328,7 @@
"TARGET_SSSE3"
"phsubd\t{%2, %0|%0, %2}"
[(set_attr "type" "sseiadd")
+ (set_attr "atom_unit" "complex")
(set_attr "prefix_extra" "1")
(set_attr "mode" "DI")])
@@ -8385,6 +8415,7 @@
"TARGET_SSSE3"
"phsubsw\t{%2, %0|%0, %2}"
[(set_attr "type" "sseiadd")
+ (set_attr "atom_unit" "complex")
(set_attr "prefix_data16" "1")
(set_attr "prefix_extra" "1")
(set_attr "mode" "TI")])
@@ -8413,6 +8444,7 @@
"TARGET_SSSE3"
"phsubsw\t{%2, %0|%0, %2}"
[(set_attr "type" "sseiadd")
+ (set_attr "atom_unit" "complex")
(set_attr "prefix_extra" "1")
(set_attr "mode" "DI")])
@@ -8519,6 +8551,7 @@
"TARGET_SSSE3"
"pmaddubsw\t{%2, %0|%0, %2}"
[(set_attr "type" "sseiadd")
+ (set_attr "atom_unit" "simul")
(set_attr "prefix_data16" "1")
(set_attr "prefix_extra" "1")
(set_attr "mode" "TI")])
@@ -8557,6 +8590,7 @@
"TARGET_SSSE3"
"pmaddubsw\t{%2, %0|%0, %2}"
[(set_attr "type" "sseiadd")
+ (set_attr "atom_unit" "simul")
(set_attr "prefix_extra" "1")
(set_attr "mode" "DI")])
@@ -8764,6 +8798,7 @@
return "palignr\t{%3, %2, %0|%0, %2, %3}";
}
[(set_attr "type" "sseishft")
+ (set_attr "atom_unit" "sishuf")
(set_attr "prefix_data16" "1")
(set_attr "prefix_extra" "1")
(set_attr "mode" "TI")])
@@ -8780,6 +8815,7 @@
return "palignr\t{%3, %2, %0|%0, %2, %3}";
}
[(set_attr "type" "sseishft")
+ (set_attr "atom_unit" "sishuf")
(set_attr "prefix_extra" "1")
(set_attr "mode" "DI")])
@@ -8966,7 +9002,7 @@
UNSPEC_MOVNTDQA))]
"TARGET_SSE4_1"
"%vmovntdqa\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssecvt")
+ [(set_attr "type" "ssemov")
(set_attr "prefix_extra" "1")
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "TI")])
diff --git a/gcc-4.4.3/gcc/config/i386/ssemath.h b/gcc-4.4.3/gcc/config/i386/ssemath.h
new file mode 100644
index 000000000..357d6a378
--- /dev/null
+++ b/gcc-4.4.3/gcc/config/i386/ssemath.h
@@ -0,0 +1,25 @@
+/* Copyright (C) 2010
+ Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#undef TARGET_FPMATH_DEFAULT
+#define TARGET_FPMATH_DEFAULT (TARGET_SSE2 ? FPMATH_SSE : FPMATH_387)
+
+#undef TARGET_SUBTARGET32_ISA_DEFAULT
+#define TARGET_SUBTARGET32_ISA_DEFAULT \
+ (OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE | OPTION_MASK_ISA_SSE2)
diff --git a/gcc-4.4.3/gcc/config/i386/x86intrin.h b/gcc-4.4.3/gcc/config/i386/x86intrin.h
index d848811d3..fead76635 100644
--- a/gcc-4.4.3/gcc/config/i386/x86intrin.h
+++ b/gcc-4.4.3/gcc/config/i386/x86intrin.h
@@ -56,6 +56,10 @@
#include <bmmintrin.h>
#endif
+#ifdef __LWP__
+#include <lwpintrin.h>
+#endif
+
#if defined (__AES__) || defined (__PCLMUL__)
#include <wmmintrin.h>
#endif
diff --git a/gcc-4.4.3/gcc/config/linux-android.h b/gcc-4.4.3/gcc/config/linux-android.h
index a43bab5b0..5ca3858a2 100644
--- a/gcc-4.4.3/gcc/config/linux-android.h
+++ b/gcc-4.4.3/gcc/config/linux-android.h
@@ -20,6 +20,12 @@
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
+#define ANDROID_TARGET_OS_CPP_BUILTINS() \
+ do { \
+ if (OPTION_ANDROID) \
+ builtin_define ("__ANDROID__"); \
+ } while (0)
+
#if ANDROID_DEFAULT
# define NOANDROID "mno-android"
#else
diff --git a/gcc-4.4.3/gcc/config/linux.h b/gcc-4.4.3/gcc/config/linux.h
index 443db22bd..740ddb7be 100644
--- a/gcc-4.4.3/gcc/config/linux.h
+++ b/gcc-4.4.3/gcc/config/linux.h
@@ -42,7 +42,11 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
provides part of the support for getting C++ file-scope static
object constructed before entering `main'. */
-#if defined HAVE_LD_PIE
+#if defined (HAVE_LD_PIE) && defined (ENABLE_CRTBEGINTS)
+#define LINUX_TARGET_STARTFILE_SPEC \
+ "%{!shared: %{pg|p|profile:gcrt1.o%s;pie:Scrt1.o%s;:crt1.o%s}} crti.o%s \
+ %{static:%{pie:crtbeginTS.o%s;:crtbeginT.o%s}} %{!static:%{shared|pie:crtbeginS.o%s;:crtbegin.o%s}}"
+#elif defined (HAVE_LD_PIE) && ! defined (ENABLE_CRTBEGINTS)
#define LINUX_TARGET_STARTFILE_SPEC \
"%{!shared: %{pg|p|profile:gcrt1.o%s;pie:Scrt1.o%s;:crt1.o%s}} \
crti.o%s %{static:crtbeginT.o%s;shared|pie:crtbeginS.o%s;:crtbegin.o%s}"
@@ -96,8 +100,6 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
builtin_assert ("system=linux"); \
builtin_assert ("system=unix"); \
builtin_assert ("system=posix"); \
- if (OPTION_ANDROID) \
- builtin_define ("__ANDROID__"); \
} while (0)
#if defined(HAVE_LD_EH_FRAME_HDR)
diff --git a/gcc-4.4.3/gcc/config/mips/linux64.h b/gcc-4.4.3/gcc/config/mips/linux64.h
index 2f24dfa14..505d8b1d4 100644
--- a/gcc-4.4.3/gcc/config/mips/linux64.h
+++ b/gcc-4.4.3/gcc/config/mips/linux64.h
@@ -39,8 +39,10 @@ along with GCC; see the file COPYING3. If not see
#define GLIBC_DYNAMIC_LINKER64 "/lib64/ld.so.1"
#define GLIBC_DYNAMIC_LINKERN32 "/lib32/ld.so.1"
#define UCLIBC_DYNAMIC_LINKERN32 "/lib32/ld-uClibc.so.0"
+#define BIONIC_DYNAMIC_LINKERN32 "/system/bin/linker32"
#define LINUX_DYNAMIC_LINKERN32 \
- CHOOSE_DYNAMIC_LINKER (GLIBC_DYNAMIC_LINKERN32, UCLIBC_DYNAMIC_LINKERN32)
+ CHOOSE_DYNAMIC_LINKER (GLIBC_DYNAMIC_LINKERN32, UCLIBC_DYNAMIC_LINKERN32, \
+ BIONIC_DYNAMIC_LINKERN32)
#undef LINK_SPEC
#define LINK_SPEC "\
diff --git a/gcc-4.4.3/gcc/config/rs6000/linux64.h b/gcc-4.4.3/gcc/config/rs6000/linux64.h
index 3ccbe21c8..7ecf98742 100644
--- a/gcc-4.4.3/gcc/config/rs6000/linux64.h
+++ b/gcc-4.4.3/gcc/config/rs6000/linux64.h
@@ -156,7 +156,7 @@ extern int dot_symbols;
#endif
#define ASM_SPEC32 "-a32 %{n} %{T} %{Ym,*} %{Yd,*} \
-%{mrelocatable} %{mrelocatable-lib} %{fpic:-K PIC} %{fPIC:-K PIC} \
+%{mrelocatable} %{mrelocatable-lib} %{fpic|fPIC|fpie|fPIE:-K PIC} \
%{memb} %{!memb: %{msdata: -memb} %{msdata=eabi: -memb}} \
%{!mlittle: %{!mlittle-endian: %{!mbig: %{!mbig-endian: \
%{mcall-freebsd: -mbig} \
diff --git a/gcc-4.4.3/gcc/config/rs6000/sysv4.h b/gcc-4.4.3/gcc/config/rs6000/sysv4.h
index 339d51847..d9407e97d 100644
--- a/gcc-4.4.3/gcc/config/rs6000/sysv4.h
+++ b/gcc-4.4.3/gcc/config/rs6000/sysv4.h
@@ -883,7 +883,12 @@ SVR4_ASM_SPEC \
%{!mnewlib: %{pthread:-lpthread} %{shared:-lc} \
%{!shared: %{profile:-lc_p} %{!profile:-lc}}}"
-#ifdef HAVE_LD_PIE
+#if defined (HAVE_LD_PIE) && defined (ENABLE_CRTBEGINTS)
+#define STARTFILE_LINUX_SPEC "\
+%{!shared: %{pg|p|profile:gcrt1.o%s;pie:Scrt1.o%s;:crt1.o%s}} \
+%{mnewlib:ecrti.o%s;:crti.o%s} \
+%{static:%{pie:crtbeginTS.o%s;:crtbeginT.o%s}} %{!static:%{shared|pie:crtbeginS.o%s;:crtbegin.o%s}}"
+#elif defined (HAVE_LD_PIE) && ! defined (ENABLE_CRTBEGINTS)
#define STARTFILE_LINUX_SPEC "\
%{!shared: %{pg|p|profile:gcrt1.o%s;pie:Scrt1.o%s;:crt1.o%s}} \
%{mnewlib:ecrti.o%s;:crti.o%s} \
diff --git a/gcc-4.4.3/gcc/config/sparc/sparc.c b/gcc-4.4.3/gcc/config/sparc/sparc.c
index d007ce551..b7d94f545 100644
--- a/gcc-4.4.3/gcc/config/sparc/sparc.c
+++ b/gcc-4.4.3/gcc/config/sparc/sparc.c
@@ -6104,7 +6104,7 @@ enum rtx_code
sparc_emit_float_lib_cmp (rtx x, rtx y, enum rtx_code comparison)
{
const char *qpfunc;
- rtx slot0, slot1, result, tem, tem2;
+ rtx slot0, slot1, result, tem, tem2, libfunc;
enum machine_mode mode;
enum rtx_code new_comparison;
@@ -6167,7 +6167,8 @@ sparc_emit_float_lib_cmp (rtx x, rtx y, enum rtx_code comparison)
emit_move_insn (slot1, y);
}
- emit_library_call (gen_rtx_SYMBOL_REF (Pmode, qpfunc), LCT_NORMAL,
+ libfunc = gen_rtx_SYMBOL_REF (Pmode, qpfunc);
+ emit_library_call (libfunc, LCT_NORMAL,
DImode, 2,
XEXP (slot0, 0), Pmode,
XEXP (slot1, 0), Pmode);
@@ -6175,7 +6176,8 @@ sparc_emit_float_lib_cmp (rtx x, rtx y, enum rtx_code comparison)
}
else
{
- emit_library_call (gen_rtx_SYMBOL_REF (Pmode, qpfunc), LCT_NORMAL,
+ libfunc = gen_rtx_SYMBOL_REF (Pmode, qpfunc);
+ emit_library_call (libfunc, LCT_NORMAL,
SImode, 2,
x, TFmode, y, TFmode);
mode = SImode;
@@ -6186,7 +6188,7 @@ sparc_emit_float_lib_cmp (rtx x, rtx y, enum rtx_code comparison)
register so reload doesn't clobber the value if it needs
the return register for a spill reg. */
result = gen_reg_rtx (mode);
- emit_move_insn (result, hard_libcall_value (mode));
+ emit_move_insn (result, hard_libcall_value (mode, libfunc));
switch (comparison)
{
diff --git a/gcc-4.4.3/gcc/configure b/gcc-4.4.3/gcc/configure
index 47a400135..51db4d2b8 100755
--- a/gcc-4.4.3/gcc/configure
+++ b/gcc-4.4.3/gcc/configure
@@ -458,7 +458,7 @@ ac_includes_default="\
# include <unistd.h>
#endif"
-ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os target_noncanonical build_libsubdir build_subdir host_subdir target_subdir GENINSRC CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT GNATBIND ac_ct_GNATBIND GNATMAKE ac_ct_GNATMAKE NO_MINUS_C_MINUS_O OUTPUT_OPTION CPP EGREP loose_warn strict_warn warn_cflags nocommon_flag TREEBROWSER valgrind_path valgrind_path_defines valgrind_command coverage_flags enable_multilib enable_decimal_float enable_fixed_point enable_shared NATIVE_SYSTEM_HEADER_DIR RUNTIME_ROOT_PREFIX_DEFINE SYSROOT_CFLAGS_FOR_TARGET TARGET_SYSTEM_ROOT TARGET_SYSTEM_ROOT_DEFINE CROSS_SYSTEM_HEADER_DIR onestep PKGVERSION REPORT_BUGS_TO REPORT_BUGS_TEXI datarootdir docdir htmldir SET_MAKE AWK LN_S LN RANLIB ac_ct_RANLIB ranlib_flags INSTALL INSTALL_PROGRAM INSTALL_DATA make_compare_target have_mktemp_command MAKEINFO BUILD_INFO GENERATED_MANPAGES FLEX BISON NM AR COLLECT2_LIBS GNAT_LIBEXC LDEXP_LIB TARGET_GETGROUPS_T LIBICONV LTLIBICONV LIBICONV_DEP manext objext gthread_flags extra_modes_file extra_opt_files USE_NLS LIBINTL LIBINTL_DEP INCINTL XGETTEXT GMSGFMT POSUB CATALOGS DATADIRNAME INSTOBJEXT GENCAT CATOBJEXT CROSS ALL SYSTEM_HEADER_DIR inhibit_libc CC_FOR_BUILD BUILD_CFLAGS BUILD_LDFLAGS STMP_FIXINC STMP_FIXPROTO collect2 LIBTOOL SED FGREP GREP LD DUMPBIN ac_ct_DUMPBIN OBJDUMP ac_ct_OBJDUMP ac_ct_AR STRIP ac_ct_STRIP lt_ECHO DSYMUTIL ac_ct_DSYMUTIL NMEDIT ac_ct_NMEDIT LIPO ac_ct_LIPO OTOOL ac_ct_OTOOL OTOOL64 ac_ct_OTOOL64 objdir enable_fast_install gcc_cv_as ORIGINAL_AS_FOR_TARGET gcc_cv_ld ORIGINAL_LD_FOR_TARGET ORIGINAL_GOLD_FOR_TARGET gcc_cv_nm ORIGINAL_NM_FOR_TARGET gcc_cv_objdump gcc_cv_readelf libgcc_visibility GGC zlibdir zlibinc MAINT gcc_tooldir dollar slibdir subdirs srcdir all_compilers all_gtfiles all_lang_makefrags all_lang_makefiles all_languages all_selected_languages build_exeext build_install_headers_dir build_xm_file_list build_xm_include_list build_xm_defines build_file_translate check_languages cpp_install_dir xmake_file tmake_file extra_gcc_objs extra_headers_list extra_objs extra_parts extra_passes extra_programs float_h_file gcc_config_arguments gcc_gxx_include_dir host_exeext host_xm_file_list host_xm_include_list host_xm_defines out_host_hook_obj install lang_opt_files lang_specs_files lang_tree_files local_prefix md_file objc_boehm_gc out_file out_object_file thread_file tm_file_list tm_include_list tm_defines tm_p_file_list tm_p_include_list xm_file_list xm_include_list xm_defines c_target_objs cxx_target_objs fortran_target_objs target_cpu_default GMPLIBS GMPINC PPLLIBS PPLINC CLOOGLIBS CLOOGINC pluginlibs enable_plugin LIBOBJS LTLIBOBJS'
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os target_noncanonical build_libsubdir build_subdir host_subdir target_subdir GENINSRC CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT GNATBIND ac_ct_GNATBIND GNATMAKE ac_ct_GNATMAKE NO_MINUS_C_MINUS_O OUTPUT_OPTION CPP EGREP loose_warn strict_warn warn_cflags nocommon_flag TREEBROWSER valgrind_path valgrind_path_defines valgrind_command coverage_flags enable_multilib enable_decimal_float enable_fixed_point enable_shared NATIVE_SYSTEM_HEADER_DIR RUNTIME_ROOT_PREFIX_DEFINE SYSROOT_CFLAGS_FOR_TARGET TARGET_SYSTEM_ROOT TARGET_SYSTEM_ROOT_DEFINE CROSS_SYSTEM_HEADER_DIR onestep PKGVERSION REPORT_BUGS_TO REPORT_BUGS_TEXI datarootdir docdir htmldir SET_MAKE AWK LN_S LN RANLIB ac_ct_RANLIB ranlib_flags INSTALL INSTALL_PROGRAM INSTALL_DATA make_compare_target have_mktemp_command MAKEINFO BUILD_INFO GENERATED_MANPAGES FLEX BISON NM AR COLLECT2_LIBS GNAT_LIBEXC LDEXP_LIB TARGET_GETGROUPS_T LIBICONV LTLIBICONV LIBICONV_DEP manext objext gthread_flags extra_modes_file extra_opt_files USE_NLS LIBINTL LIBINTL_DEP INCINTL XGETTEXT GMSGFMT POSUB CATALOGS DATADIRNAME INSTOBJEXT GENCAT CATOBJEXT CROSS ALL SYSTEM_HEADER_DIR inhibit_libc CC_FOR_BUILD BUILD_CFLAGS BUILD_LDFLAGS STMP_FIXINC STMP_FIXPROTO collect2 LIBTOOL SED FGREP GREP LD DUMPBIN ac_ct_DUMPBIN OBJDUMP ac_ct_OBJDUMP ac_ct_AR STRIP ac_ct_STRIP lt_ECHO DSYMUTIL ac_ct_DSYMUTIL NMEDIT ac_ct_NMEDIT LIPO ac_ct_LIPO OTOOL ac_ct_OTOOL OTOOL64 ac_ct_OTOOL64 objdir enable_fast_install gcc_cv_as ORIGINAL_AS_FOR_TARGET gcc_cv_ld ORIGINAL_LD_FOR_TARGET ORIGINAL_GOLD_FOR_TARGET gcc_cv_nm ORIGINAL_NM_FOR_TARGET gcc_cv_objdump gcc_cv_readelf libgcc_visibility enable_esp enable_crtbeginTS GGC zlibdir zlibinc MAINT gcc_tooldir dollar slibdir link_rpath_spec subdirs srcdir all_compilers all_gtfiles all_lang_makefrags all_lang_makefiles all_languages all_selected_languages build_exeext build_install_headers_dir build_xm_file_list build_xm_include_list build_xm_defines build_file_translate check_languages cpp_install_dir xmake_file tmake_file extra_gcc_objs extra_headers_list extra_objs extra_parts extra_passes extra_programs float_h_file gcc_config_arguments gcc_gxx_include_dir host_exeext host_xm_file_list host_xm_include_list host_xm_defines out_host_hook_obj install lang_opt_files lang_specs_files lang_tree_files local_prefix md_file objc_boehm_gc out_file out_object_file thread_file tm_file_list tm_include_list tm_defines tm_p_file_list tm_p_include_list xm_file_list xm_include_list xm_defines c_target_objs cxx_target_objs fortran_target_objs target_cpu_default GMPLIBS GMPINC PPLLIBS PPLINC CLOOGLIBS CLOOGINC pluginlibs enable_plugin LIBOBJS LTLIBOBJS'
ac_subst_files='language_hooks'
ac_pwd=`pwd`
@@ -1132,6 +1132,7 @@ Optional Packages:
--with-datarootdir=DIR Use DIR as the data root [PREFIX/share]
--with-docdir=DIR Install documentation in DIR [DATAROOTDIR]
--with-htmldir=DIR html documentation in in DIR [DOCDIR]
+ --with-rpath-spec=SPEC Use rpath spec as part of default link specs
Some influential environment variables:
CC C compiler command
@@ -14594,13 +14595,13 @@ if test "${lt_cv_nm_interface+set}" = set; then
else
lt_cv_nm_interface="BSD nm"
echo "int some_variable = 0;" > conftest.$ac_ext
- (eval echo "\"\$as_me:14597: $ac_compile\"" >&5)
+ (eval echo "\"\$as_me:14598: $ac_compile\"" >&5)
(eval "$ac_compile" 2>conftest.err)
cat conftest.err >&5
- (eval echo "\"\$as_me:14600: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
+ (eval echo "\"\$as_me:14601: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
(eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
cat conftest.err >&5
- (eval echo "\"\$as_me:14603: output\"" >&5)
+ (eval echo "\"\$as_me:14604: output\"" >&5)
cat conftest.out >&5
if $GREP 'External.*some_variable' conftest.out > /dev/null; then
lt_cv_nm_interface="MS dumpbin"
@@ -15757,7 +15758,7 @@ ia64-*-hpux*)
;;
*-*-irix6*)
# Find out which ABI we are using.
- echo '#line 15760 "configure"' > conftest.$ac_ext
+ echo '#line 15761 "configure"' > conftest.$ac_ext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
@@ -17071,11 +17072,11 @@ else
-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:17074: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:17075: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:17078: \$? = $ac_status" >&5
+ echo "$as_me:17079: \$? = $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.
@@ -17410,11 +17411,11 @@ else
-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:17413: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:17414: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:17417: \$? = $ac_status" >&5
+ echo "$as_me:17418: \$? = $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.
@@ -17515,11 +17516,11 @@ else
-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:17518: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:17519: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:17522: \$? = $ac_status" >&5
+ echo "$as_me:17523: \$? = $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
@@ -17570,11 +17571,11 @@ else
-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:17573: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:17574: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:17577: \$? = $ac_status" >&5
+ echo "$as_me:17578: \$? = $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
@@ -20382,7 +20383,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 20385 "configure"
+#line 20386 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -20478,7 +20479,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 20481 "configure"
+#line 20482 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -24438,6 +24439,50 @@ echo "$as_me: WARNING: --build-id is not supported by your linker; --enable-link
fi
fi
+echo "$as_me:$LINENO: checking linker -z now support" >&5
+echo $ECHO_N "checking linker -z now support... $ECHO_C" >&6
+if test "${gcc_cv_ld_now+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ gcc_cv_ld_now=no
+if test $in_tree_ld = yes ; then
+ if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 16 -o "$gcc_cv_gld_major_version" -gt 2 \
+ && test $in_tree_ld_is_elf = yes; then
+ gcc_cv_ld_now=yes
+ fi
+elif test x$gcc_cv_ld != x; then
+ # Check if linker supports -z now options
+ if $gcc_cv_ld --help 2>/dev/null | grep now > /dev/null; then
+ gcc_cv_ld_now=yes
+ fi
+fi
+
+fi
+echo "$as_me:$LINENO: result: $gcc_cv_ld_now" >&5
+echo "${ECHO_T}$gcc_cv_ld_now" >&6
+
+echo "$as_me:$LINENO: checking linker -z relro support" >&5
+echo $ECHO_N "checking linker -z relro support... $ECHO_C" >&6
+if test "${gcc_cv_ld_relro+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ gcc_cv_ld_relro=no
+if test $in_tree_ld = yes ; then
+ if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 16 -o "$gcc_cv_gld_major_version" -gt 2 \
+ && test $in_tree_ld_is_elf = yes; then
+ gcc_cv_ld_relro=yes
+ fi
+elif test x$gcc_cv_ld != x; then
+ # Check if linker supports -z relro and -z norelro options
+ if $gcc_cv_ld --help 2>/dev/null | grep relro > /dev/null; then
+ gcc_cv_ld_relro=yes
+ fi
+fi
+
+fi
+echo "$as_me:$LINENO: result: $gcc_cv_ld_relro" >&5
+echo "${ECHO_T}$gcc_cv_ld_relro" >&6
+
echo "$as_me:$LINENO: checking linker --sysroot support" >&5
echo $ECHO_N "checking linker --sysroot support... $ECHO_C" >&6
if test "${gcc_cv_ld_sysroot+set}" = set; then
@@ -24636,6 +24681,40 @@ _ACEOF
fi
+if test x$enable_esp = xyes ; then
+ if test x$gcc_cv_ld_relro = xyes && test x$gcc_cv_ld_now = xyes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define ENABLE_ESP 1
+_ACEOF
+
+ else
+ { { echo "$as_me:$LINENO: error: *** --enable-esp Need a linker that support -z now and -z relro." >&5
+echo "$as_me: error: *** --enable-esp Need a linker that support -z now and -z relro." >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+fi
+
+
+if test x$enable_esp = xyes ; then
+ case "$target" in
+ *-*-linux*)
+ if test x$gcc_cv_ld_pie = xyes && test x$lt_cv_prog_compiler_static_works = xyes; then
+ enable_crtbeginTS=yes
+ fi
+ ;;
+ *) enable_crtbeginTS=no ;;
+ esac
+fi
+
+if test x$enable_crtbeginTS = xyes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define ENABLE_CRTBEGINTS 1
+_ACEOF
+
+fi
+
# Check if TFmode long double should be used by default or not.
# Some glibc targets used DFmode long double, but with glibc 2.4
# and later they can use TFmode.
@@ -24972,6 +25051,17 @@ else
fi;
+# Google-local http://b/2739909
+
+# Check whether --with-rpath-spec or --without-rpath-spec was given.
+if test "${with_rpath_spec+set}" = set; then
+ withval="$with_rpath_spec"
+ link_rpath_spec="$withval"
+else
+ link_rpath_spec=
+fi;
+
+
# Substitute configuration variables
@@ -26060,6 +26150,8 @@ s,@ORIGINAL_NM_FOR_TARGET@,$ORIGINAL_NM_FOR_TARGET,;t t
s,@gcc_cv_objdump@,$gcc_cv_objdump,;t t
s,@gcc_cv_readelf@,$gcc_cv_readelf,;t t
s,@libgcc_visibility@,$libgcc_visibility,;t t
+s,@enable_esp@,$enable_esp,;t t
+s,@enable_crtbeginTS@,$enable_crtbeginTS,;t t
s,@GGC@,$GGC,;t t
s,@zlibdir@,$zlibdir,;t t
s,@zlibinc@,$zlibinc,;t t
@@ -26067,6 +26159,7 @@ s,@MAINT@,$MAINT,;t t
s,@gcc_tooldir@,$gcc_tooldir,;t t
s,@dollar@,$dollar,;t t
s,@slibdir@,$slibdir,;t t
+s,@link_rpath_spec@,$link_rpath_spec,;t t
s,@subdirs@,$subdirs,;t t
s,@srcdir@,$srcdir,;t t
s,@all_compilers@,$all_compilers,;t t
diff --git a/gcc-4.4.3/gcc/configure.ac b/gcc-4.4.3/gcc/configure.ac
index 1b8fcf614..1ee190a76 100644
--- a/gcc-4.4.3/gcc/configure.ac
+++ b/gcc-4.4.3/gcc/configure.ac
@@ -3651,6 +3651,38 @@ if test x"$enable_linker_build_id" = xyes; then
fi
fi
+AC_CACHE_CHECK(linker -z now support,
+gcc_cv_ld_now,
+[gcc_cv_ld_now=no
+if test $in_tree_ld = yes ; then
+ if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 16 -o "$gcc_cv_gld_major_version" -gt 2 \
+ && test $in_tree_ld_is_elf = yes; then
+ gcc_cv_ld_now=yes
+ fi
+elif test x$gcc_cv_ld != x; then
+ # Check if linker supports -z now options
+ if $gcc_cv_ld --help 2>/dev/null | grep now > /dev/null; then
+ gcc_cv_ld_now=yes
+ fi
+fi
+])
+
+AC_CACHE_CHECK(linker -z relro support,
+gcc_cv_ld_relro,
+[gcc_cv_ld_relro=no
+if test $in_tree_ld = yes ; then
+ if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 16 -o "$gcc_cv_gld_major_version" -gt 2 \
+ && test $in_tree_ld_is_elf = yes; then
+ gcc_cv_ld_relro=yes
+ fi
+elif test x$gcc_cv_ld != x; then
+ # Check if linker supports -z relro and -z norelro options
+ if $gcc_cv_ld --help 2>/dev/null | grep relro > /dev/null; then
+ gcc_cv_ld_relro=yes
+ fi
+fi
+])
+
AC_CACHE_CHECK(linker --sysroot support,
gcc_cv_ld_sysroot,
[gcc_cv_ld_sysroot=no
@@ -3734,6 +3766,32 @@ if test x$gcc_cv_libc_provides_ssp = xyes; then
[Define if your target C library provides stack protector support])
fi
+if test x$enable_esp = xyes ; then
+ if test x$gcc_cv_ld_relro = xyes && test x$gcc_cv_ld_now = xyes; then
+ AC_DEFINE(ENABLE_ESP, 1,
+ [Define if your target support esp and you have enable it.])
+ else
+ AC_MSG_ERROR([*** --enable-esp Need a linker that support -z now and -z relro.])
+ fi
+fi
+AC_SUBST([enable_esp])
+
+if test x$enable_esp = xyes ; then
+ case "$target" in
+ *-*-linux*)
+ if test x$gcc_cv_ld_pie = xyes && test x$lt_cv_prog_compiler_static_works = xyes; then
+ enable_crtbeginTS=yes
+ fi
+ ;;
+ *) enable_crtbeginTS=no ;;
+ esac
+fi
+AC_SUBST([enable_crtbeginTS])
+if test x$enable_crtbeginTS = xyes; then
+ AC_DEFINE(ENABLE_CRTBEGINTS, 1,
+ [Define if your target crtbeginTS support])
+fi
+
# Check if TFmode long double should be used by default or not.
# Some glibc targets used DFmode long double, but with glibc 2.4
# and later they can use TFmode.
@@ -4038,6 +4096,13 @@ htmldir="\${prefix}/$with_htmldir",
htmldir='$(docdir)')
AC_SUBST(htmldir)
+# Google-local http://b/2739909
+AC_ARG_WITH([rpath-spec],
+[ --with-rpath-spec=SPEC Use rpath spec as part of default link specs],
+[link_rpath_spec="$withval"],
+[link_rpath_spec=])
+AC_SUBST(link_rpath_spec)
+
# Substitute configuration variables
AC_SUBST(subdirs)
AC_SUBST(srcdir)
diff --git a/gcc-4.4.3/gcc/coverage.c b/gcc-4.4.3/gcc/coverage.c
index de9c0e401..19466d35a 100644
--- a/gcc-4.4.3/gcc/coverage.c
+++ b/gcc-4.4.3/gcc/coverage.c
@@ -119,6 +119,9 @@ static char *da_file_name;
static char *da_base_file_name;
static char *main_input_file_name;
+/* Filename for the global pmu profile */
+static char pmu_profile_filename[] = "pmuprofile";
+
/* Hash table of count data. */
static htab_t counts_hash = NULL;
@@ -149,6 +152,16 @@ static unsigned num_cpp_includes = 0;
/* True if the current module has any asm statements. */
static bool has_asm_statement;
+/* extern const char * __gcov_pmu_profile_filename */
+static tree gcov_pmu_filename_decl = NULL_TREE;
+/* extern const char * __gcov_pmu_profile_options */
+static tree gcov_pmu_options_decl = NULL_TREE;
+/* extern gcov_unsigned_t __gcov_pmu_top_n_address */
+static tree gcov_pmu_top_n_address_decl = NULL_TREE;
+
+/* To ensure that the above variables are initialized only once. */
+static int pmu_profiling_initialized = 0;
+
/* Forward declarations. */
static hashval_t htab_counts_entry_hash (const void *);
static int htab_counts_entry_eq (const void *, const void *);
@@ -160,8 +173,10 @@ static tree build_ctr_info_type (void);
static tree build_ctr_info_value (unsigned, tree);
static tree build_gcov_info (void);
static void create_coverage (void);
-static char * get_da_file_name (const char *);
static char * xstrdup_mask_random (const char *);
+static void init_pmu_profiling (void);
+static bool profiling_enabled_p (void);
+
/* Return the type node for gcov_type. */
@@ -171,6 +186,15 @@ get_gcov_type (void)
return lang_hooks.types.type_for_size (GCOV_TYPE_SIZE, false);
}
+/* Return the type node for gcov_float_t. */
+
+tree
+get_gcov_float_t (void)
+{
+ return double_type_node;
+}
+
+
/* Return the type node for gcov_unsigned_t. */
tree
@@ -745,16 +769,24 @@ get_coverage_counts_no_warn (struct function *f, unsigned counter,
{
counts_entry_t *entry, elt;
- gcc_assert (flag_dyn_ipa);
+ gcc_assert (flag_dyn_ipa || flag_optimize_locality);
/* No hash table, no counts. */
if (!counts_hash || !f)
return NULL;
elt.ident = FUNC_DECL_GLOBAL_ID (f);
- elt.name = NULL;
+
+ if (flag_dyn_ipa)
+ elt.name = NULL;
+ else
+ elt.name = xstrdup_mask_random (IDENTIFIER_POINTER (
+ DECL_ASSEMBLER_NAME (current_function_decl)));
+
elt.ctr = counter;
entry = (counts_entry_t *) htab_find (counts_hash, &elt);
+ if (elt.name)
+ free (elt.name);
if (!entry)
return NULL;
@@ -1779,7 +1811,7 @@ create_coverage (void)
no_coverage = 1; /* Disable any further coverage. */
- if (!prg_ctr_mask)
+ if (!prg_ctr_mask && !flag_pmu_profile_generate)
return;
t = build_gcov_info ();
@@ -1813,7 +1845,7 @@ create_coverage (void)
/* Get the da file name, given base file name. */
-static char *
+char *
get_da_file_name (const char *base_file_name)
{
char *da_file_name;
@@ -1999,6 +2031,117 @@ coverage_init (const char *filename, const char* source_name)
read_counts_file (get_da_file_name (module_infos[i]->da_filename),
module_infos[i]->ident);
}
+
+ /* Define variables which are referenced at runtime by libgcov. */
+ if (profiling_enabled_p ())
+ {
+ init_pmu_profiling ();
+ tree_init_instrumentation_sampling ();
+ }
+}
+
+/* Return True if any type of profiling is enabled which requires linking
+ in libgcov otherwise return False. */
+
+static bool
+profiling_enabled_p (void)
+{
+ return flag_pmu_profile_generate || profile_arc_flag ||
+ flag_profile_generate_sampling || flag_test_coverage ||
+ flag_branch_probabilities || flag_profile_reusedist;
+}
+
+/* Construct variables for PMU profiling.
+ 1) __gcov_pmu_profile_filename,
+ 2) __gcov_pmu_profile_options,
+ 3) __gcov_pmu_top_n_address. */
+
+static void
+init_pmu_profiling (void)
+{
+ if (!pmu_profiling_initialized)
+ {
+ unsigned top_n_addr = PARAM_VALUE (PARAM_PMU_PROFILE_N_ADDRESS);
+ tree filename_ptr, options_ptr;
+
+ /* Construct an initializer for __gcov_pmu_profile_filename. */
+ gcov_pmu_filename_decl =
+ build_decl (VAR_DECL,
+ get_identifier ("__gcov_pmu_profile_filename"),
+ get_const_string_type ());
+ TREE_PUBLIC (gcov_pmu_filename_decl) = 1;
+ DECL_ARTIFICIAL (gcov_pmu_filename_decl) = 1;
+ DECL_ONE_ONLY (gcov_pmu_filename_decl) = 1;
+ TREE_STATIC (gcov_pmu_filename_decl) = 1;
+
+ if (flag_pmu_profile_generate)
+ {
+ const char *filename = get_da_file_name (pmu_profile_filename);
+ int file_name_len;
+ tree filename_string;
+ file_name_len = strlen (filename);
+ filename_string = build_string (file_name_len + 1, filename);
+ TREE_TYPE (filename_string) = build_array_type
+ (char_type_node, build_index_type
+ (build_int_cst (NULL_TREE, file_name_len)));
+ filename_ptr = build1 (ADDR_EXPR, get_const_string_type (),
+ filename_string);
+ }
+ else
+ filename_ptr = null_pointer_node;
+
+ DECL_INITIAL (gcov_pmu_filename_decl) = filename_ptr;
+ assemble_variable (gcov_pmu_filename_decl, 0, 0, 0);
+
+ /* Construct an initializer for __gcov_pmu_profile_options. */
+ gcov_pmu_options_decl =
+ build_decl (VAR_DECL,
+ get_identifier ("__gcov_pmu_profile_options"),
+ get_const_string_type ());
+ TREE_PUBLIC (gcov_pmu_options_decl) = 1;
+ DECL_ARTIFICIAL (gcov_pmu_options_decl) = 1;
+ DECL_ONE_ONLY (gcov_pmu_options_decl) = 1;
+ TREE_STATIC (gcov_pmu_options_decl) = 1;
+
+ /* If the flag is false we generate a null pointer to indicate
+ that we are not doing the pmu profiling. */
+ if (flag_pmu_profile_generate)
+ {
+ const char *pmu_options = flag_pmu_profile_generate;
+ int pmu_options_len;
+ tree pmu_options_string;
+
+ pmu_options_len = strlen (pmu_options);
+ pmu_options_string = build_string (pmu_options_len + 1, pmu_options);
+ TREE_TYPE (pmu_options_string) = build_array_type
+ (char_type_node, build_index_type
+ (build_int_cst (NULL_TREE, pmu_options_len)));
+ options_ptr = build1 (ADDR_EXPR, get_const_string_type (),
+ pmu_options_string);
+ }
+ else
+ options_ptr = null_pointer_node;
+
+ DECL_INITIAL (gcov_pmu_options_decl) = options_ptr;
+ assemble_variable (gcov_pmu_options_decl, 0, 0, 0);
+
+ /* Construct an initializer for __gcov_pmu_top_n_address. We
+ don't need to guard this with the flag_pmu_profile generate
+ because the value of __gcov_pmu_top_n_address is ignored when
+ not doing profiling. */
+ gcov_pmu_top_n_address_decl =
+ build_decl (VAR_DECL,
+ get_identifier ("__gcov_pmu_top_n_address"),
+ get_gcov_unsigned_t ());
+ TREE_PUBLIC (gcov_pmu_top_n_address_decl) = 1;
+ DECL_ARTIFICIAL (gcov_pmu_top_n_address_decl) = 1;
+ DECL_ONE_ONLY (gcov_pmu_top_n_address_decl) = 1;
+ TREE_STATIC (gcov_pmu_top_n_address_decl) = 1;
+ DECL_INITIAL (gcov_pmu_top_n_address_decl) =
+ build_int_cstu (get_gcov_unsigned_t (), top_n_addr);
+ assemble_variable (gcov_pmu_top_n_address_decl, 0, 0, 0);
+ }
+ pmu_profiling_initialized = 1;
}
/* Performs file-level cleanup. Close graph file, generate coverage
@@ -2038,6 +2181,10 @@ str_list_append (struct str_list **head, struct str_list **tail, const char *s)
*tail = e;
}
+extern bool is_kernel_build;
+
+#define KERNEL_BUILD_PREDEF_STRING "__KERNEL__"
+
/* Copies the macro def or undef CPP_DEF and saves the copy
in a list. IS_DEF is a flag indicating if CPP_DEF represents
a -D or -U. */
@@ -2050,6 +2197,11 @@ coverage_note_define (const char *cpp_def, bool is_def)
strcpy (s + 1, cpp_def);
str_list_append (&cpp_defines_head, &cpp_defines_tail, s);
num_cpp_defines++;
+
+ /* When -D__KERNEL__ is in the option list, we assume this is
+ compilation for Linux Kernel. */
+ if (!strcmp(cpp_def, KERNEL_BUILD_PREDEF_STRING))
+ is_kernel_build = is_def;
}
/* Copies the -imacro/-include FILENAME and saves the copy in a list. */
@@ -2130,5 +2282,19 @@ write_opts_to_asm (void)
dw2_asm_output_nstring (lipo_cl_args[i], -1, NULL);
}
-#include "gt-coverage.h"
+/* Check the command line OPTIONS passed to
+ -fpmu-profile-generate. Return 0 if the options are valid, non-zero
+ otherwise. */
+
+int
+check_pmu_profile_options (const char *options)
+{
+ if (strcmp(options, "load-latency") &&
+ strcmp(options, "load-latency-verbose") &&
+ strcmp(options, "branch-mispredict") &&
+ strcmp(options, "branch-mispredict-verbose"))
+ return 1;
+ return 0;
+}
+#include "gt-coverage.h"
diff --git a/gcc-4.4.3/gcc/coverage.h b/gcc-4.4.3/gcc/coverage.h
index 2562a1fa4..13abcb65e 100644
--- a/gcc-4.4.3/gcc/coverage.h
+++ b/gcc-4.4.3/gcc/coverage.h
@@ -58,6 +58,7 @@ extern gcov_type *get_coverage_counts_no_warn (struct function *,
extern struct cgraph_node * find_func_by_global_id (unsigned HOST_WIDE_INT gid);
+extern struct cgraph_node * find_func_by_name (const char *name);
/* All the coverage counters are supposed to be allocated by the time
coverage_end_function is called. However, direct-call counters are
allocated after coverage_end_function has been called. This function
@@ -72,8 +73,18 @@ extern bool coverage_function_present (unsigned fn_ident);
extern tree get_gcov_type (void);
extern tree get_gcov_unsigned_t (void);
+extern tree get_gcov_float_t (void);
/* Mark this module as containing asm statements. */
extern void coverage_has_asm_stmt (void);
+/* Get the da file name, given base file name. */
+extern char * get_da_file_name (const char *base_file_name);
+
+/* Check if the specified options are valid for pmu profilig. */
+extern int check_pmu_profile_options (const char *options);
+
+/* Defined in tree-profile.c. */
+extern void tree_init_instrumentation_sampling (void);
+
#endif
diff --git a/gcc-4.4.3/gcc/cp/call.c b/gcc-4.4.3/gcc/cp/call.c
index 2a85c6684..4eb1974c0 100644
--- a/gcc-4.4.3/gcc/cp/call.c
+++ b/gcc-4.4.3/gcc/cp/call.c
@@ -195,6 +195,8 @@ static conversion *direct_reference_binding (tree, conversion *);
static bool promoted_arithmetic_type_p (tree);
static conversion *conditional_conversion (tree, tree);
static char *name_as_c_string (tree, tree, bool *);
+static void find_const_memfunc_with_identical_prototype (tree,
+ struct z_candidate *);
static tree call_builtin_trap (void);
static tree prep_operand (tree);
static void add_candidates (tree, tree, tree, bool, tree, tree,
@@ -4159,7 +4161,20 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3,
if (resolve_args (arglist) == error_mark_node)
result = error_mark_node;
else
- result = build_over_call (cand, LOOKUP_NORMAL, complain);
+ {
+ result = build_over_call (cand, LOOKUP_NORMAL, complain);
+ /* If thread safety check is enabled and FN is not a const
+ member function, try to see if there is a const overload in
+ the candidates list (if we haven't done so already). */
+ if (warn_thread_safety
+ && DECL_FUNCTION_MEMBER_P (cand->fn)
+ && !DECL_CONST_MEMFUNC_P (cand->fn)
+ && (!DECL_ATTRIBUTES (cand->fn)
+ || !lookup_attribute ("has_const_overload",
+ DECL_ATTRIBUTES (cand->fn))))
+ find_const_memfunc_with_identical_prototype (cand->fn,
+ candidates);
+ }
}
else
{
@@ -4546,21 +4561,21 @@ conversion_null_warnings (tree totype, tree expr, tree fn, int argnum)
if (expr == null_node && TREE_CODE (t) != BOOLEAN_TYPE && ARITHMETIC_TYPE_P (t))
{
if (fn)
- warning (OPT_Wnull_conversion, "passing NULL to non-pointer argument %P of %qD",
+ warning (OPT_Wconversion_null, "passing NULL to non-pointer argument %P of %qD",
argnum, fn);
else
- warning (OPT_Wnull_conversion, "converting to non-pointer type %qT from NULL", t);
+ warning (OPT_Wconversion_null, "converting to non-pointer type %qT from NULL", t);
}
/* Issue warnings if "false" is converted to a NULL pointer */
else if (expr == boolean_false_node && POINTER_TYPE_P (t))
{
if (fn)
- warning (OPT_Wnull_conversion,
+ warning (OPT_Wconversion_null,
"converting %<false%> to pointer type for argument %P of %qD",
argnum, fn);
else
- warning (OPT_Wnull_conversion, "converting %<false%> to pointer type");
+ warning (OPT_Wconversion_null, "converting %<false%> to pointer type");
}
}
@@ -5882,6 +5897,53 @@ name_as_c_string (tree name, tree type, bool *free_p)
return pretty_name;
}
+/* Given a decl FN which is a non-const member function, try to find if
+ there is another candidate that is a const member function with the same
+ prototype (i.e. parameter list) as FN. And if found, attach an internal
+ attribute "has_const_overload" to FN. */
+
+static void
+find_const_memfunc_with_identical_prototype (tree fn,
+ struct z_candidate *candidates)
+{
+ bool find_const_overload = false;
+ struct z_candidate *cand;
+
+ for (cand = candidates; cand; cand = cand->next)
+ {
+ tree candfunc = cand->fn;
+ tree t1, t2;
+
+ /* candfunc (or cand->fn) can be an IDENTIFIER_NODE if the candidate
+ is a builtin (see the add_candidate call in build_builtin_candidate).
+ Since it's not a user-defined overload, just skip it. */
+ if (TREE_CODE (candfunc) != FUNCTION_DECL)
+ continue;
+
+ /* Skip FN itself and candidates that are not const. */
+ if (candfunc == fn || !DECL_CONST_MEMFUNC_P (candfunc))
+ continue;
+
+ /* Compare the parameter lists of FN and CANDFUNC. */
+ for (t1 = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (fn))),
+ t2 = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (candfunc)));
+ t1 && t2;
+ t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2))
+ if (t1 != t2)
+ break;
+
+ if (!t1 && !t2)
+ {
+ find_const_overload = true;
+ break;
+ }
+ }
+
+ if (find_const_overload)
+ DECL_ATTRIBUTES (fn) = tree_cons (get_identifier ("has_const_overload"),
+ NULL_TREE, DECL_ATTRIBUTES (fn));
+}
+
/* Build a call to "INSTANCE.FN (ARGS)". If FN_P is non-NULL, it will
be set, upon return, to the function called. */
@@ -6152,6 +6214,15 @@ build_new_method_call (tree instance, tree fns, tree args,
"operator delete(~X(f()))" (rather than generating
"t = f(), ~X(t), operator delete (t)"). */
call = build_nop (void_type_node, call);
+ /* If thread safety check is enabled and FN is not a const
+ member function, try to see if there is a const overload in
+ the candidates list (if we haven't done so already). */
+ if (warn_thread_safety
+ && !DECL_CONST_MEMFUNC_P (fn)
+ && (!DECL_ATTRIBUTES (fn)
+ || !lookup_attribute ("has_const_overload",
+ DECL_ATTRIBUTES (fn))))
+ find_const_memfunc_with_identical_prototype (fn, candidates);
}
}
}
diff --git a/gcc-4.4.3/gcc/cp/class.c b/gcc-4.4.3/gcc/cp/class.c
index d1b9bff4c..e7b78cc29 100644
--- a/gcc-4.4.3/gcc/cp/class.c
+++ b/gcc-4.4.3/gcc/cp/class.c
@@ -8090,4 +8090,22 @@ cp_decl_is_destructor (tree decl)
return DECL_DESTRUCTOR_P (decl);
}
+/* Return
+ 1 if decl is a const member function,
+ 2 if decl is not a const member function but has a const overload that
+ has identical parameter list,
+ 0 otherwise. */
+
+int
+cp_decl_is_const_member_func (tree decl)
+{
+ if (DECL_CONST_MEMFUNC_P (decl))
+ return 1;
+ else if (DECL_ATTRIBUTES (decl)
+ && lookup_attribute ("has_const_overload", DECL_ATTRIBUTES (decl)))
+ return 2;
+ else
+ return 0;
+}
+
#include "gt-cp-class.h"
diff --git a/gcc-4.4.3/gcc/cp/cp-lang.c b/gcc-4.4.3/gcc/cp/cp-lang.c
index ef7bd33af..4fe8c6727 100644
--- a/gcc-4.4.3/gcc/cp/cp-lang.c
+++ b/gcc-4.4.3/gcc/cp/cp-lang.c
@@ -1,5 +1,5 @@
/* Language-dependent hooks for C++.
- Copyright 2001, 2002, 2004, 2007, 2008 Free Software Foundation, Inc.
+ Copyright 2001, 2002, 2004, 2007, 2008, 2009 Free Software Foundation, Inc.
Contributed by Alexandre Oliva <aoliva@redhat.com>
This file is part of GCC.
@@ -80,6 +80,8 @@ static bool cp_is_global_delete_fndecl_p (tree);
#define LANG_HOOKS_DECL_IS_CONSTRUCTOR cp_decl_is_constructor
#undef LANG_HOOKS_DECL_IS_DESTRUCTOR
#define LANG_HOOKS_DECL_IS_DESTRUCTOR cp_decl_is_destructor
+#undef LANG_HOOKS_DECL_IS_CONST_MEMBER_FUNC
+#define LANG_HOOKS_DECL_IS_CONST_MEMBER_FUNC cp_decl_is_const_member_func
/* LIPO support. */
#undef LANG_HOOKS_ADD_BUILT_IN_DECL
@@ -163,7 +165,9 @@ cxx_dwarf_name (tree t, int verbosity)
gcc_assert (DECL_P (t));
if (verbosity >= 2)
- return decl_as_string (t, TFF_DECL_SPECIFIERS | TFF_UNQUALIFIED_NAME);
+ return decl_as_string (t,
+ TFF_DECL_SPECIFIERS | TFF_UNQUALIFIED_NAME
+ | TFF_NO_OMIT_DEFAULT_TEMPLATE_ARGUMENTS);
return cxx_printable_name (t, verbosity);
}
diff --git a/gcc-4.4.3/gcc/cp/cp-tree.h b/gcc-4.4.3/gcc/cp/cp-tree.h
index d8823152a..29948c97f 100644
--- a/gcc-4.4.3/gcc/cp/cp-tree.h
+++ b/gcc-4.4.3/gcc/cp/cp-tree.h
@@ -2258,6 +2258,24 @@ extern void decl_shadowed_for_var_insert (tree, tree);
#define TI_ARGS(NODE) (TREE_VALUE (NODE))
#define TI_PENDING_TEMPLATE_FLAG(NODE) TREE_LANG_FLAG_1 (NODE)
+/* For a given TREE_VEC containing a template argument list,
+ this property contains the number of arguments that are not
+ defaulted. */
+#define NON_DEFAULT_TEMPLATE_ARGS_COUNT(NODE) TREE_CHAIN (TREE_VEC_CHECK (NODE))
+/* Below are the setter and getter of the NON_DEFAULT_TEMPLATE_ARGS_COUNT
+ property. */
+#define SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT(NODE, INT_VALUE) \
+ NON_DEFAULT_TEMPLATE_ARGS_COUNT(NODE) = build_int_cst (NULL_TREE, INT_VALUE)
+#ifdef ENABLE_CHECKING
+#define GET_NON_DEFAULT_TEMPLATE_ARGS_COUNT(NODE) \
+ int_cst_value (NON_DEFAULT_TEMPLATE_ARGS_COUNT (NODE))
+#else
+#define GET_NON_DEFAULT_TEMPLATE_ARGS_COUNT(NODE) \
+ NON_DEFAULT_TEMPLATE_ARGS_COUNT (NODE) \
+ ? int_cst_value (NON_DEFAULT_TEMPLATE_ARGS_COUNT (NODE)) \
+ : TREE_VEC_LENGTH (INNERMOST_TEMPLATE_ARGS (NODE))
+#endif
+
/* We use TREE_VECs to hold template arguments. If there is only one
level of template arguments, then the TREE_VEC contains the
arguments directly. If there is more than one level of template
@@ -2268,7 +2286,13 @@ extern void decl_shadowed_for_var_insert (tree, tree);
It is incorrect to ever form a template argument vector containing
only one level of arguments, but which is a TREE_VEC containing as
- its only entry the TREE_VEC for that level. */
+ its only entry the TREE_VEC for that level.
+
+ For each TREE_VEC containing the template arguments for a single
+ level, it's possible to get or set the number of non defaulted
+ template arguments by using the accessor macros
+ GET_NON_DEFAULT_TEMPLATE_ARGS_COUNT or
+ SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT. */
/* Nonzero if the template arguments is actually a vector of vectors,
rather than just a vector. */
@@ -3584,6 +3608,8 @@ typedef enum tsubst_flags_t {
conversion. */
tf_no_access_control = 1 << 7, /* Do not perform access checks, even
when issuing other errors. */
+ /* Do not instantiate classes (used by count_non_default_template_args). */
+ tf_no_class_instantiations = 1 << 8,
/* Convenient substitution flags combinations. */
tf_warning_or_error = tf_warning | tf_error
} tsubst_flags_t;
@@ -3933,7 +3959,9 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, OP_FLAG, TYPENAME_FLAG };
TFF_EXPR_IN_PARENS: parenthesize expressions.
TFF_NO_FUNCTION_ARGUMENTS: don't show function arguments.
TFF_UNQUALIFIED_NAME: do not print the qualifying scope of the
- top-level entity. */
+ top-level entity.
+ TFF_NO_OMIT_DEFAULT_TEMPLATE_ARGUMENTS: do not omit template arguments
+ identical to their defaults. */
#define TFF_PLAIN_IDENTIFIER (0)
#define TFF_SCOPE (1)
@@ -3948,6 +3976,7 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, OP_FLAG, TYPENAME_FLAG };
#define TFF_EXPR_IN_PARENS (1 << 9)
#define TFF_NO_FUNCTION_ARGUMENTS (1 << 10)
#define TFF_UNQUALIFIED_NAME (1 << 11)
+#define TFF_NO_OMIT_DEFAULT_TEMPLATE_ARGUMENTS (1 << 12)
/* Returns the TEMPLATE_DECL associated to a TEMPLATE_TEMPLATE_PARM
node. */
@@ -4281,6 +4310,7 @@ extern tree cp_fold_obj_type_ref (tree, tree);
extern bool cp_decl_is_base_field (tree);
extern bool cp_decl_is_constructor (tree);
extern bool cp_decl_is_destructor (tree);
+extern int cp_decl_is_const_member_func (tree);
extern void set_linkage_according_to_type (tree, tree);
extern void determine_key_method (tree);
extern void check_for_override (tree, tree);
diff --git a/gcc-4.4.3/gcc/cp/cvt.c b/gcc-4.4.3/gcc/cp/cvt.c
index 28533092d..62f7a26f5 100644
--- a/gcc-4.4.3/gcc/cp/cvt.c
+++ b/gcc-4.4.3/gcc/cp/cvt.c
@@ -1116,7 +1116,7 @@ build_expr_type_conversion (int desires, tree expr, bool complain)
if (expr == null_node
&& (desires & WANT_INT)
&& !(desires & WANT_NULL))
- warning (OPT_Wnull_conversion, "converting NULL to non-pointer type");
+ warning (OPT_Wconversion_null, "converting NULL to non-pointer type");
basetype = TREE_TYPE (expr);
diff --git a/gcc-4.4.3/gcc/cp/error.c b/gcc-4.4.3/gcc/cp/error.c
index 727c2fdec..301a1693a 100644
--- a/gcc-4.4.3/gcc/cp/error.c
+++ b/gcc-4.4.3/gcc/cp/error.c
@@ -78,6 +78,8 @@ static void dump_template_bindings (tree, tree);
static void dump_scope (tree, int);
static void dump_template_parms (tree, int, int);
+static int get_non_default_template_args_count (tree, int);
+
static const char *function_category (tree);
static void maybe_print_instantiation_context (diagnostic_context *);
static void print_instantiation_full_context (diagnostic_context *);
@@ -151,17 +153,36 @@ dump_template_argument (tree arg, int flags)
}
}
+/* Count the number of template arguments ARGS whose value does not
+ match the (optional) default template parameter in PARAMS */
+
+static int
+get_non_default_template_args_count (tree args, int flags)
+{
+ int n = TREE_VEC_LENGTH (INNERMOST_TEMPLATE_ARGS (args));
+
+ if (/* We use this flag when generating debug information. We don't
+ want to expand templates at this point, for this may generate
+ new decls, which gets decl counts out of sync, which may in
+ turn cause codegen differences between compilations with and
+ without -g. */
+ (flags & TFF_NO_OMIT_DEFAULT_TEMPLATE_ARGUMENTS) != 0)
+ return n;
+
+ return GET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (INNERMOST_TEMPLATE_ARGS (args));
+}
+
/* Dump a template-argument-list ARGS (always a TREE_VEC) under control
of FLAGS. */
static void
dump_template_argument_list (tree args, int flags)
{
- int n = TREE_VEC_LENGTH (args);
+ int n = get_non_default_template_args_count (args, flags);
int need_comma = 0;
int i;
- for (i = 0; i< n; ++i)
+ for (i = 0; i < n; ++i)
{
tree arg = TREE_VEC_ELT (args, i);
@@ -237,18 +258,19 @@ dump_template_bindings (tree parms, tree args)
int lvl = TMPL_PARMS_DEPTH (parms);
int arg_idx = 0;
int i;
+ tree lvl_args = NULL_TREE;
+
+ /* Don't crash if we had an invalid argument list. */
+ if (TMPL_ARGS_DEPTH (args) >= lvl)
+ lvl_args = TMPL_ARGS_LEVEL (args, lvl);
for (i = 0; i < TREE_VEC_LENGTH (p); ++i)
{
tree arg = NULL_TREE;
/* Don't crash if we had an invalid argument list. */
- if (TMPL_ARGS_DEPTH (args) >= lvl)
- {
- tree lvl_args = TMPL_ARGS_LEVEL (args, lvl);
- if (NUM_TMPL_ARGS (lvl_args) > arg_idx)
- arg = TREE_VEC_ELT (lvl_args, arg_idx);
- }
+ if (lvl_args && NUM_TMPL_ARGS (lvl_args) > arg_idx)
+ arg = TREE_VEC_ELT (lvl_args, arg_idx);
if (need_comma)
pp_separate_with_comma (cxx_pp);
@@ -1332,16 +1354,13 @@ dump_template_parms (tree info, int primary, int flags)
pp_cxx_begin_template_argument_list (cxx_pp);
/* Be careful only to print things when we have them, so as not
- to crash producing error messages. */
+ to crash producing error messages. */
if (args && !primary)
{
int len, ix;
+ len = get_non_default_template_args_count (args, flags);
- if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args))
- args = TREE_VEC_ELT (args, TREE_VEC_LENGTH (args) - 1);
-
- len = TREE_VEC_LENGTH (args);
-
+ args = INNERMOST_TEMPLATE_ARGS (args);
for (ix = 0; ix != len; ix++)
{
tree arg = TREE_VEC_ELT (args, ix);
diff --git a/gcc-4.4.3/gcc/cp/lang-specs.h b/gcc-4.4.3/gcc/cp/lang-specs.h
index 54d69a115..cb396b1c9 100644
--- a/gcc-4.4.3/gcc/cp/lang-specs.h
+++ b/gcc-4.4.3/gcc/cp/lang-specs.h
@@ -47,7 +47,7 @@ along with GCC; see the file COPYING3. If not see
%(cpp_options) %2 -o %{save-temps:%b.ii} %{!save-temps:%g.ii} \n}\
cc1plus %{save-temps|no-integrated-cpp:-fpreprocessed %{save-temps:%b.ii} %{!save-temps:%g.ii}}\
%{!save-temps:%{!no-integrated-cpp:%(cpp_unique_options)}}\
- %(cc1_options) %2 %{+e1*}\
+ %(cc1_options) %(esp_options) %2 %{+e1*}\
%{!fsyntax-only:-o %g.s %{!o*:--output-pch=%i.gch} %W{o*:--output-pch=%*}%V}}}}",
CPLUSPLUS_CPP_SPEC, 0, 0},
{"@c++",
@@ -57,11 +57,11 @@ along with GCC; see the file COPYING3. If not see
%(cpp_options) %2 -o %{save-temps:%b.ii} %{!save-temps:%g.ii} \n}\
cc1plus %{save-temps|no-integrated-cpp:-fpreprocessed %{save-temps:%b.ii} %{!save-temps:%g.ii}}\
%{!save-temps:%{!no-integrated-cpp:%(cpp_unique_options)}}\
- %(cc1_options) %2 %{+e1*}\
+ %(cc1_options) %(esp_options) %2 %{+e1*}\
%{!fsyntax-only:%(invoke_as)}}}}",
CPLUSPLUS_CPP_SPEC, 0, 0},
{".ii", "@c++-cpp-output", 0, 0, 0},
{"@c++-cpp-output",
"%{!M:%{!MM:%{!E:\
- cc1plus -fpreprocessed %i %(cc1_options) %2 %{+e*}\
+ cc1plus -fpreprocessed %i %(cc1_options) %(esp_options) %2 %{+e*}\
%{!fsyntax-only:%(invoke_as)}}}}", 0, 0, 0},
diff --git a/gcc-4.4.3/gcc/cp/name-lookup.c b/gcc-4.4.3/gcc/cp/name-lookup.c
index ddc0afc8d..46b45ea66 100644
--- a/gcc-4.4.3/gcc/cp/name-lookup.c
+++ b/gcc-4.4.3/gcc/cp/name-lookup.c
@@ -4516,26 +4516,15 @@ add_function (struct arg_lookup *k, tree fn)
total number of functions being compared, which should usually be the
case. */
- /* We must find only functions, or exactly one non-function. */
- if (!k->functions)
+ if (!is_overloaded_fn (fn))
+ /* All names except those of (possibly overloaded) functions and
+ function templates are ignored. */;
+ else if (!k->functions)
k->functions = fn;
else if (fn == k->functions)
;
- else if (is_overloaded_fn (k->functions) && is_overloaded_fn (fn))
- k->functions = build_overload (fn, k->functions);
else
- {
- tree f1 = OVL_CURRENT (k->functions);
- tree f2 = fn;
- if (is_overloaded_fn (f1))
- {
- fn = f1; f1 = f2; f2 = fn;
- }
- error ("%q+D is not a function,", f1);
- error (" conflict with %q+D", f2);
- error (" in call to %qD", k->name);
- return true;
- }
+ k->functions = build_overload (fn, k->functions);
return false;
}
diff --git a/gcc-4.4.3/gcc/cp/parser.c b/gcc-4.4.3/gcc/cp/parser.c
index 9dff007bb..461f280da 100644
--- a/gcc-4.4.3/gcc/cp/parser.c
+++ b/gcc-4.4.3/gcc/cp/parser.c
@@ -6472,6 +6472,16 @@ cp_parser_question_colon_clause (cp_parser* parser, tree logical_or_expr)
tf_warning_or_error);
}
+/* A helpfer function to check if the given expression (EXPR) is of POD type.
+ Note that if the expression's type is NULL (e.g. when its type depends on
+ template parameters), we return false. */
+
+static bool
+expr_is_pod (tree expr)
+{
+ return TREE_TYPE (expr) && pod_type_p (TREE_TYPE (expr));
+}
+
/* Parse an assignment-expression.
assignment-expression:
@@ -6529,8 +6539,12 @@ cp_parser_assignment_expression (cp_parser* parser, bool cast_p,
return error_mark_node;
/* Check for and warn about self-assignment if -Wself-assign is
- enabled and the assignment operator is "=". */
- if (warn_self_assign && assignment_operator == NOP_EXPR)
+ enabled and the assignment operator is "=".
+ Checking for non-POD self-assignment will be performed only
+ when -Wself-assign-non-pod is enabled. */
+ if (warn_self_assign
+ && assignment_operator == NOP_EXPR
+ && (warn_self_assign_non_pod || expr_is_pod (expr)))
check_for_self_assign (input_location, expr, rhs);
/* Build the assignment expression. */
@@ -10615,6 +10629,9 @@ cp_parser_template_argument_list (cp_parser* parser)
parser->non_integral_constant_expression_p = saved_non_ice_p;
parser->integral_constant_expression_p = saved_ice_p;
parser->in_template_argument_list_p = saved_in_template_argument_list_p;
+#ifdef ENABLE_CHECKING
+ SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (vec, TREE_VEC_LENGTH (vec));
+#endif
return vec;
}
@@ -17896,6 +17913,35 @@ cp_parser_function_definition_from_specifiers_and_declarator
might be a friend. */
perform_deferred_access_checks ();
+ /* If the function definition is annotated with lock attributes with
+ arguments that are data members in the class, the parser would not be
+ able to bind those names to their FIELD_DECLs earlier when parsing the
+ attributes because the class context was not in scope at that time.
+ Now that we have entered the class context, try and bind and resolve
+ those identifiers. */
+ if (attributes)
+ {
+ tree attr;
+ for (attr = attributes; attr; attr = TREE_CHAIN (attr))
+ {
+ tree arg;
+ if (!is_lock_attribute_with_args (TREE_PURPOSE (attr)))
+ continue;
+ for (arg = TREE_VALUE (attr); arg; arg = TREE_CHAIN (arg))
+ {
+ tree lock = TREE_VALUE (arg);
+ if (TREE_CODE (lock) == IDENTIFIER_NODE)
+ {
+ tree lock_decl =
+ cp_parser_lookup_name_simple (parser, lock,
+ input_location);
+ if (lock_decl && lock_decl != error_mark_node)
+ TREE_VALUE (arg) = lock_decl;
+ }
+ }
+ }
+ }
+
if (!success_p)
{
/* Skip the entire function. */
diff --git a/gcc-4.4.3/gcc/cp/pt.c b/gcc-4.4.3/gcc/cp/pt.c
index 663d42037..57e5884ed 100644
--- a/gcc-4.4.3/gcc/cp/pt.c
+++ b/gcc-4.4.3/gcc/cp/pt.c
@@ -87,6 +87,12 @@ struct pending_attribute GTY (()) {
static GTY(()) struct pending_attribute *pending_lock_attributes = NULL;
+typedef struct pending_attribute *pending_attribute_p;
+DEF_VEC_P(pending_attribute_p);
+DEF_VEC_ALLOC_P(pending_attribute_p,gc);
+
+static GTY(()) VEC(pending_attribute_p,gc) *pending_lock_attr_stack;
+
int processing_template_parmlist;
static int template_header_count;
@@ -2809,6 +2815,7 @@ expand_template_argument_pack (tree args)
tree result_args = NULL_TREE;
int in_arg, out_arg = 0, nargs = args ? TREE_VEC_LENGTH (args) : 0;
int num_result_args = -1;
+ int non_default_args_count = -1;
/* First, determine if we need to expand anything, and the number of
slots we'll need. */
@@ -2838,6 +2845,9 @@ expand_template_argument_pack (tree args)
/* Expand arguments. */
result_args = make_tree_vec (num_result_args);
+ if (NON_DEFAULT_TEMPLATE_ARGS_COUNT (args))
+ non_default_args_count =
+ GET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (args);
for (in_arg = 0; in_arg < nargs; ++in_arg)
{
tree arg = TREE_VEC_ELT (args, in_arg);
@@ -2847,6 +2857,8 @@ expand_template_argument_pack (tree args)
int i, num_packed = TREE_VEC_LENGTH (packed);
for (i = 0; i < num_packed; ++i, ++out_arg)
TREE_VEC_ELT (result_args, out_arg) = TREE_VEC_ELT(packed, i);
+ if (non_default_args_count > 0)
+ non_default_args_count += num_packed;
}
else
{
@@ -2854,7 +2866,8 @@ expand_template_argument_pack (tree args)
++out_arg;
}
}
-
+ if (non_default_args_count >= 0)
+ SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (result_args, non_default_args_count);
return result_args;
}
@@ -3213,6 +3226,10 @@ current_template_args (void)
/* Turn this argument into a TYPE_ARGUMENT_PACK
with a single element, which expands T. */
tree vec = make_tree_vec (1);
+#ifdef ENABLE_CHECKING
+ SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT
+ (vec, TREE_VEC_LENGTH (vec));
+#endif
TREE_VEC_ELT (vec, 0) = make_pack_expansion (t);
t = make_node (TYPE_ARGUMENT_PACK);
@@ -3229,6 +3246,10 @@ current_template_args (void)
with a single element, which expands T. */
tree vec = make_tree_vec (1);
tree type = TREE_TYPE (TEMPLATE_PARM_DECL (t));
+#ifdef ENABLE_CHECKING
+ SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT
+ (vec, TREE_VEC_LENGTH (vec));
+#endif
TREE_VEC_ELT (vec, 0) = make_pack_expansion (t);
t = make_node (NONTYPE_ARGUMENT_PACK);
@@ -3241,6 +3262,10 @@ current_template_args (void)
}
}
+#ifdef ENABLE_CHECKING
+ SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (a, TREE_VEC_LENGTH (a));
+#endif
+
if (length > 1)
TREE_VEC_ELT (args, --l) = a;
else
@@ -5300,6 +5325,10 @@ coerce_template_parameter_pack (tree parms,
}
SET_ARGUMENT_PACK_ARGS (argument_pack, packed_args);
+#ifdef ENABLE_CHECKING
+ SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (packed_args,
+ TREE_VEC_LENGTH (packed_args));
+#endif
return argument_pack;
}
@@ -5452,9 +5481,16 @@ coerce_template_parms (tree parms,
}
}
else if (require_all_args)
- /* There must be a default arg in this case. */
- arg = tsubst_template_arg (TREE_PURPOSE (parm), new_args,
- complain, in_decl);
+ {
+ /* There must be a default arg in this case. */
+ arg = tsubst_template_arg (TREE_PURPOSE (parm), new_args,
+ complain, in_decl);
+ /* The position of the first default template argument,
+ is also the number of non-defaulted arguments in NEW_INNER_ARGS.
+ Record that. */
+ if (!NON_DEFAULT_TEMPLATE_ARGS_COUNT (new_inner_args))
+ SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (new_inner_args, arg_idx);
+ }
else
break;
@@ -5484,6 +5520,12 @@ coerce_template_parms (tree parms,
if (lost)
return error_mark_node;
+#ifdef ENABLE_CHECKING
+ if (!NON_DEFAULT_TEMPLATE_ARGS_COUNT (new_inner_args))
+ SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (new_inner_args,
+ TREE_VEC_LENGTH (new_inner_args));
+#endif
+
return new_inner_args;
}
@@ -7102,12 +7144,18 @@ instantiate_class_template (tree type)
push_to_top_level ();
+ /* Push the existing pending lock attributes to the stack. */
+ VEC_safe_push (pending_attribute_p, gc, pending_lock_attr_stack,
+ pending_lock_attributes);
+ pending_lock_attributes = NULL;
+
SET_CLASSTYPE_INTERFACE_UNKNOWN (type);
- /* Set the input location to the template definition. This is needed
- if tsubsting causes an error. */
- typedecl = TYPE_MAIN_DECL (type);
- input_location = DECL_SOURCE_LOCATION (typedecl);
+ /* Set the input location to the most specialized template definition.
+ This is needed if tsubsting causes an error. */
+ typedecl = TYPE_MAIN_DECL (pattern);
+ input_location = DECL_SOURCE_LOCATION (TYPE_NAME (type)) =
+ DECL_SOURCE_LOCATION (typedecl);
TYPE_HAS_USER_CONSTRUCTOR (type) = TYPE_HAS_USER_CONSTRUCTOR (pattern);
TYPE_HAS_NEW_OPERATOR (type) = TYPE_HAS_NEW_OPERATOR (pattern);
@@ -7528,10 +7576,13 @@ instantiate_class_template (tree type)
cplus_decl_attributes (&pa->decl, t, pa->attr_flags);
}
parsing_lock_attribute = false;
- pending_lock_attributes = NULL;
input_location = saved_location;
}
+ /* Pop out the pending attributes of the outer class/template. */
+ pending_lock_attributes = VEC_pop (pending_attribute_p,
+ pending_lock_attr_stack);
+
pop_nested_class ();
pop_from_top_level ();
pop_deferring_access_checks ();
@@ -7964,6 +8015,19 @@ tsubst_template_args (tree t, tree args, tsubst_flags_t complain, tree in_decl)
/* Make space for the expanded arguments coming from template
argument packs. */
t = make_tree_vec (len + expanded_len_adjust);
+ /* ORIG_T can contain TREE_VECs. That happens if ORIG_T contains the
+ arguments for a member template.
+ In that case each TREE_VEC in ORIG_T represents a level of template
+ arguments, and ORIG_T won't carry any non defaulted argument count.
+ It will rather be the nested TREE_VECs that will carry one.
+ In other words, ORIG_T carries a non defaulted argument count only
+ if it doesn't contain any nested TREE_VEC. */
+ if (NON_DEFAULT_TEMPLATE_ARGS_COUNT (orig_t))
+ {
+ int count = GET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (orig_t);
+ count += expanded_len_adjust;
+ SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (t, count);
+ }
for (i = 0, out = 0; i < len; i++)
{
if ((PACK_EXPANSION_P (TREE_VEC_ELT (orig_t, i))
@@ -9821,7 +9885,8 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
But, such constructs have already been resolved by this
point, so here CTX really should have complete type, unless
it's a partial instantiation. */
- ctx = complete_type (ctx);
+ if (!(complain & tf_no_class_instantiations))
+ ctx = complete_type (ctx);
if (!COMPLETE_TYPE_P (ctx))
{
if (complain & tf_error)
@@ -12604,6 +12669,10 @@ type_unification_real (tree tparms,
gcc_assert (!xargs || TREE_CODE (xargs) == TREE_LIST);
gcc_assert (ntparms > 0);
+ /* Reset the number of non-defaulted template arguments contained
+ in in TARGS. */
+ NON_DEFAULT_TEMPLATE_ARGS_COUNT (targs) = NULL_TREE;
+
switch (strict)
{
case DEDUCE_CALL:
@@ -12789,6 +12858,11 @@ type_unification_real (tree tparms,
else
{
TREE_VEC_ELT (targs, i) = arg;
+ /* The position of the first default template argument,
+ is also the number of non-defaulted arguments in TARGS.
+ Record that. */
+ if (!NON_DEFAULT_TEMPLATE_ARGS_COUNT (targs))
+ SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (targs, i);
continue;
}
}
@@ -12816,6 +12890,10 @@ type_unification_real (tree tparms,
return 2;
}
+#ifdef ENABLE_CHECKING
+ if (!NON_DEFAULT_TEMPLATE_ARGS_COUNT (targs))
+ SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (targs, TREE_VEC_LENGTH (targs));
+#endif
return 0;
}
@@ -15575,6 +15653,8 @@ instantiate_decl (tree d, int defer_ok,
&& !DECL_NOT_REALLY_EXTERN (d))
mark_definable (d);
+ DECL_SOURCE_LOCATION (td) = DECL_SOURCE_LOCATION (code_pattern);
+ DECL_SOURCE_LOCATION (d) = DECL_SOURCE_LOCATION (code_pattern);
input_location = DECL_SOURCE_LOCATION (d);
/* If D is a member of an explicitly instantiated class template,
diff --git a/gcc-4.4.3/gcc/cp/typeck2.c b/gcc-4.4.3/gcc/cp/typeck2.c
index 021f11f3f..3ac21948f 100644
--- a/gcc-4.4.3/gcc/cp/typeck2.c
+++ b/gcc-4.4.3/gcc/cp/typeck2.c
@@ -451,13 +451,15 @@ cxx_incomplete_type_error (const_tree value, const_tree type)
expression to which INIT should be assigned. INIT is a CONSTRUCTOR. */
static void
-split_nonconstant_init_1 (tree dest, tree init)
+split_nonconstant_init_1 (tree dest, tree *initp)
{
unsigned HOST_WIDE_INT idx;
+ tree init = *initp;
tree field_index, value;
tree type = TREE_TYPE (dest);
tree inner_type = NULL;
bool array_type_p = false;
+ HOST_WIDE_INT num_type_elements, num_initialized_elements;
switch (TREE_CODE (type))
{
@@ -469,6 +471,7 @@ split_nonconstant_init_1 (tree dest, tree init)
case RECORD_TYPE:
case UNION_TYPE:
case QUAL_UNION_TYPE:
+ num_initialized_elements = 0;
FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (init), idx,
field_index, value)
{
@@ -491,12 +494,13 @@ split_nonconstant_init_1 (tree dest, tree init)
sub = build3 (COMPONENT_REF, inner_type, dest, field_index,
NULL_TREE);
- split_nonconstant_init_1 (sub, value);
+ split_nonconstant_init_1 (sub, &value);
}
else if (!initializer_constant_valid_p (value, inner_type))
{
tree code;
tree sub;
+ HOST_WIDE_INT inner_elements;
/* FIXME: Ordered removal is O(1) so the whole function is
worst-case quadratic. This could be fixed using an aside
@@ -519,9 +523,22 @@ split_nonconstant_init_1 (tree dest, tree init)
code = build2 (INIT_EXPR, inner_type, sub, value);
code = build_stmt (EXPR_STMT, code);
add_stmt (code);
+
+ inner_elements = count_type_elements (inner_type, true);
+ if (inner_elements < 0)
+ num_initialized_elements = -1;
+ else if (num_initialized_elements >= 0)
+ num_initialized_elements += inner_elements;
continue;
}
}
+
+ num_type_elements = count_type_elements (type, true);
+ /* If all elements of the initializer are non-constant and
+ have been split out, we don't need the empty CONSTRUCTOR. */
+ if (num_type_elements > 0
+ && num_type_elements == num_initialized_elements)
+ *initp = NULL;
break;
case VECTOR_TYPE:
@@ -557,7 +574,7 @@ split_nonconstant_init (tree dest, tree init)
if (TREE_CODE (init) == CONSTRUCTOR)
{
code = push_stmt_list ();
- split_nonconstant_init_1 (dest, init);
+ split_nonconstant_init_1 (dest, &init);
code = pop_stmt_list (code);
DECL_INITIAL (dest) = init;
TREE_READONLY (dest) = 0;
diff --git a/gcc-4.4.3/gcc/dbgcnt.def b/gcc-4.4.3/gcc/dbgcnt.def
index aeeeeaa2f..4b904e4c6 100644
--- a/gcc-4.4.3/gcc/dbgcnt.def
+++ b/gcc-4.4.3/gcc/dbgcnt.def
@@ -164,6 +164,7 @@ DEBUG_COUNTER (if_conversion)
DEBUG_COUNTER (if_after_combine)
DEBUG_COUNTER (if_after_reload)
DEBUG_COUNTER (inl)
+DEBUG_COUNTER (ivopts)
DEBUG_COUNTER (jump_bypass)
DEBUG_COUNTER (local_alloc_for_sched)
DEBUG_COUNTER (lrs)
diff --git a/gcc-4.4.3/gcc/doc/extend.texi b/gcc-4.4.3/gcc/doc/extend.texi
index 02c2725a5..4f247f4c0 100644
--- a/gcc-4.4.3/gcc/doc/extend.texi
+++ b/gcc-4.4.3/gcc/doc/extend.texi
@@ -2635,6 +2635,10 @@ as non-null, and the @option{-Wnonnull} option is enabled, a warning
is issued. The compiler may also choose to make optimizations based
on the knowledge that certain function arguments will not be null.
+Since non-static C++ methods have an implicit @code{this} argument, the
+arguments of such methods should be counted from two, not one, when
+giving values for @var{arg-index}.
+
If no argument index list is given to the @code{nonnull} attribute,
all pointer arguments are marked as non-null. To illustrate, the
following declaration is equivalent to the previous example:
@@ -2721,6 +2725,28 @@ compiled with more aggressive optimization options that produce faster
and larger code, while other functions can be called with less
aggressive options.
+@item pcs
+@cindex @code{pcs} function attribute
+
+The @code{pcs} attribute can be used to control the calling convention
+used for a function on ARM. The attribute takes an argument that specifies
+the calling convention to use.
+
+When compiling using the AAPCS ABI (or a variant of that) then valid
+values for the argument are @code{"aapcs"} and @code{"aapcs-vfp"}. In
+order to use a variant other than @code{"aapcs"} then the compiler must
+be permitted to use the appropriate co-processor registers (i.e., the
+VFP registers must be available in order to use @code{"aapcs-vfp"}).
+For example,
+
+@smallexample
+/* Argument passed in r0, and result returned in r0+r1. */
+double f2d (float) __attribute__((pcs("aapcs")));
+@end smallexample
+
+Variadic functions always use the @code{"aapcs"} calling convention and
+the compiler will reject attempts to specify an alternative.
+
@item pure
@cindex @code{pure} function attribute
Many functions have no effects except the return value and their
@@ -3022,6 +3048,11 @@ Enable/disable the generation of the SSE4A instructions.
@cindex @code{target("sse5")} attribute
Enable/disable the generation of the SSE5 instructions.
+@item lwp
+@itemx no-lwp
+@cindex @code{target("lwp")} attribute
+Enable/disable the generation of the LWP instructions.
+
@item ssse3
@itemx no-ssse3
@cindex @code{target("ssse3")} attribute
@@ -8704,6 +8735,23 @@ v2di __builtin_ia32_protq_imm (v2di, int)
v8hi __builtin_ia32_protw_imm (v8hi, int)
@end smallexample
+The following built-in functions are available when @option{-mlwp} is used.
+
+@smallexample
+void __builtin_ia32_llwpcb16 (void *);
+void __builtin_ia32_llwpcb32 (void *);
+void __builtin_ia32_llwpcb64 (void *);
+void * __builtin_ia32_llwpcb16 (void);
+void * __builtin_ia32_llwpcb32 (void);
+void * __builtin_ia32_llwpcb64 (void);
+void __builtin_ia32_lwpval16 (unsigned short, unsigned int, unsigned short)
+void __builtin_ia32_lwpval32 (unsigned int, unsigned int, unsigned int)
+void __builtin_ia32_lwpval64 (unsigned __int64, unsigned int, unsigned int)
+unsigned char __builtin_ia32_lwpins16 (unsigned short, unsigned int, unsigned short)
+unsigned char __builtin_ia32_lwpins32 (unsigned int, unsigned int, unsigned int)
+unsigned char __builtin_ia32_lwpins64 (unsigned __int64, unsigned int, unsigned int)
+@end smallexample
+
The following built-in functions are available when @option{-m3dnow} is used.
All of them generate the machine instruction that is part of the name.
diff --git a/gcc-4.4.3/gcc/doc/gcov.texi b/gcc-4.4.3/gcc/doc/gcov.texi
index 0225b1973..3c9eeafda 100644
--- a/gcc-4.4.3/gcc/doc/gcov.texi
+++ b/gcc-4.4.3/gcc/doc/gcov.texi
@@ -124,9 +124,11 @@ gcov [@option{-v}|@option{--version}] [@option{-h}|@option{--help}]
[@option{-a}|@option{--all-blocks}]
[@option{-b}|@option{--branch-probabilities}]
[@option{-c}|@option{--branch-counts}]
+ [@option{-m}|@option{--pmu-profile}]
[@option{-n}|@option{--no-output}]
[@option{-l}|@option{--long-file-names}]
[@option{-p}|@option{--preserve-paths}]
+ [@option{-q}|@option{--pmu_profile-path}]
[@option{-f}|@option{--function-summaries}]
[@option{-o}|@option{--object-directory} @var{directory|file}] @var{sourcefiles}
[@option{-u}|@option{--unconditional-branches}]
@@ -168,6 +170,14 @@ be shown, unless the @option{-u} option is given.
Write branch frequencies as the number of branches taken, rather than
the percentage of branches taken.
+@item -m
+@itemx --pmu-profile
+Output the additional PMU profile information if available.
+
+@item -q
+@itemx --pmu_profile-path
+PMU profile path (default @file{pmuprofile.gcda}).
+
@item -n
@itemx --no-output
Do not create the @command{gcov} output file.
diff --git a/gcc-4.4.3/gcc/doc/install.texi b/gcc-4.4.3/gcc/doc/install.texi
index fe45f893c..b2f6c4c93 100644
--- a/gcc-4.4.3/gcc/doc/install.texi
+++ b/gcc-4.4.3/gcc/doc/install.texi
@@ -1112,6 +1112,11 @@ of the arguments depend on the target.
Specify if the compiler should default to @option{-marm} or @option{-mthumb}.
This option is only supported on ARM targets.
+@item --with-fpmath=sse
+Specify if the compiler should default to @option{-msse2} and
+@option{-mfpmath=sse}. This option is only supported on i386 and
+x86-64 targets.
+
@item --with-divide=@var{type}
Specify how the compiler should generate code for checking for
division by zero. This option is only supported on the MIPS target.
diff --git a/gcc-4.4.3/gcc/doc/invoke.texi b/gcc-4.4.3/gcc/doc/invoke.texi
index 8f7e654c8..f35cee8b1 100644
--- a/gcc-4.4.3/gcc/doc/invoke.texi
+++ b/gcc-4.4.3/gcc/doc/invoke.texi
@@ -245,16 +245,16 @@ Objective-C and Objective-C++ Dialects}.
-Wno-int-to-pointer-cast -Wno-invalid-offsetof @gol
-Winvalid-pch -Wlarger-than=@var{len} -Wunsafe-loop-optimizations @gol
-Wlogical-op -Wlong-long @gol
--Wmain -Wmissing-braces -Wmissing-field-initializers @gol
+-Wmain -Wmaybe-uninitialized -Wmissing-braces -Wmissing-field-initializers @gol
-Wmissing-format-attribute -Wmissing-include-dirs @gol
-Wmissing-noreturn -Wno-mudflap @gol
--Wno-multichar -Wnonnull -Wno-overflow -Wnull-conversion @gol
+-Wno-multichar -Wnonnull -Wno-overflow -Wconversion-null @gol
-Woverlength-strings -Wpacked -Wpacked-bitfield-compat -Wpadded @gol
-Wparentheses -Wpedantic-ms-format -Wno-pedantic-ms-format @gol
-Wpointer-arith -Wno-pointer-to-int-cast @gol
-Wreal-conversion -Wredundant-decls @gol
--Wreturn-type -Wripa-opt-mismatch -Wself-assign -Wsequence-point @gol
--Wshadow -Wshadow-compatible-local -Wshadow-local @gol
+-Wreturn-type -Wripa-opt-mismatch -Wself-assign -Wself-assign-non-pod @gol
+-Wsequence-point -Wshadow -Wshadow-compatible-local -Wshadow-local @gol
-Wsign-compare -Wsign-conversion -Wstack-protector @gol
-Wstrict-aliasing -Wstrict-aliasing=n @gol
-Wstrict-overflow -Wstrict-overflow=@var{n} @gol
@@ -329,13 +329,15 @@ Objective-C and Objective-C++ Dialects}.
-falign-labels[=@var{n}] -falign-loops[=@var{n}] -fassociative-math @gol
-fauto-inc-dec -fbranch-probabilities -fbranch-target-load-optimize @gol
-fbranch-target-load-optimize2 -fbtr-bb-exclusive -fcaller-saves @gol
--fcheck-data-deps -fconserve-stack -fcprop-registers -fcrossjumping @gol
+-fcgraph-section -fcheck-data-deps @gol
+-fconserve-stack -fcprop-registers -fcrossjumping @gol
-fcse-follow-jumps -fcse-skip-blocks -fcx-fortran-rules -fcx-limited-range @gol
-fdata-sections -fdce -fdce @gol
-fdelayed-branch -fdelete-null-pointer-checks -fdse -fdse @gol
-fearly-inlining -fexpensive-optimizations -ffast-math @gol
-ffinite-math-only -ffloat-store -fforward-propagate @gol
--ffunction-sections -fgcse -fgcse-after-reload -fgcse-las -fgcse-lm @gol
+-ffunction-sections -ffvpt -ffvpt-functions=@var{ffvptfunctions} -fgcse @gol
+-fgcse-after-reload -fgcse-las -fgcse-lm @gol
-fgcse-sm -fif-conversion -fif-conversion2 -findirect-inlining @gol
-finline-functions -finline-functions-called-once -finline-limit=@var{n} @gol
-finline-small-functions -fipa-cp -fipa-cp-clone -fipa-matrix-reorg -fipa-pta @gol
@@ -355,14 +357,16 @@ Objective-C and Objective-C++ Dialects}.
-fomit-frame-pointer -foptimize-register-move -foptimize-sibling-calls @gol
-fpeel-loops -fpredictive-commoning -fprefetch-loop-arrays @gol
-fprofile-correction -fprofile-dir=@var{path} -fprofile-generate @gol
--fprofile-generate=@var{path} @gol
+-fprofile-generate=@var{path} -fprofile-generate-sampling @gol
-fprofile-use -fprofile-use=@var{path} -fprofile-values @gol
+-fpmu-profile-generate=@var{pmuoption} @gol
+-fpmu-profile-use=@var{pmuoption} @gol
-freciprocal-math -fregmove -frename-registers -freorder-blocks @gol
-freorder-blocks-and-partition -freorder-functions @gol
-frerun-cse-after-loop -freschedule-modulo-scheduled-loops @gol
--fripa -fripa-disallow-asm-modules @gol
--fripa-disallow-opt-mismatch -fripa-verbose -frounding-math @gol
--fsample-profile -fsample-profile-aggregate-using @gol
+-fripa -fripa-disallow-asm-modules -fripa-disallow-opt-mismatch @gol
+-fripa-no-promote-always-inline-func -fripa-verbose @gol
+-frounding-math -fsample-profile -fsample-profile-aggregate-using @gol
-fsample-profile-use-entry -fsched2-use-superblocks @gol
-fsched2-use-traces -fsched-spec-load -fsched-spec-load-dangerous @gol
-fsched-stalled-insns-dep[=@var{n}] -fsched-stalled-insns[=@var{n}] @gol
@@ -583,17 +587,17 @@ Objective-C and Objective-C++ Dialects}.
-mno-wide-multiply -mrtd -malign-double @gol
-mpreferred-stack-boundary=@var{num}
-mincoming-stack-boundary=@var{num}
--mcld -mcx16 -msahf -mrecip @gol
+-mcld -mcx16 -msahf -mmovbe -mrecip @gol
-mmmx -msse -msse2 -msse3 -mssse3 -msse4.1 -msse4.2 -msse4 -mavx @gol
-maes -mpclmul @gol
--msse4a -m3dnow -mpopcnt -mabm -msse5 @gol
+-msse4a -m3dnow -mpopcnt -mabm -msse5 -mlwp @gol
-mthreads -mno-align-stringops -minline-all-stringops @gol
-minline-stringops-dynamically -minline-compares @gol
-mstringop-strategy=@var{alg} -mpush-args -maccumulate-outgoing-args @gol
-m128bit-long-double -m96bit-long-double -mregparm=@var{num} -msseregparm @gol
-mveclibabi=@var{type} -mpc32 -mpc64 -mpc80 -mstackrealign @gol
-momit-leaf-frame-pointer -mno-red-zone -mno-tls-direct-seg-refs @gol
--mcmodel=@var{code-model} @gol
+-mcmodel=@var{code-model} -mabi=@var{name} @gol
-m32 -m64 -mlarge-data-threshold=@var{num} @gol
-mfused-madd -mno-fused-madd -msse2avx}
@@ -2786,6 +2790,7 @@ Options} and @ref{Objective-C and Objective-C++ Dialect Options}.
-Wcomment @gol
-Wformat @gol
-Wmain @r{(only for C/ObjC and unless} @option{-ffreestanding}@r{)} @gol
+-Wmaybe-uninitialized @gol
-Wmissing-braces @gol
-Wnonnull @gol
-Wparentheses @gol
@@ -2834,6 +2839,7 @@ name is still supported, but the newer name is more descriptive.)
-Wsign-compare @gol
-Wtype-limits @gol
-Wuninitialized @gol
+-Wmaybe-uninitialized @gol
-Wunused-parameter @r{(only with} @option{-Wunused} @r{or} @option{-Wall}@r{)} @gol
}
@@ -2978,7 +2984,7 @@ Enable @option{-Wformat} plus format checks not included in
@option{-Wformat}. Currently equivalent to @samp{-Wformat
-Wformat-nonliteral -Wformat-security -Wformat-y2k}.
-@item -Wnonnull @r{(C and Objective-C only)}
+@item -Wnonnull @r{(C, C++, Objective-C, and Objective-C++ only)}
@opindex Wnonnull
@opindex Wno-nonnull
Warn about passing a null pointer for arguments marked as
@@ -3193,12 +3199,22 @@ void func()
@end group
@end smallexample
+In C++ it will not warn on self-assignment of non-POD variables unless
+@option{-Wself-assign-non-pod} is also enabled.
+
+@item -Wself-assign-non-pod
+@opindex Wself-assign-non-pod
+@opindex Wno-self-assign-non-pod
+Warn about self-assignment of non-POD variables. This is a C++-specific
+warning and only effective when @option{-Wself-assign} is enabled.
+
There are cases where self-assignment might be intentional. For example,
-a C++ programmers might write code to test whether an overloaded
+a C++ programmer might write code to test whether an overloaded
@code{operator=} works when the same object is assigned to itself.
-One way to work around the self-assign warning in such case is using
-the functional form @code{object.operator=(object)} instead of the
-assignment form @code{object = object}, as shown in the following example.
+One way to work around the self-assign warning in such cases when this flag
+is enabled is using the functional form @code{object.operator=(object)}
+instead of the assignment form @code{object = object}, as shown in the
+following example.
@smallexample
@group
@@ -3358,8 +3374,15 @@ to compute a value that itself is never used, because such
computations may be deleted by data flow analysis before the warnings
are printed.
-These warnings are made optional because GCC is not smart
-enough to see all the reasons why the code might be correct
+@item -Wmaybe-uninitialized
+@opindex Wmaybe-uninitialized
+@opindex Wno-maybe-uninitialized
+For an automatic variable, if there exists a path from the function
+entry to a use of the variable that is initialized, but there exist
+some other paths the variable is not initialized, the compiler will
+emit a warning if it can not prove the uninitialized paths do not
+happen at runtime. These warnings are made optional because GCC is
+not smart enough to see all the reasons why the code might be correct
despite appearing to have an error. Here is one example of how
this can happen:
@@ -3382,20 +3405,9 @@ this can happen:
@noindent
If the value of @code{y} is always 1, 2 or 3, then @code{x} is
-always initialized, but GCC doesn't know this. Here is
-another common case:
-
-@smallexample
-@{
- int save_y;
- if (change_y) save_y = y, y = new_y;
- @dots{}
- if (change_y) y = save_y;
-@}
-@end smallexample
-
-@noindent
-This has no bug because @code{save_y} is used only if it is set.
+always initialized, but GCC doesn't know this. To suppress the
+warning, the user needs to provide a default case with assert(0) or
+similar code.
@cindex @code{longjmp} warnings
This option also warns when a non-volatile automatic variable might be
@@ -3857,9 +3869,9 @@ to them. Warnings about conversions between signed and unsigned
integers are disabled by default in C++ unless
@option{-Wsign-conversion} is explicitly enabled.
-@item -Wnull-conversion
-@opindex Wnull-conversion
-@opindex Wno-null-conversion
+@item -Wconversion-null
+@opindex Wconversion-null
+@opindex Wno-conversion-null
Warn about peculiar, but valid, conversions from/to @code{NULL}.
This includes converting @code{NULL} to non-pointer type and
converting the boolean value @code{false} to @code{NULL}. This warning
@@ -6975,6 +6987,20 @@ The following options are enabled: @code{-fprofile-arcs}, @code{-fprofile-values
If @var{path} is specified, GCC will look at the @var{path} to find
the profile feedback data files. See @option{-fprofile-dir}.
+@item -fprofile-generate-sampling
+@opindex -fprofile-generate-sampling
+
+Enable sampling for instrumented binaries. Instead of recording every event,
+record only every N-th event, where N (the sampling rate) can be set either
+at compile time using
+@option{--param profile-generate-sampling-rate=@var{value}}, or
+at execution start time through environment variable @samp{GCOV_SAMPLING_RATE}.
+
+At this time sampling applies only to branch counters. A sampling rate of 100
+decreases instrumentated binary slowdown from up to 20x for heavily threaded
+applications down to around 2x. @option{-fprofile-correction} is always
+needed with sampling.
+
@item -fprofile-use
@itemx -fprofile-use=@var{path}
@opindex fprofile-use
@@ -6992,6 +7018,35 @@ code.
If @var{path} is specified, GCC will look at the @var{path} to find
the profile feedback data files. See @option{-fprofile-dir}.
+@item -fpmu-profile-generate=@var{pmuoption}
+@opindex fpmu-profile-generate
+
+Enable performance monitoring unit (PMU) profiling. This collects
+hardware counter data corresponding to @var{pmuoption}. Currently
+only @var{load-latency} and @var{branch-mispredict} are supported
+using pfmon tool. You must use @option{-fpmu-profile-generate} both
+when compiling and when linking your program. This PMU profile data
+may later be used by the compiler during optimizations as well can be
+displayed using coverage tool gcov. The params variable
+"pmu_profile_n_addresses" can be used to restrict PMU data collection
+to only this many addresses.
+
+@item -fpmu-profile-use=@var{pmuoption}
+@opindex fpmu-profile-use
+
+Enable performance monitoring unit (PMU) profiling based
+optimizations. Currently only @var{load-latency} and
+@var{branch-mispredict} are supported.
+
+@item -fcgraph-section
+@opindex fcgraph-section
+Emit call graph edge profile counts in .note.callgraph.text sections. This is
+used in conjunction with @option{-fprofile-use}. A new .note.callgraph.text
+section is created for each function. This section lists every callee and the
+number of times it is called. The params variable
+"note-cgraph-section-edge-threshold" can be used to only list edges above a
+certain threshold.
+
@item -fripa
@opindex fripa
Perform dynamic inter-procedural analysis. This is used in conjunction with
@@ -7021,6 +7076,10 @@ ignored for this comparison.
Enable printing of verbose information about dynamic inter-procedural optimizations.
This is used in conjunction with the @option{-fripa}.
+@item -fripa-no-promote-always-inline-func
+@opindex fripa-no-promote-always-inline-func
+Do not promote static functions with always inline attribute in LIPO compilation.
+
@item -fsample-profile
@itemx -fsample-profile=@var{path}
@opindex fsample-profile
@@ -7293,6 +7352,23 @@ and actually performs the optimizations based on them.
Currently the optimizations include specialization of division operation
using the knowledge about the value of the denominator.
+@item -ffvpt
+@opindex ffvpt
+If combined with @option{-fvpt and -ffvpt_functions}, it instructs the
+compiler to add a code to gather information about math library calls.
+
+With @option{-fbranch-probabilities}, it reads back the data gathered
+and actually performs the optimizations based on them.
+Currently the optimizations include specialization of function calls
+using precalculated values of common inputs.
+
+@item -ffvpt-functions=@var{ffvptfunctions}
+@opindex ffvpt
+This options takes a comma separated list of math functions to be
+profiled/optimized by @option{-ffvpt}. The special name ``all'' can be
+used to specify all supported math functions. Currently, exp, log,
+pow, and sqrt are supported.
+
@item -frename-registers
@opindex frename-registers
Attempt to avoid false dependencies in scheduled code by making use
@@ -7401,6 +7477,11 @@ If a guard check fails, an error message is printed and the program exits.
@opindex fstack-protector-all
Like @option{-fstack-protector} except that all functions are protected.
+NOTE: When --enable-esp this option is enabled by default
+for C, C++, ObjC, ObjC++, if neither @option{-fno-stack-protector}
+or @option{-nostdlib} or @option{-nodefaultlibs} or
+@option{-fstack-protector} are found.
+
@item -fsection-anchors
@opindex fsection-anchors
Try to reduce the number of symbolic address calculations by using
@@ -8138,6 +8219,15 @@ attributed to it, it will be assigned a weight of 0 with high
confidence. This parameter is only useful when using
@option{-fsample-profile}.
+@item max-lipo-mem
+When importing auxiliary modules during profile-use, check current
+memory consumption after parsing each auxiliary module. If it exceeds
+this limit (specified in kb), don't import any more auxiliary modules.
+Specifying a value of 0 means don't enforce this limit. This parameter
+is only useful when using @option{-fprofile-use} and @option{-fripa}.
+
+@item profile-generate-sampling-rate
+Set the sampling rate with @option{-fprofile-generate-sampling}.
@end table
@end table
@@ -8321,6 +8411,12 @@ For predictable results, you must also specify the same set of options
that were used to generate code (@option{-fpie}, @option{-fPIE},
or model suboptions) when you specify this option.
+NOTE: When --enable-esp this option is enabled by default
+for C, C++, ObjC, ObjC++, if neither @option{-fno-pie} or @option{-fno-PIE}
+or @option{-fno-pic} or @option{-fno-PIC} or @option{-nostdlib} or
+@option{-nostartfiles} or @option{-shared} or @option{-pg} or @option{-p}
+are found.
+
@item -rdynamic
@opindex rdynamic
Pass the flag @option{-export-dynamic} to the ELF linker, on targets
@@ -9354,11 +9450,6 @@ instructions, but still uses the soft-float calling conventions.
@samp{hard} allows generation of floating-point instructions
and uses FPU-specific calling conventions.
-Using @option{-mfloat-abi=hard} with VFP coprocessors is not supported.
-Use @option{-mfloat-abi=softfp} with the appropriate @option{-mfpu} option
-to allow the compiler to generate code that makes use of the hardware
-floating-point capabilities for these CPUs.
-
The default depends on the specific target configuration. Note that
the hard-float and soft-float ABIs are not link-compatible; you must
compile your entire program with the same ABI, and link with a
@@ -11342,6 +11433,9 @@ SSE2 and SSE3 instruction set support.
@item core2
Intel Core2 CPU with 64-bit extensions, MMX, SSE, SSE2, SSE3 and SSSE3
instruction set support.
+@item atom
+Intel Atom CPU with 64-bit extensions, MMX, SSE, SSE2, SSE3 and SSSE3
+instruction set support.
@item k6
AMD K6 CPU with MMX instruction set support.
@item k6-2, k6-3
@@ -11677,6 +11771,8 @@ preferred alignment to @option{-mpreferred-stack-boundary=2}.
@itemx -mno-sse4a
@itemx -msse5
@itemx -mno-sse5
+@itemx -mlwp
+@itemx -mno-lwp
@itemx -m3dnow
@itemx -mno-3dnow
@itemx -mpopcnt
@@ -11690,8 +11786,8 @@ preferred alignment to @option{-mpreferred-stack-boundary=2}.
@opindex m3dnow
@opindex mno-3dnow
These switches enable or disable the use of instructions in the MMX,
-SSE, SSE2, SSE3, SSSE3, SSE4.1, AVX, AES, PCLMUL, SSE4A, SSE5, ABM or
-3DNow!@: extended instruction sets.
+SSE, SSE2, SSE3, SSSE3, SSE4.1, AVX, AES, PCLMUL, SSE4A, SSE5, LWP,
+ABM or 3DNow!@: extended instruction sets.
These extensions are also available as built-in functions: see
@ref{X86 Built-in Functions}, for details of the functions enabled and
disabled by these switches.
@@ -11741,6 +11837,11 @@ SAHF are load and store instructions, respectively, for certain status flags.
In 64-bit mode, SAHF instruction is used to optimize @code{fmod}, @code{drem}
or @code{remainder} built-in functions: see @ref{Other Builtins} for details.
+@item -mmovbe
+@opindex mmovbe
+This option will enable GCC to use movbe instruction to implement
+@code{__builtin_bswap32} and @code{__builtin_bswap64}.
+
@item -mrecip
@opindex mrecip
This option will enable GCC to use RCPSS and RSQRTSS instructions (and their
@@ -11777,6 +11878,16 @@ when @option{-mveclibabi=acml} is used. Both @option{-ftree-vectorize} and
@option{-funsafe-math-optimizations} have to be enabled. A SVML or ACML ABI
compatible library will have to be specified at link time.
+@item -mabi=@var{name}
+@opindex mabi
+Generate code for the specified calling convention. Permissible values
+are: @samp{sysv} for the ABI used on GNU/Linux and other systems and
+@samp{ms} for the Microsoft ABI. The default is to use the Microsoft
+ABI when targeting Windows. On all other systems, the default is the
+SYSV ABI. You can control this behavior for a specific function by
+using the function attribute @samp{ms_abi}/@samp{sysv_abi}.
+@xref{Function Attributes}.
+
@item -mpush-args
@itemx -mno-push-args
@opindex mpush-args
@@ -16278,6 +16389,11 @@ used during linking.
@code{__pie__} and @code{__PIE__}. The macros have the value 1
for @option{-fpie} and 2 for @option{-fPIE}.
+NOTE: When --enable-esp this option is enabled by default
+for C, C++, ObjC, ObjC++, if neither @option{-fno-pie} or @option{-fno-PIE}
+or @option{-fno-pic} or @option{-fno-PIC} or @option{-nostdlib} or
+@option{-nostartfiles} or @option{-shared} are found.
+
@item -fno-jump-tables
@opindex fno-jump-tables
Do not use jump tables for switch statements even where it would be
diff --git a/gcc-4.4.3/gcc/doc/md.texi b/gcc-4.4.3/gcc/doc/md.texi
index cdfe379fb..6b3ca0a9d 100644
--- a/gcc-4.4.3/gcc/doc/md.texi
+++ b/gcc-4.4.3/gcc/doc/md.texi
@@ -7504,6 +7504,11 @@ be ignored for this case. The additional guard is necessary to
recognize complicated bypasses, e.g.@: when the consumer is only an address
of insn @samp{store} (not a stored value).
+If there are more one bypass with the same output and input insns, the
+chosen bypass is the first bypass with a guard in description whose
+guard function returns nonzero. If there is no such bypass, then
+bypass without the guard function is chosen.
+
@findex exclusion_set
@findex presence_set
@findex final_presence_set
diff --git a/gcc-4.4.3/gcc/doc/tm.texi b/gcc-4.4.3/gcc/doc/tm.texi
index 6168a446f..b6c3692d9 100644
--- a/gcc-4.4.3/gcc/doc/tm.texi
+++ b/gcc-4.4.3/gcc/doc/tm.texi
@@ -4341,6 +4341,18 @@ specially by the compiler and was not mentioned in the C code being
compiled.
@end defmac
+@deftypefn {Target Hook} rtx TARGET_LIBCALL_VALUE (enum machine_mode
+@var{mode}, rtx @var{fun})
+Define this hook if the back-end needs to know the name of the libcall
+function in order to determine where the result should be returned.
+
+The mode of the result is given by @var{mode} and the name of the called
+library function is given by @var{fun}. The hook should return an RTX
+representing the place where the library function result will be returned.
+
+If this hook is not defined, then LIBCALL_VALUE will be used.
+@end deftypefn
+
@defmac FUNCTION_VALUE_REGNO_P (@var{regno})
A C expression that is nonzero if @var{regno} is the number of a hard
register in which the values of called function may come back.
@@ -10687,17 +10699,18 @@ After successful simplify-got optimization, the pic_reg is useless. So a
target can use this hook to clear pic_reg.
@end deftypefn
-@deftypefn {Target Hook} rtx TARGET_LOADED_GLOBAL_VAR (rtx insn, rtx * offset_reg)
+@deftypefn {Target Hook} rtx TARGET_LOADED_GLOBAL_VAR (rtx @var{insn}, rtx * @var{offset_reg}, rtx * @var{offset_insn})
This hook is used to detect if the given @var{insn} loads a global
variable's address from GOT with the form of
@smallexample
-(set @var{address_reg} (mem (plus pic_reg @var{off})))
+(set @var{address_reg} (mem (plus pic_reg @var{offset_reg})))
@end smallexample
-If so store @var{off} into the memory pointed to by @var{offset_reg} and
-return the global variable whose address will be loaded. Otherwise return
-@code{NULL_RTX}.
+If so return the global variable whose address will be loaded and fill in
+@var{offset_insn} and @var{offset_reg}. @var{offset_reg} is set at
+@var{offset_insn} to hold the offset from GOT base to the GOT entry of the
+global variable. Otherwise return @code{NULL_RTX}.
@end deftypefn
@deftypefn {Target Hook} bool TARGET_CAN_SIMPLIFY_GOT_ACCESS (int @var{n_symbol}, int @var{n_access})
@@ -10707,10 +10720,10 @@ number of accessed symbols. If the returned value is false the GOT access
insns will not be rewritten. Otherwise we will rewrite these insns.
@end deftypefn
-@deftypefn {Target Hook} void TARGET_LOAD_GLOBAL_ADDRESS (rtx @var{symbol}, rtx @var{offset_reg}, rtx @var{address_reg}, rtx @var{load_insn})
+@deftypefn {Target Hook} void TARGET_LOAD_GLOBAL_ADDRESS (rtx @var{symbol}, rtx @var{offset_reg}, rtx @var{address_reg}, rtx @var{load_insn}, rtx @var{offset_insn})
This hook does the actual rewriting of GOT access insn @var{load_insn}.
The global variable is @var{symbol}. The global address should be loaded
-into @var{address_reg}. The register @var{offset_reg} was previously used
-to hold the offset from GOT base to the GOT entry of the global variable.
-Now it can be used as a scratch register.
+into @var{address_reg}. The register @var{offset_reg} was previously set
+in insn @var{offset_insn} to hold the offset from GOT base to the GOT
+entry of the global variable. Now it can be used as a scratch register.
@end deftypefn
diff --git a/gcc-4.4.3/gcc/dwarf2out.c b/gcc-4.4.3/gcc/dwarf2out.c
index 2f4ec13de..fd53312d9 100644
--- a/gcc-4.4.3/gcc/dwarf2out.c
+++ b/gcc-4.4.3/gcc/dwarf2out.c
@@ -14895,22 +14895,6 @@ decl_start_label (tree decl)
return fnname;
}
#endif
-
-/* Returns the DIE for a context. */
-
-static inline dw_die_ref
-get_context_die (tree context)
-{
- if (context)
- {
- /* Find die that represents this context. */
- if (TYPE_P (context))
- return force_type_die (context);
- else
- return force_decl_die (context);
- }
- return comp_unit_die;
-}
/* These routines generate the internal representation of the DIE's for
the compilation unit. Debugging information is collected by walking
@@ -16827,17 +16811,6 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
statement. */
TREE_ASM_WRITTEN (type) = 1;
- /* Figure out the proper context for the basis type. If it is
- local to a function, use NULL for now; it will be fixed up
- in decls_for_scope. */
- if (TYPE_STUB_DECL (TREE_TYPE (type)) != NULL_TREE)
- {
- if (decl_function_context (TYPE_STUB_DECL (TREE_TYPE (type))))
- context_die = NULL;
- else
- context_die = get_context_die (TYPE_CONTEXT (TREE_TYPE (type)));
- }
-
/* For these types, all that is required is that we output a DIE (or a
set of DIEs) to represent the "basis" type. */
gen_type_die_with_usage (TREE_TYPE (type), context_die,
@@ -16905,6 +16878,15 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
context_die = lookup_type_die (TYPE_CONTEXT (type));
need_pop = 1;
}
+ else if (TYPE_CONTEXT (type) != NULL_TREE
+ && (TREE_CODE (TYPE_CONTEXT (type)) == FUNCTION_DECL))
+ {
+ /* If this type is local to a function that hasn't been written
+ out yet, use a NULL context for now; it will be fixed up in
+ decls_for_scope. */
+ context_die = lookup_decl_die (TYPE_CONTEXT (type));
+ need_pop = 0;
+ }
else
{
context_die = declare_in_namespace (type, context_die);
@@ -17130,6 +17112,22 @@ is_redundant_typedef (const_tree decl)
return 0;
}
+/* Returns the DIE for a context. */
+
+static inline dw_die_ref
+get_context_die (tree context)
+{
+ if (context)
+ {
+ /* Find die that represents this context. */
+ if (TYPE_P (context))
+ return force_type_die (context);
+ else
+ return force_decl_die (context);
+ }
+ return comp_unit_die;
+}
+
/* Returns the DIE for decl. A DIE will always be returned. */
static dw_die_ref
@@ -17172,10 +17170,6 @@ force_decl_die (tree decl)
dwarf2out_decl (decl);
break;
- case TRANSLATION_UNIT_DECL:
- decl_die = comp_unit_die;
- break;
-
default:
gcc_unreachable ();
}
diff --git a/gcc-4.4.3/gcc/dyn-ipa.c b/gcc-4.4.3/gcc/dyn-ipa.c
index ae2bf2793..537acff61 100644
--- a/gcc-4.4.3/gcc/dyn-ipa.c
+++ b/gcc-4.4.3/gcc/dyn-ipa.c
@@ -43,7 +43,6 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include "gcov-io.h"
struct dyn_pointer_set;
-struct dyn_vect;
#define XNEWVEC(type,ne) (type *)malloc(sizeof(type) * (ne))
#define XNEW(type) (type *)malloc(sizeof(type))
@@ -57,6 +56,7 @@ struct dyn_cgraph_node
struct dyn_pointer_set *imported_modules;
gcov_type guid;
+ gcov_type sum_in_count;
gcov_unsigned_t visited;
};
@@ -77,7 +77,7 @@ struct dyn_module_info
struct dyn_cgraph
{
- struct dyn_cgraph_node **call_graph_nodes;
+ struct dyn_pointer_set **call_graph_nodes;
struct gcov_info **modules;
/* supplement module information */
struct dyn_module_info *sup_modules;
@@ -92,7 +92,8 @@ struct dyn_pointer_set
size_t n_slots; /* n_slots = 2^log_slots */
size_t n_elements;
- const void **slots;
+ void **slots;
+ unsigned (*get_key) (const void *);
};
@@ -105,13 +106,18 @@ void __gcov_finalize_dyn_callgraph (void) ATTRIBUTE_HIDDEN;
static void gcov_dump_callgraph (gcov_type);
static void gcov_dump_cgraph_node_short (struct dyn_cgraph_node *node);
static void gcov_dump_cgraph_node (struct dyn_cgraph_node *node,
- unsigned m, unsigned f);
+ unsigned m, unsigned f, const char *n);
static void
gcov_dump_cgraph_node_dot (struct dyn_cgraph_node *node,
unsigned m, unsigned f,
+ const char *func_nm,
gcov_type cutoff_count);
static void
pointer_set_destroy (struct dyn_pointer_set *pset);
+static void **
+pointer_set_find_or_insert (struct dyn_pointer_set *pset, unsigned key);
+static struct dyn_pointer_set *
+pointer_set_create (unsigned (*get_key) (const void *));
static struct dyn_cgraph the_dyn_call_graph;
static int total_zero_count = 0;
@@ -172,7 +178,8 @@ get_cgraph_node (gcov_type func_guid)
if (func_id > the_dyn_call_graph.sup_modules[mod_id].max_func_ident)
return 0;
- return &the_dyn_call_graph.call_graph_nodes[mod_id][func_id];
+ return *(pointer_set_find_or_insert
+ (the_dyn_call_graph.call_graph_nodes[mod_id], func_id));
}
/* Return the gcov_info pointer for module with id MODULE_ID. */
@@ -185,6 +192,12 @@ get_module_info (gcov_unsigned_t module_id)
struct gcov_info *__gcov_list ATTRIBUTE_HIDDEN;
+static inline unsigned
+cgraph_node_get_key (const void *p)
+{
+ return get_intra_module_func_id (((const struct dyn_cgraph_node *) p)->guid);
+}
+
/* Initialize dynamic call graph. */
static void
@@ -217,7 +230,7 @@ init_dyn_call_graph (void)
= XNEWVEC (const struct gcov_fn_info **, num_modules);
the_dyn_call_graph.call_graph_nodes
- = XNEWVEC (struct dyn_cgraph_node *, num_modules);
+ = XNEWVEC (struct dyn_pointer_set *, num_modules);
gi_ptr = __gcov_list;
@@ -255,21 +268,20 @@ init_dyn_call_graph (void)
the_dyn_call_graph.call_graph_nodes[mod_id]
- = XNEWVEC (struct dyn_cgraph_node, max_func_ident + 1);
+ = pointer_set_create (cgraph_node_get_key);
the_dyn_call_graph.sup_modules[mod_id].max_func_ident = max_func_ident;
- for (j = 0; j < max_func_ident + 1; j++)
- init_dyn_cgraph_node (&the_dyn_call_graph.call_graph_nodes[mod_id][j], 0);
-
for (j = 0; j < gi_ptr->n_functions; j++)
{
const struct gcov_fn_info *fi_ptr
= the_dyn_call_graph.functions[mod_id][j];
-
- node = &the_dyn_call_graph.call_graph_nodes[mod_id][fi_ptr->ident];
- init_dyn_cgraph_node (node, GEN_FUNC_GLOBAL_ID (gi_ptr->mod_info->ident,
- fi_ptr->ident));
+ *(pointer_set_find_or_insert
+ (the_dyn_call_graph.call_graph_nodes[mod_id], fi_ptr->ident))
+ = node = XNEW (struct dyn_cgraph_node);
+ the_dyn_call_graph.call_graph_nodes[mod_id]->n_elements++;
+ init_dyn_cgraph_node (node, GEN_FUNC_GLOBAL_ID (gi_ptr->mod_info->ident,
+ fi_ptr->ident));
}
}
}
@@ -292,7 +304,9 @@ __gcov_finalize_dyn_callgraph (void)
struct dyn_cgraph_node *node;
struct dyn_cgraph_edge *callees, *next_callee;
fi_ptr = the_dyn_call_graph.functions[i][f_ix];
- node = &the_dyn_call_graph.call_graph_nodes[i][fi_ptr->ident];
+ node = *(pointer_set_find_or_insert
+ (the_dyn_call_graph.call_graph_nodes[i], fi_ptr->ident));
+ gcc_assert (node);
callees = node->callees;
if (!callees)
@@ -307,7 +321,7 @@ __gcov_finalize_dyn_callgraph (void)
pointer_set_destroy (node->imported_modules);
}
if (the_dyn_call_graph.call_graph_nodes[i])
- XDELETEVEC (the_dyn_call_graph.call_graph_nodes[i]);
+ pointer_set_destroy (the_dyn_call_graph.call_graph_nodes[i]);
if (the_dyn_call_graph.functions[i])
XDELETEVEC (the_dyn_call_graph.functions[i]);
/* Now delete sup modules */
@@ -486,7 +500,10 @@ gcov_build_callgraph (void)
{
struct dyn_cgraph_node *caller;
fi_ptr = the_dyn_call_graph.functions[m_ix][f_ix];
- caller = &the_dyn_call_graph.call_graph_nodes[m_ix][fi_ptr->ident];
+ caller = *(pointer_set_find_or_insert
+ (the_dyn_call_graph.call_graph_nodes[m_ix],
+ fi_ptr->ident));
+ gcc_assert (caller);
if (dcall_profile_values)
{
unsigned offset;
@@ -519,7 +536,7 @@ gcov_build_callgraph (void)
}
static inline size_t
-hash1 (const void *p, unsigned long max, unsigned long logmax)
+hash1 (unsigned p, unsigned long max, unsigned long logmax)
{
const unsigned long long A = 0x9e3779b97f4a7c16ull;
const unsigned long long shift = 64 - logmax;
@@ -527,10 +544,10 @@ hash1 (const void *p, unsigned long max, unsigned long logmax)
return ((A * (unsigned long) p) >> shift) & (max - 1);
}
-/* Allocate an empty pointer set. */
+/* Allocate an empty imported-modules set. */
static struct dyn_pointer_set *
-pointer_set_create (void)
+pointer_set_create (unsigned (*get_key) (const void *))
{
struct dyn_pointer_set *result = XNEW (struct dyn_pointer_set);
@@ -538,8 +555,10 @@ pointer_set_create (void)
result->log_slots = 8;
result->n_slots = (size_t) 1 << result->log_slots;
- result->slots = XNEWVEC (const void *, result->n_slots);
- memset (result->slots, 0, sizeof (const void *) * result->n_slots);
+ result->slots = XNEWVEC (void *, result->n_slots);
+ memset (result->slots, 0, sizeof (void *) * result->n_slots);
+ result->get_key = get_key;
+
return result;
}
@@ -548,19 +567,25 @@ pointer_set_create (void)
static void
pointer_set_destroy (struct dyn_pointer_set *pset)
{
+ size_t i;
+ for (i = 0; i < pset->n_slots; i++)
+ if (pset->slots[i])
+ XDELETE (pset->slots[i]);
XDELETEVEC (pset->slots);
XDELETE (pset);
}
-/* Subroutine of pointer_set_insert. Return the insertion slot for P into
- an empty element of SLOTS, an array of length N_SLOTS. */
+/* Subroutine of pointer_set_find_or_insert. Return the insertion slot for KEY
+ into an empty element of SLOTS, an array of length N_SLOTS. */
static inline size_t
-insert_aux (const void *p, const void **slots, size_t n_slots, size_t log_slots)
+insert_aux (unsigned key, void **slots,
+ size_t n_slots, size_t log_slots,
+ unsigned (*get_key) (const void *))
{
- size_t n = hash1 (p, n_slots, log_slots);
+ size_t n = hash1 (key, n_slots, log_slots);
while (1)
{
- if (slots[n] == p || slots[n] == 0)
+ if (slots[n] == 0 || get_key (slots[n]) == key)
return n;
else
{
@@ -571,28 +596,30 @@ insert_aux (const void *p, const void **slots, size_t n_slots, size_t log_slots)
}
}
-/* Insert P into PSET if it wasn't already there. Returns nonzero
- if it was already there. P must be nonnull. */
+/* Find slot for KEY. KEY must be nonnull. */
-static int
-pointer_set_insert (struct dyn_pointer_set *pset, const void *p)
+static void **
+pointer_set_find_or_insert (struct dyn_pointer_set *pset, unsigned key)
{
size_t n;
- /* For simplicity, expand the set even if P is already there. This can be
+ /* For simplicity, expand the set even if KEY is already there. This can be
superfluous but can happen at most once. */
if (pset->n_elements > pset->n_slots / 4)
{
size_t new_log_slots = pset->log_slots + 1;
size_t new_n_slots = pset->n_slots * 2;
- const void **new_slots = XNEWVEC (const void *, new_n_slots);
- memset (new_slots, 0, sizeof (const void*) * new_n_slots);
+ void **new_slots = XNEWVEC (void *, new_n_slots);
+ memset (new_slots, 0, sizeof (void *) * new_n_slots);
size_t i;
for (i = 0; i < pset->n_slots; ++i)
{
- const void *value = pset->slots[i];
- n = insert_aux (value, new_slots, new_n_slots, new_log_slots);
+ void *value = pset->slots[i];
+ if (!value)
+ continue;
+ n = insert_aux (pset->get_key (value), new_slots, new_n_slots,
+ new_log_slots, pset->get_key);
new_slots[n] = value;
}
@@ -602,37 +629,64 @@ pointer_set_insert (struct dyn_pointer_set *pset, const void *p)
pset->slots = new_slots;
}
- n = insert_aux (p, pset->slots, pset->n_slots, pset->log_slots);
- if (pset->slots[n])
- return 1;
-
- pset->slots[n] = p;
- ++pset->n_elements;
- return 0;
+ n = insert_aux (key, pset->slots, pset->n_slots, pset->log_slots,
+ pset->get_key);
+ return &pset->slots[n];
}
/* Pass each pointer in PSET to the function in FN, together with the fixed
- parameter DATA. If FN returns false, the iteration stops. */
+ parameters DATA1, DATA2, DATA3. If FN returns false, the iteration stops. */
static void
pointer_set_traverse (const struct dyn_pointer_set *pset,
- int (*fn) (const void *, void *), void *data)
+ int (*fn) (const void *, void *, void *, void *),
+ void *data1, void *data2, void *data3)
{
size_t i;
for (i = 0; i < pset->n_slots; ++i)
- if (pset->slots[i] && !fn (pset->slots[i], data))
+ if (pset->slots[i] && !fn (pset->slots[i], data1, data2, data3))
break;
}
-/* Callback function to propagate import module set (VALUE) from callee to
- caller (DATA). */
static int
-gcov_propagate_imp_modules (const void *value, void *data)
+imp_mod_set_insert (struct dyn_pointer_set *p, const struct gcov_info *imp_mod,
+ double wt)
{
- struct dyn_pointer_set *receiving_set
- = (struct dyn_pointer_set *) data;
+ struct dyn_imp_mod **m = (struct dyn_imp_mod **)
+ pointer_set_find_or_insert (p, imp_mod->mod_info->ident);
+ if (*m)
+ {
+ (*m)->weight += wt;
+ return 1;
+ }
+ else
+ {
+ *m = XNEW (struct dyn_imp_mod);
+ (*m)->imp_mod = imp_mod;
+ (*m)->weight = wt;
+ p->n_elements++;
+ return 0;
+ }
+}
- pointer_set_insert (receiving_set, value);
+/* Callback function to propagate import module (VALUE) from callee to
+ caller's imported-module-set (DATA1).
+ The weight is scaled by the scaling-factor (DATA2) before propagation,
+ and accumulated into DATA3. */
+static int
+gcov_propagate_imp_modules (const void *value, void *data1, void *data2,
+ void *data3)
+{
+ const struct dyn_imp_mod *m = (const struct dyn_imp_mod *) value;
+ struct dyn_pointer_set *receiving_set = (struct dyn_pointer_set *) data1;
+ double *scale = (double *) data2;
+ double *sum = (double *) data3;
+ double wt = m->weight;
+ if (scale)
+ wt *= *scale;
+ if (sum)
+ (*sum) += wt;
+ imp_mod_set_insert (receiving_set, m->imp_mod, wt);
return 1;
}
@@ -668,6 +722,7 @@ gcov_compute_cutoff_count (void)
unsigned cutoff_perc;
unsigned num_perc;
int do_dump;
+ const char *dump_str;
capacity = 100;
/* allocate an edge array */
@@ -687,7 +742,9 @@ gcov_compute_cutoff_count (void)
fi_ptr = the_dyn_call_graph.functions[m_ix][f_ix];
- node = &the_dyn_call_graph.call_graph_nodes[m_ix][fi_ptr->ident];
+ node = *(pointer_set_find_or_insert
+ (the_dyn_call_graph.call_graph_nodes[m_ix], fi_ptr->ident));
+ gcc_assert (node);
callees = node->callees;
while (callees != 0)
@@ -708,7 +765,7 @@ gcov_compute_cutoff_count (void)
/* Now sort */
qsort (edges, num_edges, sizeof (void *), sort_by_count);
-#define CUM_CUTOFF_PERCENT 95
+#define CUM_CUTOFF_PERCENT 80
#define MIN_NUM_EDGE_PERCENT 0
cutoff_str = getenv ("GCOV_DYN_CGRAPH_CUTOFF");
if (cutoff_str && strlen (cutoff_str))
@@ -736,11 +793,12 @@ gcov_compute_cutoff_count (void)
total += edges[i]->count;
cum_cutoff = (total * cutoff_perc)/100;
- do_dump = (getenv ("GCOV_DYN_CGRAPH_DUMP") != 0);
+ dump_str = getenv ("GCOV_DYN_CGRAPH_DUMP");
+ do_dump = (dump_str != 0 && strlen (dump_str));
for (i = 0; i < num_edges; i++)
{
cum += edges[i]->count;
- if (do_dump)
+ if (do_dump && dump_str[0] == '1')
fprintf (stderr, "// edge[%d] count = %.0f [%llx --> %llx]\n",
i, (double) edges[i]->count,
(long long) edges[i]->caller->guid,
@@ -752,7 +810,7 @@ gcov_compute_cutoff_count (void)
}
}
- if (do_dump)
+ if (do_dump && dump_str[0] == '1')
fprintf (stderr, "// total = %.0f cum = %.0f cum/total = %.0f%%"
" cutoff_count = %lld [total edges: %d hot edges: %d perc: %d%%]\n"
" total_zero_count_edges = %d total_insane_count_edgess = %d\n"
@@ -765,13 +823,19 @@ gcov_compute_cutoff_count (void)
return cutoff_count;
}
+static inline unsigned
+imp_mod_get_key (const void *p)
+{
+ return ((const struct dyn_imp_mod *) p)->imp_mod->mod_info->ident;
+}
+
/* Return the imported module set for NODE. */
static struct dyn_pointer_set *
gcov_get_imp_module_set (struct dyn_cgraph_node *node)
{
if (!node->imported_modules)
- node->imported_modules = pointer_set_create ();
+ node->imported_modules = pointer_set_create (imp_mod_get_key);
return node->imported_modules;
}
@@ -782,7 +846,7 @@ static struct dyn_pointer_set *
gcov_get_module_imp_module_set (struct dyn_module_info *mi)
{
if (!mi->imported_modules)
- mi->imported_modules = pointer_set_create ();
+ mi->imported_modules = pointer_set_create (imp_mod_get_key);
return mi->imported_modules;
}
@@ -790,10 +854,13 @@ gcov_get_module_imp_module_set (struct dyn_module_info *mi)
/* Callback function to mark if a module needs to be exported. */
static int
-gcov_mark_export_modules (const void *value, void *data ATTRIBUTE_UNUSED)
+gcov_mark_export_modules (const void *value,
+ void *data1 ATTRIBUTE_UNUSED,
+ void *data2 ATTRIBUTE_UNUSED,
+ void *data3 ATTRIBUTE_UNUSED)
{
const struct gcov_info *module_info
- = (const struct gcov_info *)value;
+ = ((const struct dyn_imp_mod *) value)->imp_mod;
module_info->mod_info->is_exported = 1;
return 1;
@@ -801,7 +868,7 @@ gcov_mark_export_modules (const void *value, void *data ATTRIBUTE_UNUSED)
struct gcov_import_mod_array
{
- const struct gcov_info **imported_modules;
+ const struct dyn_imp_mod **imported_modules;
struct gcov_info *importing_module;
unsigned len;
};
@@ -809,10 +876,12 @@ struct gcov_import_mod_array
/* Callback function to compute pointer set size. */
static int
-gcov_compute_pset_size (const void *value ATTRIBUTE_UNUSED,
- void *data)
+gcov_compute_mset_size (const void *value ATTRIBUTE_UNUSED,
+ void *data1,
+ void *data2 ATTRIBUTE_UNUSED,
+ void *data3 ATTRIBUTE_UNUSED)
{
- unsigned *len = (unsigned *) data;
+ unsigned *len = (unsigned *) data1;
(*len)++;
return 1;
}
@@ -820,36 +889,44 @@ gcov_compute_pset_size (const void *value ATTRIBUTE_UNUSED,
/* Callback function to collect imported modules. */
static int
-gcov_collect_imported_modules (const void *value, void *data)
+gcov_collect_imported_modules (const void *value,
+ void *data1,
+ void *data2 ATTRIBUTE_UNUSED,
+ void *data3 ATTRIBUTE_UNUSED)
{
struct gcov_import_mod_array *out_array;
- const struct gcov_info *module_info
- = (const struct gcov_info *)value;
+ const struct dyn_imp_mod *m
+ = (const struct dyn_imp_mod *) value;
- out_array = (struct gcov_import_mod_array *) data;
+ out_array = (struct gcov_import_mod_array *) data1;
- if (module_info != out_array->importing_module)
- out_array->imported_modules[out_array->len++] = module_info;
+ if (m->imp_mod != out_array->importing_module)
+ out_array->imported_modules[out_array->len++] = m;
return 1;
}
-/* Comparitor for sorting imported modules using module ids. */
+/* Comparator for sorting imported modules using weights. */
static int
-sort_by_module_id (const void *pa, const void *pb)
+sort_by_module_wt (const void *pa, const void *pb)
{
- const struct gcov_info *m_a = *(struct gcov_info * const *)pa;
- const struct gcov_info *m_b = *(struct gcov_info * const *)pb;
+ const struct dyn_imp_mod *m_a = *((const struct dyn_imp_mod * const *) pa);
+ const struct dyn_imp_mod *m_b = *((const struct dyn_imp_mod * const *) pb);
- return (int) m_a->mod_info->ident - (int) m_b->mod_info->ident;
+ /* We want to sort in descending order of weights. */
+ if (m_a->weight < m_b->weight)
+ return +1;
+ if (m_a->weight > m_b->weight)
+ return -1;
+ return get_module_idx (m_a->imp_mod) - get_module_idx (m_b->imp_mod);
}
/* Return a dynamic array of imported modules that is sorted for
the importing module MOD_INFO. The length of the array is returned
in *LEN. */
-const struct gcov_info **
+const struct dyn_imp_mod **
gcov_get_sorted_import_module_array (struct gcov_info *mod_info,
unsigned *len)
{
@@ -865,28 +942,86 @@ gcov_get_sorted_import_module_array (struct gcov_info *mod_info,
return 0;
pointer_set_traverse (sup_mod_info->imported_modules,
- gcov_compute_pset_size, &array_len);
- imp_array.imported_modules = XNEWVEC (const struct gcov_info *, array_len);
+ gcov_compute_mset_size, &array_len, 0, 0);
+ imp_array.imported_modules = XNEWVEC (const struct dyn_imp_mod *, array_len);
imp_array.len = 0;
imp_array.importing_module = mod_info;
pointer_set_traverse (sup_mod_info->imported_modules,
- gcov_collect_imported_modules, &imp_array);
+ gcov_collect_imported_modules, &imp_array, 0, 0);
*len = imp_array.len;
qsort (imp_array.imported_modules, imp_array.len,
- sizeof (void *), sort_by_module_id);
+ sizeof (void *), sort_by_module_wt);
return imp_array.imported_modules;
}
/* Compute modules that are needed for NODE (for cross module inlining).
- CUTTOFF_COUNT is the call graph edge count cutoff value. */
+ CUTTOFF_COUNT is the call graph edge count cutoff value.
+ IMPORT_SCALE is the scaling-factor (percent) by which to scale the
+ weights of imported modules of a callee before propagating them to
+ the caller, if the callee and caller are in different modules.
+
+ Each imported module is assigned a weight that corresponds to the
+ expected benefit due to cross-module inlining. When the imported modules
+ are written out, they are sorted with highest weight first.
+
+ The following example illustrates how the weight is computed:
+
+ Suppose we are processing call-graph node A. It calls function B 50 times,
+ which calls function C 1000 times, and function E 800 times. Lets say B has
+ another in-edge from function D, with edge-count of 50. Say all the
+ functions are in separate modules (modules a, b, c, d, e, respectively):
+
+ D
+ |
+ | 50
+ |
+ 50 v 1000
+ A --------> B ----------> C
+ |
+ | 800
+ |
+ v
+ E
+
+ Nodes are processed in depth-first order, so when processing A, we first
+ process B. For node B, we are going to add module c to the imported-module
+ set, with weight 1000 (edge-count), and module e with weight 800.
+ Coming back to A, we are going to add the imported-module-set of B to A,
+ after doing some scaling.
+ The first scaling factor comes from the fact that A calls B 50 times, but B
+ has in-edge-count total of 100. So this scaling factor is 50/100 = 0.5
+ The second scaling factor is that since B is in a different module than A,
+ we want to slightly downgrade imported modules of B, before adding to the
+ imported-modules set of A. This scaling factor has a default value of 50%
+ (can be set via env variable GCOV_DYN_IMPORT_SCALE).
+ So we end up adding modules c and e to the imported-set of A, with weights
+ 0.5*0.5*1000=250 and 0.5*0.5*800=200, respectively.
+
+ Next, we have to add module b itself to A. The weight is computed as the
+ edge-count plus the sum of scaled-weights of all modules in the
+ imported-module set of B, i.e., 50 + 250 + 200 = 500.
+
+ In computing the weight of module b, we add the sum of scaled-weights of
+ imported modules of b, because it doesn't make sense to import c, e in
+ module a, until module b is imported. */
static void
gcov_process_cgraph_node (struct dyn_cgraph_node *node,
- gcov_type cutoff_count)
+ gcov_type cutoff_count,
+ unsigned import_scale)
{
unsigned mod_id;
struct dyn_cgraph_edge *callees;
+ struct dyn_cgraph_edge *callers;
node->visited = 1;
+ node->sum_in_count = 0;
+
+ callers = node->callers;
+ while (callers)
+ {
+ node->sum_in_count += callers->count;
+ callers = callers->next_caller;
+ }
callees = node->callees;
mod_id = get_module_idx_from_func_glob_uid (node->guid);
@@ -895,7 +1030,8 @@ gcov_process_cgraph_node (struct dyn_cgraph_node *node,
{
if (!callees->callee->visited)
gcov_process_cgraph_node (callees->callee,
- cutoff_count);
+ cutoff_count,
+ import_scale);
callees = callees->next_callee;
}
@@ -911,16 +1047,24 @@ gcov_process_cgraph_node (struct dyn_cgraph_node *node,
callee_mod_id
= get_module_idx_from_func_glob_uid (callees->callee->guid);
+ double callee_mod_wt = (double) callees->count;
+ if (callees->callee->imported_modules)
+ {
+ double scale = ((double) callees->count) /
+ ((double) callees->callee->sum_in_count);
+ /* Reduce weight if callee is in different module. */
+ if (mod_id != callee_mod_id)
+ scale = (scale * import_scale) / 100.0;
+ pointer_set_traverse (callees->callee->imported_modules,
+ gcov_propagate_imp_modules,
+ imp_modules, &scale, &callee_mod_wt);
+ }
if (mod_id != callee_mod_id)
{
struct gcov_info *callee_mod_info
= get_module_info (callee_mod_id);
- pointer_set_insert (imp_modules, callee_mod_info);
+ imp_mod_set_insert (imp_modules, callee_mod_info, callee_mod_wt);
}
- if (callees->callee->imported_modules)
- pointer_set_traverse (callees->callee->imported_modules,
- gcov_propagate_imp_modules,
- imp_modules);
}
callees = callees->next_callee;
@@ -930,11 +1074,18 @@ gcov_process_cgraph_node (struct dyn_cgraph_node *node,
/* Compute module grouping using CUTOFF_COUNT as the hot edge
threshold. */
+#define DEFAULT_IMPORT_SCALE 100
static void
gcov_compute_module_groups (gcov_type cutoff_count)
{
unsigned m_ix;
struct gcov_info *gi_ptr;
+ const char *import_scale_str;
+ unsigned import_scale = DEFAULT_IMPORT_SCALE;
+
+ import_scale_str = getenv ("GCOV_DYN_IMPORT_SCALE");
+ if (import_scale_str && strlen (import_scale_str))
+ import_scale = atoi (import_scale_str);
for (m_ix = 0; m_ix < the_dyn_call_graph.num_modules; m_ix++)
{
@@ -948,11 +1099,13 @@ gcov_compute_module_groups (gcov_type cutoff_count)
struct dyn_cgraph_node *node;
fi_ptr = the_dyn_call_graph.functions[m_ix][f_ix];
- node = &the_dyn_call_graph.call_graph_nodes[m_ix][fi_ptr->ident];
+ node = *(pointer_set_find_or_insert
+ (the_dyn_call_graph.call_graph_nodes[m_ix], fi_ptr->ident));
+ gcc_assert (node);
if (node->visited)
continue;
- gcov_process_cgraph_node (node, cutoff_count);
+ gcov_process_cgraph_node (node, cutoff_count, import_scale);
}
}
@@ -970,7 +1123,9 @@ gcov_compute_module_groups (gcov_type cutoff_count)
struct dyn_pointer_set *imp_modules;
fi_ptr = the_dyn_call_graph.functions[m_ix][f_ix];
- node = &the_dyn_call_graph.call_graph_nodes[m_ix][fi_ptr->ident];
+ node = *(pointer_set_find_or_insert
+ (the_dyn_call_graph.call_graph_nodes[m_ix], fi_ptr->ident));
+ gcc_assert (node);
if (!node->imported_modules)
continue;
@@ -984,7 +1139,7 @@ gcov_compute_module_groups (gcov_type cutoff_count)
pointer_set_traverse (node->imported_modules,
gcov_propagate_imp_modules,
- imp_modules);
+ imp_modules, 0, 0);
}
}
@@ -995,7 +1150,7 @@ gcov_compute_module_groups (gcov_type cutoff_count)
= &the_dyn_call_graph.sup_modules[m_ix];
if (mi->imported_modules)
pointer_set_traverse (mi->imported_modules,
- gcov_mark_export_modules, 0);
+ gcov_mark_export_modules, 0, 0, 0);
}
}
@@ -1023,7 +1178,7 @@ gcov_compute_random_module_groups (unsigned max_group_size)
if (mod_id == m_ix)
continue;
imp_mod_info = get_module_info (mod_id);
- if (!pointer_set_insert (imp_modules, imp_mod_info))
+ if (!imp_mod_set_insert (imp_modules, imp_mod_info, 1.0))
i++;
}
}
@@ -1035,7 +1190,7 @@ gcov_compute_random_module_groups (unsigned max_group_size)
= &the_dyn_call_graph.sup_modules[m_ix];
if (mi->imported_modules)
pointer_set_traverse (mi->imported_modules,
- gcov_mark_export_modules, 0);
+ gcov_mark_export_modules, 0, 0, 0);
}
}
@@ -1118,7 +1273,7 @@ void
gcov_write_module_infos (struct gcov_info *mod_info)
{
unsigned mod_id, imp_len = 0;
- const struct gcov_info **imp_mods;
+ const struct dyn_imp_mod **imp_mods;
mod_id = get_module_idx (mod_info);
gcov_write_module_info (mod_info, 1);
@@ -1130,7 +1285,7 @@ gcov_write_module_infos (struct gcov_info *mod_info)
for (i = 0; i < imp_len; i++)
{
- const struct gcov_info *imp_mod = imp_mods[i];
+ const struct gcov_info *imp_mod = imp_mods[i]->imp_mod;
gcov_write_module_info (imp_mod, 0);
}
free (imp_mods);
@@ -1186,7 +1341,8 @@ gcov_dump_cgraph_node_short (struct dyn_cgraph_node *node)
/* Dumper function for NODE. M is the module id and F is the function id. */
static void
-gcov_dump_cgraph_node (struct dyn_cgraph_node *node, unsigned m, unsigned f)
+gcov_dump_cgraph_node (struct dyn_cgraph_node *node, unsigned m, unsigned f,
+ const char *n)
{
unsigned mod_id, func_id;
struct gcov_info *mod_info;
@@ -1199,9 +1355,9 @@ gcov_dump_cgraph_node (struct dyn_cgraph_node *node, unsigned m, unsigned f)
mod_info = the_dyn_call_graph.modules[mod_id];
- fprintf (stderr, "NODE(%llx) module(%s) func(%x)\n",
+ fprintf (stderr, "NODE(%llx) module(%s):%s(%x)\n",
(long long) node->guid,
- mod_info->mod_info->source_filename, f);
+ mod_info->mod_info->source_filename, n, f);
/* Now dump callers. */
callers = node->callers;
@@ -1228,13 +1384,12 @@ gcov_dump_cgraph_node (struct dyn_cgraph_node *node, unsigned m, unsigned f)
/* Dumper function for NODE. M is the module id and F is the function id. */
static void
-gcov_dump_cgraph_node_dot (struct dyn_cgraph_node *node,
- unsigned m, unsigned f,
- gcov_type cutoff_count)
+gcov_dump_cgraph_node_dot (struct dyn_cgraph_node *node, unsigned m,
+ unsigned f, const char * n, gcov_type cutoff_count)
{
unsigned mod_id, func_id, imp_len = 0, i;
struct gcov_info *mod_info;
- const struct gcov_info **imp_mods;
+ const struct dyn_imp_mod **imp_mods;
struct dyn_cgraph_edge *callees;
mod_id = get_module_idx_from_func_glob_uid (node->guid);
@@ -1243,15 +1398,15 @@ gcov_dump_cgraph_node_dot (struct dyn_cgraph_node *node,
mod_info = the_dyn_call_graph.modules[mod_id];
- fprintf (stderr, "NODE_%llx[label=\"MODULE\\n(%s)\\n FUNC(%x)\\n",
- (long long) node->guid, mod_info->mod_info->source_filename, f);
+ fprintf (stderr, "NODE_%llx[label=\"MODULE\\n(%s)\\n %s(%x)\\n",
+ (long long) node->guid, mod_info->mod_info->source_filename, n, f);
imp_mods = gcov_get_sorted_import_module_array (mod_info, &imp_len);
fprintf (stderr, "IMPORTS:\\n");
if (imp_mods)
{
for (i = 0; i < imp_len; i++)
- fprintf (stderr, "%s\\n", imp_mods[i]->mod_info->source_filename);
+ fprintf (stderr, "%s\\n", imp_mods[i]->imp_mod->mod_info->source_filename);
fprintf (stderr, "\"]\n");
free (imp_mods);
}
@@ -1302,17 +1457,19 @@ gcov_dump_callgraph (gcov_type cutoff_count)
struct dyn_cgraph_node *node;
fi_ptr = the_dyn_call_graph.functions[m_ix][f_ix];
- node = &the_dyn_call_graph.call_graph_nodes[m_ix][fi_ptr->ident];
+ node = *(pointer_set_find_or_insert
+ (the_dyn_call_graph.call_graph_nodes[m_ix], fi_ptr->ident));
+ gcc_assert (node);
/* skip dead functions */
if (!node->callees && !node->callers)
continue;
if (dyn_cgraph_dump[0] == '1')
- gcov_dump_cgraph_node (node, m_ix, fi_ptr->ident);
+ gcov_dump_cgraph_node (node, m_ix, fi_ptr->ident, fi_ptr->name);
else
gcov_dump_cgraph_node_dot (node, m_ix, fi_ptr->ident,
- cutoff_count);
+ fi_ptr->name, cutoff_count);
}
}
fprintf (stderr,"}\n");
diff --git a/gcc-4.4.3/gcc/esp.h b/gcc-4.4.3/gcc/esp.h
new file mode 100644
index 000000000..db2135b72
--- /dev/null
+++ b/gcc-4.4.3/gcc/esp.h
@@ -0,0 +1,145 @@
+/* License terms see GNU GENERAL PUBLIC LICENSE Version 3.
+ * Version 20100527.1
+ * Magnus Granberg (Zorry) <zorry@gentoo.org> */
+#ifndef GCC_ESP_H
+#define GCC_ESP_H
+
+/* This file will add -fstack-protector-all, -fPIE, -pie and -z now
+ as default if the defines and the spec allow it.
+ Added a hack for gcc-specs-* in toolchain-funcs.eclass and _filter-hardened in flag-o-matic.eclass
+ to support older hardened GCC patches and we don't need to change the code on gcc-specs-* and _filter-hardened.
+ This will add some unsupported upstream commands options as -nopie and -nonow.
+ -D__KERNEL__ is added so we don't have -fPIE, -pie and -fstack-protector-all when building kernels.
+ ESP_CC1_SPEC is added to CC1_SPEC.
+ ESP_CC1_STRICT_OVERFLOW_SPEC is added so we don't disable the strict-overflow check.
+ ESP_LINK_PIE_CHECK_SPEC check for -pie, -p, -pg, -profile and -static.
+ ENABLE_CRTBEGINTS add support for crtbeginTS.o, build -static with -fPIE or -fpie.
+*/
+#ifdef ENABLE_ESP
+
+ /* Hack to support gcc-specs-* in toolchain-funcs.eclass and _filter-hardened in flag-o-matic.eclass */
+ #define ESP_CC1_SPEC " %(esp_cc1_ssp) %(esp_cc1_pie) %(esp_cc1_strict_overflow)"
+ #if defined ( EFAULT_SSP ) || defined ( EFAULT_PIE_SSP )
+ #define ESP_CC1_SSP_SPEC "%{!fno-stack-protector: %{!fno-stack-protector-all: }}"
+ #else
+ #define ESP_CC1_SSP_SPEC ""
+ #endif
+ #if defined ( EFAULT_PIE ) || defined ( EFAULT_PIE_SSP )
+ #define ESP_CC1_PIE_SPEC "%{!nopie: }"
+ #else
+ #define ESP_CC1_PIE_SPEC ""
+ #endif
+ #define ESP_CC1_STRICT_OVERFLOW_SPEC "%{!fstrict-overflow:%{!fno-strict-overflow: -fno-strict-overflow}}"
+
+ /* ESP_LINK_SPEC is added to LINK_PIE_SPEC if esp is enable
+ -z now will be added if we don't have -vanilla spec. We do a -pie incompatible check
+ Don't remove the specs in the end */
+ #define ESP_LINK_SPEC "%(esp_link_now) %(esp_link_pie_check) "
+ #define ESP_LINK_NOW_SPEC "%{!nonow:-z now}"
+
+ /* We use ESP_COMMAND_OPTIONS_SPEC to add pie command-line options. */
+ #define ESP_COMMAND_OPTIONS_SPEC "%{!D__KERNEL__:%{!nopie:%(esp_options_pie) %(esp_link_pie)}}"
+
+ /* ESP_OPTIONS_SPEC is added to the compiler spec in gcc/gcc.c */
+ #define ESP_OPTIONS_SPEC "%(esp_options_ssp)"
+
+ /* ESP_CPP_OPTIONS_SPEC is added to the cpp_options spec in gcc/gcc.c
+ For precompiling headers. */
+ #define ESP_CPP_OPTIONS_SPEC "%(esp_options_ssp)"
+
+ /* This will add -fstack-protector-all if we don't have -nostdlib -nodefaultlibs -fno-stack-protector -fstack-protector
+ -fstack-protector-all and we have EFAULT_SSP or EFAULT_PIE_SSP defined. */
+ #if defined ( EFAULT_SSP ) || defined ( EFAULT_PIE_SSP )
+ #define ESP_OPTIONS_SSP_SPEC \
+ "%{!D__KERNEL__:%{!nostdlib:%{!nodefaultlibs: %{!fno-stack-protector: \
+ %{!fstack-protector:%{!fstack-protector-all:-fstack-protector-all}}}}}}"
+ #else
+ #define ESP_OPTIONS_SSP_SPEC ""
+ #endif
+
+ /* If EFAULT_PIE or EFAULT_PIE_SSP is defined we will add -fPIE -pie */
+ #if defined ( EFAULT_PIE ) || defined ( EFAULT_PIE_SSP )
+
+ /* This will add -fPIE if we don't have -pie -fpic -fPIC -fpie -fPIE -fno-pic -fno-PIC -fno-pie -fno-PIE -shared -static
+ -nostdlib -nostartfiles. */
+ /* With ENABLE_CRTBEGINTS we don't need to check for -static */
+ #ifdef ENABLE_CRTBEGINTS
+ #define ESP_OPTIONS_PIE_SPEC \
+ "%{!pie: %{!fpic:%{!fPIC:%{!fpie:%{!fPIE: %{!fno-pic:%{!fno-PIC:%{!fno-pie:%{!fno-PIE: \
+ %{!shared: %{!nostdlib: %{!nostartfiles:-fPIE}} } }}}} }}}} }"
+ #else
+ #define ESP_OPTIONS_PIE_SPEC \
+ "%{!pie: %{!fpic:%{!fPIC:%{!fpie:%{!fPIE: %{!fno-pic:%{!fno-PIC:%{!fno-pie:%{!fno-PIE: \
+ %{!shared: %{!static: %{!nostdlib: %{!nostartfiles:-fPIE}} } }}}} }}}} }}"
+ #endif
+
+ /* This will add -pie if we don't have -pie -A -fno-pic -fno-PIC -fno-pie -fno-PIE -shared -static -r -nostdlib
+ -nostartfiles */
+ /* With ENABLE_CRTBEGINTS we don't need to check for -static
+ and we add -pie only to get the start and endfiles. -pie will not go to the linker. */
+ #ifdef ENABLE_CRTBEGINTS
+ #define ESP_LINK_PIE_SPEC \
+ "%{!pie:%{!A:%{!fno-pie:%{!fno-PIE:%{!fno-pic:%{!fno-PIC:%{!shared:%{!r: \
+ %{!nostdlib:%{!nostartfiles:-pie}}}}}}}}}}"
+ #else
+ #define ESP_LINK_PIE_SPEC \
+ "%{!pie:%{!A:%{!fno-pie:%{!fno-PIE:%{!fno-pic:%{!fno-PIC:%{!shared:%{!static:%{!r: \
+ %{!nostdlib:%{!nostartfiles:-pie}}}}}}}}}}}"
+ #endif
+
+ /* This will check if -pie is set when (-static) -pg -p -profile. If set it will make gcc print out
+ "-pie and (static)|pg|p|profile are incompatible when linking" */
+ /* With ENABLE_CRTBEGINTS we don't need to check for -static */
+ #ifdef ENABLE_CRTBEGINTS
+ #define ESP_LINK_PIE_CHECK_SPEC \
+ "%{pie:%{pg|p|profile:%e-pie and -pg|p|profile are incompatible when linking}}"
+ #else
+ #define ESP_LINK_PIE_CHECK_SPEC \
+ "%{pie:%{static|pg|p|profile:%e-pie and -static|pg|p|profile are incompatible when linking}}"
+ #endif
+
+ /* We don't pass -pie to the linker when -static. */
+ #ifdef ENABLE_CRTBEGINTS
+ #define LINK_PIE_SPEC "%{!static:%{pie:-pie}} %(esp_link)"
+ #else
+ #define LINK_PIE_SPEC "%{pie:-pie} %(esp_link)"
+ #endif
+
+ #else
+ #define ESP_OPTIONS_PIE_SPEC ""
+ #define ESP_LINK_PIE_CHECK_SPEC ""
+ #define ESP_LINK_PIE_SPEC ""
+ #define LINK_PIE_SPEC "%{pie:-pie} %(esp_link)"
+ #endif
+
+ /* We add extra spec name's to the EXTRA_SPECS list */
+ #define ESP_EXTRA_SPECS \
+ { "esp_cc1", ESP_CC1_SPEC }, \
+ { "esp_cc1_pie", ESP_CC1_PIE_SPEC }, \
+ { "esp_cc1_ssp", ESP_CC1_SSP_SPEC }, \
+ { "esp_cc1_strict_overflow", ESP_CC1_STRICT_OVERFLOW_SPEC }, \
+ { "esp_link", ESP_LINK_SPEC }, \
+ { "esp_link_now", ESP_LINK_NOW_SPEC }, \
+ { "esp_link_pie", ESP_LINK_PIE_SPEC }, \
+ { "esp_link_pie_check", ESP_LINK_PIE_CHECK_SPEC }, \
+ { "esp_command_options", ESP_COMMAND_OPTIONS_SPEC }, \
+ { "esp_cpp_options", ESP_CPP_OPTIONS_SPEC }, \
+ { "esp_options", ESP_OPTIONS_SPEC }, \
+ { "esp_options_pie", ESP_OPTIONS_PIE_SPEC }, \
+ { "esp_options_ssp", ESP_OPTIONS_SSP_SPEC }
+
+ static const char *esp_command_options_spec = ESP_COMMAND_OPTIONS_SPEC;
+ static const char *cc1_spec = CC1_SPEC ESP_CC1_SPEC;
+
+#else /* If not ESP_ENABLE defined do this. */
+
+ #define ESP_OPTIONS_SPEC ""
+ #define ESP_CPP_OPTIONS_SPEC ""
+
+ /* We add extra spec name's to the EXTRA_SPECS list */
+ #define ESP_EXTRA_SPECS \
+ { "esp_options", ESP_OPTIONS_SPEC }, \
+ { "esp_cpp_options", ESP_CPP_OPTIONS_SPEC }
+
+#endif
+#endif /* End GCC_ESP_H */
diff --git a/gcc-4.4.3/gcc/explow.c b/gcc-4.4.3/gcc/explow.c
index c9bf675d3..d43aad00d 100644
--- a/gcc-4.4.3/gcc/explow.c
+++ b/gcc-4.4.3/gcc/explow.c
@@ -1491,9 +1491,9 @@ hard_function_value (const_tree valtype, const_tree func, const_tree fntype,
in which a scalar value of mode MODE was returned by a library call. */
rtx
-hard_libcall_value (enum machine_mode mode)
+hard_libcall_value (enum machine_mode mode, rtx fun)
{
- return LIBCALL_VALUE (mode);
+ return targetm.calls.libcall_value (mode, fun);
}
/* Look up the tree code for a given rtx code
diff --git a/gcc-4.4.3/gcc/expr.h b/gcc-4.4.3/gcc/expr.h
index 216de87fe..a89d4f916 100644
--- a/gcc-4.4.3/gcc/expr.h
+++ b/gcc-4.4.3/gcc/expr.h
@@ -757,7 +757,7 @@ extern void probe_stack_range (HOST_WIDE_INT, rtx);
/* Return an rtx that refers to the value returned by a library call
in its original home. This becomes invalid if any more code is emitted. */
-extern rtx hard_libcall_value (enum machine_mode);
+extern rtx hard_libcall_value (enum machine_mode, rtx);
/* Return the mode desired by operand N of a particular bitfield
insert/extract insn, or MAX_MACHINE_MODE if no such insn is
diff --git a/gcc-4.4.3/gcc/final.c b/gcc-4.4.3/gcc/final.c
index dc9a6d818..2c0be960d 100644
--- a/gcc-4.4.3/gcc/final.c
+++ b/gcc-4.4.3/gcc/final.c
@@ -1649,6 +1649,58 @@ final_end_function (void)
#endif
}
+
+static basic_block *start_to_bb = NULL;
+static basic_block *end_to_bb = NULL;
+static int bb_map_size = 0;
+static int bb_seq = 0;
+
+/* Dumper helper for basic block information. FILE is the assembly
+ output file, and INSN is the instruction being emitted. */
+
+static void
+dump_basic_block_info (FILE *file, rtx insn)
+{
+ basic_block bb;
+
+ if (!flag_debug_asm)
+ return;
+
+ if (INSN_UID (insn) < bb_map_size
+ && (bb = start_to_bb[INSN_UID (insn)]) != NULL)
+ {
+ edge e;
+ edge_iterator ei;
+
+ fprintf (file, "# BLOCK %d", bb->index);
+ if (bb->frequency)
+ fprintf (file, " freq:%d", bb->frequency);
+ if (bb->count)
+ fprintf (file, " count:" HOST_WIDEST_INT_PRINT_DEC,
+ bb->count);
+ fprintf (file, " seq:%d", bb_seq++);
+ fprintf (file, "\n# PRED:");
+ FOR_EACH_EDGE (e, ei, bb->preds)
+ {
+ dump_edge_info (file, e, 0);
+ }
+ fprintf (file, "\n");
+ }
+ if (INSN_UID (insn) < bb_map_size
+ && (bb = end_to_bb[INSN_UID (insn)]) != NULL)
+ {
+ edge e;
+ edge_iterator ei;
+
+ fprintf (asm_out_file, "# SUCC:");
+ FOR_EACH_EDGE (e, ei, bb->succs)
+ {
+ dump_edge_info (asm_out_file, e, 1);
+ }
+ fprintf (file, "\n");
+ }
+}
+
/* Output assembler code for some insns: all or part of a function.
For description of args, see `final_start_function', above. */
@@ -1683,6 +1735,21 @@ final (rtx first, FILE *file, int optimize)
CC_STATUS_INIT;
+ if (flag_debug_asm)
+ {
+ basic_block bb;
+
+ bb_map_size = get_max_uid () + 1;
+ start_to_bb = XCNEWVEC (basic_block, bb_map_size);
+ end_to_bb = XCNEWVEC (basic_block, bb_map_size);
+
+ FOR_EACH_BB_REVERSE (bb)
+ {
+ start_to_bb[INSN_UID (BB_HEAD (bb))] = bb;
+ end_to_bb[INSN_UID (BB_END (bb))] = bb;
+ }
+ }
+
/* Output the insns. */
for (insn = first; insn;)
{
@@ -1698,8 +1765,19 @@ final (rtx first, FILE *file, int optimize)
insn_current_address = INSN_ADDRESSES (INSN_UID (insn));
#endif /* HAVE_ATTR_length */
+ dump_basic_block_info (file, insn);
insn = final_scan_insn (insn, file, optimize, 0, &seen);
}
+
+ if (flag_debug_asm)
+ {
+ free (start_to_bb);
+ free (end_to_bb);
+ start_to_bb = NULL;
+ end_to_bb = NULL;
+ bb_map_size = 0;
+ bb_seq = 0;
+ }
}
const char *
@@ -1834,10 +1912,6 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
targetm.asm_out.unwind_emit (asm_out_file, insn);
#endif
- if (flag_debug_asm)
- fprintf (asm_out_file, "\t%s basic block %d\n",
- ASM_COMMENT_START, NOTE_BASIC_BLOCK (insn)->index);
-
if ((*seen & (SEEN_EMITTED | SEEN_BB)) == SEEN_BB)
{
*seen |= SEEN_EMITTED;
@@ -4203,13 +4277,35 @@ debug_free_queue (void)
symbol_queue_size = 0;
}
}
-
+
+/* List the call graph profiled edges in the ".note.callgraph.text" section. */
+static void
+cgraph_get_profiles (void)
+{
+ struct cgraph_node *node = cgraph_node (current_function_decl);
+ struct cgraph_edge *e;
+ struct cgraph_node *callee;
+
+ for (e = node->callees; e != NULL; e = e->next_callee)
+ {
+ if (e->count <= PARAM_VALUE (PARAM_NOTE_CGRAPH_SECTION_EDGE_THRESHOLD))
+ continue;
+ callee = e->callee;
+ fprintf (asm_out_file, "\t.string \"%s\"\n",
+ IDENTIFIER_POINTER (decl_assembler_name (callee->decl)));
+ fprintf (asm_out_file, "\t.string \"" HOST_WIDEST_INT_PRINT_DEC "\"\n",
+ e->count);
+ }
+}
+
/* Turn the RTL into assembly. */
static unsigned int
rest_of_handle_final (void)
{
rtx x;
const char *fnname;
+ char *profile_fnname;
+ unsigned int flags;
/* Get the function's name, as described by its RTL. This may be
different from the DECL_NAME name used in the source file. */
@@ -4274,6 +4370,22 @@ rest_of_handle_final (void)
targetm.asm_out.destructor (XEXP (DECL_RTL (current_function_decl), 0),
decl_fini_priority_lookup
(current_function_decl));
+
+ /* With -fcgraph-section, add ".note.callgraph.text" section for storing
+ profiling information. */
+ if (flag_cgraph_section
+ && flag_profile_use
+ && cgraph_node (current_function_decl) != NULL)
+ {
+ flags = SECTION_NOTYPE;
+ profile_fnname = (char *)xmalloc(strlen(".note.callgraph.text.")
+ + strlen(fnname) + 1);
+ sprintf(profile_fnname, ".note.callgraph.text.%s", fnname);
+ switch_to_section(get_section(profile_fnname, flags, NULL));
+ fprintf (asm_out_file, "\t.string \"Function %s\"\n", fnname);
+ cgraph_get_profiles ();
+ free (profile_fnname);
+ }
return 0;
}
diff --git a/gcc-4.4.3/gcc/flags.h b/gcc-4.4.3/gcc/flags.h
index 57ea8c0c4..9507d2b94 100644
--- a/gcc-4.4.3/gcc/flags.h
+++ b/gcc-4.4.3/gcc/flags.h
@@ -399,6 +399,16 @@ enum warn_strict_overflow_code
WARN_STRICT_OVERFLOW_MAGNITUDE = 5
};
+/* Math functions that the ffvpt-pass will profile and optimize. */
+struct ffvpt_options_s
+{
+ bool exp_set;
+ bool log_set;
+ bool pow_set;
+ bool sqrt_set;
+};
+extern struct ffvpt_options_s ffvpt_options;
+
/* Whether to emit an overflow warning whose code is C. */
#define issue_strict_overflow_warning(c) (warn_strict_overflow >= (int) (c))
diff --git a/gcc-4.4.3/gcc/fold-const.c b/gcc-4.4.3/gcc/fold-const.c
index fd4debd36..e1931e66b 100644
--- a/gcc-4.4.3/gcc/fold-const.c
+++ b/gcc-4.4.3/gcc/fold-const.c
@@ -7901,46 +7901,11 @@ native_interpret_int (tree type, const unsigned char *ptr, int len)
static tree
native_interpret_real (tree type, const unsigned char *ptr, int len)
{
- enum machine_mode mode = TYPE_MODE (type);
- int total_bytes = GET_MODE_SIZE (mode);
- int byte, offset, word, words, bitpos;
- unsigned char value;
- /* There are always 32 bits in each long, no matter the size of
- the hosts long. We handle floating point representations with
- up to 192 bits. */
REAL_VALUE_TYPE r;
- long tmp[6];
-
- total_bytes = GET_MODE_SIZE (TYPE_MODE (type));
- if (total_bytes > len || total_bytes > 24)
+ if (!real_from_native (type, ptr, len, &r))
return NULL_TREE;
- words = (32 / BITS_PER_UNIT) / UNITS_PER_WORD;
-
- memset (tmp, 0, sizeof (tmp));
- for (bitpos = 0; bitpos < total_bytes * BITS_PER_UNIT;
- bitpos += BITS_PER_UNIT)
- {
- byte = (bitpos / BITS_PER_UNIT) & 3;
- if (UNITS_PER_WORD < 4)
- {
- word = byte / UNITS_PER_WORD;
- if (WORDS_BIG_ENDIAN)
- word = (words - 1) - word;
- offset = word * UNITS_PER_WORD;
- if (BYTES_BIG_ENDIAN)
- offset += (UNITS_PER_WORD - 1) - (byte % UNITS_PER_WORD);
- else
- offset += byte % UNITS_PER_WORD;
- }
- else
- offset = BYTES_BIG_ENDIAN ? 3 - byte : byte;
- value = ptr[offset + ((bitpos / BITS_PER_UNIT) & ~3)];
-
- tmp[bitpos / 32] |= (unsigned long)value << (bitpos & 31);
- }
-
- real_from_target (&r, tmp, mode);
- return build_real (type, r);
+ else
+ return build_real (type, r);
}
diff --git a/gcc-4.4.3/gcc/fortran/module.c b/gcc-4.4.3/gcc/fortran/module.c
index b5c522f93..5a2b6d1ea 100644
--- a/gcc-4.4.3/gcc/fortran/module.c
+++ b/gcc-4.4.3/gcc/fortran/module.c
@@ -3319,7 +3319,7 @@ mio_f2k_derived (gfc_namespace *f2k)
f2k->finalizers = NULL;
while (peek_atom () != ATOM_RPAREN)
{
- gfc_finalizer *cur;
+ gfc_finalizer *cur = NULL;
mio_finalizer (&cur);
cur->next = f2k->finalizers;
f2k->finalizers = cur;
diff --git a/gcc-4.4.3/gcc/function.h b/gcc-4.4.3/gcc/function.h
index 2e2542b13..967846707 100644
--- a/gcc-4.4.3/gcc/function.h
+++ b/gcc-4.4.3/gcc/function.h
@@ -521,6 +521,10 @@ struct function GTY(())
/* Used types hash table. */
htab_t GTY ((param_is (union tree_node))) used_types_hash;
+ /* Map between variables synthesized in stack_overlay to the original
+ variables. Used in RTL emission.*/
+ htab_t GTY ((param_is (struct overlay_decl_mapping))) union_decl_list_map;
+
/* Last statement uid. */
int last_stmt_uid;
diff --git a/gcc-4.4.3/gcc/gcc.c b/gcc-4.4.3/gcc/gcc.c
index f22ef3385..3ce244cdf 100644
--- a/gcc-4.4.3/gcc/gcc.c
+++ b/gcc-4.4.3/gcc/gcc.c
@@ -83,6 +83,7 @@ compilation is specified by a string called a "spec". */
#include "gcc.h"
#include "flags.h"
#include "opts.h"
+#include "esp.h" /* for --enable-esp support */
/* By default there is no special suffix for target executables. */
/* FIXME: when autoconf is fixed, remove the host check - dj */
@@ -727,6 +728,10 @@ proper position among the other output files. */
# endif
#endif
+/* Google-local http://b/2739909 */
+#ifndef LINK_RPATH_SPEC
+# define LINK_RPATH_SPEC ""
+#endif
/* -u* was put back because both BSD and SysV seem to support it. */
/* %{static:} simply prevents an error message if the target machine
@@ -738,6 +743,7 @@ proper position among the other output files. */
#define LINK_COMMAND_SPEC "\
%{!fsyntax-only:%{!c:%{!M:%{!MM:%{!E:%{!S:\
%(linker) %l " LINK_PIE_SPEC \
+ LINK_RPATH_SPEC \
"%{fuse-ld=gold:%{fuse-ld=bfd:%e-fuse-ld=gold and -fuse-ld=bfd may not be used together}} \
%{fuse-ld=gold:-use-gold} \
%{fuse-ld=bfd:-use-ld}" \
@@ -745,7 +751,7 @@ proper position among the other output files. */
%{s} %{t} %{u*} %{x} %{z} %{Z} %{!A:%{!nostdlib:%{!nostartfiles:%S}}}\
%{static:} %{L*} %(mfwrap) %(link_libgcc) %o\
%{fopenmp|ftree-parallelize-loops=*:%:include(libgomp.spec)%(link_gomp)} %(mflib)\
- %{fprofile-arcs|fprofile-generate*|coverage:-lgcov}\
+ %{fprofile-arcs|fprofile-generate*|fpmu-profile-generate*|coverage:-lgcov}\
%{!nostdlib:%{!nodefaultlibs:%(link_ssp) %(link_gcc_c_sequence)}}\
%{!A:%{!nostdlib:%{!nostartfiles:%E}}} %{T*} }}}}}}"
#endif
@@ -773,7 +779,9 @@ proper position among the other output files. */
static const char *asm_debug;
static const char *cpp_spec = CPP_SPEC;
+#ifndef ENABLE_ESP
static const char *cc1_spec = CC1_SPEC;
+#endif
static const char *cc1plus_spec = CC1PLUS_SPEC;
static const char *link_gcc_c_sequence_spec = LINK_GCC_C_SEQUENCE_SPEC;
static const char *link_ssp_spec = LINK_SSP_SPEC;
@@ -832,7 +840,7 @@ static const char *cpp_unique_options =
static const char *cpp_options =
"%(cpp_unique_options) %1 %{m*} %{std*&ansi&trigraphs} %{W*&pedantic*} %{w}\
%{f*} %{g*:%{!g0:%{g*} %{!fno-working-directory:-fworking-directory}}} %{O*}\
- %{undef} %{save-temps:-fpch-preprocess}";
+ %{undef} %{save-temps:-fpch-preprocess} %(esp_cpp_options)";
/* This contains cpp options which are not passed when the preprocessor
output will be used by another program. */
@@ -1014,15 +1022,15 @@ static const struct compiler default_compilers[] =
%{save-temps|traditional-cpp|no-integrated-cpp:%(trad_capable_cpp) \
%(cpp_options) -o %{save-temps:%b.i} %{!save-temps:%g.i} \n\
cc1 -fpreprocessed %{save-temps:%b.i} %{!save-temps:%g.i} \
- %(cc1_options)}\
+ %(cc1_options) %(espf_options)}\
%{!save-temps:%{!traditional-cpp:%{!no-integrated-cpp:\
- cc1 %(cpp_unique_options) %(cc1_options)}}}\
+ cc1 %(cpp_unique_options) %(cc1_options) %(esp_options)}}}\
%{!fsyntax-only:%(invoke_as)}} \
%{combine:\
%{save-temps|traditional-cpp|no-integrated-cpp:%(trad_capable_cpp) \
%(cpp_options) -o %{save-temps:%b.i} %{!save-temps:%g.i}}\
%{!save-temps:%{!traditional-cpp:%{!no-integrated-cpp:\
- cc1 %(cpp_unique_options) %(cc1_options)}}\
+ cc1 %(cpp_unique_options) %(cc1_options) %(esp_options)}}\
%{!fsyntax-only:%(invoke_as)}}}}}}", 0, 1, 1},
{"-",
"%{!E:%e-E or -x required when input is from standard input}\
@@ -1045,7 +1053,7 @@ static const struct compiler default_compilers[] =
%W{o*:--output-pch=%*}%V}}}}}}", 0, 0, 0},
{".i", "@cpp-output", 0, 1, 0},
{"@cpp-output",
- "%{!M:%{!MM:%{!E:cc1 -fpreprocessed %i %(cc1_options) %{!fsyntax-only:%(invoke_as)}}}}", 0, 1, 0},
+ "%{!M:%{!MM:%{!E:cc1 -fpreprocessed %i %(cc1_options) %(esp_options) %{!fsyntax-only:%(invoke_as)}}}}", 0, 1, 0},
{".s", "@assembler", 0, 1, 0},
{"@assembler",
"%{!M:%{!MM:%{!E:%{!S:as %(asm_debug) %(asm_options) %i %A }}}}", 0, 1, 0},
@@ -1634,18 +1642,23 @@ static struct spec_list static_specs[] =
INIT_STATIC_SPEC ("sysroot_hdrs_suffix_spec", &sysroot_hdrs_suffix_spec),
};
-#ifdef EXTRA_SPECS /* additional specs needed */
+/* EXTRA_SPECS needs to be defined */
+#ifndef EXTRA_SPECS
+#define EXTRA_SPECS
+#endif
+
+/* EXTRA_SPECS and ESP_EXTRA_SPECS add additional specs */
/* Structure to keep track of just the first two args of a spec_list.
- That is all that the EXTRA_SPECS macro gives us. */
+ That is all that the EXTRA_SPECS and ESP_EXTRA_SPECS macro gives us. */
struct spec_list_1
{
const char *const name;
const char *const ptr;
};
-static const struct spec_list_1 extra_specs_1[] = { EXTRA_SPECS };
+/* ESP_EXTRA_SPECS before EXTRA_SPECS */
+static const struct spec_list_1 extra_specs_1[] = { ESP_EXTRA_SPECS, EXTRA_SPECS };
static struct spec_list *extra_specs = (struct spec_list *) 0;
-#endif
/* List of dynamically allocates specs that have been defined so far. */
@@ -1730,7 +1743,6 @@ init_spec (void)
if (verbose_flag)
notice ("Using built-in specs.\n");
-#ifdef EXTRA_SPECS
extra_specs = XCNEWVEC (struct spec_list, ARRAY_SIZE (extra_specs_1));
for (i = ARRAY_SIZE (extra_specs_1) - 1; i >= 0; i--)
@@ -1743,7 +1755,6 @@ init_spec (void)
sl->ptr_spec = &sl->ptr;
next = sl;
}
-#endif
for (i = ARRAY_SIZE (static_specs) - 1; i >= 0; i--)
{
@@ -6536,6 +6547,12 @@ main (int argc, char **argv)
gcc_exec_prefix = concat (gcc_exec_prefix, spec_machine, dir_separator_str,
spec_version, dir_separator_str, NULL);
+#ifdef ENABLE_ESP
+ /* Process ESP_COMMAND_OPTIONS_SPEC, adding any new options to the end
+ of the command line. */
+ do_self_spec (esp_command_options_spec);
+#endif
+
/* Now we have the specs.
Set the `valid' bits for switches that match anything in any spec. */
diff --git a/gcc-4.4.3/gcc/gcov-dump.c b/gcc-4.4.3/gcc/gcov-dump.c
index 681bdbfbe..0417ab1a9 100644
--- a/gcc-4.4.3/gcc/gcov-dump.c
+++ b/gcc-4.4.3/gcc/gcov-dump.c
@@ -39,6 +39,10 @@ static void tag_lines (const char *, unsigned, unsigned);
static void tag_counters (const char *, unsigned, unsigned);
static void tag_summary (const char *, unsigned, unsigned);
static void tag_module_info (const char *, unsigned, unsigned);
+static void tag_pmu_load_latency_info (const char *, unsigned, unsigned);
+static void tag_pmu_branch_mispredict_info (const char *, unsigned, unsigned);
+static void tag_pmu_tool_header (const char *, unsigned, unsigned);
+
extern int main (int, char **);
typedef struct tag_format
@@ -73,6 +77,11 @@ static const tag_format_t tag_table[] =
{GCOV_TAG_OBJECT_SUMMARY, "OBJECT_SUMMARY", tag_summary},
{GCOV_TAG_PROGRAM_SUMMARY, "PROGRAM_SUMMARY", tag_summary},
{GCOV_TAG_MODULE_INFO, "MODULE INFO", tag_module_info},
+ {GCOV_TAG_PMU_LOAD_LATENCY_INFO, "PMU_LOAD_LATENCY_INFO",
+ tag_pmu_load_latency_info},
+ {GCOV_TAG_PMU_BRANCH_MISPREDICT_INFO, "PMU_BRANCH_MISPREDICT_INFO",
+ tag_pmu_branch_mispredict_info},
+ {GCOV_TAG_PMU_TOOL_HEADER, "PMU_TOOL_HEADER", tag_pmu_tool_header},
{0, NULL, NULL}
};
@@ -516,3 +525,45 @@ tag_module_info (const char *filename ATTRIBUTE_UNUSED,
printf (": %s [%s]", mod_info->source_filename, suffix);
}
}
+
+/* Read gcov tag GCOV_TAG_PMU_LOAD_LATENCY_INFO from the gcda file and
+ print the contents in a human readable form. */
+
+static void
+tag_pmu_load_latency_info (const char *filename ATTRIBUTE_UNUSED,
+ unsigned tag ATTRIBUTE_UNUSED, unsigned length)
+{
+ gcov_pmu_ll_info_t ll_info;
+ gcov_read_pmu_load_latency_info (&ll_info, length);
+ print_load_latency_line (stdout, &ll_info, 0);
+ if (ll_info.filename)
+ free (ll_info.filename);
+}
+
+/* Read gcov tag GCOV_TAG_PMU_BRANCH_MISPREDICT_INFO from the gcda
+ file and print the contents in a human readable form. */
+
+static void
+tag_pmu_branch_mispredict_info (const char *filename ATTRIBUTE_UNUSED,
+ unsigned tag ATTRIBUTE_UNUSED, unsigned length)
+{
+ gcov_pmu_brm_info_t brm_info;
+ gcov_read_pmu_branch_mispredict_info (&brm_info, length);
+ print_branch_mispredict_line (stdout, &brm_info, 0);
+ if (brm_info.filename)
+ free (brm_info.filename);
+}
+
+
+/* Read gcov tag GCOV_TAG_PMU_TOOL_HEADER from the gcda file and print
+ the contents in a human readable form. */
+
+static void
+tag_pmu_tool_header (const char *filename ATTRIBUTE_UNUSED,
+ unsigned tag ATTRIBUTE_UNUSED, unsigned length)
+{
+ gcov_pmu_tool_header_t tool_header;
+ gcov_read_pmu_tool_header (&tool_header, length);
+ print_pmu_tool_header (stdout, &tool_header, 0);
+ destroy_pmu_tool_header (&tool_header);
+}
diff --git a/gcc-4.4.3/gcc/gcov-io.c b/gcc-4.4.3/gcc/gcov-io.c
index 0e60b51de..f56f07cdf 100644
--- a/gcc-4.4.3/gcc/gcov-io.c
+++ b/gcc-4.4.3/gcc/gcov-io.c
@@ -25,7 +25,7 @@ along with GCC; see the file COPYING3. If not see
/* Redefine these here, rather than using the ones in system.h since
* including system.h leads to conflicting definitions of other
- * symbols and macros. */
+ * symbols and macros. */
#undef MIN
#define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
@@ -38,6 +38,10 @@ static const gcov_unsigned_t *gcov_read_words (unsigned);
static void gcov_allocate (unsigned);
#endif
+#ifdef __GCOV_KERNEL__
+struct gcov_var gcov_var ATTRIBUTE_HIDDEN;
+#endif
+
static inline gcov_unsigned_t from_file (gcov_unsigned_t value)
{
#if !IN_LIBGCOV
@@ -59,6 +63,7 @@ static inline gcov_unsigned_t from_file (gcov_unsigned_t value)
opening an existing file and <0 on creating a new one.
MODE > 0 is read-only mode. */
+#ifndef __GCOV_KERNEL__
GCOV_LINKAGE int
#if IN_LIBGCOV
gcov_open (const char *name)
@@ -78,7 +83,7 @@ gcov_open (const char *name, int mode)
s_flock.l_len = 0; /* Until EOF. */
s_flock.l_pid = getpid ();
#endif
-
+
gcc_assert (!gcov_var.file);
gcov_var.start = 0;
gcov_var.offset = gcov_var.length = 0;
@@ -150,9 +155,26 @@ gcov_open (const char *name, int mode)
#endif
setbuf (gcov_var.file, (char *)0);
-
+
+ return 1;
+}
+#else /* __GCOV_KERNEL__ */
+
+extern _GCOV_FILE *gcov_current_file;
+
+GCOV_LINKAGE int
+gcov_open (const char *name)
+{
+ gcov_var.start = 0;
+ gcov_var.offset = gcov_var.length = 0;
+ gcov_var.overread = -1u;
+ gcov_var.error = 0;
+ gcov_var.file = gcov_current_file;
+ gcov_var.mode = 1;
+
return 1;
}
+#endif /* __GCOV_KERNEL__ */
/* Close the current gcov file. Flushes data to disk. Returns nonzero
on failure or error flag set. */
@@ -166,7 +188,7 @@ gcov_close (void)
if (gcov_var.offset && gcov_var.mode < 0)
gcov_write_block (gcov_var.offset);
#endif
- fclose (gcov_var.file);
+ _GCOV_fclose (gcov_var.file);
gcov_var.file = 0;
gcov_var.length = 0;
}
@@ -180,6 +202,76 @@ gcov_close (void)
}
#if !IN_LIBGCOV
+/* Read LEN words and construct load latency info LL_INFO. */
+
+GCOV_LINKAGE void
+gcov_read_pmu_load_latency_info (gcov_pmu_ll_info_t *ll_info,
+ gcov_unsigned_t len ATTRIBUTE_UNUSED)
+{
+ const char *filename;
+ ll_info->counts = gcov_read_unsigned ();
+ ll_info->self = gcov_read_unsigned ();
+ ll_info->cum = gcov_read_unsigned ();
+ ll_info->lt_10 = gcov_read_unsigned ();
+ ll_info->lt_32 = gcov_read_unsigned ();
+ ll_info->lt_64 = gcov_read_unsigned ();
+ ll_info->lt_256 = gcov_read_unsigned ();
+ ll_info->lt_1024 = gcov_read_unsigned ();
+ ll_info->gt_1024 = gcov_read_unsigned ();
+ ll_info->wself = gcov_read_unsigned ();
+ ll_info->code_addr = gcov_read_counter ();
+ ll_info->line = gcov_read_unsigned ();
+ ll_info->discriminator = gcov_read_unsigned ();
+ filename = gcov_read_string ();
+ if (filename)
+ ll_info->filename = xstrdup (filename);
+ else
+ ll_info->filename = 0;
+}
+
+/* Read LEN words and construct branch mispredict info BRM_INFO. */
+
+GCOV_LINKAGE void
+gcov_read_pmu_branch_mispredict_info (gcov_pmu_brm_info_t *brm_info,
+ gcov_unsigned_t len ATTRIBUTE_UNUSED)
+{
+ const char *filename;
+ brm_info->counts = gcov_read_unsigned ();
+ brm_info->self = gcov_read_unsigned ();
+ brm_info->cum = gcov_read_unsigned ();
+ brm_info->code_addr = gcov_read_counter ();
+ brm_info->line = gcov_read_unsigned ();
+ brm_info->discriminator = gcov_read_unsigned ();
+ filename = gcov_read_string ();
+ if (filename)
+ brm_info->filename = xstrdup (filename);
+ else
+ brm_info->filename = 0;
+}
+
+/* Read LEN words from an open gcov file and construct data into pmu
+ tool header TOOL_HEADER. */
+
+GCOV_LINKAGE void gcov_read_pmu_tool_header (gcov_pmu_tool_header_t *header,
+ gcov_unsigned_t len ATTRIBUTE_UNUSED)
+{
+ const char *str;
+ str = gcov_read_string ();
+ header->host_cpu = str ? xstrdup (str) : 0;
+ str = gcov_read_string ();
+ header->hostname = str ? xstrdup (str) : 0;
+ str = gcov_read_string ();
+ header->kernel_version = str ? xstrdup (str) : 0;
+ str = gcov_read_string ();
+ header->column_header = str ? xstrdup (str) : 0;
+ str = gcov_read_string ();
+ header->column_description = str ? xstrdup (str) : 0;
+ str = gcov_read_string ();
+ header->full_header = str ? xstrdup (str) : 0;
+}
+#endif
+
+#if !IN_LIBGCOV
/* Check if MAGIC is EXPECTED. Use it to determine endianness of the
file. Returns +1 for same endian, -1 for other endian and zero for
not EXPECTED. */
@@ -205,12 +297,12 @@ static void
gcov_allocate (unsigned length)
{
size_t new_size = gcov_var.alloc;
-
+
if (!new_size)
new_size = GCOV_BLOCK_SIZE;
new_size += length;
new_size *= 2;
-
+
gcov_var.alloc = new_size;
gcov_var.buffer = XRESIZEVAR (gcov_unsigned_t, gcov_var.buffer, new_size << 2);
}
@@ -222,7 +314,7 @@ gcov_allocate (unsigned length)
static void
gcov_write_block (unsigned size)
{
- if (fwrite (gcov_var.buffer, size << 2, 1, gcov_var.file) != 1)
+ if (_GCOV_fwrite (gcov_var.buffer, size << 2, 1, gcov_var.file) != 1)
gcov_var.error = 1;
gcov_var.start += size;
gcov_var.offset -= size;
@@ -240,7 +332,7 @@ GCOV_LINKAGE gcov_unsigned_t
gcov_string_length (const char *string)
{
gcov_unsigned_t len = (string) ? strlen (string) : 0;
- /* + 1 because of the length field. */
+ /* + 1 because of the length field. */
gcov_unsigned_t alloc = 1 + ((len + 4) >> 2);
/* Can not write a bigger than GCOV_BLOCK_SIZE string yet */
@@ -276,7 +368,7 @@ gcov_write_words (unsigned words)
#endif
result = &gcov_var.buffer[gcov_var.offset];
gcov_var.offset += words;
-
+
return result;
}
@@ -323,7 +415,7 @@ gcov_write_string (const char *string)
length = strlen (string);
alloc = (length + 4) >> 2;
}
-
+
buffer = gcov_write_words (1 + alloc);
buffer[0] = alloc;
@@ -331,7 +423,6 @@ gcov_write_string (const char *string)
memcpy (&buffer[1], string, length);
}
-
#if !IN_LIBGCOV
/* Write a tag TAG and reserve space for the record length. Return a
value to be used for gcov_write_length. */
@@ -344,7 +435,7 @@ gcov_write_tag (gcov_unsigned_t tag)
buffer[0] = tag;
buffer[1] = 0;
-
+
return result;
}
@@ -416,7 +507,7 @@ gcov_read_words (unsigned words)
{
const gcov_unsigned_t *result;
unsigned excess = gcov_var.length - gcov_var.offset;
-
+
gcc_assert (gcov_var.mode > 0);
gcc_assert (words < GCOV_BLOCK_SIZE);
if (excess < words)
@@ -440,7 +531,7 @@ gcov_read_words (unsigned words)
gcov_allocate (gcov_var.length + words);
excess = gcov_var.alloc - gcov_var.length;
#endif
- excess = fread (gcov_var.buffer + gcov_var.length,
+ excess = _GCOV_fread (gcov_var.buffer + gcov_var.length,
1, excess << 2, gcov_var.file) >> 2;
gcov_var.length += excess;
if (gcov_var.length < words)
@@ -498,7 +589,7 @@ GCOV_LINKAGE const char *
gcov_read_string (void)
{
unsigned length = gcov_read_unsigned ();
-
+
if (!length)
return 0;
@@ -511,7 +602,7 @@ gcov_read_summary (struct gcov_summary *summary)
{
unsigned ix;
struct gcov_ctr_summary *csum;
-
+
summary->checksum = gcov_read_unsigned ();
for (csum = summary->ctrs, ix = GCOV_COUNTERS_SUMMABLE; ix--; csum++)
{
@@ -523,6 +614,31 @@ gcov_read_summary (struct gcov_summary *summary)
}
}
+#ifndef __GCOV_KERNEL__
+#if IN_GCOV != 1
+/* Delete pmu tool header TOOL_HEADER. */
+
+GCOV_LINKAGE void
+destroy_pmu_tool_header (gcov_pmu_tool_header_t *tool_header)
+{
+ if (!tool_header)
+ return;
+ if (tool_header->host_cpu)
+ free (tool_header->host_cpu);
+ if (tool_header->hostname)
+ free (tool_header->hostname);
+ if (tool_header->kernel_version)
+ free (tool_header->kernel_version);
+ if (tool_header->column_header)
+ free (tool_header->column_header);
+ if (tool_header->column_description)
+ free (tool_header->column_description);
+ if (tool_header->full_header)
+ free (tool_header->full_header);
+}
+#endif
+#endif /* __GCOV_KERNEL__ */
+
#if !IN_LIBGCOV && IN_GCOV != 1
/* Read LEN words (unsigned type) and construct MOD_INFO. */
@@ -580,6 +696,10 @@ gcov_read_module_info (struct gcov_module_info *mod_info,
GCOV_LINKAGE void
gcov_sync (gcov_position_t base, gcov_unsigned_t length)
{
+#ifdef __GCOV_KERNEL__
+ /* should not reach this point */
+ gcc_assert (0);
+#else /* __GCOV_KERNEL__ */
gcc_assert (gcov_var.mode > 0);
base += length;
if (base - gcov_var.start <= gcov_var.length)
@@ -587,9 +707,93 @@ gcov_sync (gcov_position_t base, gcov_unsigned_t length)
else
{
gcov_var.offset = gcov_var.length = 0;
- fseek (gcov_var.file, base << 2, SEEK_SET);
- gcov_var.start = ftell (gcov_var.file) >> 2;
+ _GCOV_fseek (gcov_var.file, base << 2, SEEK_SET);
+ gcov_var.start = _GCOV_ftell (gcov_var.file) >> 2;
}
+#endif /* __GCOV_KERNEL__ */
+}
+#endif
+
+#ifndef __GCOV_KERNEL__
+/* Convert an unsigned NUMBER to a percentage after dividing by
+ 100. */
+
+GCOV_LINKAGE float
+convert_unsigned_to_pct (const unsigned number)
+{
+ return (float)number / 100.0;
+}
+#endif /* __GCOV_KERNEL__ */
+
+#if !IN_LIBGCOV && IN_GCOV != 1
+/* Print load latency information given by LL_INFO in a human readable
+ format into an open output file pointed by FP. If NEWLINE is
+ nonzero, then a trailing newline is also printed. */
+
+GCOV_LINKAGE void
+print_load_latency_line (FILE *fp, const gcov_pmu_ll_info_t *ll_info,
+ const int print_newline)
+{
+ if (!ll_info)
+ return;
+ fprintf (fp, " %u %.2f%% %.2f%% %.2f%% %.2f%% %.2f%% %.2f%% %.2f%% "
+ "%.2f%% %.2f%% " HOST_WIDEST_INT_PRINT_HEX " %s %d %d",
+ ll_info->counts,
+ convert_unsigned_to_pct (ll_info->self),
+ convert_unsigned_to_pct (ll_info->cum),
+ convert_unsigned_to_pct (ll_info->lt_10),
+ convert_unsigned_to_pct (ll_info->lt_32),
+ convert_unsigned_to_pct (ll_info->lt_64),
+ convert_unsigned_to_pct (ll_info->lt_256),
+ convert_unsigned_to_pct (ll_info->lt_1024),
+ convert_unsigned_to_pct (ll_info->gt_1024),
+ convert_unsigned_to_pct (ll_info->wself),
+ ll_info->code_addr,
+ ll_info->filename,
+ ll_info->line,
+ ll_info->discriminator);
+ if (print_newline)
+ fprintf (fp, "\n");
+}
+
+/* Print BRM_INFO into the file pointed by FP. If PRINT_NEWLINE is
+ * non-zero then output a trailing newline as well. */
+
+GCOV_LINKAGE void
+print_branch_mispredict_line (FILE *fp, const gcov_pmu_brm_info_t *brm_info,
+ const int print_newline)
+{
+ if (!brm_info)
+ return;
+ fprintf (fp, " %u %.2f%% %.2f%% %llx %s %d %d",
+ brm_info->counts,
+ convert_unsigned_to_pct (brm_info->self),
+ convert_unsigned_to_pct (brm_info->cum),
+ (long long unsigned int)brm_info->code_addr,
+ brm_info->filename,
+ brm_info->line,
+ brm_info->discriminator);
+ if (print_newline)
+ fprintf (fp, "\n");
+}
+
+/* Print TOOL_HEADER into the file pointed by FP. If PRINT_NEWLINE is
+ non-zero then output a trailing newline as well. */
+
+GCOV_LINKAGE void
+print_pmu_tool_header (FILE *fp, gcov_pmu_tool_header_t *tool_header,
+ const int print_newline)
+{
+ if (!tool_header)
+ return;
+ fprintf (fp, "\nhost_cpu: %s\n", tool_header->host_cpu);
+ fprintf (fp, "hostname: %s\n", tool_header->hostname);
+ fprintf (fp, "kernel_version: %s\n", tool_header->kernel_version);
+ fprintf (fp, "column_header: %s\n", tool_header->column_header);
+ fprintf (fp, "column_description: %s\n", tool_header->column_description);
+ fprintf (fp, "full_header: %s\n", tool_header->full_header);
+ if (print_newline)
+ fprintf (fp, "\n");
}
#endif
@@ -602,8 +806,8 @@ gcov_seek (gcov_position_t base)
gcc_assert (gcov_var.mode < 0);
if (gcov_var.offset)
gcov_write_block (gcov_var.offset);
- fseek (gcov_var.file, base << 2, SEEK_SET);
- gcov_var.start = ftell (gcov_var.file) >> 2;
+ _GCOV_fseek (gcov_var.file, base << 2, SEEK_SET);
+ gcov_var.start = _GCOV_ftell (gcov_var.file) >> 2;
}
/* Truncate the gcov file at the current position. */
@@ -611,15 +815,20 @@ gcov_seek (gcov_position_t base)
GCOV_LINKAGE void
gcov_truncate (void)
{
+#ifdef __GCOV_KERNEL__
+ /* should not reach this point */
+ gcc_assert (0);
+#else /* __GCOV_KERNEL__ */
long offs;
int filenum;
gcc_assert (gcov_var.mode < 0);
if (gcov_var.offset)
gcov_write_block (gcov_var.offset);
- offs = ftell (gcov_var.file);
- filenum = fileno (gcov_var.file);
- if (offs == -1 || filenum == -1 || ftruncate (filenum, offs))
+ offs = _GCOV_ftell (gcov_var.file);
+ filenum = _GCOV_fileno (gcov_var.file);
+ if (offs == -1 || filenum == -1 || _GCOV_ftruncate (filenum, offs))
gcov_var.error = 1;
+#endif /* __GCOV_KERNEL__ */
}
#endif
@@ -630,10 +839,138 @@ GCOV_LINKAGE time_t
gcov_time (void)
{
struct stat status;
-
+
if (fstat (fileno (gcov_var.file), &status))
return 0;
else
return status.st_mtime;
}
#endif /* IN_GCOV */
+
+#ifndef __GCOV_KERNEL__
+union gcov_float_converter
+{
+ gcov_float_t f;
+ gcov_type t;
+};
+
+/* Convert from gcov_float_t (double) to gcov_type. */
+gcov_type
+gcov_float_to_type (gcov_float_t f)
+{
+ union gcov_float_converter u;
+ u.f = f;
+ return u.t;
+}
+
+/* Convert from gcov_type and gcov_float_t (double). */
+gcov_float_t
+gcov_type_to_float (gcov_type t)
+{
+ union gcov_float_converter u;
+ u.t = t;
+ return u.f;
+}
+#endif /* __GCOV_KERNEL__ */
+
+#ifdef __GCOV_KERNEL__
+
+/* File fclose operation in kernel mode. */
+
+int
+kernel_file_fclose (gcov_kernel_vfile *fp)
+{
+ return 0;
+}
+
+/* File ftell operation in kernel mode. It currently should not
+ be called. */
+
+long
+kernel_file_ftell (gcov_kernel_vfile *fp)
+{
+ gcc_assert (0); /* should not reach here */
+ return 0;
+}
+
+/* File fseek operation in kernel mode. It should only be called
+ with OFFSET==0 and WHENCE==0 to a freshly opened file. */
+
+int
+kernel_file_fseek (gcov_kernel_vfile *fp, long offset, int whence)
+{
+ gcc_assert (offset == 0 && whence == 0 && fp->count == 0);
+ return 0;
+}
+
+/* File ftruncate operation in kernel mode. It currently should not
+ be called. */
+
+int
+kernel_file_ftruncate (gcov_kernel_vfile *fp, off_t value)
+{
+ gcc_assert (0); /* should not reach here */
+ return 0;
+}
+
+/* File fread operation in kernel mode. It currently should not
+ be called. */
+
+int
+kernel_file_fread (void *ptr, size_t size, size_t nitems,
+ gcov_kernel_vfile *fp)
+{
+ gcc_assert (0); /* should not reach here */
+ return 0;
+}
+
+/* File fwrite operation in kernel mode. It outputs the data
+ to a buffer in the virual file. */
+
+int
+kernel_file_fwrite (const void *ptr, size_t size,
+ size_t nitems, gcov_kernel_vfile *fp)
+{
+ char *vbuf;
+ unsigned vsize, vpos;
+ unsigned len;
+
+ if (!fp) return 0;
+
+ vbuf = fp->buf;
+ vsize = fp->size;
+ vpos = fp->count;
+
+ if (vsize <= vpos)
+ {
+ printk (KERN_ERR
+ "GCOV_KERNEL: something wrong: vbuf=%p vsize=%u vpos=%u\n",
+ vbuf, vsize, vpos);
+ return 0;
+ }
+ len = vsize - vpos;
+ len /= size;
+
+ if (len > nitems)
+ len = nitems;
+
+ memcpy (vbuf+vpos, ptr, size*len);
+ fp->count += len*size;
+
+ if (len != nitems)
+ printk (KERN_ERR
+ "GCOV_KERNEL: something wrong: size=%lu nitems=%lu ret=%d\n",
+ size, nitems, len);
+ return len;
+}
+
+/* File fileno operation in kernel mode. It currently should not
+ be called. */
+
+int
+kernel_file_fileno (gcov_kernel_vfile *fp)
+{
+ gcc_assert (0); /* should not reach here */
+ return 0;
+}
+#endif /* GCOV_KERNEL */
diff --git a/gcc-4.4.3/gcc/gcov-io.h b/gcc-4.4.3/gcc/gcov-io.h
index ffee38e53..7584f4c4f 100644
--- a/gcc-4.4.3/gcc/gcov-io.h
+++ b/gcc-4.4.3/gcc/gcov-io.h
@@ -61,7 +61,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
file. It need not be an absolute time stamp, merely a ticker that
increments fast enough and cycles slow enough to distinguish
different compile/run/compile cycles.
-
+
Although the ident and version are formally 32 bit numbers, they
are derived from 4 character ASCII strings. The version number
consists of the single character major version number, a two
@@ -164,6 +164,89 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#ifndef GCC_GCOV_IO_H
#define GCC_GCOV_IO_H
+typedef double gcov_float_t;
+#ifdef __KERNEL__
+#ifndef __GCOV_KERNEL__
+#define __GCOV_KERNEL__
+#endif /* __GCOV_KERNEL__ */
+#endif /* __KERNEL__ */
+
+#ifdef __GCOV_KERNEL__
+#define GCOV_LINKAGE /* nothing */
+
+/* We need the definitions for
+ BITS_PER_UNIT and
+ LONG_LONG_TYPE_SIZE
+ They are defined in gcc/defaults.h and gcc/config/<arch_depend_files>
+ (like, gcc/config/i386/i386.h). It's not easy to included them
+ cleanly. So I hardcoded the value for x86. */
+#define BITS_PER_UNIT 8
+#define LONG_LONG_TYPE_SIZE 64
+
+/* There are many gcc_assertions. Set the vaule to 1 if we want a warning
+ message if the assertion fails. */
+#ifndef ENABLE_ASSERT_CHECKING
+#define ENABLE_ASSERT_CHECKING 1
+#endif
+
+#include <linux/fs.h>
+#endif /* __GCOV_KERNEL__ */
+
+/* Wrappers to the file operations. */
+#ifndef __GCOV_KERNEL__
+# define _GCOV_FILE FILE
+# define _GCOV_fclose fclose
+# define _GCOV_ftell ftell
+# define _GCOV_fseek fseek
+# define _GCOV_ftruncate ftruncate
+# define _GCOV_fread fread
+# define _GCOV_fwrite fwrite
+# define _GCOV_fread fread
+# define _GCOV_fileno fileno
+#else /* __GCOV_KERNEL__ */
+/* In Linux kernel mode, a virtual file is used for file operations. */
+struct gcov_info;
+typedef struct {
+ long size; /* size of buf */
+ long count; /* element written into buf */
+ struct gcov_info *info;
+ char buf[0];
+} gcov_kernel_vfile;
+
+# define _GCOV_FILE gcov_kernel_vfile
+
+/* gcc_assert() prints out a warning if the check fails. It
+ will not abort. */
+#if ENABLE_ASSERT_CHECKING
+# define gcc_assert(EXPR) \
+ ((void)(!(EXPR) ? printk (KERN_WARNING \
+ "GCOV assertion fails: func=%s line=%d\n", \
+ __FUNCTION__, __LINE__), 0 : 0))
+#else
+# define gcc_assert(EXPR) ((void)(0 && (EXPR)))
+#endif
+
+/* Wrappers to the file operations. */
+# define _GCOV_fclose kernel_file_fclose
+# define _GCOV_ftell kernel_file_ftell
+# define _GCOV_fseek kernel_file_fseek
+# define _GCOV_ftruncate kernel_file_ftruncate
+# define _GCOV_fread kernel_file_fread
+# define _GCOV_fwrite kernel_file_fwrite
+# define _GCOV_fileno kernel_file_fileno
+
+/* Declarations for virtual files operations. */
+extern int kernel_file_fclose (gcov_kernel_vfile *);
+extern long kernel_file_ftell (gcov_kernel_vfile *);
+extern int kernel_file_fseek (gcov_kernel_vfile *, long, int);
+extern int kernel_file_ftruncate (gcov_kernel_vfile *, off_t);
+extern int kernel_file_fread (void *, size_t, size_t,
+ gcov_kernel_vfile *);
+extern int kernel_file_fwrite (const void *, size_t, size_t,
+ gcov_kernel_vfile *);
+extern int kernel_file_fileno(gcov_kernel_vfile *);
+#endif /* GCOV_KERNEL */
+
#if IN_LIBGCOV
#undef FUNC_ID_WIDTH
@@ -207,7 +290,7 @@ typedef signed gcov_type __attribute__ ((mode (QI)));
#define FUNC_ID_WIDTH 16
#define FUNC_ID_MASK ((1 << FUNC_ID_WIDTH) - 1)
#endif
-#endif /* BITS_PER_UNIT == 16 */
+#endif /* BITS_PER_UNIT == 16 */
#endif /* BITS_PER_UNIT == 8 */
@@ -265,7 +348,9 @@ typedef HOST_WIDEST_INT gcov_type;
is not also used in a DSO. */
#if IN_LIBGCOV
+#ifndef __GCOV_KERNEL__
#include "tconfig.h"
+#endif /* __GCOV_KERNEL__ */
#define gcov_var __gcov_var
#define gcov_open __gcov_open
@@ -288,6 +373,11 @@ typedef HOST_WIDEST_INT gcov_type;
#define gcov_read_summary __gcov_read_summary
#define gcov_read_module_info __gcov_read_module_info
#define gcov_sort_n_vals __gcov_sort_n_vals
+#define gcov_read_pmu_load_latency_info __gcov_read_pmu_load_latency_info
+#define gcov_read_pmu_branch_mispredict_info __gcov_read_pmu_branch_mispredict_info
+#define gcov_read_pmu_tool_header __gcov_read_pmu_tool_header
+#define destroy_pmu_tool_header __destroy_pmu_tool_header
+
/* Poison these, so they don't accidentally slip in. */
#pragma GCC poison gcov_write_tag gcov_write_length
@@ -352,6 +442,13 @@ typedef HOST_WIDEST_INT gcov_type;
#define GCOV_TAG_SUMMARY_LENGTH \
(1 + GCOV_COUNTERS_SUMMABLE * (2 + 3 * 2))
#define GCOV_TAG_MODULE_INFO ((gcov_unsigned_t)0xa4000000)
+#define GCOV_TAG_PMU_LOAD_LATENCY_INFO ((gcov_unsigned_t)0xa5000000)
+#define GCOV_TAG_PMU_LOAD_LATENCY_LENGTH(filename) \
+ (gcov_string_length (filename) + 12 + 2)
+#define GCOV_TAG_PMU_BRANCH_MISPREDICT_INFO ((gcov_unsigned_t)0xa7000000)
+#define GCOV_TAG_PMU_BRANCH_MISPREDICT_LENGTH(filename) \
+ (gcov_string_length (filename) + 5 + 2)
+#define GCOV_TAG_PMU_TOOL_HEADER ((gcov_unsigned_t)0xa9000000)
/* Counters that are collected. */
#define GCOV_COUNTER_ARCS 0 /* Arc transitions. */
@@ -366,29 +463,32 @@ typedef HOST_WIDEST_INT gcov_type;
#define GCOV_COUNTER_V_POW2 2 /* Histogram of exact power2 logarithm
of a value. */
#define GCOV_COUNTER_V_SINGLE 3 /* The most common value of expression. */
-#define GCOV_COUNTER_V_DELTA 4 /* The most common difference between
+#define GCOV_COUNTER_V_SINGLE_FLOAT 4 /* The most common float value */
+#define GCOV_COUNTER_V_DELTA 5 /* The most common difference between
consecutive values of expression. */
-#define GCOV_COUNTER_V_INDIR 5 /* The most common indirect address */
-#define GCOV_COUNTER_AVERAGE 6 /* Compute average value passed to the
+#define GCOV_COUNTER_V_INDIR 6 /* The most common indirect address */
+#define GCOV_COUNTER_AVERAGE 7 /* Compute average value passed to the
counter. */
-#define GCOV_COUNTER_IOR 7 /* IOR of the all values passed to
+#define GCOV_COUNTER_IOR 8 /* IOR of the all values passed to
counter. */
-#define GCOV_COUNTER_ICALL_TOPNV 8 /* Top N value tracking for indirect calls */
-#define GCOV_LAST_VALUE_COUNTER 8 /* The last of counters used for value
+#define GCOV_COUNTER_ICALL_TOPNV 9 /* Top N value tracking for indirect calls */
+#define GCOV_LAST_VALUE_COUNTER 9 /* The last of counters used for value
profiling. */
-#define GCOV_COUNTER_DIRECT_CALL 9 /* Direct call counts. */
-#define GCOV_COUNTERS 10
+#define GCOV_COUNTER_DIRECT_CALL 10 /* Direct call counts. */
+#define GCOV_COUNTER_REUSE_DIST 11 /* Reuse distance measure. */
+#define GCOV_COUNTERS 12
/* Number of counters used for value profiling. */
#define GCOV_N_VALUE_COUNTERS \
(GCOV_LAST_VALUE_COUNTER - GCOV_FIRST_VALUE_COUNTER + 1)
-
+
/* A list of human readable names of the counters */
#define GCOV_COUNTER_NAMES {"arcs", "interval", "pow2", "single", \
- "delta","indirect_call", "average", "ior", \
- "indirect_call_topn", "direct_call"}
-
+ "single_float", "delta","indirect_call", \
+ "average", "ior", "indirect_call_topn", \
+ "direct_call", "reuse_distance"}
+
#define GCOV_ICALL_TOPN_VAL 2 /* Track two hottest callees */
#define GCOV_ICALL_TOPN_NCOUNTS 9 /* The number of counter entries per icall callsite */
/* Names of merge functions for counters. */
@@ -396,13 +496,15 @@ typedef HOST_WIDEST_INT gcov_type;
"__gcov_merge_add", \
"__gcov_merge_add", \
"__gcov_merge_single", \
+ "__gcov_merge_single_float", \
"__gcov_merge_delta", \
"__gcov_merge_single", \
"__gcov_merge_add", \
"__gcov_merge_ior", \
"__gcov_merge_icall_topn",\
- "__gcov_merge_dc" }
-
+ "__gcov_merge_dc", \
+ "__gcov_merge_reusedist"}
+
/* Convert a counter index to a tag. */
#define GCOV_TAG_FOR_COUNTER(COUNT) \
(GCOV_TAG_COUNTER_BASE + ((gcov_unsigned_t)(COUNT) << 17))
@@ -493,6 +595,91 @@ extern unsigned primary_module_id;
&& !((module_infos[0]->lang & GCOV_MODULE_ASM_STMTS) \
&& flag_ripa_disallow_asm_modules))
+/* Information about the hardware performance monitoring unit. */
+struct gcov_pmu_info
+{
+ const char *pmu_profile_filename; /* pmu profile filename */
+ const char *pmu_tool; /* canonical pmu tool options */
+ gcov_unsigned_t pmu_top_n_address; /* how many top addresses to symbolize */
+};
+
+/* Information about the PMU tool header. */
+typedef struct gcov_pmu_tool_header {
+ char *host_cpu;
+ char *hostname;
+ char *kernel_version;
+ char *column_header;
+ char *column_description;
+ char *full_header;
+} gcov_pmu_tool_header_t;
+
+/* Available only for PMUs which support PEBS or IBS using pfmon
+ tool. If any field here is changed, the length computation in
+ GCOV_TAG_PMU_LOAD_LATENCY_LENGTH must be updated as well. All
+ percentages are multiplied by 100 to make them out of 10000 and
+ only integer part is kept. */
+typedef struct gcov_pmu_load_latency_info
+{
+ gcov_unsigned_t counts; /* raw count of samples */
+ gcov_unsigned_t self; /* per 10k of total samples */
+ gcov_unsigned_t cum; /* per 10k cumulative weight */
+ gcov_unsigned_t lt_10; /* per 10k with latency <= 10 cycles */
+ gcov_unsigned_t lt_32; /* per 10k with latency <= 32 cycles */
+ gcov_unsigned_t lt_64; /* per 10k with latency <= 64 cycles */
+ gcov_unsigned_t lt_256; /* per 10k with latency <= 256 cycles */
+ gcov_unsigned_t lt_1024; /* per 10k with latency <= 1024 cycles */
+ gcov_unsigned_t gt_1024; /* per 10k with latency > 1024 cycles */
+ gcov_unsigned_t wself; /* weighted average cost of this miss in cycles */
+ gcov_type code_addr; /* the actual miss address (pc+1 for Intel) */
+ gcov_unsigned_t line; /* line number corresponding to this miss */
+ gcov_unsigned_t discriminator; /* discriminator information for this miss */
+ char *filename; /* filename corresponding to this miss */
+} gcov_pmu_ll_info_t;
+
+/* This structure is used during runtime as well as in gcov. */
+typedef struct load_latency_infos
+{
+ /* An array describing the total number of load latency fields. */
+ gcov_pmu_ll_info_t **ll_array;
+ /* The total number of entries in the load latency array. */
+ unsigned ll_count;
+ /* The total number of entries currently allocated in the array.
+ Used for bookkeeping. */
+ unsigned alloc_ll_count;
+ /* PMU tool header */
+ gcov_pmu_tool_header_t *pmu_tool_header;
+} ll_infos_t;
+
+/* Available only for PMUs which support PEBS or IBS using pfmon
+ tool. If any field here is changed, the length computation in
+ GCOV_TAG_PMU_BR_MISPREDICT_LENGTH must be updated as well. All
+ percentages are multiplied by 100 to make them out of 10000 and
+ only integer part is kept. */
+typedef struct gcov_pmu_branch_mispredict_info
+{
+ gcov_unsigned_t counts; /* raw count of samples */
+ gcov_unsigned_t self; /* per 10k of total samples */
+ gcov_unsigned_t cum; /* per 10k cumulative weight */
+ gcov_type code_addr; /* the actual mispredict address */
+ gcov_unsigned_t line; /* line number corresponding to this event */
+ gcov_unsigned_t discriminator; /* discriminator for this event */
+ char *filename; /* filename corresponding to this event */
+} gcov_pmu_brm_info_t;
+
+/* This structure is used during runtime as well as in gcov. */
+typedef struct branch_mispredict_infos
+{
+ /* An array describing the total number of mispredict entries. */
+ gcov_pmu_brm_info_t **brm_array;
+ /* The total number of entries in the above array. */
+ unsigned brm_count;
+ /* The total number of entries currently allocated in the array.
+ Used for bookkeeping. */
+ unsigned alloc_brm_count;
+ /* PMU tool header */
+ gcov_pmu_tool_header_t *pmu_tool_header;
+} brm_infos_t;
+
/* Structures embedded in coveraged program. The structures generated
by write_profile must match these. */
@@ -500,7 +687,7 @@ extern unsigned primary_module_id;
/* Information about a single function. This uses the trailing array
idiom. The number of counters is determined from the counter_mask
in gcov_info. We hold an array of function info, so have to
- explicitly calculate the correct array stride.
+ explicitly calculate the correct array stride.
"ident" is no longer used in hash computation. Additionally,
"name" is used in hash computation. This makes the profile data
@@ -549,6 +736,13 @@ struct gcov_info
is. */
};
+/* Information about a single imported module. */
+struct dyn_imp_mod
+{
+ const struct gcov_info *imp_mod;
+ double weight;
+};
+
/* Register a new object file module. */
extern void __gcov_init (struct gcov_info *) ATTRIBUTE_HIDDEN;
@@ -561,6 +755,9 @@ extern void __gcov_merge_add (gcov_type *, unsigned) ATTRIBUTE_HIDDEN;
/* The merge function to choose the most common value. */
extern void __gcov_merge_single (gcov_type *, unsigned) ATTRIBUTE_HIDDEN;
+/* The merge function to choose the most common value. */
+extern void __gcov_merge_single_float (gcov_type *, unsigned) ATTRIBUTE_HIDDEN;
+
/* The merge function to choose the most common difference between
consecutive values. */
extern void __gcov_merge_delta (gcov_type *, unsigned) ATTRIBUTE_HIDDEN;
@@ -571,13 +768,17 @@ extern void __gcov_merge_ior (gcov_type *, unsigned) ATTRIBUTE_HIDDEN;
/* The merge function used for direct call counters. */
extern void __gcov_merge_dc (gcov_type *, unsigned) ATTRIBUTE_HIDDEN;
+/* The merge function used for reuse distance counters. */
+extern void __gcov_merge_reusedist (gcov_type *, unsigned) ATTRIBUTE_HIDDEN;
+
/* The merge function used for indirect call counters. */
extern void __gcov_merge_icall_topn (gcov_type *, unsigned) ATTRIBUTE_HIDDEN;
/* The profiler functions. */
-extern void __gcov_interval_profiler (gcov_type *, gcov_type, int, unsigned);
+extern void __gcov_interval_profiler (gcov_type *, gcov_type, int, unsigned);
extern void __gcov_pow2_profiler (gcov_type *, gcov_type);
extern void __gcov_one_value_profiler (gcov_type *, gcov_type);
+extern void __gcov_one_float_value_profiler (gcov_type *, gcov_float_t);
extern void __gcov_indirect_call_profiler (gcov_type *, gcov_type, void *, void *);
extern void __gcov_indirect_call_topn_profiler (void *, void *, gcov_unsigned_t) ATTRIBUTE_HIDDEN;
extern void __gcov_direct_call_profiler (void *, void *, gcov_unsigned_t) ATTRIBUTE_HIDDEN;
@@ -585,6 +786,12 @@ extern void __gcov_average_profiler (gcov_type *, gcov_type);
extern void __gcov_ior_profiler (gcov_type *, gcov_type);
extern void __gcov_sort_n_vals (gcov_type *value_array, int n);
+/* Initialize/start/stop/dump performance monitoring unit (PMU) profile */
+void __gcov_init_pmu_profiler (struct gcov_pmu_info *) ATTRIBUTE_HIDDEN;
+void __gcov_start_pmu_profiler (void) ATTRIBUTE_HIDDEN;
+void __gcov_stop_pmu_profiler (void) ATTRIBUTE_HIDDEN;
+void __gcov_end_pmu_profiler (void) ATTRIBUTE_HIDDEN;
+
#ifndef inhibit_libc
/* The wrappers around some library functions.. */
extern pid_t __gcov_fork (void) ATTRIBUTE_HIDDEN;
@@ -604,9 +811,9 @@ extern int __gcov_execve (const char *, char *const [], char *const [])
/* Optimum number of gcov_unsigned_t's read from or written to disk. */
#define GCOV_BLOCK_SIZE (1 << 10)
-GCOV_LINKAGE struct gcov_var
+struct gcov_var
{
- FILE *file;
+ _GCOV_FILE *file;
gcov_position_t start; /* Position of first byte of block */
unsigned offset; /* Read/write position within the block. */
unsigned length; /* Read limit in the block. */
@@ -626,7 +833,15 @@ GCOV_LINKAGE struct gcov_var
size_t alloc;
gcov_unsigned_t *buffer;
#endif
-} gcov_var ATTRIBUTE_HIDDEN;
+};
+
+/* In kernel mode, move gcov_var definition to gcov-io.c
+ to avoid dulipcate definitions. */
+#ifndef __GCOV_KERNEL__
+GCOV_LINKAGE struct gcov_var gcov_var ATTRIBUTE_HIDDEN;
+#else
+extern struct gcov_var gcov_var;
+#endif
/* Functions for reading and writing gcov files. In libgcov you can
open the file for reading then writing. Elsewhere you can open the
@@ -652,11 +867,33 @@ static int gcov_is_error (void);
GCOV_LINKAGE gcov_unsigned_t gcov_read_unsigned (void) ATTRIBUTE_HIDDEN;
GCOV_LINKAGE gcov_type gcov_read_counter (void) ATTRIBUTE_HIDDEN;
GCOV_LINKAGE void gcov_read_summary (struct gcov_summary *) ATTRIBUTE_HIDDEN;
+GCOV_LINKAGE void gcov_read_pmu_load_latency_info (
+ gcov_pmu_ll_info_t *ll_info, gcov_unsigned_t len) ATTRIBUTE_HIDDEN;
+GCOV_LINKAGE void gcov_read_pmu_branch_mispredict_info (
+ gcov_pmu_brm_info_t *brm_info, gcov_unsigned_t len) ATTRIBUTE_HIDDEN;
+GCOV_LINKAGE void gcov_read_pmu_tool_header (
+ gcov_pmu_tool_header_t *tool_header, gcov_unsigned_t len) ATTRIBUTE_HIDDEN;
+
#if !IN_LIBGCOV && IN_GCOV != 1
GCOV_LINKAGE void gcov_read_module_info (struct gcov_module_info *mod_info,
gcov_unsigned_t len) ATTRIBUTE_HIDDEN;
+GCOV_LINKAGE void print_load_latency_line (FILE *fp,
+ const gcov_pmu_ll_info_t *ll_info,
+ const int print_newline);
+GCOV_LINKAGE void print_branch_mispredict_line (
+ FILE *fp, const gcov_pmu_brm_info_t *brm_info, const int print_newline);
+GCOV_LINKAGE void print_pmu_tool_header (FILE *fp,
+ gcov_pmu_tool_header_t *tool_header,
+ const int print_newline);
#endif
+
+#if IN_GCOV != 1
+GCOV_LINKAGE void destroy_pmu_tool_header (gcov_pmu_tool_header_t *tool_header)
+ ATTRIBUTE_HIDDEN;
+#endif
+
GCOV_LINKAGE const char *gcov_read_string (void) ATTRIBUTE_HIDDEN;
+GCOV_LINKAGE float convert_unsigned_to_pct (const unsigned number);
#if IN_LIBGCOV
/* Available only in libgcov */
@@ -669,13 +906,14 @@ GCOV_LINKAGE void gcov_write_summary (gcov_unsigned_t /*tag*/,
GCOV_LINKAGE void gcov_write_module_infos (struct gcov_info *mod_info)
ATTRIBUTE_HIDDEN;
-GCOV_LINKAGE const struct gcov_info **
+GCOV_LINKAGE const struct dyn_imp_mod **
gcov_get_sorted_import_module_array (struct gcov_info *mod_info, unsigned *len)
ATTRIBUTE_HIDDEN;
static void gcov_rewrite (void);
GCOV_LINKAGE void gcov_seek (gcov_position_t /*position*/) ATTRIBUTE_HIDDEN;
GCOV_LINKAGE void gcov_truncate (void) ATTRIBUTE_HIDDEN;
GCOV_LINKAGE gcov_unsigned_t gcov_string_length (const char *) ATTRIBUTE_HIDDEN;
+GCOV_LINKAGE unsigned gcov_gcda_file_size (struct gcov_info *);
#else
/* Available outside libgcov */
GCOV_LINKAGE void gcov_sync (gcov_position_t /*base*/,
@@ -725,10 +963,14 @@ gcov_rewrite (void)
gcov_var.mode = -1;
gcov_var.start = 0;
gcov_var.offset = 0;
- fseek (gcov_var.file, 0L, SEEK_SET);
+ _GCOV_fseek (gcov_var.file, 0L, SEEK_SET);
}
#endif
#endif /* IN_LIBGCOV >= 0 */
+/* Convert between gcov_type and gcov_float_t. */
+gcov_type gcov_float_to_type(gcov_float_t f);
+gcov_float_t gcov_type_to_float(gcov_type t);
+
#endif /* GCC_GCOV_IO_H */
diff --git a/gcc-4.4.3/gcc/gcov.c b/gcc-4.4.3/gcc/gcov.c
index d67e621bc..38937917e 100644
--- a/gcc-4.4.3/gcc/gcov.c
+++ b/gcc-4.4.3/gcc/gcov.c
@@ -209,6 +209,15 @@ typedef struct coverage_info
char *name;
} coverage_t;
+/* Describes PMU profile data for either one source file or for the
+ entire program. */
+
+typedef struct pmu_data
+{
+ ll_infos_t ll_infos;
+ brm_infos_t brm_infos;
+} pmu_data_t;
+
/* Describes a single line of source. Contains a chain of basic blocks
with code on it. */
@@ -242,6 +251,8 @@ typedef struct source_info
coverage_t coverage;
+ pmu_data_t *pmu_data; /* PMU profile information for this file. */
+
/* Functions in this source file. These are in ascending line
number order. */
function_t *functions;
@@ -301,6 +312,10 @@ static int flag_branches = 0;
/* Show unconditional branches too. */
static int flag_unconditional = 0;
+/* Output performance monitoring unit (PMU) data, if available. */
+
+static int flag_pmu_profile = 0;
+
/* Output a gcov file if this is true. This is on by default, and can
be turned off by the -n option. */
@@ -340,6 +355,18 @@ static int flag_preserve_paths = 0;
static int flag_counts = 0;
+/* PMU profile default filename. */
+
+static char pmu_profile_default_filename[] = "pmuprofile.gcda";
+
+/* PMU profile filename where the PMU profile data is read from. */
+
+static char *pmu_profile_filename = 0;
+
+/* PMU data for the entire program. */
+
+static pmu_data_t pmu_global_info;
+
/* Forward declarations. */
static void fnotice (FILE *, const char *, ...) ATTRIBUTE_PRINTF_2;
static int process_args (int, char **);
@@ -361,6 +388,17 @@ static int output_branch_count (FILE *, int, const arc_t *);
static void output_lines (FILE *, const source_t *);
static char *make_gcov_file_name (const char *, const char *);
static void release_structures (void);
+static void process_pmu_profile (void);
+static void filter_pmu_data_lines (source_t *src);
+static void output_pmu_data_header (FILE *gcov_file, pmu_data_t *pmu_data);
+static void output_pmu_data (FILE *gcov_file, const source_t *src,
+ const unsigned line_num);
+static void output_load_latency_line (FILE *fp,
+ const gcov_pmu_ll_info_t *ll_info,
+ gcov_pmu_tool_header_t *tool_header);
+static void output_branch_mispredict_line (FILE *fp,
+ const gcov_pmu_brm_info_t *brm_info);
+
extern int main (int, char **);
int
@@ -383,6 +421,15 @@ main (int argc, char **argv)
if (argc - argno > 1)
multiple_files = 1;
+ /* We read pmu profile first because we later filter
+ src:line_numbers for each source. */
+ if (flag_pmu_profile)
+ {
+ if (!pmu_profile_filename)
+ pmu_profile_filename = pmu_profile_default_filename;
+ process_pmu_profile ();
+ }
+
for (; argno != argc; argno++)
process_file (argv[argno]);
@@ -420,6 +467,7 @@ print_usage (int error_p)
fnotice (file, " -b, --branch-probabilities Include branch probabilities in output\n");
fnotice (file, " -c, --branch-counts Given counts of branches taken\n\
rather than percentages\n");
+ fnotice (file, " -m, --pmu-profile Output PMU profile data if available\n");
fnotice (file, " -n, --no-output Do not create an output file\n");
fnotice (file, " -l, --long-file-names Use long output file names for included\n\
source files\n");
@@ -432,6 +480,7 @@ print_usage (int error_p)
applications. It will output a single\n\
.gcov file per .gcda file. No source file\n\
is required.\n");
+ fnotice (file, " -q, --pmu_profile-path Path for PMU profile (default pmuprofile.gcda)\n");
fnotice (file, "\nFor bug reporting instructions, please see:\n%s.\n",
bug_report_url);
exit (status);
@@ -459,6 +508,7 @@ static const struct option options[] =
{ "all-blocks", no_argument, NULL, 'a' },
{ "branch-probabilities", no_argument, NULL, 'b' },
{ "branch-counts", no_argument, NULL, 'c' },
+ { "pmu-profile", no_argument, NULL, 'm' },
{ "no-output", no_argument, NULL, 'n' },
{ "long-file-names", no_argument, NULL, 'l' },
{ "function-summaries", no_argument, NULL, 'f' },
@@ -467,6 +517,7 @@ static const struct option options[] =
{ "object-file", required_argument, NULL, 'o' },
{ "unconditional-branches", no_argument, NULL, 'u' },
{ "intermediate-format", no_argument, NULL, 'i' },
+ { "pmu_profile-path", required_argument, NULL, 'q' },
{ 0, 0, 0, 0 }
};
@@ -477,7 +528,8 @@ process_args (int argc, char **argv)
{
int opt;
- while ((opt = getopt_long (argc, argv, "abcfhilno:puv", options, NULL)) != -1)
+ while ((opt = getopt_long (argc, argv, "abcfhilmno:q:puv", options, NULL))
+ != -1)
{
switch (opt)
{
@@ -499,6 +551,9 @@ process_args (int argc, char **argv)
case 'l':
flag_long_names = 1;
break;
+ case 'm':
+ flag_pmu_profile = 1;
+ break;
case 'n':
flag_gcov_file = 0;
break;
@@ -508,6 +563,9 @@ process_args (int argc, char **argv)
case 'p':
flag_preserve_paths = 1;
break;
+ case 'q':
+ pmu_profile_filename = optarg;
+ break;
case 'u':
flag_unconditional = 1;
break;
@@ -747,6 +805,8 @@ release_structures (void)
{
function_t *fn;
source_t *src;
+ ll_infos_t *ll_infos = &pmu_global_info.ll_infos;
+ brm_infos_t *brm_infos = &pmu_global_info.brm_infos;
while ((src = sources))
{
@@ -754,6 +814,14 @@ release_structures (void)
free (src->name);
free (src->lines);
+ if (src->pmu_data)
+ {
+ if (src->pmu_data->ll_infos.ll_array)
+ free (src->pmu_data->ll_infos.ll_array);
+ if (src->pmu_data->brm_infos.brm_array)
+ free (src->pmu_data->brm_infos.brm_array);
+ free (src->pmu_data);
+ }
}
while ((fn = functions))
@@ -775,6 +843,42 @@ release_structures (void)
free (fn->blocks);
free (fn->counts);
}
+
+ /* Cleanup PMU load latency info. */
+ if (ll_infos->ll_count)
+ {
+ unsigned i;
+
+ /* delete each element */
+ for (i = 0; i < ll_infos->ll_count; ++i)
+ {
+ if (ll_infos->ll_array[i]->filename)
+ XDELETE (ll_infos->ll_array[i]->filename);
+ XDELETE (ll_infos->ll_array[i]);
+ }
+ /* delete the array itself */
+ XDELETE (ll_infos->ll_array);
+ ll_infos->ll_array = NULL;
+ ll_infos->ll_count = 0;
+ }
+
+ /* Cleanup PMU branch mispredict info. */
+ if (brm_infos->brm_count)
+ {
+ unsigned i;
+
+ /* delete each element */
+ for (i = 0; i < brm_infos->brm_count; ++i)
+ {
+ if (brm_infos->brm_array[i]->filename)
+ XDELETE (brm_infos->brm_array[i]->filename);
+ XDELETE (brm_infos->brm_array[i]);
+ }
+ /* delete the array itself */
+ XDELETE (brm_infos->brm_array);
+ brm_infos->brm_array = NULL;
+ brm_infos->brm_count = 0;
+ }
}
/* Generate the names of the graph and data files. If OBJECT_DIRECTORY
@@ -871,6 +975,7 @@ find_source (const char *file_name)
src->coverage.name = src->name;
src->index = source_index++;
src->next = sources;
+ src->pmu_data = 0;
sources = src;
if (!stat (file_name, &status))
@@ -1792,6 +1897,148 @@ add_line_counts (coverage_t *coverage, function_t *fn)
fnotice (stderr, "%s:no lines for '%s'\n", bbg_file_name, fn->name);
}
+/* Filter PMU profile global data for lines for SRC. Save PMU info
+ matching the source file and sort them by line number for later
+ line by line processing. */
+
+static void
+filter_pmu_data_lines (source_t *src)
+{
+ unsigned i;
+ int changed;
+ ll_infos_t *ll_infos; /* load latency information for this source */
+ brm_infos_t *brm_infos; /* branch mispredict information for this source */
+
+ if (pmu_global_info.ll_infos.ll_count == 0 &&
+ pmu_global_info.brm_infos.brm_count == 0)
+ /* If there are no global entries, there is nothing to filter. */
+ return;
+
+ src->pmu_data = XCNEW (pmu_data_t);
+ ll_infos = &src->pmu_data->ll_infos;
+ brm_infos = &src->pmu_data->brm_infos;
+ ll_infos->pmu_tool_header = pmu_global_info.ll_infos.pmu_tool_header;
+ brm_infos->pmu_tool_header = pmu_global_info.brm_infos.pmu_tool_header;
+ ll_infos->ll_array = 0;
+ brm_infos->brm_array = 0;
+
+ /* Go over all the load latency entries and save the ones
+ corresponding to this source file. */
+ for (i = 0; i < pmu_global_info.ll_infos.ll_count; ++i)
+ {
+ gcov_pmu_ll_info_t *ll_info = pmu_global_info.ll_infos.ll_array[i];
+ if (0 == strcmp (src->name, ll_info->filename))
+ {
+ if (!ll_infos->ll_array)
+ {
+ ll_infos->ll_count = 0;
+ ll_infos->alloc_ll_count = 64;
+ ll_infos->ll_array = XCNEWVEC (gcov_pmu_ll_info_t *,
+ ll_infos->alloc_ll_count);
+ }
+ /* Found a matching entry, save it. */
+ ll_infos->ll_count++;
+ if (ll_infos->ll_count >= ll_infos->alloc_ll_count)
+ {
+ /* need to realloc */
+ ll_infos->ll_array = (gcov_pmu_ll_info_t **)
+ xrealloc (ll_infos->ll_array, 2 * ll_infos->alloc_ll_count);
+ if (ll_infos->ll_array == NULL) {
+ fprintf (stderr, "Cannot allocate memory for load latency.\n");
+ return;
+ }
+ }
+ ll_infos->ll_array[ll_infos->ll_count - 1] = ll_info;
+ }
+ }
+
+ /* Go over all the branch mispredict entries and save the ones
+ corresponding to this source file. */
+ for (i = 0; i < pmu_global_info.brm_infos.brm_count; ++i)
+ {
+ gcov_pmu_brm_info_t *brm_info = pmu_global_info.brm_infos.brm_array[i];
+ if (0 == strcmp (src->name, brm_info->filename))
+ {
+ if (!brm_infos->brm_array)
+ {
+ brm_infos->brm_count = 0;
+ brm_infos->alloc_brm_count = 64;
+ brm_infos->brm_array = XCNEWVEC (gcov_pmu_brm_info_t *,
+ brm_infos->alloc_brm_count);
+ }
+ /* Found a matching entry, save it. */
+ brm_infos->brm_count++;
+ if (brm_infos->brm_count >= brm_infos->alloc_brm_count)
+ {
+ /* need to realloc */
+ brm_infos->brm_array = (gcov_pmu_brm_info_t **)
+ xrealloc (brm_infos->brm_array, 2 * brm_infos->alloc_brm_count);
+ if (brm_infos->brm_array == NULL) {
+ fprintf (stderr, "Cannot allocate memory for load latency.\n");
+ return;
+ }
+ }
+ brm_infos->brm_array[brm_infos->brm_count - 1] = brm_info;
+ }
+ }
+
+ /* Sort the load latency data according to the line numbers because
+ we later iterate over sources in line number order. Normally we
+ expect the PMU tool to provide sorted data, but a few entries can
+ be out of order. Thus we use a very simple bubble sort here. */
+ if (ll_infos->ll_count > 1)
+ {
+ changed = 1;
+ while (changed)
+ {
+ changed = 0;
+ for (i = 0; i < ll_infos->ll_count - 1; ++i)
+ {
+ gcov_pmu_ll_info_t *item1 = ll_infos->ll_array[i];
+ gcov_pmu_ll_info_t *item2 = ll_infos->ll_array[i+1];
+ if (item1->line > item2->line)
+ {
+ /* swap */
+ gcov_pmu_ll_info_t *tmp = ll_infos->ll_array[i];
+ ll_infos->ll_array[i] = ll_infos->ll_array[i+1];
+ ll_infos->ll_array[i+1] = tmp;
+ changed = 1;
+ }
+ }
+ }
+ }
+
+ /* Similarly, sort branch mispredict info as well. */
+ if (brm_infos->brm_count > 1)
+ {
+ changed = 1;
+ while (changed)
+ {
+ changed = 0;
+ for (i = 0; i < brm_infos->brm_count - 1; ++i)
+ {
+ gcov_pmu_brm_info_t *item1 = brm_infos->brm_array[i];
+ gcov_pmu_brm_info_t *item2 = brm_infos->brm_array[i+1];
+ if (item1->line > item2->line)
+ {
+ /* swap */
+ gcov_pmu_brm_info_t *tmp = brm_infos->brm_array[i];
+ brm_infos->brm_array[i] = brm_infos->brm_array[i+1];
+ brm_infos->brm_array[i+1] = tmp;
+ changed = 1;
+ }
+ }
+ }
+ }
+
+ /* If no matching PMU info was found, relase the structures. */
+ if (!brm_infos->brm_array && !ll_infos->ll_array)
+ {
+ free (src->pmu_data);
+ src->pmu_data = 0;
+ }
+}
+
/* Accumulate the line counts of a file. */
static void
@@ -1801,6 +2048,10 @@ accumulate_line_counts (source_t *src)
function_t *fn, *fn_p, *fn_n;
unsigned ix;
+ if (flag_pmu_profile)
+ /* Filter PMU profile by source files and save into matching line(s). */
+ filter_pmu_data_lines (src);
+
/* Reverse the function order. */
for (fn = src->functions, fn_p = NULL; fn;
fn_p = fn, fn = fn_n)
@@ -2048,6 +2299,9 @@ output_lines (FILE *gcov_file, const source_t *src)
else if (src->file_time == 0)
fprintf (gcov_file, "%9s:%5d:Source is newer than graph\n", "-", 0);
+ if (src->pmu_data)
+ output_pmu_data_header (gcov_file, src->pmu_data);
+
if (flag_branches)
fn = src->functions;
@@ -2125,6 +2379,10 @@ output_lines (FILE *gcov_file, const source_t *src)
for (ix = 0, arc = line->u.branches; arc; arc = arc->line_next)
ix += output_branch_count (gcov_file, ix, arc);
}
+
+ /* Output PMU profile info if available. */
+ if (flag_pmu_profile)
+ output_pmu_data (gcov_file, src, line_num);
}
/* Handle all remaining source lines. There may be lines after the
@@ -2148,3 +2406,244 @@ output_lines (FILE *gcov_file, const source_t *src)
if (source_file)
fclose (source_file);
}
+
+/* Print an explanatory header for PMU_DATA into GCOV_FILE. */
+
+static void
+output_pmu_data_header (FILE *gcov_file, pmu_data_t *pmu_data)
+{
+ /* Print header for the applicable PMU events. */
+ fprintf (gcov_file, "%9s:%5d\n", "-", 0);
+ if (pmu_data->ll_infos.ll_count)
+ {
+ char *text = pmu_data->ll_infos.pmu_tool_header->column_description;
+ char c;
+ fprintf (gcov_file, "%9s:%5u: %s", "PMU_LL", 0,
+ pmu_data->ll_infos.pmu_tool_header->column_header);
+ /* The column description is multiline text and we want to print
+ each line separately after formatting it. */
+ fprintf (gcov_file, "%9s:%5u: ", "PMU_LL", 0);
+ while ((c = *text++))
+ {
+ fprintf (gcov_file, "%c", c);
+ /* Do not print a new header on trailing newline. */
+ if (c == '\n' && text[1])
+ fprintf (gcov_file, "%9s:%5u: ", "PMU_LL", 0);
+ }
+ fprintf (gcov_file, "%9s:%5d\n", "-", 0);
+ }
+
+ if (pmu_data->brm_infos.brm_count)
+ {
+
+ fprintf (gcov_file, "%9s:%5d:PMU BRM: line: %s %s %s\n",
+ "-", 0, "count", "self", "address");
+ fprintf (gcov_file, "%9s:%5d: "
+ "count: number of branch mispredicts sampled at this address\n",
+ "-", 0);
+ fprintf (gcov_file, "%9s:%5d: "
+ "self: branch mispredicts as percentage of the entire program\n",
+ "-", 0);
+ fprintf (gcov_file, "%9s:%5d\n", "-", 0);
+ }
+}
+
+/* Output pmu data corresponding to SRC and LINE_NUM into GCOV_FILE. */
+
+static void
+output_pmu_data (FILE *gcov_file, const source_t *src, const unsigned line_num)
+{
+ unsigned i;
+ ll_infos_t *ll_infos;
+ brm_infos_t *brm_infos;
+ gcov_pmu_tool_header_t *tool_header;
+
+ if (!src->pmu_data)
+ return;
+
+ ll_infos = &src->pmu_data->ll_infos;
+ brm_infos = &src->pmu_data->brm_infos;
+
+ if (ll_infos->ll_array)
+ {
+ tool_header = src->pmu_data->ll_infos.pmu_tool_header;
+
+ /* Search PMU load latency data for the matching line
+ numbers. There could be multiple entries with the same line
+ number. We use the fact that line numbers are sorted in
+ ll_array. */
+ for (i = 0; i < ll_infos->ll_count &&
+ ll_infos->ll_array[i]->line <= line_num; ++i)
+ {
+ gcov_pmu_ll_info_t *ll_info = ll_infos->ll_array[i];
+ if (ll_info->line == line_num)
+ output_load_latency_line (gcov_file, ll_info, tool_header);
+ }
+ }
+
+ if (brm_infos->brm_array)
+ {
+ tool_header = src->pmu_data->brm_infos.pmu_tool_header;
+
+ /* Search PMU branch mispredict data for the matching line
+ numbers. There could be multiple entries with the same line
+ number. We use the fact that line numbers are sorted in
+ brm_array. */
+ for (i = 0; i < brm_infos->brm_count &&
+ brm_infos->brm_array[i]->line <= line_num; ++i)
+ {
+ gcov_pmu_brm_info_t *brm_info = brm_infos->brm_array[i];
+ if (brm_info->line == line_num)
+ output_branch_mispredict_line (gcov_file, brm_info);
+ }
+ }
+}
+
+
+/* Output formatted load latency info pointed to by LL_INFO into the
+ open file FP. TOOL_HEADER contains additional explanation of
+ fields. */
+
+static void
+output_load_latency_line (FILE *fp, const gcov_pmu_ll_info_t *ll_info,
+ gcov_pmu_tool_header_t *tool_header ATTRIBUTE_UNUSED)
+{
+ fprintf (fp, "%9s:%5u: ", "PMU_LL", ll_info->line);
+ fprintf (fp, " %u %.2f%% %.2f%% %.2f%% %.2f%% %.2f%% %.2f%% %.2f%% "
+ "%.2f%% %.2f%% " HOST_WIDEST_INT_PRINT_HEX "\n",
+ ll_info->counts,
+ convert_unsigned_to_pct (ll_info->self),
+ convert_unsigned_to_pct (ll_info->cum),
+ convert_unsigned_to_pct (ll_info->lt_10),
+ convert_unsigned_to_pct (ll_info->lt_32),
+ convert_unsigned_to_pct (ll_info->lt_64),
+ convert_unsigned_to_pct (ll_info->lt_256),
+ convert_unsigned_to_pct (ll_info->lt_1024),
+ convert_unsigned_to_pct (ll_info->gt_1024),
+ convert_unsigned_to_pct (ll_info->wself),
+ ll_info->code_addr);
+}
+
+
+/* Output formatted branch mispredict info pointed to by BRM_INFO into
+ the open file FP. */
+
+static void
+output_branch_mispredict_line (FILE *fp,
+ const gcov_pmu_brm_info_t *ll_info)
+{
+ fprintf (fp, "%9s:%5u: count: %u self: %.2f%% addr: "
+ HOST_WIDEST_INT_PRINT_HEX "\n",
+ "PMU BRM",
+ ll_info->line,
+ ll_info->counts,
+ convert_unsigned_to_pct (ll_info->self),
+ ll_info->code_addr);
+}
+
+/* Read in the PMU profile information from the global PMU profile file. */
+
+static void process_pmu_profile (void)
+{
+ unsigned tag;
+ unsigned version;
+ int error = 0;
+ ll_infos_t *ll_infos = &pmu_global_info.ll_infos;
+ brm_infos_t *brm_infos = &pmu_global_info.brm_infos;
+
+ /* Construct path for pmuprofile.gcda filename. */
+ create_file_names (pmu_profile_filename);
+ if (!gcov_open (da_file_name, 1))
+ {
+ fnotice (stderr, "%s:cannot open pmu profile file\n",
+ pmu_profile_filename);
+ return;
+ }
+ if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
+ {
+ fnotice (stderr, "%s:not a gcov data file\n", da_file_name);
+ cleanup:;
+ gcov_close ();
+ return;
+ }
+ version = gcov_read_unsigned ();
+ if (version != GCOV_VERSION)
+ {
+ char v[4], e[4];
+
+ GCOV_UNSIGNED2STRING (v, version);
+ GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
+ fnotice (stderr, "%s:version '%.4s', prefer version '%.4s'\n",
+ da_file_name, v, e);
+ }
+ /* read stamp */
+ tag = gcov_read_unsigned ();
+
+ /* Initialize PMU data fields. */
+ ll_infos->ll_count = 0;
+ ll_infos->alloc_ll_count = 64;
+ ll_infos->ll_array = XCNEWVEC (gcov_pmu_ll_info_t *,
+ ll_infos->alloc_ll_count);
+ brm_infos->brm_count = 0;
+ brm_infos->alloc_brm_count = 64;
+ brm_infos->brm_array = XCNEWVEC (gcov_pmu_brm_info_t *,
+ brm_infos->alloc_brm_count);
+
+ while ((tag = gcov_read_unsigned ()))
+ {
+ unsigned length = gcov_read_unsigned ();
+ unsigned long base = gcov_position ();
+
+ if (tag == GCOV_TAG_PMU_LOAD_LATENCY_INFO)
+ {
+ gcov_pmu_ll_info_t *ll_info = XCNEW (gcov_pmu_ll_info_t);
+ gcov_read_pmu_load_latency_info (ll_info, length);
+ ll_infos->ll_count++;
+ if (ll_infos->ll_count >= ll_infos->alloc_ll_count)
+ {
+ /* need to realloc */
+ ll_infos->ll_array = (gcov_pmu_ll_info_t **)
+ xrealloc (ll_infos->ll_array, 2 * ll_infos->alloc_ll_count);
+ if (ll_infos->ll_array == NULL) {
+ fprintf (stderr, "Cannot allocate memory for load latency.\n");
+ goto cleanup;
+ }
+ }
+ ll_infos->ll_array[ll_infos->ll_count - 1] = ll_info;
+ }
+ else if (tag == GCOV_TAG_PMU_BRANCH_MISPREDICT_INFO)
+ {
+ gcov_pmu_brm_info_t *brm_info = XCNEW (gcov_pmu_brm_info_t);
+ gcov_read_pmu_branch_mispredict_info (brm_info, length);
+ brm_infos->brm_count++;
+ if (brm_infos->brm_count >= brm_infos->alloc_brm_count)
+ {
+ /* need to realloc */
+ brm_infos->brm_array = (gcov_pmu_brm_info_t **)
+ xrealloc (brm_infos->brm_array, 2 * brm_infos->alloc_brm_count);
+ if (brm_infos->brm_array == NULL) {
+ fprintf (stderr, "Cannot allocate memory for load latency.\n");
+ goto cleanup;
+ }
+ }
+ brm_infos->brm_array[brm_infos->brm_count - 1] = brm_info;
+ }
+ else if (tag == GCOV_TAG_PMU_TOOL_HEADER)
+ {
+ gcov_pmu_tool_header_t *tool_header = XCNEW (gcov_pmu_tool_header_t);
+ gcov_read_pmu_tool_header (tool_header, length);
+ ll_infos->pmu_tool_header = tool_header;
+ brm_infos->pmu_tool_header = tool_header;
+ }
+
+ gcov_sync (base, length);
+ if ((error = gcov_is_error ()))
+ {
+ fnotice (stderr, error < 0 ? "%s:overflowed\n" : "%s:corrupted\n",
+ da_file_name);
+ goto cleanup;
+ }
+ }
+
+ gcov_close ();
+}
diff --git a/gcc-4.4.3/gcc/genautomata.c b/gcc-4.4.3/gcc/genautomata.c
index d314b8f22..1d742f4dc 100644
--- a/gcc-4.4.3/gcc/genautomata.c
+++ b/gcc-4.4.3/gcc/genautomata.c
@@ -1,5 +1,5 @@
/* Pipeline hazard description translator.
- Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008
+ Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009
Free Software Foundation, Inc.
Written by Vladimir Makarov <vmakarov@redhat.com>
@@ -22,21 +22,25 @@ along with GCC; see the file COPYING3. If not see
/* References:
- 1. Detecting pipeline structural hazards quickly. T. Proebsting,
+ 1. The finite state automaton based pipeline hazard recognizer and
+ instruction scheduler in GCC. V. Makarov. Proceedings of GCC
+ summit, 2003.
+
+ 2. Detecting pipeline structural hazards quickly. T. Proebsting,
C. Fraser. Proceedings of ACM SIGPLAN-SIGACT Symposium on
Principles of Programming Languages, pages 280--286, 1994.
This article is a good start point to understand usage of finite
state automata for pipeline hazard recognizers. But I'd
- recommend the 2nd article for more deep understanding.
+ recommend the 1st and 3rd article for more deep understanding.
- 2. Efficient Instruction Scheduling Using Finite State Automata:
+ 3. Efficient Instruction Scheduling Using Finite State Automata:
V. Bala and N. Rubin, Proceedings of MICRO-28. This is the best
article about usage of finite state automata for pipeline hazard
recognizers.
- The current implementation is different from the 2nd article in the
- following:
+ The current implementation is described in the 1st article and it
+ is different from the 3rd article in the following:
1. New operator `|' (alternative) is permitted in functional unit
reservation which can be treated deterministically and
@@ -463,7 +467,10 @@ struct insn_reserv_decl
insn. */
int insn_num;
/* The following field value is list of bypasses in which given insn
- is output insn. */
+ is output insn. Bypasses with the same input insn stay one after
+ another in the list in the same order as their occurrences in the
+ description but the bypass without a guard stays always the last
+ in a row of bypasses with the same input insn. */
struct bypass_decl *bypass_list;
/* The following fields are defined by automaton generator. */
@@ -2367,18 +2374,67 @@ add_presence_absence (unit_set_el_t dest_list,
}
-/* The function searches for bypass with given IN_INSN_RESERV in given
- BYPASS_LIST. */
-static struct bypass_decl *
-find_bypass (struct bypass_decl *bypass_list,
- struct insn_reserv_decl *in_insn_reserv)
+/* The function inserts BYPASS in the list of bypasses of the
+ corresponding output insn. The order of bypasses in the list is
+ decribed in a comment for member `bypass_list' (see above). If
+ there is already the same bypass in the list the function reports
+ this and does nothing. */
+static void
+insert_bypass (struct bypass_decl *bypass)
{
- struct bypass_decl *bypass;
-
- for (bypass = bypass_list; bypass != NULL; bypass = bypass->next)
- if (bypass->in_insn_reserv == in_insn_reserv)
- break;
- return bypass;
+ struct bypass_decl *curr, *last;
+ struct insn_reserv_decl *out_insn_reserv = bypass->out_insn_reserv;
+ struct insn_reserv_decl *in_insn_reserv = bypass->in_insn_reserv;
+
+ for (curr = out_insn_reserv->bypass_list, last = NULL;
+ curr != NULL;
+ last = curr, curr = curr->next)
+ if (curr->in_insn_reserv == in_insn_reserv)
+ {
+ if ((bypass->bypass_guard_name != NULL
+ && curr->bypass_guard_name != NULL
+ && ! strcmp (bypass->bypass_guard_name, curr->bypass_guard_name))
+ || bypass->bypass_guard_name == curr->bypass_guard_name)
+ {
+ if (bypass->bypass_guard_name == NULL)
+ {
+ if (!w_flag)
+ error ("the same bypass `%s - %s' is already defined",
+ bypass->out_insn_name, bypass->in_insn_name);
+ else
+ warning (0, "the same bypass `%s - %s' is already defined",
+ bypass->out_insn_name, bypass->in_insn_name);
+ }
+ else if (!w_flag)
+ error ("the same bypass `%s - %s' (guard %s) is already defined",
+ bypass->out_insn_name, bypass->in_insn_name,
+ bypass->bypass_guard_name);
+ else
+ warning
+ (0, "the same bypass `%s - %s' (guard %s) is already defined",
+ bypass->out_insn_name, bypass->in_insn_name,
+ bypass->bypass_guard_name);
+ return;
+ }
+ if (curr->bypass_guard_name == NULL)
+ break;
+ if (curr->next == NULL || curr->next->in_insn_reserv != in_insn_reserv)
+ {
+ last = curr;
+ break;
+ }
+
+ }
+ if (last == NULL)
+ {
+ bypass->next = out_insn_reserv->bypass_list;
+ out_insn_reserv->bypass_list = bypass;
+ }
+ else
+ {
+ bypass->next = last->next;
+ last->next = bypass;
+ }
}
/* The function processes pipeline description declarations, checks
@@ -2391,7 +2447,6 @@ process_decls (void)
decl_t decl_in_table;
decl_t out_insn_reserv;
decl_t in_insn_reserv;
- struct bypass_decl *bypass;
int automaton_presence;
int i;
@@ -2514,36 +2569,7 @@ process_decls (void)
= DECL_INSN_RESERV (out_insn_reserv);
DECL_BYPASS (decl)->in_insn_reserv
= DECL_INSN_RESERV (in_insn_reserv);
- bypass
- = find_bypass (DECL_INSN_RESERV (out_insn_reserv)->bypass_list,
- DECL_BYPASS (decl)->in_insn_reserv);
- if (bypass != NULL)
- {
- if (DECL_BYPASS (decl)->latency == bypass->latency)
- {
- if (!w_flag)
- error
- ("the same bypass `%s - %s' is already defined",
- DECL_BYPASS (decl)->out_insn_name,
- DECL_BYPASS (decl)->in_insn_name);
- else
- warning
- (0, "the same bypass `%s - %s' is already defined",
- DECL_BYPASS (decl)->out_insn_name,
- DECL_BYPASS (decl)->in_insn_name);
- }
- else
- error ("bypass `%s - %s' is already defined",
- DECL_BYPASS (decl)->out_insn_name,
- DECL_BYPASS (decl)->in_insn_name);
- }
- else
- {
- DECL_BYPASS (decl)->next
- = DECL_INSN_RESERV (out_insn_reserv)->bypass_list;
- DECL_INSN_RESERV (out_insn_reserv)->bypass_list
- = DECL_BYPASS (decl);
- }
+ insert_bypass (DECL_BYPASS (decl));
}
}
}
@@ -8159,19 +8185,32 @@ output_internal_insn_latency_func (void)
(advance_cycle_insn_decl)->insn_num));
fprintf (output_file, " case %d:\n",
bypass->in_insn_reserv->insn_num);
- if (bypass->bypass_guard_name == NULL)
- fprintf (output_file, " return %d;\n",
- bypass->latency);
- else
+ for (;;)
{
- fprintf (output_file,
- " if (%s (%s, %s))\n",
- bypass->bypass_guard_name, INSN_PARAMETER_NAME,
- INSN2_PARAMETER_NAME);
- fprintf (output_file,
- " return %d;\n break;\n",
- bypass->latency);
+ if (bypass->bypass_guard_name == NULL)
+ {
+ gcc_assert (bypass->next == NULL
+ || (bypass->in_insn_reserv
+ != bypass->next->in_insn_reserv));
+ fprintf (output_file, " return %d;\n",
+ bypass->latency);
+ }
+ else
+ {
+ fprintf (output_file,
+ " if (%s (%s, %s))\n",
+ bypass->bypass_guard_name, INSN_PARAMETER_NAME,
+ INSN2_PARAMETER_NAME);
+ fprintf (output_file, " return %d;\n",
+ bypass->latency);
+ }
+ if (bypass->next == NULL
+ || bypass->in_insn_reserv != bypass->next->in_insn_reserv)
+ break;
+ bypass = bypass->next;
}
+ if (bypass->bypass_guard_name != NULL)
+ fprintf (output_file, " break;\n");
}
fputs (" }\n break;\n", output_file);
}
diff --git a/gcc-4.4.3/gcc/ggc-page.c b/gcc-4.4.3/gcc/ggc-page.c
index 567ea6fb5..2ddb3dc36 100644
--- a/gcc-4.4.3/gcc/ggc-page.c
+++ b/gcc-4.4.3/gcc/ggc-page.c
@@ -2363,3 +2363,9 @@ ggc_pch_read (FILE *f, void *addr)
/* Update the statistics. */
G.allocated = G.allocated_last_gc = offs - (char *)addr;
}
+
+size_t
+ggc_total_allocated (void)
+{
+ return G.bytes_mapped;
+}
diff --git a/gcc-4.4.3/gcc/ggc.h b/gcc-4.4.3/gcc/ggc.h
index e3471e453..f9670ac90 100644
--- a/gcc-4.4.3/gcc/ggc.h
+++ b/gcc-4.4.3/gcc/ggc.h
@@ -328,4 +328,6 @@ extern void *ggc_alloc_zone_stat (size_t, struct alloc_zone * MEM_STAT_DECL);
#endif
+extern size_t ggc_total_allocated (void);
+
#endif
diff --git a/gcc-4.4.3/gcc/ipa-cp.c b/gcc-4.4.3/gcc/ipa-cp.c
index 73e6b52a6..0bc01ef0d 100644
--- a/gcc-4.4.3/gcc/ipa-cp.c
+++ b/gcc-4.4.3/gcc/ipa-cp.c
@@ -228,6 +228,8 @@ ipcp_update_cloned_node (struct cgraph_node *new_node)
for (cs = new_node->callees; cs; cs = cs->next_callee)
{
+ if (!cs->callee->analyzed)
+ continue;
ipa_count_arguments (cs);
ipa_compute_jump_functions (cs);
}
diff --git a/gcc-4.4.3/gcc/ipa-inline.c b/gcc-4.4.3/gcc/ipa-inline.c
index cb1257211..da7ac498d 100644
--- a/gcc-4.4.3/gcc/ipa-inline.c
+++ b/gcc-4.4.3/gcc/ipa-inline.c
@@ -52,7 +52,7 @@ along with GCC; see the file COPYING3. If not see
To mark given call inline, use cgraph_mark_inline function, the
verification is performed by cgraph_default_inline_p and
- cgraph_check_inline_limits.
+ cgraph_check_inline_constraints.
The heuristics implements simple knapsack style algorithm ordering
all functions by their "profitability" (estimated by code size growth)
@@ -145,6 +145,8 @@ along with GCC; see the file COPYING3. If not see
#include "dbgcnt.h"
#include "tree-dump.h"
+#include <math.h>
+
/* Mode incremental inliner operate on:
In ALWAYS_INLINE only functions marked
@@ -272,28 +274,6 @@ inline_summary (struct cgraph_node *node)
return &node->local.inline_summary;
}
-/* Return true if NODE is a hot function. */
-
-static bool
-hot_function_p (struct cgraph_node *node)
-{
- struct cgraph_edge *edge;
-
- if (node->local.inline_summary.self_hot_insns > 0)
- return true;
-
- for (edge = node->callees; edge; edge = edge->next_callee)
- if (cgraph_maybe_hot_edge_p (edge))
- return true;
-
- for (edge = node->callers; edge; edge = edge->next_caller)
- if (cgraph_maybe_hot_edge_p (edge))
- return true;
-
- return false;
-}
-
-
/* Return the pointer to the list of hot components for NODE. Global
array NODE_HOT_COMPONENT_LIST is resized as necessary for new nodes
with uid's that exceed the bounds of the current array. This may
@@ -1046,48 +1026,107 @@ cgraph_mark_inline (struct cgraph_edge *edge)
return edge;
}
-/* Estimate the growth caused by inlining NODE into all callees. */
+/* Estimate the growth caused by inlining NODE into all callees.
+ Return value is the average expected growth per callsite. */
static int
cgraph_estimate_growth (struct cgraph_node *node)
{
- int growth = 0;
+ int growth = 0, ncalls = 0;
struct cgraph_edge *e;
bool self_recursive = false;
- if (node->global.estimated_growth != INT_MIN)
- return node->global.estimated_growth;
+ if (node->global.estimated_average_growth != INT_MIN)
+ return node->global.estimated_average_growth;
for (e = node->callers; e; e = e->next_caller)
{
if (e->caller == node)
self_recursive = true;
if (e->inline_failed)
- growth += (cgraph_estimate_size_after_inlining (1, e->caller, node)
- - e->caller->global.insns);
+ {
+ growth += (cgraph_estimate_size_after_inlining (1, e->caller, node)
+ - e->caller->global.insns);
+ ncalls++;
+ }
}
/* ??? Wrong for non-trivially self recursive functions or cases where
we decide to not inline for different reasons, but it is not big deal
as in that case we will keep the body around, but we will also avoid
some inlining. */
- if (!node->needed && !DECL_EXTERNAL (node->decl) && !self_recursive)
- growth -= node->global.insns;
+ if (!self_recursive)
+ {
+ int emitted_size = (node->global.insns
+ + PARAM_VALUE(PARAM_INLINE_FUNCTION_SIZE_ADJUSTMENT));
+ if (!node->needed && !DECL_EXTERNAL (node->decl))
+ growth -= emitted_size;
+ else if (node->address_taken)
+ growth -= ((100.0
+ - PARAM_VALUE (PARAM_INLINE_ADDRESS_TAKEN_FUNCTION_EMIT_PROBABILITY))
+ * emitted_size) / 100;
+ else
+ growth -= ((100.0
+ - PARAM_VALUE (PARAM_INLINE_ADDRESS_NOT_TAKEN_FUNCTION_EMIT_PROBABILITY))
+ * emitted_size) / 100;
+ }
- node->global.estimated_growth = growth;
+ if (ncalls > 0)
+ /* If growth before averaging is less than zero, we'd like the
+ average to be less than zero because some heuristics cue off
+ this less-than-zero growth condition, so subtract NCALLS - 1 to
+ ensure that -1/NCALLS rounds down to -1. */
+ growth = (growth - (ncalls - 1)) / ncalls;
+
+ node->global.estimated_average_growth = growth;
return growth;
}
-/* Return false when inlining WHAT into TO is not good idea
- as it would cause too large growth of function bodies.
- When ONE_ONLY is true, assume that only one call site is going
- to be inlined, otherwise figure out how many call sites in
- TO calls WHAT and verify that all can be inlined.
+/* Return true if there exists a path from FROM to TO in the call
+ graph which consists entirely of functions with the always_inline
+ attribute. This is trivially true if FROM calls TO. MAX_DEPTH
+ limits search depth to avoid infinite recursion and otherwise
+ expensive searches. */
+
+static bool
+always_inline_path (struct cgraph_node *from, struct cgraph_node *to,
+ int max_depth)
+{
+ struct cgraph_edge *e;
+
+ if (max_depth == 0)
+ return false;
+
+ for (e = from->callees; e; e = e->next_callee)
+ {
+ if (e->callee == to)
+ return true;
+
+ if (!e->inline_failed
+ || lookup_attribute ("always_inline", DECL_ATTRIBUTES (e->callee->decl)))
+ {
+ /* Edge is an inlined edge or callee is always_inline.
+ Continue search down edge. Only decrement MAX_DEPTH if
+ entering a new function. */
+ if (always_inline_path(e->callee, to,
+ e->inline_failed ? max_depth - 1 : max_depth))
+ return true;
+ }
+ }
+ return false;
+}
+
+/* Return false when inlining WHAT into TO is not good idea as it
+ would violate growth limits or other constraints. When ONE_ONLY is
+ true, assume that only one call site is going to be inlined,
+ otherwise figure out how many call sites in TO calls WHAT and
+ verify that all can be inlined.
*/
static bool
-cgraph_check_inline_limits (struct cgraph_node *to, struct cgraph_node *what,
- const char **reason, bool one_only)
+cgraph_check_inline_constraints (struct cgraph_node *to,
+ struct cgraph_node *what,
+ const char **reason, bool one_only)
{
int times = 0;
struct cgraph_edge *e;
@@ -1144,15 +1183,29 @@ cgraph_check_inline_limits (struct cgraph_node *to, struct cgraph_node *what,
*reason = N_("--param large-stack-frame-growth limit reached");
return false;
}
+
+ /* Not inlining a call to a function marked always_inline is an
+ error. If TO is marked always_inline, verify that inlining WHAT
+ into TO will not result in the impossible-to-resolve situation of
+ TO calling itself directly or via a chain of always_inline
+ functions. */
+ if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (to->decl))
+ && always_inline_path (what, to, 10))
+ {
+ if (reason)
+ *reason = N_("inlining would result in recursive always_inline function");
+ return false;
+ }
+
return true;
}
/* Return false when inlining EDGE is not good idea. Checks for hot
- component growth and calls cgraph_check_inline_limits for all other
+ component growth and calls cgraph_check_inline_constraints for all other
checks. */
static bool
-cgraph_check_inline_limits_edge (struct cgraph_edge *edge, const char **reason)
+cgraph_check_inline_constraints_edge (struct cgraph_edge *edge, const char **reason)
{
if (flag_limit_hot_components && n_hot_components
&& cgraph_maybe_hot_edge_p (edge))
@@ -1176,7 +1229,8 @@ cgraph_check_inline_limits_edge (struct cgraph_edge *edge, const char **reason)
}
}
}
- return cgraph_check_inline_limits (edge->caller, edge->callee, reason, true);
+ return cgraph_check_inline_constraints (edge->caller, edge->callee,
+ reason, true);
}
/* Return true when function N is small enough to be inlined. */
@@ -1295,92 +1349,137 @@ better_inline_comdat_function_p (struct cgraph_node *node)
}
-/* A cost model driving the inlining heuristics in a way so the edges with
- smallest badness are inlined first. After each inlining is performed
- the costs of all caller edges of nodes affected are recomputed so the
- metrics may accurately depend on values such as number of inlinable callers
- of the function or function body size. */
+/* Compute the inlining priority for EDGE. The value is generally
+ computed as the growth of inlining the callsite divided by the
+ frequency of the callsite. Lower values are higher priority. */
static int
-cgraph_edge_badness (struct cgraph_edge *edge)
-{
- int badness;
- int growth =
- cgraph_estimate_size_after_inlining (1, edge->caller, edge->callee);
-
- growth -= edge->caller->global.insns;
-
- /* Always prefer inlining saving code size. */
- if (growth <= 0)
- badness = INT_MIN - growth;
-
- /* When profiling is available, base priorities -(#calls / growth).
- So we optimize for overall number of "executed" inlined calls. */
- else if (max_count)
- if (flag_sample_profile && get_total_count_edge (edge,
- cgraph_node_name (edge->caller->global.inlined_to ?
- edge->caller->global.inlined_to :
- edge->caller)) > 0)
- /* When using sample profile, if the function is inlined during the
- profiling run, we will give it higher priority to be inlined. */
- badness = INT_MIN / growth;
- else
- badness = ((int)((double)edge->count * INT_MIN / max_count)) / growth;
-
- /* When function local profile is available, base priorities on
- growth / frequency, so we optimize for overall frequency of inlined
- calls. This is not too accurate since while the call might be frequent
- within function, the function itself is infrequent.
-
- Other objective to optimize for is number of different calls inlined.
- We add the estimated growth after inlining all functions to bias the
- priorities slightly in this direction (so fewer times called functions
- of the same size gets priority). */
- else if (flag_guess_branch_prob)
- {
- int div = edge->frequency * 100 / CGRAPH_FREQ_BASE;
- int growth =
- cgraph_estimate_size_after_inlining (1, edge->caller, edge->callee);
- growth -= edge->caller->global.insns;
- badness = growth * 256;
-
- /* Decrease badness if call is nested. */
- /* Compress the range so we don't overflow. */
- if (div > 256)
- div = 256 + ceil_log2 (div) - 8;
- if (div < 1)
- div = 1;
- if (badness > 0)
- badness /= div;
- badness += cgraph_estimate_growth (edge->callee);
- }
- /* When function local profile is not available or it does not give
- useful information (ie frequency is zero), base the cost on
- loop nest and overall size growth, so we optimize for overall number
- of functions fully inlined in program. */
+cgraph_edge_priority (struct cgraph_edge *edge)
+{
+ /* GROWTH is the minimum of the code growth of inlining the callsite
+ and the average growth of inlining all the callsite of the
+ callee. Including the average callsite growth factors in the
+ potential benefit of not having to emit the function body should
+ all callsites of the callee be inlined and the function is not
+ needed. */
+ int growth = MIN (cgraph_estimate_size_after_inlining (1, edge->caller,
+ edge->callee)
+ - edge->caller->global.insns,
+ cgraph_estimate_growth (edge->callee));
+ int priority;
+
+ /* Always prefer inlining saving code size, and inline comdat
+ functions with LIPO. */
+ if (growth <= 0
+ || better_inline_comdat_function_p (edge->callee))
+ priority = 0;
else
{
- int nest = MIN (edge->loop_nest, 8);
- badness = cgraph_estimate_growth (edge->callee) * 256;
+ /* FREQ_DIVISOR is some estimate of the frequency of the
+ callsite. The value can range from 0 to 1.0. */
+ double freq_divisor;
- /* Decrease badness if call is nested. */
- if (badness > 0)
- badness >>= nest;
+ if (max_count)
+ {
+ /* When profiling is available, use the execution count of the
+ callsite as a fraction of the maximum count. */
+ struct cgraph_node *caller = (edge->caller->global.inlined_to
+ ? edge->caller->global.inlined_to
+ : edge->caller);
+ if (flag_sample_profile
+ && get_total_count_edge (edge, cgraph_node_name (caller)) > 0)
+ /* When using sample profile, if the function is inlined during the
+ profiling run, we will give it higher priority to be inlined. */
+ freq_divisor = 1.0;
+ else
+ freq_divisor = (double)edge->count / max_count;
+ }
+ else if (flag_guess_branch_prob)
+ /* When function local profile is available, base priorities on
+ estimated frequency, so we optimize for overall frequency of
+ inlined calls. This is not too accurate since while the call
+ might be frequent within function, the function itself is
+ infrequent. */
+ freq_divisor = (double)edge->frequency / CGRAPH_FREQ_MAX;
else
- {
- badness <<= nest;
- }
- }
- /* Make recursive inlining happen always after other inlining is done. */
- if (cgraph_recursive_inlining_p (edge->caller, edge->callee, NULL))
- return badness + 1;
- else
- {
- if (better_inline_comdat_function_p (edge->callee))
- return INT_MIN + 1;
+ {
+ /* When function local profile is not available or it does not
+ give useful information (ie frequency is zero), base the
+ frequency upon the loop nest where each loop is estimated to
+ be executed twice. The nest depth is capped at a
+ constant so the maximum FREQ_DIVISOR value is 1.0. */
+ int nest = MIN (edge->loop_nest, 8);
+ freq_divisor = 1.0 / (1 << (8 - nest));
+ }
+
+ if ((freq_divisor <= 0.0)
+ || (growth / freq_divisor > INT_MAX - 1))
+ /* Limit priority to one less than INT_MAX to leave room for
+ incrementing priority due to recursive inlining below. */
+ priority = INT_MAX - 1;
else
- return badness;
- }
+ priority = (int) (growth / freq_divisor);
+
+ /* Make recursive inlining happen always after other inlining is done. */
+ if (cgraph_recursive_inlining_p (edge->caller, edge->callee, NULL))
+ priority += 1;
+ }
+ gcc_assert (priority >= 0);
+ return priority;
+}
+
+/* Compute a key for EDGE for the priority heap of edges to inline.
+ The most-significant bits of the key are the callsite priority. To
+ improve the stability of inlining decisions, the least-significant
+ bits are the caller and callee sizes. Callsites with identical key
+ values are essentially selected in arbitrary order during inlining,
+ so seemingly innocuous source code changes can affect inlining
+ decisions significantly by changing the inlining order of callsites
+ with the same key. Adding tie-breakers (caller and callee sizes)
+ reduces the incidence of such cases. */
+
+static fibheapkey_t
+cgraph_edge_priority_key (struct cgraph_edge *edge)
+{
+ int priority = cgraph_edge_priority (edge);
+ int shift = 0;
+
+ /* To make room for the callee and caller sizes (prioirity tie
+ breakers), the priority must be packed into 16-bits. Rather than
+ truncate or clip the value, the priority is compressed. Values
+ greater than or equal to 2**12 are right-shifted by one or more
+ bits. This is represented in 16-bits with 2 fields: the value to
+ shift (lower 12 bits), and the amount to shift (upper 4 bits).
+ This compressed value increases monotonically as the priority
+ increases. Priorities higher than 2**27 are clipped, but the
+ priority is never that high for any callsite that has a chance of
+ being inlined */
+ gcc_assert (priority >= 0);
+ while ((priority >= (1 << 12)) && (shift < 16))
+ {
+ priority >>= 1;
+ shift++;
+ }
+ if (shift == 16)
+ priority = (1 << 16) - 1;
+ else
+ priority = (shift << 12) + priority;
+
+ return (INT_MIN
+ + (priority << 16)
+ + (MIN (255, edge->callee->global.insns) << 8)
+ + MIN (255, edge->caller->global.insns));
+}
+
+static int
+key_to_priority (fibheapkey_t key)
+{
+ int value = (key >> 16) - (INT_MIN >> 16);
+ int shift;
+ gcc_assert ((value >= 0) && (value < (1 << 16)));
+ shift = (value >> 12) & 0xf;
+ value = value & 0xfff;
+ return value << shift;
}
/* Recompute heap nodes for each of caller edge. */
@@ -1398,7 +1497,7 @@ update_caller_keys (fibheap_t heap, struct cgraph_node *node,
if (bitmap_bit_p (updated_nodes, node->uid))
return;
bitmap_set_bit (updated_nodes, node->uid);
- node->global.estimated_growth = INT_MIN;
+ node->global.estimated_average_growth = INT_MIN;
if (!node->local.inlinable)
return;
@@ -1420,20 +1519,24 @@ update_caller_keys (fibheap_t heap, struct cgraph_node *node,
for (edge = node->callers; edge; edge = edge->next_caller)
if (edge->inline_failed)
{
- int badness = cgraph_edge_badness (edge);
+ fibheapkey_t new_key = cgraph_edge_priority_key (edge);
if (edge->aux)
{
fibnode_t n = (fibnode_t) edge->aux;
gcc_assert (n->data == edge);
- if (n->key == badness)
+ if (n->key == new_key)
continue;
/* fibheap_replace_key only increase the keys. */
- if (fibheap_replace_key (heap, n, badness))
- continue;
+ if (new_key < n->key)
+ {
+ fibheap_replace_key (heap, n, new_key);
+ gcc_assert (n->key == new_key);
+ continue;
+ }
fibheap_delete_node (heap, (fibnode_t) edge->aux);
}
- edge->aux = fibheap_insert (heap, badness, edge);
+ edge->aux = fibheap_insert (heap, new_key, edge);
}
}
@@ -1444,7 +1547,7 @@ update_callee_keys (fibheap_t heap, struct cgraph_node *node,
bitmap updated_nodes)
{
struct cgraph_edge *e;
- node->global.estimated_growth = INT_MIN;
+ node->global.estimated_average_growth = INT_MIN;
for (e = node->callees; e; e = e->next_callee)
if (e->inline_failed)
@@ -1588,7 +1691,7 @@ cgraph_decide_recursive_inlining (struct cgraph_node *node,
fprintf (dump_file, " Not inlining cold call\n");
continue;
}
- if (curr->count * 100 / node->count < probability)
+ if (node->count == 0 || (curr->count * 100 / node->count < probability))
{
if (dump_file)
fprintf (dump_file,
@@ -1664,7 +1767,8 @@ compute_max_insns (int insns)
* (100 + PARAM_VALUE (PARAM_INLINE_UNIT_GROWTH)) / 100);
}
-/* Compute badness of all edges in NEW_EDGES and add them to the HEAP. */
+/* Compute priority keys of all edges in NEW_EDGES and add them to the
+ HEAP. */
static void
add_new_edges_to_heap (fibheap_t heap, VEC (cgraph_edge_p, heap) *new_edges)
{
@@ -1673,7 +1777,7 @@ add_new_edges_to_heap (fibheap_t heap, VEC (cgraph_edge_p, heap) *new_edges)
struct cgraph_edge *edge = VEC_pop (cgraph_edge_p, new_edges);
gcc_assert (!edge->aux);
- edge->aux = fibheap_insert (heap, cgraph_edge_badness (edge), edge);
+ edge->aux = fibheap_insert (heap, cgraph_edge_priority_key (edge), edge);
}
}
@@ -1714,7 +1818,7 @@ cgraph_decide_inlining_of_small_functions (void)
fprintf (dump_file, "Considering inline candidate %s.\n",
cgraph_node_name (node));
- node->global.estimated_growth = INT_MIN;
+ node->global.estimated_average_growth = INT_MIN;
if (!cgraph_default_inline_p (node, &failed_reason) &&
!better_inline_comdat_function_p (node))
{
@@ -1726,7 +1830,8 @@ cgraph_decide_inlining_of_small_functions (void)
if (edge->inline_failed)
{
gcc_assert (!edge->aux);
- edge->aux = fibheap_insert (heap, cgraph_edge_badness (edge), edge);
+ edge->aux = fibheap_insert (heap,
+ cgraph_edge_priority_key (edge), edge);
}
}
@@ -1739,38 +1844,45 @@ cgraph_decide_inlining_of_small_functions (void)
fprintf (dump_file, "Initial min_insns = %d\n", min_insns);
}
- while (overall_insns <= max_insns
- && (edge = (struct cgraph_edge *) fibheap_extract_min (heap)))
+ while (overall_insns <= max_insns && !fibheap_empty (heap))
{
- int old_insns = overall_insns;
- struct cgraph_node *where;
- int growth =
- cgraph_estimate_size_after_inlining (1, edge->caller, edge->callee);
+ int old_insns = overall_insns, growth;
+ fibheapkey_t key;
+ struct cgraph_node *caller, *callee;
const char *not_good = NULL;
- growth -= edge->caller->global.insns;
+ key = fibheap_min_key (heap);
+ edge = (struct cgraph_edge *) fibheap_extract_min (heap);
+ gcc_assert (edge->aux);
+ edge->aux = NULL;
+ if (!edge->inline_failed)
+ continue;
+
+ growth =
+ (cgraph_estimate_size_after_inlining (1, edge->caller, edge->callee)
+ - edge->caller->global.insns);
+
+ /* If fibheap keys are updated properly, these values should
+ always be identical. */
+ gcc_assert (key == cgraph_edge_priority_key (edge));
if (dump_file)
{
- fprintf (dump_file,
+ fprintf (dump_file,
"\nConsidering %s with %i insns\n",
cgraph_node_name (edge->callee),
edge->callee->global.insns);
- fprintf (dump_file,
+ fprintf (dump_file,
" to be inlined into %s\n"
- " Estimated growth after inlined into all callees is %+i insns.\n"
- " Estimated badness is %i, frequency %.2f.\n",
+ " Estimated average growth after inlined into all callees is %+i insns.\n"
+ " Estimated priority is %i, frequency %.2f.\n",
cgraph_node_name (edge->caller),
- cgraph_estimate_growth (edge->callee),
- cgraph_edge_badness (edge),
+ cgraph_estimate_growth (edge->callee), key_to_priority (key),
edge->frequency / (double)CGRAPH_FREQ_BASE);
if (edge->count)
fprintf (dump_file," Called "HOST_WIDEST_INT_PRINT_DEC"x\n", edge->count);
}
- gcc_assert (edge->aux);
- edge->aux = NULL;
- if (!edge->inline_failed)
- continue;
+
/* When not having profile info ready we don't weight by any way the
position of call in procedure itself. This means if call of
@@ -1791,7 +1903,7 @@ cgraph_decide_inlining_of_small_functions (void)
edge->caller->global.inlined_to :
edge->caller)) > 0))
{
- where = edge->caller;
+ struct cgraph_node *where = edge->caller;
while (where->global.inlined_to)
{
if (where->decl == edge->callee->decl)
@@ -1841,8 +1953,11 @@ cgraph_decide_inlining_of_small_functions (void)
not_good = N_("call is unlikely and code size would grow");
}
if (!flag_inline_functions
- && !DECL_DECLARED_INLINE_P (edge->callee->decl))
- not_good = N_("function not declared inline and code size would grow");
+ && !DECL_DECLARED_INLINE_P (edge->callee->decl)
+ && (key_to_priority (key)
+ > PARAM_VALUE (PARAM_INLINE_PRIORITY_THRESHOLD)))
+ not_good = N_("function not declared inline, code size would grow, "
+ "and priority too low");
if (optimize_function_for_size_p (DECL_STRUCT_FUNCTION(edge->caller->decl)))
not_good = N_("optimizing for size and code size would grow");
if (not_good && growth > 0 && cgraph_estimate_growth (edge->callee) > 0)
@@ -1875,25 +1990,26 @@ cgraph_decide_inlining_of_small_functions (void)
fprintf (dump_file, " inline_failed:%s.\n", edge->inline_failed);
continue;
}
+
+ caller = edge->caller;
+ if (caller->global.inlined_to)
+ caller = caller->global.inlined_to;
+ callee = edge->callee;
+
if (cgraph_recursive_inlining_p (edge->caller, edge->callee,
&edge->inline_failed))
{
- where = edge->caller;
- if (where->global.inlined_to)
- where = where->global.inlined_to;
- if (!cgraph_decide_recursive_inlining (where,
+ if (!cgraph_decide_recursive_inlining (caller,
flag_indirect_inlining
? &new_indirect_edges : NULL))
continue;
if (flag_indirect_inlining)
add_new_edges_to_heap (heap, new_indirect_edges);
- update_callee_keys (heap, where, updated_nodes);
}
else
{
- struct cgraph_node *callee;
if (gimple_call_cannot_inline_p (edge->call_stmt)
- || !cgraph_check_inline_limits_edge (edge, &edge->inline_failed))
+ || !cgraph_check_inline_constraints_edge (edge, &edge->inline_failed))
{
if (dump_file)
fprintf (dump_file, " Not inlining into %s:%s.\n",
@@ -1904,27 +2020,40 @@ cgraph_decide_inlining_of_small_functions (void)
if (!dbg_cnt (inl))
continue;
- if (dump_file)
- fprintf (dump_file, "END EDGE inline success\n");
-
- callee = edge->callee;
cgraph_mark_inline_edge (edge, true, &new_indirect_edges);
if (flag_indirect_inlining)
add_new_edges_to_heap (heap, new_indirect_edges);
+ }
+ /* Our profitability metric depends upon local properties of the
+ caller and callee, as well as global properties such as the
+ number of times a function is called. The priority of edges
+ already in the heap need to be adjusted accordingly. */
+
+ /* CALLER is the function that the callee is ultimately inlined
+ into, potentially via multiple transitive inlining decisions.
+ It's size likely changed, so update all of its callers.
+ Update it's callees as well because the caller size is used
+ when computing prioirity keys. Furthermore, updating the
+ callee keys will update callsites within the newly inlined
+ function body. */
+ update_caller_keys (heap, caller, updated_nodes);
+ update_callee_keys (heap, caller, updated_nodes);
+
+ /* If the non-inlined body of the callee is still around (CALLEE
+ is not marked as inline), then it must be updated as with
+ INLINED_CALLEE. Also, because the number of callers of the
+ function which has been inlined has been reduced by one, all
+ callers of the function must be updated. */
+ if (!callee->global.inlined_to)
+ {
update_callee_keys (heap, callee, updated_nodes);
+ if (caller != callee)
+ /* Add condition to avoid duplicating call to
+ UPDATE_CALLER_KEYS above. */
+ update_caller_keys (heap, callee, updated_nodes);
}
- where = edge->caller;
- if (where->global.inlined_to)
- where = where->global.inlined_to;
-
- /* Our profitability metric can depend on local properties
- such as number of inlinable calls and size of the function body.
- After inlining these properties might change for the function we
- inlined into (since it's body size changed) and for the functions
- called by function we inlined (since number of it inlinable callers
- might change). */
- update_caller_keys (heap, where, updated_nodes);
+
bitmap_clear (updated_nodes);
if (dump_file)
@@ -1952,6 +2081,14 @@ cgraph_decide_inlining_of_small_functions (void)
fprintf (dump_file, "overall_insns = %d\n", overall_insns);
}
}
+ if (dump_file)
+ {
+ if (fibheap_empty (heap))
+ fprintf (dump_file, "All small function candidates inlined.\n");
+ else
+ fprintf (dump_file, "Small function priority cutoff is %d.\n",
+ (int) key_to_priority (fibheap_min_key (heap)));
+ }
while ((edge = (struct cgraph_edge *) fibheap_extract_min (heap)) != NULL)
{
gcc_assert (edge->aux);
@@ -2439,59 +2576,47 @@ apply_plan (struct inline_plan *plan,
return inlined;
}
-/* Dump information about every function and callsite (call graph
- edge) to FILE. */
+/* Recursive helper function for dumping inlining decisions within a
+ function. */
static void
-dump_cgraph_info (FILE *file)
+dump_function_inlining_decisions_1 (FILE *file, struct cgraph_node *node,
+ int indent)
{
- struct cgraph_node *node;
struct cgraph_edge *edge;
- fprintf (file, "CALL GRAPH:\n");
- for (node = cgraph_nodes; node; node = node->next)
- if (!node->global.inlined_to)
- {
- fprintf (file, "FUNCTION: %s\n", cgraph_node_name (node));
- fprintf (file, "FUNCTION: uid=%d, ", node->uid);
- if (DECL_DECLARED_INLINE_P (node->decl))
- fprintf (file, "marked inline, ");
- else
- fprintf (file, "not marked inline, ");
- fprintf (file, "frequency=%s, ", function_frequency_string (node));
- fprintf (file, "count=" HOST_WIDEST_INT_PRINT_DEC ", ", node->count);
- fprintf (file, "size=%d", node->global.insns);
- if (node->local.inlinable)
- fprintf (file, ", all inlined growth=%d", cgraph_estimate_growth (node));
- if (flag_dyn_ipa && (cgraph_get_module_id (node->decl) != primary_module_id))
- fprintf (file, ", aux module id=%u", cgraph_get_module_id (node->decl));
- fprintf (file, "\n");
- }
-
- for (node = cgraph_nodes; node; node = node->next)
- for (edge = node->callers; edge; edge = edge->next_caller)
- {
- fprintf (file, "CALLSITE: ");
- dump_inlining_decision (file, edge);
- fprintf (file, "\n");
- fprintf (file, "CALLSITE: uid=%d, ", edge->uid);
- fprintf (file, "frequency=%0.4f, ",
- (double)edge->frequency / CGRAPH_FREQ_BASE);
- fprintf (file, "count=" HOST_WIDEST_INT_PRINT_DEC, edge->count);
- if (edge->inline_failed)
- {
- /* Don't print growth for non-inlinable nodes as these may
- ICE in CGRAPH_ESTIMATE_SIZE_AFTER_INLINING. */
- if (node->local.inlinable)
- fprintf (file, ", growth=%d",
- cgraph_estimate_size_after_inlining (1, edge->caller,
- node)
- - edge->caller->global.insns);
- if (flag_dyn_ipa)
- {
- /* For LIPO, if the edge is not entirely within the
- main module, label it as in an auxilliary module or
- as crossmodule. */
+ for (edge = node->callees; edge; edge = edge->next_callee)
+ {
+ int i;
+ for (i = 0; i < indent; i++)
+ fprintf (file, " ");
+ if (!edge->inline_failed)
+ fprintf (file, "[inlined] ");
+ fprintf (file, "%s [callsite #%d]",
+ cgraph_node_name (edge->callee),
+ callsite_position (edge));
+ if (DECL_DECLARED_INLINE_P (edge->callee->decl))
+ fprintf (file, " marked inline");
+ else
+ fprintf (file, " not marked inline");
+ fprintf (file, ", uid %d, size %d, frequency %0.4f",
+ edge->uid, edge->callee->global.insns,
+ (double)edge->frequency / CGRAPH_FREQ_BASE);
+ if (max_count)
+ fprintf (file, ", count " HOST_WIDEST_INT_PRINT_DEC, edge->count);
+ if (edge->inline_failed)
+ {
+ if (edge->callee->local.inlinable)
+ fprintf (file, ", priority %d, inline growth %d, all inline growth %d",
+ cgraph_edge_priority (edge),
+ cgraph_estimate_size_after_inlining (1, edge->caller, edge->callee)
+ - edge->caller->global.insns,
+ cgraph_estimate_growth (edge->callee));
+ if (flag_dyn_ipa)
+ {
+ /* For LIPO, if the edge is not entirely within the
+ main module, label it as in an auxilliary module or
+ as crossmodule. */
unsigned caller_id = cgraph_get_module_id (edge->caller->decl);
unsigned callee_id = cgraph_get_module_id (edge->callee->decl);
if (caller_id == callee_id)
@@ -2512,13 +2637,44 @@ dump_cgraph_info (FILE *file)
else
fprintf (file, "%u", callee_id);
}
- }
- fprintf (file, "\nCALLSITE: not inlined: %s\n",
- edge->inline_failed);
- }
- else
- fprintf (file, "\nCALLSITE: inlined\n");
- }
+ }
+ fprintf (file, ", inlining failed: %s", edge->inline_failed);
+ }
+ fprintf (file, "\n");
+
+ if (!edge->inline_failed)
+ dump_function_inlining_decisions_1 (file, edge->callee, indent + 1);
+ }
+}
+
+/* Dump inlining decisions for all callsites in NODE to FILE. */
+
+static void
+dump_function_inlining_decisions (FILE *file, struct cgraph_node *node)
+{
+ fprintf (file, "%s, uid %d, size %d, %s",
+ cgraph_node_name (node), node->uid, node->global.insns,
+ function_frequency_string (node));
+ if (max_count)
+ fprintf (file, "count " HOST_WIDEST_INT_PRINT_DEC, node->count);
+ if (flag_dyn_ipa && (cgraph_get_module_id (node->decl) != primary_module_id))
+ fprintf (file, ", aux module id %u", cgraph_get_module_id (node->decl));
+ fprintf (file, "\n");
+ dump_function_inlining_decisions_1 (file, node, 1);
+ fprintf (file, "\n");
+}
+
+/* Dump inlining decisions for all callsites in all functions to FILE. */
+
+static void
+dump_cgraph_inlining_decisions (FILE *file)
+{
+ struct cgraph_node *node;
+
+ fprintf (file, "\nInlining decisions:\n");
+ for (node = cgraph_nodes; node; node = node->next)
+ dump_function_inlining_decisions (file, node);
+ fprintf (file, "\n");
}
/* Decide on the inlining. We do so in the topological order to avoid
@@ -2701,22 +2857,19 @@ cgraph_decide_inlining (void)
old_insns = overall_insns;
- if (cgraph_check_inline_limits (node->callers->caller, node,
- NULL, false)
+ if (cgraph_check_inline_constraints (node->callers->caller, node,
+ NULL, false)
&& dbg_cnt (inl))
{
cgraph_mark_inline (node->callers);
if (dump_file)
- {
- fprintf (dump_file, "END FUNCTION_ONCE inlined\n");
- fprintf (dump_file,
- "INFO: %s Inlined into %s which now has %i insns"
- " for a net change of %+i insns.\n",
- cgraph_node_name (node),
- cgraph_node_name (node->callers->caller),
- node->callers->caller->global.insns,
- overall_insns - old_insns);
- }
+ fprintf (dump_file,
+ "INFO: %s Inlined into %s which now has %i insns"
+ " for a net change of %+i insns.\n",
+ cgraph_node_name (node),
+ cgraph_node_name (node->callers->caller),
+ node->callers->caller->global.insns,
+ overall_insns - old_insns);
}
else
{
@@ -2744,8 +2897,8 @@ cgraph_decide_inlining (void)
overall_insns);
if (dump_file && (dump_flags & TDF_DETAILS))
- dump_cgraph_info (dump_file);
-
+ dump_cgraph_inlining_decisions (dump_file);
+
return 0;
}
@@ -3028,8 +3181,8 @@ cgraph_decide_inlining_incrementally (struct cgraph_node *node,
}
continue;
}
- if (!cgraph_check_inline_limits (node, e->callee, &e->inline_failed,
- false)
+ if (!cgraph_check_inline_constraints (node, e->callee, &e->inline_failed,
+ false)
|| gimple_call_cannot_inline_p (e->call_stmt))
{
if (dump_file)
diff --git a/gcc-4.4.3/gcc/ipa-struct-reorg.c b/gcc-4.4.3/gcc/ipa-struct-reorg.c
index 1bf782200..08df79638 100644
--- a/gcc-4.4.3/gcc/ipa-struct-reorg.c
+++ b/gcc-4.4.3/gcc/ipa-struct-reorg.c
@@ -1113,7 +1113,7 @@ create_new_field_access (struct field_access_site *f_acc,
{
tree new_type = field.field_mapping;
gimple new_stmt;
- tree size_res;
+ tree size_res = NULL;
gimple mult_stmt;
gimple cast_stmt;
tree cast_res = NULL;
diff --git a/gcc-4.4.3/gcc/ira.c b/gcc-4.4.3/gcc/ira.c
index 97287f43d..f373b156b 100644
--- a/gcc-4.4.3/gcc/ira.c
+++ b/gcc-4.4.3/gcc/ira.c
@@ -1308,9 +1308,9 @@ setup_prohibited_mode_move_regs (void)
{
if (! HARD_REGNO_MODE_OK (j, i))
continue;
- SET_REGNO (test_reg1, j);
+ SET_REGNO_RAW (test_reg1, j);
PUT_MODE (test_reg1, i);
- SET_REGNO (test_reg2, j);
+ SET_REGNO_RAW (test_reg2, j);
PUT_MODE (test_reg2, i);
INSN_CODE (move_insn) = -1;
recog_memoized (move_insn);
diff --git a/gcc-4.4.3/gcc/l-ipo.c b/gcc-4.4.3/gcc/l-ipo.c
index 121baadc2..1a9232af3 100644
--- a/gcc-4.4.3/gcc/l-ipo.c
+++ b/gcc-4.4.3/gcc/l-ipo.c
@@ -1689,6 +1689,10 @@ process_module_scope_static_func (struct cgraph_node *cnode)
|| DECL_ARTIFICIAL (decl))
return;
+ if (flag_ripa_no_promote_always_inline
+ && lookup_attribute ("always_inline", DECL_ATTRIBUTES (decl)) != NULL)
+ return;
+
if (cgraph_is_auxiliary (cnode->decl))
{
gcc_assert (cgraph_get_module_id (cnode->decl)
diff --git a/gcc-4.4.3/gcc/langhooks-def.h b/gcc-4.4.3/gcc/langhooks-def.h
index b5517ed31..c91eb90f1 100644
--- a/gcc-4.4.3/gcc/langhooks-def.h
+++ b/gcc-4.4.3/gcc/langhooks-def.h
@@ -156,6 +156,7 @@ extern void lhd_omp_firstprivatize_type_sizes (struct gimplify_omp_ctx *,
#define LANG_HOOKS_DECL_IS_BASE_FIELD lhd_do_nothing_t_return_bool
#define LANG_HOOKS_DECL_IS_CONSTRUCTOR lhd_do_nothing_t_return_bool
#define LANG_HOOKS_DECL_IS_DESTRUCTOR lhd_do_nothing_t_return_bool
+#define LANG_HOOKS_DECL_IS_CONST_MEMBER_FUNC lhd_do_nothing_t_return_int
/* Tree dump hooks. */
extern bool lhd_tree_dump_dump_tree (void *, tree);
@@ -330,6 +331,7 @@ extern tree lhd_make_node (enum tree_code);
LANG_HOOKS_DECL_IS_BASE_FIELD, \
LANG_HOOKS_DECL_IS_CONSTRUCTOR, \
LANG_HOOKS_DECL_IS_DESTRUCTOR, \
+ LANG_HOOKS_DECL_IS_CONST_MEMBER_FUNC, \
LANG_HOOKS_BUILTIN_FUNCTION, \
LANG_HOOKS_BUILTIN_FUNCTION_EXT_SCOPE, \
LANG_HOOKS_USER_CONV_FUNCTION, \
diff --git a/gcc-4.4.3/gcc/langhooks.c b/gcc-4.4.3/gcc/langhooks.c
index 5ab62f99d..2af60d151 100644
--- a/gcc-4.4.3/gcc/langhooks.c
+++ b/gcc-4.4.3/gcc/langhooks.c
@@ -114,7 +114,7 @@ lhd_do_nothing_u (unsigned ARG_UNUSED (t))
int
lhd_do_nothing_t_return_int (tree ARG_UNUSED (t))
{
- return false;
+ return 0;
}
bool
diff --git a/gcc-4.4.3/gcc/langhooks.h b/gcc-4.4.3/gcc/langhooks.h
index 45e92ce76..c560cc1bf 100644
--- a/gcc-4.4.3/gcc/langhooks.h
+++ b/gcc-4.4.3/gcc/langhooks.h
@@ -477,6 +477,13 @@ struct lang_hooks
/* Return true if DECL is a destructor. */
bool (*decl_is_destructor) (tree);
+ /* Return
+ 1 if decl is a const member function,
+ 2 if decl is not a const member function but has a const overload that
+ has identical parameter list,
+ 0 otherwise. */
+ int (*decl_is_const_member_func) (tree);
+
/* Do language specific processing in the builtin function DECL */
tree (*builtin_function) (tree decl);
diff --git a/gcc-4.4.3/gcc/libgcov.c b/gcc-4.4.3/gcc/libgcov.c
index 3557b5dd7..9b1c7bb3e 100644
--- a/gcc-4.4.3/gcc/libgcov.c
+++ b/gcc-4.4.3/gcc/libgcov.c
@@ -25,10 +25,29 @@ a copy of the GCC Runtime Library Exception along with this program;
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
+/* Assume compiling for Linux Kernel if __KERNEL__ is defined. */
+#ifdef __KERNEL__
+ /* Define MACROs to be used by kernel compilation. */
+# define L_gcov
+# define L_gcov_interval_profiler
+# define L_gcov_pow2_profiler
+# define L_gcov_one_value_profiler
+# define L_gcov_indirect_call_profiler
+# define L_gcov_average_profiler
+# define L_gcov_ior_profiler
+
+# define TARGET_VTABLE_USES_DESCRIPTORS 0
+# define HAVE_CC_TLS 0
+# define __GCOV_KERNEL__
+
+# define IN_LIBGCOV 1
+# define IN_GCOV 0
+#else /* __KERNEL__ */
#include "tconfig.h"
#include "tsystem.h"
#include "coretypes.h"
#include "tm.h"
+#endif /* __KERNEL__ */
#if HAVE_CC_TLS
#define THREAD_PREFIX __thread
@@ -36,6 +55,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#define THREAD_PREFIX
#endif
+#ifndef __GCOV_KERNEL__
#if defined(inhibit_libc)
#define IN_LIBGCOV (-1)
#else
@@ -46,6 +66,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#define GCOV_LINKAGE /* nothing */
#endif
#endif
+#endif /* __GCOV_KERNEL__ */
+
#include "gcov-io.h"
#if defined(inhibit_libc)
@@ -66,6 +88,12 @@ void __gcov_merge_single (gcov_type *counters __attribute__ ((unused)),
unsigned n_counters __attribute__ ((unused))) {}
#endif
+#ifdef L_gcov_merge_single_float
+void __gcov_merge_single_float (gcov_type *counters __attribute__ ((unused)),
+ unsigned n_counters __attribute__ ((unused))) {}
+#endif
+
+
#ifdef L_gcov_merge_delta
void __gcov_merge_delta (gcov_type *counters __attribute__ ((unused)),
unsigned n_counters __attribute__ ((unused))) {}
@@ -73,22 +101,65 @@ void __gcov_merge_delta (gcov_type *counters __attribute__ ((unused)),
#else
+#ifndef __GCOV_KERNEL__
#include <string.h>
#if GCOV_LOCKED
#include <fcntl.h>
#include <errno.h>
#include <sys/stat.h>
#endif
+#endif /* __GCOV_KERNEL__ */
#ifdef L_gcov
#include "gcov-io.c"
+/* Utility function for outputing errors. */
+static int
+gcov_error (const char *fmt, ...)
+{
+ int ret;
+ va_list argp;
+ va_start (argp, fmt);
+#ifdef __GCOV_KERNEL__
+ ret = vprintk (fmt, argp);
+#else
+ ret = vfprintf (stderr, fmt, argp);
+#endif
+ va_end (argp);
+ return ret;
+}
+
/* Chain of per-object gcov structures. */
extern struct gcov_info *__gcov_list;
+#ifndef __GCOV_KERNEL__
+/* Per thread sample counter. */
+THREAD_PREFIX gcov_unsigned_t __gcov_sample_counter = 0;
+
+/* Emitted in coverage.c. */
+extern char * __gcov_pmu_profile_filename;
+extern char * __gcov_pmu_profile_options;
+extern gcov_unsigned_t __gcov_pmu_top_n_address;
+
+/* Sampling rate. */
+extern gcov_unsigned_t __gcov_sampling_rate;
+static int gcov_sampling_rate_initialized = 0;
+void __gcov_set_sampling_rate (unsigned int rate);
+
+/* Set sampling rate to RATE. */
+
+void __gcov_set_sampling_rate (unsigned int rate)
+{
+ __gcov_sampling_rate = rate;
+}
+
/* Unique identifier assigned to each module (object file). */
static gcov_unsigned_t gcov_cur_module_id = 0;
+/* Size of the longest file name. */
+static size_t gcov_max_filename = 0;
+#endif /* __GCOV_KERNEL__ */
+
/* Pointer to the direct-call counters (per call-site counters).
Initialized by the caller. */
THREAD_PREFIX gcov_type *__gcov_direct_call_counters ATTRIBUTE_HIDDEN;
@@ -107,16 +178,48 @@ THREAD_PREFIX void *__gcov_indirect_call_topn_callee ATTRIBUTE_HIDDEN;
object file included in multiple programs. */
static gcov_unsigned_t gcov_crc32;
-/* Size of the longest file name. */
-static size_t gcov_max_filename = 0;
-
/* Dynamic call graph build and form module groups. */
void __gcov_compute_module_groups (void) ATTRIBUTE_HIDDEN;
void __gcov_finalize_dyn_callgraph (void) ATTRIBUTE_HIDDEN;
+/* Profile summary for the gdca file, used in sanity check? */
+static struct gcov_summary all;
+
+/* Profile summary for this program in current exeuction. */
+static struct gcov_summary this_program;
+
+/* Profile summary for this object in current execuction. */
+static struct gcov_summary this_object;
+
+/* Merged profile summary for this program. */
+static struct gcov_summary program;
+
+/* Merged profile summary for this object. */
+static struct gcov_summary object;
+
+/* Record the position of summary info. */
+static gcov_position_t summary_pos = 0;
+
+/* Record the postion of eof. */
+static gcov_position_t eof_pos = 0;
+
+/* Number of chars in prefix to be stripped. */
+static int gcov_prefix_strip = 0;
+
+/* The length of path prefix. */
+static size_t prefix_length = 0;
+
+/* gi_filename is current object filename.
+ gi_filename_up points to the stripped filename. */
+static char *gi_filename, *gi_filename_up;
+
+static int gcov_open_by_filename (char * gi_filename);
+static int gcov_exit_init (void);
+static void gcov_dump_one_gcov (struct gcov_info *gi_ptr);
+
#ifdef TARGET_POSIX_IO
-/* Make sure path component of the given FILENAME exists, create
- missing directories. FILENAME must be writable.
+/* Make sure path component of the given FILENAME exists, create
+ missing directories. FILENAME must be writable.
Returns zero on success, or -1 if an error occurred. */
static int
@@ -125,7 +228,7 @@ create_file_directory (char *filename)
char *s;
for (s = filename + 1; *s != '\0'; s++)
- if (IS_DIR_SEPARATOR(*s))
+ if (IS_DIR_SEPARATOR (*s))
{
char sep = *s;
*s = '\0';
@@ -136,23 +239,58 @@ create_file_directory (char *filename)
/* The directory might have been made by another process. */
&& errno != EEXIST)
{
- fprintf (stderr, "profiling:%s:Cannot create directory\n",
+ gcov_error ("profiling:%s:Cannot create directory\n",
filename);
*s = sep;
return -1;
};
-
+
*s = sep;
};
return 0;
}
#endif
+/* Open a file with the specified name. */
+
+static int
+gcov_open_by_filename (char * gi_filename)
+{
+ if (!gcov_open (gi_filename))
+ {
+#ifdef TARGET_POSIX_IO
+ /* Open failed likely due to missed directory.
+ Create directory and retry to open file. */
+ if (create_file_directory (gi_filename))
+ {
+ gcov_error ("profiling:%s:Skip\n", gi_filename);
+ return -1;
+ }
+#endif
+ if (!gcov_open (gi_filename))
+ {
+ gcov_error ("profiling:%s:Cannot open\n", gi_filename);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+
+/* Determine whether a counter is active. */
+
+static inline int
+gcov_counter_active (const struct gcov_info *info, unsigned int type)
+{
+ return (1 << type) & info->ctr_mask;
+}
+
+#ifndef __GCOV_KERNEL__
/* Check if VERSION of the info block PTR matches libgcov one.
Return 1 on success, or zero in case of versions mismatch.
- If FILENAME is not NULL, its value used for reporting purposes
+ If FILENAME is not NULL, its value used for reporting purposes
instead of value from the info block. */
-
+
static int
gcov_version (struct gcov_info *ptr, gcov_unsigned_t version,
const char *filename)
@@ -163,15 +301,16 @@ gcov_version (struct gcov_info *ptr, gcov_unsigned_t version,
GCOV_UNSIGNED2STRING (v, version);
GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
-
- fprintf (stderr,
- "profiling:%s:Version mismatch - expected %.4s got %.4s\n",
+
+ gcov_error ("profiling:%s:Version mismatch - expected %.4s got %.4s\n",
filename? filename : ptr->filename, e, v);
return 0;
}
return 1;
}
+#define GCOV_GET_FILENAME gcov_strip_leading_dirs
+
/* Strip GCOV_PREFIX_STRIP levels of leading '/' from FILENAME and
put the result into GI_FILENAME_UP. */
@@ -180,22 +319,22 @@ gcov_strip_leading_dirs (int gcov_prefix_strip, const char *filename,
char *gi_filename_up)
{
/* Build relocated filename, stripping off leading
- directories from the initial filename if requested. */
+ directories from the initial filename if requested. */
if (gcov_prefix_strip > 0)
{
int level = 0;
const char *fname = filename;
const char *s;
- /* Skip selected directory levels. */
+ /* Skip selected directory levels. */
for (s = fname + 1; (*s != '\0') && (level < gcov_prefix_strip); s++)
- if (IS_DIR_SEPARATOR(*s))
+ if (IS_DIR_SEPARATOR (*s))
{
fname = s;
level++;
};
- /* Update complete filename with stripped original. */
+ /* Update complete filename with stripped original. */
strcpy (gi_filename_up, fname);
}
else
@@ -258,7 +397,7 @@ gcov_write_import_file (char *gi_filename, struct gcov_info *gi_ptr)
FILE *imports_file;
size_t prefix_length, suffix_length;
- gcov_suffix = getenv("GCOV_IMPORTS_SUFFIX");
+ gcov_suffix = getenv ("GCOV_IMPORTS_SUFFIX");
if (!gcov_suffix || !strlen (gcov_suffix))
gcov_suffix = ".imports";
suffix_length = strlen (gcov_suffix);
@@ -270,7 +409,7 @@ gcov_write_import_file (char *gi_filename, struct gcov_info *gi_ptr)
imports_file = fopen (gi_imports_filename, "w");
if (imports_file)
{
- const struct gcov_info **imp_mods;
+ const struct dyn_imp_mod **imp_mods;
unsigned i, imp_len;
imp_mods = gcov_get_sorted_import_module_array (gi_ptr, &imp_len);
if (imp_mods)
@@ -278,9 +417,9 @@ gcov_write_import_file (char *gi_filename, struct gcov_info *gi_ptr)
for (i = 0; i < imp_len; i++)
{
fprintf (imports_file, "%s\n",
- imp_mods[i]->mod_info->source_filename);
+ imp_mods[i]->imp_mod->mod_info->source_filename);
fprintf (imports_file, "%s%s\n",
- imp_mods[i]->mod_info->da_filename, GCOV_DATA_SUFFIX);
+ imp_mods[i]->imp_mod->mod_info->da_filename, GCOV_DATA_SUFFIX);
}
free (imp_mods);
}
@@ -288,334 +427,640 @@ gcov_write_import_file (char *gi_filename, struct gcov_info *gi_ptr)
}
}
-/* Dump the coverage counts. We merge with existing counts when
- possible, to avoid growing the .da files ad infinitum. We use this
- program's checksum to make sure we only accumulate whole program
- statistics to the correct summary. An object file might be embedded
- in two separate programs, and we must keep the two program
- summaries separate. */
+/* This function allocates the space to store current file name. */
static void
-gcov_exit (void)
+gcov_alloc_filename (void)
{
- struct gcov_info *gi_ptr;
- struct gcov_summary this_program;
- struct gcov_summary all;
- struct gcov_ctr_summary *cs_ptr;
- const struct gcov_ctr_info *ci_ptr;
- unsigned t_ix;
- gcov_unsigned_t c_num;
- const char *gcov_prefix;
- int gcov_prefix_strip = 0;
- size_t prefix_length;
- char *gi_filename, *gi_filename_up;
- int dump_module_info = 0;
-
- memset (&all, 0, sizeof (all));
- /* Find the totals for this execution. */
- memset (&this_program, 0, sizeof (this_program));
- for (gi_ptr = __gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
- {
- ci_ptr = gi_ptr->counts;
- for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++)
- {
- if (!((1 << t_ix) & gi_ptr->ctr_mask))
- continue;
+ /* Get file name relocation prefix. Non-absolute values are ignored. */
+ char *gcov_prefix = 0;
- cs_ptr = &this_program.ctrs[t_ix];
- cs_ptr->num += ci_ptr->num;
- for (c_num = 0; c_num < ci_ptr->num; c_num++)
- {
- cs_ptr->sum_all += ci_ptr->values[c_num];
- if (cs_ptr->run_max < ci_ptr->values[c_num])
- cs_ptr->run_max = ci_ptr->values[c_num];
- }
- ci_ptr++;
- }
- /* The IS_PRIMARY field is overloaded to indicate if this module
- is FDO/LIPO. */
- dump_module_info |= gi_ptr->mod_info->is_primary;
- }
+ prefix_length = 0;
+ gcov_prefix_strip = 0;
- /* Get file name relocation prefix. Non-absolute values are ignored. */
- gcov_prefix = getenv("GCOV_PREFIX");
+ gcov_prefix = getenv ("GCOV_PREFIX");
if (gcov_prefix && IS_ABSOLUTE_PATH (gcov_prefix))
{
- /* Check if the level of dirs to strip off specified. */
- char *tmp = getenv("GCOV_PREFIX_STRIP");
+ /* Check if the level of dirs to strip off specified. */
+ char *tmp = getenv ("GCOV_PREFIX_STRIP");
if (tmp)
{
gcov_prefix_strip = atoi (tmp);
- /* Do not consider negative values. */
+ /* Do not consider negative values. */
if (gcov_prefix_strip < 0)
gcov_prefix_strip = 0;
}
-
- prefix_length = strlen(gcov_prefix);
- /* Remove an unnecessary trailing '/' */
+ prefix_length = strlen (gcov_prefix);
+
+ /* Remove an unnecessary trailing '/'. */
if (IS_DIR_SEPARATOR (gcov_prefix[prefix_length - 1]))
prefix_length--;
}
- else
- prefix_length = 0;
-
+
/* Allocate and initialize the filename scratch space. */
- gi_filename = (char *) alloca (prefix_length + gcov_max_filename + 1);
+ gi_filename = (char *) malloc (prefix_length + gcov_max_filename + 1);
if (prefix_length)
memcpy (gi_filename, gcov_prefix, prefix_length);
- gi_filename_up = gi_filename + prefix_length;
-
- /* Now merge each file. */
+}
+
+static void
+gcov_dump_module_info (void)
+{
+ struct gcov_info *gi_ptr;
+
+ __gcov_compute_module_groups ();
+
+ /* Now write out module group info. */
for (gi_ptr = __gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
+ {
+ int error;
+
+ gcov_strip_leading_dirs (gcov_prefix_strip, gi_ptr->filename,
+ gi_filename_up);
+ error = gcov_open_by_filename (gi_filename);
+ if (error != 0)
+ continue;
+
+ /* Overwrite the zero word at the of the file. */
+ gcov_rewrite ();
+ gcov_seek (gi_ptr->eof_pos);
+
+ gcov_write_module_infos (gi_ptr);
+ gcov_truncate ();
+
+ if ((error = gcov_close ()))
+ gcov_error (error < 0 ? "profiling:%s:Overflow writing\n" :
+ "profiling:%s:Error writing\n",
+ gi_filename);
+ gcov_write_import_file (gi_filename, gi_ptr);
+ }
+ __gcov_finalize_dyn_callgraph ();
+}
+
+/* Stop the pmu profiler and dump pmu info. GCOV_PREFIX is a string
+ indicating a prefix path of PREFIX_LENGTH. GCOV_PREFIX_STRIP
+ indicates how many leading directories are stripped before
+ constructing filename.
+ */
+
+static void
+pmu_profile_stop (void)
+{
+ char *pmu_gi_filename;
+ char *pmu_gi_filename_up;
+ const char *pmu_profile_filename = __gcov_pmu_profile_filename;
+ const char *pmu_options = __gcov_pmu_profile_options;
+
+ if (!pmu_profile_filename || !pmu_options)
+ return;
+
+ __gcov_stop_pmu_profiler ();
+
+ /* Allocate and initialize the filename scratch space. */
+ pmu_gi_filename = (char *) alloca (prefix_length + strlen (pmu_profile_filename)
+ + 1);
+ if (prefix_length)
{
- struct gcov_summary this_object;
- struct gcov_summary object, program;
- gcov_type *values[GCOV_COUNTERS];
- const struct gcov_fn_info *fi_ptr;
- unsigned fi_stride;
- unsigned c_ix, f_ix, n_counts;
- struct gcov_ctr_summary *cs_obj, *cs_tobj, *cs_prg, *cs_tprg, *cs_all;
- int error = 0;
- gcov_unsigned_t tag, length;
- gcov_position_t summary_pos = 0;
- gcov_position_t eof_pos = 0;
-
- memset (&this_object, 0, sizeof (this_object));
- memset (&object, 0, sizeof (object));
-
- gcov_strip_leading_dirs (gcov_prefix_strip, gi_ptr->filename,
- gi_filename_up);
-
- /* Totals for this object file. */
- ci_ptr = gi_ptr->counts;
- for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++)
+ char *gcov_prefix = getenv ("GCOV_PREFIX");
+ gcc_assert (gcov_prefix);
+ memcpy (pmu_gi_filename, gcov_prefix, prefix_length);
+ }
+ pmu_gi_filename_up = pmu_gi_filename + prefix_length;
+
+ strcpy (pmu_gi_filename, pmu_profile_filename);
+ gcov_strip_leading_dirs (gcov_prefix_strip, pmu_gi_filename,
+ pmu_gi_filename_up);
+
+ /* Open the gcda file for writing. We don't support merge yet. */
+ if (!gcov_open (pmu_gi_filename))
+ {
+#ifdef TARGET_POSIX_IO
+ /* Open failed likely due to missed directory.
+ Create directory and retry to open file. */
+ if (create_file_directory (pmu_gi_filename))
+ {
+ fprintf (stderr, "pmu profiling:%s:Skip\n", pmu_gi_filename);
+ return;
+ }
+#endif
+ if (!gcov_open (pmu_gi_filename))
+ {
+ fprintf (stderr, "pmu profiling:%s:Cannot open\n", pmu_gi_filename);
+ return;
+ }
+ }
+ __gcov_end_pmu_profiler ();
+ gcov_close ();
+}
+
+/* Dump the coverage counts. We merge with existing counts when
+ possible, to avoid growing the .da files ad infinitum. We use this
+ program's checksum to make sure we only accumulate whole program
+ statistics to the correct summary. An object file might be embedded
+ in two separate programs, and we must keep the two program
+ summaries separate. */
+
+static void
+gcov_exit (void)
+{
+ struct gcov_info *gi_ptr;
+ int dump_module_info;
+
+ dump_module_info = gcov_exit_init ();
+
+ /* Stop and write the PMU profile data into the global file. */
+ pmu_profile_stop ();
+
+ for (gi_ptr = __gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
+ gcov_dump_one_gcov (gi_ptr);
+
+ if (dump_module_info)
+ gcov_dump_module_info ();
+
+ free (gi_filename);
+}
+
+/* Add a new object file onto the bb chain. Invoked automatically
+ when running an object file's global ctors. */
+
+void
+__gcov_init (struct gcov_info *info)
+{
+ if (!info->version)
+ return;
+
+ if (gcov_version (info, info->version, 0))
+ {
+ const char *ptr = info->filename;
+ gcov_unsigned_t crc32 = gcov_crc32;
+ size_t filename_length = strlen (info->filename);
+ struct gcov_pmu_info pmu_info;
+
+ /* Refresh the longest file name information. */
+ if (filename_length > gcov_max_filename)
+ gcov_max_filename = filename_length;
+
+ if (!gcov_sampling_rate_initialized)
+ {
+ const char* env_value_str = getenv ("GCOV_SAMPLING_RATE");
+ if (env_value_str)
+ {
+ int env_value_int = atoi (env_value_str);
+ if (env_value_int >= 1)
+ __gcov_set_sampling_rate (env_value_int);
+ }
+ gcov_sampling_rate_initialized = 1;
+ }
+
+ /* Initialize pmu profiler. */
+ pmu_info.pmu_profile_filename = __gcov_pmu_profile_filename;
+ pmu_info.pmu_tool = __gcov_pmu_profile_options;
+ pmu_info.pmu_top_n_address = __gcov_pmu_top_n_address;
+ __gcov_init_pmu_profiler (&pmu_info);
+ if (pmu_info.pmu_profile_filename)
+ {
+ /* Refresh the longest file name information. */
+ filename_length = strlen (pmu_info.pmu_profile_filename);
+ if (filename_length > gcov_max_filename)
+ gcov_max_filename = filename_length;
+ }
+
+ /* Assign the module ID (starting at 1). */
+ info->mod_info->ident = (++gcov_cur_module_id);
+ gcc_assert (EXTRACT_MODULE_ID_FROM_GLOBAL_ID (GEN_FUNC_GLOBAL_ID (
+ info->mod_info->ident, 0))
+ == info->mod_info->ident);
+
+ do
{
- if (!((1 << t_ix) & gi_ptr->ctr_mask))
- continue;
+ unsigned ix;
+ gcov_unsigned_t value = *ptr << 24;
- cs_ptr = &this_object.ctrs[t_ix];
- cs_ptr->num += ci_ptr->num;
- for (c_num = 0; c_num < ci_ptr->num; c_num++)
+ for (ix = 8; ix--; value <<= 1)
{
- cs_ptr->sum_all += ci_ptr->values[c_num];
- if (cs_ptr->run_max < ci_ptr->values[c_num])
- cs_ptr->run_max = ci_ptr->values[c_num];
+ gcov_unsigned_t feedback;
+
+ feedback = (value ^ crc32) & 0x80000000 ? 0x04c11db7 : 0;
+ crc32 <<= 1;
+ crc32 ^= feedback;
}
- ci_ptr++;
- }
+ } while (*ptr++);
- c_ix = 0;
- for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
- if ((1 << t_ix) & gi_ptr->ctr_mask)
+ gcov_crc32 = crc32;
+
+ if (!__gcov_list)
+ {
+ atexit (gcov_exit);
+ /* Start pmu profiler. */
+ __gcov_start_pmu_profiler ();
+ }
+
+ info->next = __gcov_list;
+ __gcov_list = info;
+ }
+ info->version = 0;
+}
+
+/* Called before fork or exec - write out profile information gathered so
+ far and reset it to zero. This avoids duplication or loss of the
+ profile information gathered so far. */
+
+void
+__gcov_flush (void)
+{
+ const struct gcov_info *gi_ptr;
+
+ __gcov_stop_pmu_profiler ();
+ gcov_exit ();
+ for (gi_ptr = __gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
+ {
+ unsigned t_ix;
+ const struct gcov_ctr_info *ci_ptr;
+
+ for (t_ix = 0, ci_ptr = gi_ptr->counts; t_ix != GCOV_COUNTERS; t_ix++)
+ if (gcov_counter_active (gi_ptr, t_ix))
{
- values[c_ix] = gi_ptr->counts[c_ix].values;
- if (t_ix == GCOV_COUNTER_ICALL_TOPNV)
- gcov_sort_icall_topn_counter (&gi_ptr->counts[c_ix]);
- c_ix++;
+ memset (ci_ptr->values, 0, sizeof (gcov_type) * ci_ptr->num);
+ ci_ptr++;
}
+ }
+ __gcov_start_pmu_profiler ();
+}
- /* Calculate the function_info stride. This depends on the
- number of counter types being measured. */
- fi_stride = sizeof (struct gcov_fn_info) + c_ix * sizeof (unsigned);
- if (__alignof__ (struct gcov_fn_info) > sizeof (unsigned))
- {
- fi_stride += __alignof__ (struct gcov_fn_info) - 1;
- fi_stride &= ~(__alignof__ (struct gcov_fn_info) - 1);
- }
-
- if (!gcov_open (gi_filename))
- {
-#ifdef TARGET_POSIX_IO
- /* Open failed likely due to missed directory.
- Create directory and retry to open file. */
- if (create_file_directory (gi_filename))
- {
- fprintf (stderr, "profiling:%s:Skip\n", gi_filename);
- continue;
- }
-#endif
- if (!gcov_open (gi_filename))
- {
- fprintf (stderr, "profiling:%s:Cannot open\n", gi_filename);
- continue;
- }
- }
+#else /* __GCOV_KERNEL__ */
- tag = gcov_read_unsigned ();
- if (tag)
- {
- /* Merge data from file. */
- if (tag != GCOV_DATA_MAGIC)
- {
- fprintf (stderr, "profiling:%s:Not a gcov data file\n",
- gi_filename);
- goto read_fatal;
- }
- length = gcov_read_unsigned ();
- if (!gcov_version (gi_ptr, length, gi_filename))
- goto read_fatal;
-
- length = gcov_read_unsigned ();
- if (length != gi_ptr->stamp)
- /* Read from a different compilation. Overwrite the file. */
- goto rewrite;
-
- /* Merge execution counts for each function. */
- for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++)
- {
- fi_ptr = (const struct gcov_fn_info *)
- ((const char *) gi_ptr->functions + f_ix * fi_stride);
- tag = gcov_read_unsigned ();
- length = gcov_read_unsigned ();
-
- /* Check function. */
- if (tag != GCOV_TAG_FUNCTION
- || gcov_read_unsigned () != fi_ptr->ident
- || gcov_read_unsigned () != fi_ptr->lineno_checksum
- || gcov_read_unsigned () != fi_ptr->cfg_checksum
- || strcmp (gcov_read_string (), fi_ptr->name))
- {
- read_mismatch:;
- fprintf (stderr, "profiling:%s:Merge mismatch for %s\n",
- gi_filename,
- f_ix + 1 ? "function" : "summaries");
- goto read_fatal;
- }
-
- c_ix = 0;
- for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
- {
- gcov_merge_fn merge;
-
- if (!((1 << t_ix) & gi_ptr->ctr_mask))
- continue;
-
- n_counts = fi_ptr->n_ctrs[c_ix];
- merge = gi_ptr->counts[c_ix].merge;
-
- tag = gcov_read_unsigned ();
- length = gcov_read_unsigned ();
- if (tag != GCOV_TAG_FOR_COUNTER (t_ix)
- || length != GCOV_TAG_COUNTER_LENGTH (n_counts))
- goto read_mismatch;
- (*merge) (values[c_ix], n_counts);
- values[c_ix] += n_counts;
- c_ix++;
- }
- if ((error = gcov_is_error ()))
- goto read_error;
- }
+#define GCOV_GET_FILENAME gcov_get_filename
- f_ix = ~0u;
- /* Check program & object summary */
- while (1)
- {
- int is_program;
-
- eof_pos = gcov_position ();
- tag = gcov_read_unsigned ();
- if (!tag)
- break;
-
- length = gcov_read_unsigned ();
- is_program = tag == GCOV_TAG_PROGRAM_SUMMARY;
- if (length != GCOV_TAG_SUMMARY_LENGTH
- || (!is_program && tag != GCOV_TAG_OBJECT_SUMMARY))
- goto read_mismatch;
- gcov_read_summary (is_program ? &program : &object);
- if ((error = gcov_is_error ()))
- goto read_error;
- if (is_program && program.checksum == gcov_crc32)
- {
- summary_pos = eof_pos;
- goto rewrite;
- }
- }
- }
- goto rewrite;
-
- read_error:;
- fprintf (stderr, error < 0 ? "profiling:%s:Overflow merging\n"
- : "profiling:%s:Error merging\n", gi_filename);
-
- read_fatal:;
- gcov_close ();
- continue;
+/* Copy the filename to the buffer. */
- rewrite:;
- gcov_rewrite ();
- if (!summary_pos)
- memset (&program, 0, sizeof (program));
+static inline void
+gcov_get_filename (int gcov_prefix_strip __attribute__ ((unused)),
+ const char *filename, char *gi_filename_up)
+{
+ strcpy (gi_filename_up, filename);
+}
- /* Merge the summaries. */
- f_ix = ~0u;
- for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++)
- {
- cs_obj = &object.ctrs[t_ix];
- cs_tobj = &this_object.ctrs[t_ix];
- cs_prg = &program.ctrs[t_ix];
- cs_tprg = &this_program.ctrs[t_ix];
- cs_all = &all.ctrs[t_ix];
+/* Sort the profile counters for all indirect call sites. Counters
+ for each call site are allocated in array COUNTERS. */
+
+static void
+gcov_sort_icall_topn_counter (const struct gcov_ctr_info *counters)
+{
+ /* Empty */
+}
+
+/* Reserves a buffer to store the name of the file being processed. */
+static char _kernel_gi_filename[520];
+
+/* This function allocates the space to store current file name. */
+
+static void
+gcov_alloc_filename (void)
+{
+ prefix_length = 0;
+ gcov_prefix_strip = 0;
+ gi_filename = _kernel_gi_filename;
+}
+
+#endif /* __GCOV_KERNEL__ */
+
+/* Determine number of active counters in gcov_info INFO,
+ the counter arrays are stored in VALUES if the coming
+ value of VALUES !=0. If FLAG_SORT_ICALL_TOPN_COUNTER !=0,
+ the icall_topn_counter in INFO will be sorted.
+ Return: the number of active counter types. */
+
+static unsigned int
+gcov_counter_array (const struct gcov_info *info,
+ gcov_type *values[GCOV_COUNTERS],
+ int flag_sort_icall_topn_counter)
+{
+ unsigned int i;
+ unsigned int result = 0;
+
+ for (i = 0; i < GCOV_COUNTERS; i++) {
+ if (gcov_counter_active (info, i))
+ {
+ if (values)
+ values[result] = info->counts[result].values;
+ if (flag_sort_icall_topn_counter &&
+ (i == GCOV_COUNTER_ICALL_TOPNV))
+ gcov_sort_icall_topn_counter (&info->counts[result]);
+ result++;
+ }
+ }
+ return result;
+}
+
+/* Compute object summary recored in gcov_info INFO. The result is
+ stored in OBJ_SUM. Note that the caller is responsible for
+ zeroing out OBJ_SUM, otherwise the summary is accumulated. */
+
+static void
+gcov_object_summary (struct gcov_info *info,
+ struct gcov_summary *obj_sum)
+{
+ const struct gcov_ctr_info *ci_ptr;
+ struct gcov_ctr_summary *cs_ptr;
+ gcov_unsigned_t c_num;
+ unsigned t_ix;
+
+ /* Totals for this object file. */
+ ci_ptr = info->counts;
+ for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++)
+ {
+ if (!gcov_counter_active (info, t_ix))
+ continue;
+
+ cs_ptr = &(obj_sum->ctrs[t_ix]);
+ cs_ptr->num += ci_ptr->num;
+ for (c_num = 0; c_num < ci_ptr->num; c_num++)
+ {
+ cs_ptr->sum_all += ci_ptr->values[c_num];
+ if (cs_ptr->run_max < ci_ptr->values[c_num])
+ cs_ptr->run_max = ci_ptr->values[c_num];
+ }
+ ci_ptr++;
+ }
+}
+
+/* Merge with existing gcda file in the same directory to avoid
+ excessive growthe of the files. */
+
+static int
+gcov_merge_gcda_file (struct gcov_info *info,
+ gcov_type *values[GCOV_COUNTERS],
+ unsigned fi_stride)
+{
+ struct gcov_ctr_summary *cs_obj, *cs_tobj, *cs_prg, *cs_tprg, *cs_all;
+ unsigned t_ix, f_ix;
+
+#ifndef __GCOV_KERNEL__
+ const struct gcov_fn_info *fi_ptr;
+ unsigned c_ix, n_counts;
+ int error = 0;
+ gcov_unsigned_t tag, length;
+
+ tag = gcov_read_unsigned ();
+ if (tag)
+ {
+ /* Merge data from file. */
+ if (tag != GCOV_DATA_MAGIC)
+ {
+ gcov_error ("profiling:%s:Not a gcov data file\n", gi_filename);
+ goto read_fatal;
+ }
+ length = gcov_read_unsigned ();
+ if (!gcov_version (info, length, gi_filename))
+ goto read_fatal;
+
+ length = gcov_read_unsigned ();
+ if (length != info->stamp)
+ /* Read from a different compilation. Overwrite the file. */
+ goto rewrite;
+
+ /* Merge execution counts for each function. */
+ for (f_ix = 0; f_ix < info->n_functions; f_ix++)
+ {
+ fi_ptr = (const struct gcov_fn_info *)
+ ((const char *) info->functions + f_ix * fi_stride);
+ tag = gcov_read_unsigned ();
+ length = gcov_read_unsigned ();
+
+ /* Check function. */
+ if (tag != GCOV_TAG_FUNCTION
+ || gcov_read_unsigned () != fi_ptr->ident
+ || gcov_read_unsigned () != fi_ptr->lineno_checksum
+ || gcov_read_unsigned () != fi_ptr->cfg_checksum
+ || strcmp (gcov_read_string (), fi_ptr->name))
+ goto read_mismatch;
+
+ c_ix = 0;
+ for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
+ {
+ gcov_merge_fn merge;
+
+ if (!((1 << t_ix) & info->ctr_mask))
+ continue;
+
+ n_counts = fi_ptr->n_ctrs[c_ix];
+ merge = info->counts[c_ix].merge;
+
+ tag = gcov_read_unsigned ();
+ length = gcov_read_unsigned ();
+ if (tag != GCOV_TAG_FOR_COUNTER (t_ix)
+ || length != GCOV_TAG_COUNTER_LENGTH (n_counts))
+ goto read_mismatch;
+ (*merge) (values[c_ix], n_counts);
+ values[c_ix] += n_counts;
+ c_ix++;
+ }
+ if ((error = gcov_is_error ()))
+ goto read_error;
+ }
+
+ f_ix = ~0u;
+ /* Check program & object summary. */
+ while (1)
+ {
+ int is_program;
+
+ eof_pos = gcov_position ();
+ tag = gcov_read_unsigned ();
+ if (!tag)
+ break;
+
+ length = gcov_read_unsigned ();
+ is_program = tag == GCOV_TAG_PROGRAM_SUMMARY;
+ if (length != GCOV_TAG_SUMMARY_LENGTH
+ || (!is_program && tag != GCOV_TAG_OBJECT_SUMMARY))
+ goto read_mismatch;
+ gcov_read_summary (is_program ? &program : &object);
+ if ((error = gcov_is_error ()))
+ goto read_error;
+ if (is_program && program.checksum == gcov_crc32)
+ {
+ summary_pos = eof_pos;
+ goto rewrite;
+ }
+ }
+ }
+
+ goto rewrite;
+
+read_error:;
+ gcov_error (error < 0 ? "profiling:%s:Overflow merging\n"
+ : "profiling:%s:Error merging\n", gi_filename);
+ goto read_fatal;
+
+#endif /* __GCOV_KERNEL__ */
+
+ goto rewrite;
+
+read_mismatch:;
+ gcov_error ("profiling:%s:Merge mismatch for %s\n", gi_filename,
+ f_ix + 1 ? "function" : "summaries");
+ goto read_fatal; /* work-around the compiler warning */
+
+read_fatal:;
+ gcov_close ();
+ return 1;
+
+rewrite:;
+ gcov_rewrite ();
+ if (!summary_pos)
+ memset (&program, 0, sizeof (program));
+
+ /* Merge the summaries. */
+ f_ix = ~0u;
+ for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++)
+ {
+ cs_obj = &object.ctrs[t_ix];
+ cs_tobj = &this_object.ctrs[t_ix];
+ cs_prg = &program.ctrs[t_ix];
+ cs_tprg = &this_program.ctrs[t_ix];
+ cs_all = &all.ctrs[t_ix];
+
+ if ((1 << t_ix) & info->ctr_mask)
+ {
+ if (!cs_obj->runs++)
+ cs_obj->num = cs_tobj->num;
+ else if (cs_obj->num != cs_tobj->num)
+ goto read_mismatch;
+ cs_obj->sum_all += cs_tobj->sum_all;
+ if (cs_obj->run_max < cs_tobj->run_max)
+ cs_obj->run_max = cs_tobj->run_max;
+ cs_obj->sum_max += cs_tobj->run_max;
+
+ if (!cs_prg->runs++)
+ cs_prg->num = cs_tprg->num;
+ else if (cs_prg->num != cs_tprg->num)
+ goto read_mismatch;
+ cs_prg->sum_all += cs_tprg->sum_all;
+ if (cs_prg->run_max < cs_tprg->run_max)
+ cs_prg->run_max = cs_tprg->run_max;
+ cs_prg->sum_max += cs_tprg->run_max;
+ }
+ else if (cs_obj->num || cs_prg->num)
+ goto read_mismatch;
+
+ if (!cs_all->runs && cs_prg->runs)
+ memcpy (cs_all, cs_prg, sizeof (*cs_all));
+ else if (!all.checksum
+ && (!GCOV_LOCKED || cs_all->runs == cs_prg->runs)
+ && memcmp (cs_all, cs_prg, sizeof (*cs_all)))
+ {
+ gcov_error ("profiling:%s:Invocation mismatch - "
+ "some data files may have been removed%s",
+ gi_filename, GCOV_LOCKED
+ ? "" : " or concurrent update without locking support");
+ all.checksum = ~0u;
+ }
+ }
+
+ return 0;
+}
+
+/* Calculate the function_info stride. This depends on the
+ number of counter types being measured.
+ NUM_COUNTER_TYPES is number of counter types recorded.
+ Return: the number of bytes for accessing next fn_info
+ (aligned to gcov_fn_info). */
+
+static unsigned
+gcov_compute_fi_stride (unsigned num_counter_types)
+{
+ unsigned fi_stride;
+
+ fi_stride = sizeof (struct gcov_fn_info) +
+ num_counter_types * sizeof (unsigned);
+ if (__alignof__ (struct gcov_fn_info) > sizeof (unsigned))
+ {
+ fi_stride += __alignof__ (struct gcov_fn_info) - 1;
+ fi_stride &= ~(__alignof__ (struct gcov_fn_info) - 1);
+ }
+ return fi_stride;
+}
+
+/* This function returns the size of gcda file to be written. Note
+ the size is in units of gcov_type. */
+
+GCOV_LINKAGE unsigned
+gcov_gcda_file_size (struct gcov_info *gi_ptr)
+{
+ unsigned size;
+ const struct gcov_fn_info *fi_ptr;
+ unsigned f_ix, t_ix, c_ix;
+ unsigned n_counts;
+ unsigned fi_stride;
+ gcov_type *values[GCOV_COUNTERS];
+
+ c_ix = gcov_counter_array (gi_ptr, values, 0);
+ fi_stride = gcov_compute_fi_stride (c_ix);
+
+ /* GCOV_DATA_MAGIC, GCOV_VERSION and time_stamp. */
+ size = 3;
+
+ /* size for each function. */
+ for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++)
+ {
+ fi_ptr = (const struct gcov_fn_info *)
+ ((const char *) gi_ptr->functions + f_ix * fi_stride);
+
+ size += 2 /* tag_length itself */
+ + GCOV_TAG_FUNCTION_LENGTH /* ident, lineo_cksum, cfg_cksum */
+ + gcov_string_length (fi_ptr->name);
- if ((1 << t_ix) & gi_ptr->ctr_mask)
- {
- if (!cs_obj->runs++)
- cs_obj->num = cs_tobj->num;
- else if (cs_obj->num != cs_tobj->num)
- goto read_mismatch;
- cs_obj->sum_all += cs_tobj->sum_all;
- if (cs_obj->run_max < cs_tobj->run_max)
- cs_obj->run_max = cs_tobj->run_max;
- cs_obj->sum_max += cs_tobj->run_max;
-
- if (!cs_prg->runs++)
- cs_prg->num = cs_tprg->num;
- else if (cs_prg->num != cs_tprg->num)
- goto read_mismatch;
- cs_prg->sum_all += cs_tprg->sum_all;
- if (cs_prg->run_max < cs_tprg->run_max)
- cs_prg->run_max = cs_tprg->run_max;
- cs_prg->sum_max += cs_tprg->run_max;
- }
- else if (cs_obj->num || cs_prg->num)
- goto read_mismatch;
-
- if (!cs_all->runs && cs_prg->runs)
- memcpy (cs_all, cs_prg, sizeof (*cs_all));
- else if (!all.checksum
- && (!GCOV_LOCKED || cs_all->runs == cs_prg->runs)
- && memcmp (cs_all, cs_prg, sizeof (*cs_all)))
- {
- fprintf (stderr, "profiling:%s:Invocation mismatch - some data files may have been removed%s",
- gi_filename, GCOV_LOCKED
- ? "" : " or concurrent update without locking support");
- all.checksum = ~0u;
- }
- }
-
c_ix = 0;
for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
- if ((1 << t_ix) & gi_ptr->ctr_mask)
- {
- values[c_ix] = gi_ptr->counts[c_ix].values;
- c_ix++;
- }
+ {
+ if (!((1 << t_ix) & gi_ptr->ctr_mask))
+ continue;
+
+ n_counts = fi_ptr->n_ctrs[c_ix];
+ size += 2 + GCOV_TAG_COUNTER_LENGTH (n_counts);
+ c_ix++;
+ }
+ }
+
+ /* Object summary. */
+ size += 2 + GCOV_TAG_SUMMARY_LENGTH;
+
+ /* Program summary. */
+ size += 2 + GCOV_TAG_SUMMARY_LENGTH;
+
+ size += 1;
+
+ return size*4;
+}
+
+/* Write profile data (including summary and module grouping information,
+ if available, to file. */
+
+static void
+gcov_write_gcda_file (struct gcov_info *gi_ptr,
+ unsigned fi_stride)
+{
+ const struct gcov_fn_info *fi_ptr;
+ gcov_type *values[GCOV_COUNTERS];
+ unsigned t_ix, c_ix, f_ix, n_counts;
+ int error = 0;
- program.checksum = gcov_crc32;
-
/* Write out the data. */
gcov_write_tag_length (GCOV_DATA_MAGIC, GCOV_VERSION);
gcov_write_unsigned (gi_ptr->stamp);
-
+
+ gcov_counter_array (gi_ptr, values, 0);
+
/* Write execution counts for each function. */
for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++)
- {
+ {
fi_ptr = (const struct gcov_fn_info *)
((const char *) gi_ptr->functions + f_ix * fi_stride);
/* Announce function. */
- gcov_write_tag_length
+ gcov_write_tag_length
(GCOV_TAG_FUNCTION,
GCOV_TAG_FUNCTION_LENGTH + gcov_string_length (fi_ptr->name));
gcov_write_unsigned (fi_ptr->ident);
@@ -632,7 +1077,7 @@ gcov_exit (void)
continue;
n_counts = fi_ptr->n_ctrs[c_ix];
-
+
gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix),
GCOV_TAG_COUNTER_LENGTH (n_counts));
c_ptr = values[c_ix];
@@ -642,12 +1087,13 @@ gcov_exit (void)
values[c_ix] = c_ptr;
c_ix++;
}
- }
+ }
/* Object file summary. */
gcov_write_summary (GCOV_TAG_OBJECT_SUMMARY, &object);
/* Generate whole program statistics. */
+ program.checksum = gcov_crc32;
if (eof_pos)
gcov_seek (eof_pos);
gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, &program);
@@ -666,133 +1112,75 @@ gcov_exit (void)
gi_ptr->eof_pos = gcov_position ();
if ((error = gcov_close ()))
- fprintf (stderr, error < 0 ?
+ gcov_error (error < 0 ?
"profiling:%s:Overflow writing\n" :
"profiling:%s:Error writing\n",
gi_filename);
+}
- }
+/* Do some preparation work before calling the actual dumping
+ routine.
+ Return: 1 when module grouping info needs to be dumped,
+ 0 otherwise. */
- if (!dump_module_info)
- return;
+static int
+gcov_exit_init (void)
+{
+ struct gcov_info *gi_ptr;
+ int dump_module_info = 0;
- __gcov_compute_module_groups ();
+ dump_module_info = 0;
+ gcov_prefix_strip = 0;
- /* Now write out module group info. */
- for (gi_ptr = __gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
- {
- int error;
- gcov_strip_leading_dirs (gcov_prefix_strip, gi_ptr->filename,
- gi_filename_up);
+ memset (&all, 0, sizeof (all));
- if (!gcov_open (gi_filename))
- {
-#ifdef TARGET_POSIX_IO
- /* Open failed likely due to missed directory.
- Create directory and retry to open file. */
- if (create_file_directory (gi_filename))
- {
- fprintf (stderr, "profiling:%s:Skip\n", gi_filename);
- continue;
- }
-#endif
- if (!gcov_open (gi_filename))
- {
- fprintf (stderr, "profiling:%s:Cannot open\n", gi_filename);
- continue;
- }
- }
+ /* Find the totals for this execution. */
+ memset (&this_program, 0, sizeof (this_program));
+ for (gi_ptr = __gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
+ {
+ gcov_object_summary (gi_ptr, &this_program);
- /* Overwrite the zero word at the of the file. */
- gcov_rewrite ();
- gcov_seek (gi_ptr->eof_pos);
+ /* The IS_PRIMARY field is overloaded to indicate if this module
+ is FDO/LIPO. */
+ dump_module_info |= gi_ptr->mod_info->is_primary;
+ }
- gcov_write_module_infos (gi_ptr);
- gcov_truncate ();
+ gcov_alloc_filename ();
+ gi_filename_up = gi_filename + prefix_length;
- if ((error = gcov_close ()))
- fprintf (stderr, error < 0 ?
- "profiling:%s:Overflow writing\n" :
- "profiling:%s:Error writing\n",
- gi_filename);
- gcov_write_import_file (gi_filename, gi_ptr);
- }
- __gcov_finalize_dyn_callgraph ();
+ return dump_module_info;
}
-/* Add a new object file onto the bb chain. Invoked automatically
- when running an object file's global ctors. */
+/* Dump one entry in the gcov_info list (for one object). */
-void
-__gcov_init (struct gcov_info *info)
+static void
+gcov_dump_one_gcov (struct gcov_info *gi_ptr)
{
- if (!info->version)
- return;
- if (gcov_version (info, info->version, 0))
- {
- const char *ptr = info->filename;
- gcov_unsigned_t crc32 = gcov_crc32;
- size_t filename_length = strlen(info->filename);
+ gcov_type *values[GCOV_COUNTERS];
+ unsigned fi_stride;
+ unsigned c_ix;
+ int ret;
- /* Refresh the longest file name information */
- if (filename_length > gcov_max_filename)
- gcov_max_filename = filename_length;
+ memset (&this_object, 0, sizeof (this_object));
+ memset (&object, 0, sizeof (object));
- /* Assign the module ID (starting at 1). */
- info->mod_info->ident = (++gcov_cur_module_id);
- gcc_assert (EXTRACT_MODULE_ID_FROM_GLOBAL_ID (GEN_FUNC_GLOBAL_ID (
- info->mod_info->ident, 0))
- == info->mod_info->ident);
+ gcov_object_summary (gi_ptr, &this_object);
- do
- {
- unsigned ix;
- gcov_unsigned_t value = *ptr << 24;
+ c_ix = gcov_counter_array (gi_ptr, values, 1);
- for (ix = 8; ix--; value <<= 1)
- {
- gcov_unsigned_t feedback;
+ fi_stride = gcov_compute_fi_stride (c_ix);
- feedback = (value ^ crc32) & 0x80000000 ? 0x04c11db7 : 0;
- crc32 <<= 1;
- crc32 ^= feedback;
- }
- }
- while (*ptr++);
-
- gcov_crc32 = crc32;
-
- if (!__gcov_list)
- atexit (gcov_exit);
-
- info->next = __gcov_list;
- __gcov_list = info;
- }
- info->version = 0;
-}
+ GCOV_GET_FILENAME (gcov_prefix_strip, gi_ptr->filename,
+ gi_filename_up);
-/* Called before fork or exec - write out profile information gathered so
- far and reset it to zero. This avoids duplication or loss of the
- profile information gathered so far. */
+ if (gcov_open_by_filename (gi_filename) == -1)
+ return;
-void
-__gcov_flush (void)
-{
- const struct gcov_info *gi_ptr;
+ /* Now merge this file. */
+ ret = gcov_merge_gcda_file (gi_ptr, values, fi_stride);
+ if (ret != 0 ) return;
- gcov_exit ();
- for (gi_ptr = __gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
- {
- unsigned t_ix;
- const struct gcov_ctr_info *ci_ptr;
-
- for (t_ix = 0, ci_ptr = gi_ptr->counts; t_ix != GCOV_COUNTERS; t_ix++)
- if ((1 << t_ix) & gi_ptr->ctr_mask)
- {
- memset (ci_ptr->values, 0, sizeof (gcov_type) * ci_ptr->num);
- ci_ptr++;
- }
- }
+ gcov_write_gcda_file (gi_ptr, fi_stride);
}
#endif /* L_gcov */
@@ -821,6 +1209,59 @@ __gcov_merge_ior (gcov_type *counters, unsigned n_counters)
}
#endif
+#ifdef L_gcov_merge_reusedist
+
+/* Return the weighted arithmetic mean of two values. */
+
+static gcov_type
+__gcov_weighted_mean2 (gcov_type value1, gcov_type count1,
+ gcov_type value2, gcov_type count2)
+{
+ if (count1 + count2 == 0)
+ return 0;
+ else
+ return (value1 * count1 + value2 * count2) / (count1 + count2);
+}
+
+void
+__gcov_merge_reusedist (gcov_type *counters, unsigned n_counters)
+{
+ unsigned i;
+
+ gcc_assert (!(n_counters % 4));
+
+ for (i = 0; i < n_counters; i += 4)
+ {
+ /* Decode current values. */
+ gcov_type c_mean_dist = counters[i];
+ gcov_type c_mean_size = counters[i+1];
+ gcov_type c_count = counters[i+2];
+ gcov_type c_dist_x_size = counters[i+3];
+
+ /* Read and decode values in file. */
+ gcov_type f_mean_dist = __gcov_read_counter ();
+ gcov_type f_mean_size = __gcov_read_counter ();
+ gcov_type f_count = __gcov_read_counter ();
+ gcov_type f_dist_x_size = __gcov_read_counter ();
+
+ /* Compute aggregates. */
+ gcov_type a_mean_dist = __gcov_weighted_mean2 (
+ f_mean_dist, f_count, c_mean_dist, c_count);
+ gcov_type a_mean_size = __gcov_weighted_mean2 (
+ f_mean_size, f_count, c_mean_size, c_count);
+ gcov_type a_count = f_count + c_count;
+ gcov_type a_dist_x_size = f_dist_x_size + c_dist_x_size;
+
+ /* Encode back into counters. */
+ counters[i] = a_mean_dist;
+ counters[i+1] = a_mean_size;
+ counters[i+2] = a_count;
+ counters[i+3] = a_dist_x_size;
+ }
+}
+
+#endif
+
#ifdef L_gcov_merge_dc
/* Returns 1 if the function global id GID is not valid. */
@@ -866,7 +1307,7 @@ __gcov_merge_dc (gcov_type *counters, unsigned n_counters)
counters[i + 1] += call_count;
- /* Reset. */
+ /* Reset. */
if (__gcov_is_gid_insane (counters[i]))
counters[i] = counters[i + 1] = 0;
@@ -895,7 +1336,7 @@ __gcov_merge_icall_topn (gcov_type *counters, unsigned n_counters)
{
gcov_type *value_array = &counters[i + 1];
unsigned tmp_size = 2 * (GCOV_ICALL_TOPN_NCOUNTS - 1);
- gcov_type *tmp_array
+ gcov_type *tmp_array
= (gcov_type *) alloca (tmp_size * sizeof (gcov_type));
for (j = 0; j < tmp_size; j++)
@@ -930,10 +1371,10 @@ __gcov_merge_icall_topn (gcov_type *counters, unsigned n_counters)
j += 2;
}
}
- /* Now sort the temp array */
+ /* Now sort the temp array. */
gcov_sort_n_vals (tmp_array, j);
- /* Now copy back the top half of the temp array */
+ /* Now copy back the top half of the temp array. */
for (k = 0; k < GCOV_ICALL_TOPN_NCOUNTS - 1; k += 2)
{
value_array[k] = tmp_array[k];
@@ -943,19 +1384,18 @@ __gcov_merge_icall_topn (gcov_type *counters, unsigned n_counters)
}
#endif
-
-#ifdef L_gcov_merge_single
+#if defined (L_gcov_merge_single_float) || defined (L_gcov_merge_single)
/* The profile merging function for choosing the most common value.
It is given an array COUNTERS of N_COUNTERS old counters and it
reads the same number of counters from the gcov file. The counters
are split into 3-tuples where the members of the tuple have
meanings:
-
+
-- the stored candidate on the most common value of the measured entity
-- counter
-- total number of evaluations of the value */
-void
-__gcov_merge_single (gcov_type *counters, unsigned n_counters)
+static void
+__gcov_merge_single_gcov_impl (gcov_type *counters, unsigned n_counters)
{
unsigned i, n_measures;
gcov_type value, counter, all;
@@ -980,6 +1420,22 @@ __gcov_merge_single (gcov_type *counters, unsigned n_counters)
counters[2] += all;
}
}
+#endif
+
+#ifdef L_gcov_merge_single_float
+void
+__gcov_merge_single_float (gcov_type *counters, unsigned n_counters)
+{
+ __gcov_merge_single_gcov_impl (counters, n_counters);
+}
+#endif /* L_gcov_merge_single_float */
+
+#ifdef L_gcov_merge_single
+void
+__gcov_merge_single (gcov_type *counters, unsigned n_counters)
+{
+ __gcov_merge_single_gcov_impl (counters, n_counters);
+}
#endif /* L_gcov_merge_single */
#ifdef L_gcov_merge_delta
@@ -988,7 +1444,7 @@ __gcov_merge_single (gcov_type *counters, unsigned n_counters)
given an array COUNTERS of N_COUNTERS old counters and it reads the
same number of counters from the gcov file. The counters are split
into 4-tuples where the members of the tuple have meanings:
-
+
-- the last value of the measured entity
-- the stored candidate on the most common difference
-- counter
@@ -1134,14 +1590,14 @@ __gcov_topn_value_profiler_body (gcov_type *counters, gcov_type value,
#define GCOV_ICALL_COUNTER_CLEAR_THRESHOLD 3000
- /* Too many evictions -- time to clear bottom entries to
+ /* Too many evictions -- time to clear bottom entries to
avoid hot values bumping each other out. */
- if ( !have_zero_count
+ if ( !have_zero_count
&& ++*num_eviction >= GCOV_ICALL_COUNTER_CLEAR_THRESHOLD)
{
unsigned i, j;
gcov_type *p, minv;
- gcov_type* tmp_cnts
+ gcov_type* tmp_cnts
= (gcov_type *)alloca (topn_val * sizeof(gcov_type));
*num_eviction = 0;
@@ -1150,14 +1606,14 @@ __gcov_topn_value_profiler_body (gcov_type *counters, gcov_type value,
tmp_cnts[i] = 0;
/* Find the largest topn_val values from the group of
- 2*topn_val values and put them into tmp_cnts. */
+ 2*topn_val values and put them into tmp_cnts. */
- for ( i = 0; i < 2 * topn_val; i += 2 )
+ for ( i = 0; i < 2 * topn_val; i += 2 )
{
p = 0;
- for ( j = 0; j < topn_val; j++ )
+ for ( j = 0; j < topn_val; j++ )
{
- if ( !p || tmp_cnts[j] < *p )
+ if ( !p || tmp_cnts[j] < *p )
p = &tmp_cnts[j];
}
if ( value_array[i + 1] > *p )
@@ -1173,7 +1629,7 @@ __gcov_topn_value_profiler_body (gcov_type *counters, gcov_type value,
/* Zero out low value entries */
for ( i = 0; i < 2 * topn_val; i += 2 )
{
- if (value_array[i + 1] < minv)
+ if (value_array[i + 1] < minv)
{
value_array[i] = 0;
value_array[i + 1] = 0;
@@ -1191,10 +1647,19 @@ __gcov_one_value_profiler (gcov_type *counters, gcov_type value)
}
#endif
+#ifdef L_gcov_one_float_value_profiler
+
+void
+__gcov_one_float_value_profiler (gcov_type *counters, gcov_float_t value)
+{
+ __gcov_one_value_profiler_body (counters, gcov_float_to_type(value));
+}
+#endif
+
#ifdef L_gcov_indirect_call_profiler
-/* Tries to determine the most common value among its inputs. */
+/* Tries to determine the most common value among its inputs. */
void
-__gcov_indirect_call_profiler (gcov_type* counter, gcov_type value,
+__gcov_indirect_call_profiler (gcov_type* counter, gcov_type value,
void* cur_func, void* callee_func)
{
/* If the C++ virtual tables contain function descriptors then one
@@ -1225,7 +1690,7 @@ __gcov_indirect_call_topn_profiler (void *cur_func,
|| (TARGET_VTABLE_USES_DESCRIPTORS && callee_func
&& *(void **) cur_func == *(void **) callee_func))
{
- gcov_type global_id
+ gcov_type global_id
= ((struct gcov_info *) cur_module_gcov_info)->mod_info->ident;
global_id = GEN_FUNC_GLOBAL_ID (global_id, cur_func_id);
__gcov_topn_value_profiler_body (counter, global_id, GCOV_ICALL_TOPN_VAL);
@@ -1238,7 +1703,7 @@ __gcov_indirect_call_topn_profiler (void *cur_func,
#ifdef L_gcov_direct_call_profiler
extern THREAD_PREFIX gcov_type *__gcov_direct_call_counters ATTRIBUTE_HIDDEN;
extern THREAD_PREFIX void *__gcov_direct_call_callee ATTRIBUTE_HIDDEN;
-/* Direct call profiler. */
+/* Direct call profiler. */
void
__gcov_direct_call_profiler (void *cur_func,
void *cur_module_gcov_info,
@@ -1246,7 +1711,7 @@ __gcov_direct_call_profiler (void *cur_func,
{
if (cur_func == __gcov_direct_call_callee)
{
- gcov_type global_id
+ gcov_type global_id
= ((struct gcov_info *) cur_module_gcov_info)->mod_info->ident;
global_id = GEN_FUNC_GLOBAL_ID (global_id, cur_func_id);
__gcov_direct_call_counters[0] = global_id;
@@ -1422,4 +1887,99 @@ __gcov_execve (const char *path, char *const argv[], char *const envp[])
return execve (path, argv, envp);
}
#endif
+
+#ifdef __GCOV_KERNEL__
+/*
+ * Provide different implementation for the following functions:
+ * __gcov_init
+ * __gcov_exit
+ *
+ * Provide the following dummy merge functions:
+ * __gcov_merge_add
+ * __gcov_merge_single
+ * __gcov_merge_delta
+ * __gcov_merge_ior
+ * __gcov_merge_icall_topn
+ * __gcov_merge_dc
+ * __gcov_merge_reusedist
+ *
+ * Reuse the following functions:
+ * __gcov_interval_profiler()
+ * __gcov_pow2_profiler()
+ * __gcov_average_profiler()
+ * __gcov_ior_profiler()
+ * __gcov_one_value_profiler()
+ * __gcov_indirect_call_profiler()
+ * |-> __gcov_one_value_profiler_body()
+ *
+ * For LIPO: (TBD)
+ * Change slightly for the following functions:
+ * __gcov_merge_icall_topn
+ * __gcov_merge_dc
+ *
+ * Reuse the following functions:
+ * __gcov_direct_call_profiler()
+ * __gcov_indirect_call_topn_profiler()
+ * |-> __gcov_topn_value_profiler_body()
+ *
+ */
+
+/* Current virual gcda file. This is for kernel use only. */
+gcov_kernel_vfile *gcov_current_file;
+
+/* Set current virutal gcda file. It needs to be set before dumping
+ profile data. */
+
+void
+gcov_set_vfile (gcov_kernel_vfile *file)
+{
+ gcov_current_file = file;
+}
+
+/* Dump one entry in the gcov_info list (for one object) in kernel. */
+
+void
+gcov_kernel_dump_one_gcov (struct gcov_info *info)
+{
+ gcc_assert (gcov_current_file);
+
+ gcov_exit_init ();
+
+ gcov_dump_one_gcov (info);
+}
+
+#define DUMMY_FUNC(func) \
+void func (gcov_type *counters __attribute__ ((unused)), \
+ unsigned n_counters __attribute__ ((unused))) {}
+
+DUMMY_FUNC (__gcov_merge_add)
+EXPORT_SYMBOL (__gcov_merge_add);
+
+DUMMY_FUNC (__gcov_merge_single)
+EXPORT_SYMBOL (__gcov_merge_single);
+
+DUMMY_FUNC (__gcov_merge_delta)
+EXPORT_SYMBOL (__gcov_merge_delta);
+
+DUMMY_FUNC(__gcov_merge_ior)
+EXPORT_SYMBOL (__gcov_merge_ior);
+
+DUMMY_FUNC (__gcov_merge_icall_topn)
+EXPORT_SYMBOL (__gcov_merge_icall_topn);
+
+DUMMY_FUNC (__gcov_merge_dc)
+EXPORT_SYMBOL (__gcov_merge_dc);
+
+DUMMY_FUNC (__gcov_merge_reusedist)
+EXPORT_SYMBOL (__gcov_merge_reusedist);
+
+EXPORT_SYMBOL (__gcov_average_profiler);
+EXPORT_SYMBOL (__gcov_indirect_call_profiler);
+EXPORT_SYMBOL (__gcov_interval_profiler);
+EXPORT_SYMBOL (__gcov_ior_profiler);
+EXPORT_SYMBOL (__gcov_one_value_profiler);
+EXPORT_SYMBOL (__gcov_pow2_profiler);
+
+#endif /* __GCOV_KERNEL__ */
+
#endif /* inhibit_libc */
diff --git a/gcc-4.4.3/gcc/mversn-dispatch.c b/gcc-4.4.3/gcc/mversn-dispatch.c
new file mode 100644
index 000000000..97ccb2ec8
--- /dev/null
+++ b/gcc-4.4.3/gcc/mversn-dispatch.c
@@ -0,0 +1,1705 @@
+/* Mulitversion Dispatch Pass.
+ Copyright (C) 2010 Free Software Foundation, Inc.
+ Contributed by Sriraman Tallam (tmsriram@google.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 processes __builtin_dispatch calls to call multi-versioned
+ functions. Only two versions are supported now. Example use :
+
+ int popcnt_sse4(unsigned int x) __attribute__((__target__("popcnt")));
+ int popcnt_sse4(unsigned int x)
+ {
+ int count = __builtin_popcount(x);
+ return count;
+ }
+
+ int popcnt(unsigned int x) __attribute__((__target__("no-popcnt")));
+ int popcnt(unsigned int x)
+ {
+ int count = __builtin_popcount(x);
+ return count;
+ }
+
+ int testsse() __attribute__((version_selector));
+ int main ()
+ {
+ ...
+ ret = __builtin_dispatch (testsse, (void*)popcnt_sse4, (void*)popcnt, 25);
+ ...
+ }
+
+ There are two passes that are run to achieve multi-versioning.
+ "pass_ipa_multiversion_dispatch" is an ipa pass that decides which functions
+ have to be cloned and hoists the feature-test calls appropriately. This
+ pass can be enabled with the flag "-fclone-hot-version-paths" and disabled
+ with "-fno-clone-hot-version-paths".
+
+ "pass_tree_convert_builtin_dispatch" does the lowering. It is a
+ function-level pass. Functions marked with attribute "version_selector" are
+ also handled by this pass. This pass is always on.
+
+ How to use __builtin_dispatch ?
+ -----------------------------
+
+ __builtin_dispatch takes 3 mandatory arguments :
+
+ __builtin_dispatch (arg1, arg2, arg3, <arg4>, <arg5>, ...);
+
+ arg1 is the pointer to the feature-test function.
+ arg2 is the ( void *) cast pointer to the versioned function that is
+ executed when the feature test returns 1.
+ arg3 is the ( void *) cast pointer to the versioned function that is
+ executed when the feature test returns 0.
+ arg4, arg5, ... are optional. They are the arguments to the versioned
+ functions. Both versions must accept the same number of arguments.
+ The __builtin_dispatch function returns the value returned by the
+ versioned function that gets executed. The versioned function arg2
+ is executed when the feature_test function arg1 returns 1 and arg3
+ is executed when the feature_test function arg1 returns 0. arg1
+ could be marked as a "version_selector" function if it is a pure
+ function with no side-effects, returns a constant at run-time and
+ can be evaluated at any point in the execution.
+
+ When to use the "version_selector" attribute ?
+ -----------------------------------------------
+
+ Functions are marked with attribute "version_selector" only if
+ they are run-time constants. Example of such functions would
+ be those that test if a specific feature is available on a
+ particular architecture. Such functions must return a positive
+ integer. For two-way functions, those that test if a feature
+ is present or not must return 1 or 0 respectively.
+
+
+ The code is organized into five parts. The first part has the functionality
+ to detect and handle functions marked with attribute "version_selector". The
+ second part is the analysis phase where we find calls to __builtin_dispatch
+ and mark all functions that are hot and have a call-graph path to a
+ __builtin_dispatch call. The third part decides which functions
+ to clone. This is based on the number of clones that have to be created for
+ the functions marked in the analysis phase. Only two clones are allowed for
+ a function currently. The fourth part is where the actual cloning happens.
+ The fifth part contains the implementation to lower the __builtin_dispatch
+ calls.
+
+ Flags : -fclone-hot-version-paths does function unswitching via cloning.
+ --param=num-mversn-clones=<num> allows to specify the number of
+ functions that should be cloned.
+ --param=mversn-clone-depth=<num> allows to specify the length of
+ the call graph path that should be cloned. num = 0 implies only
+ leaf node that contains the __builtin_dispatch statement must be
+ cloned. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "tree.h"
+#include "tree-inline.h"
+#include "langhooks.h"
+#include "flags.h"
+#include "cgraph.h"
+#include "diagnostic.h"
+#include "toplev.h"
+#include "timevar.h"
+#include "params.h"
+#include "fibheap.h"
+#include "intl.h"
+#include "tree-pass.h"
+#include "hashtab.h"
+#include "coverage.h"
+#include "ggc.h"
+#include "tree-flow.h"
+#include "rtl.h"
+#include "ipa-prop.h"
+#include "basic-block.h"
+#include "tree-sample-profile.h"
+#include "toplev.h"
+#include "dbgcnt.h"
+#include "tree-dump.h"
+#include "output.h"
+#include "vecprim.h"
+
+typedef struct cgraph_node* NODEPTR;
+DEF_VEC_P (NODEPTR);
+DEF_VEC_ALLOC_P (NODEPTR, heap);
+
+/* Store the decl of __builtin_dispatch */
+static tree builtin_function_decl = NULL;
+
+/* Hash to map name to a decl. Used for variables and functions. */
+static htab_t name_decl_htab = NULL;
+
+/* Hashtable helpers for name_decl_htab. */
+
+static hashval_t
+name_decl_htab_hash_descriptor (const void *p)
+{
+ const_tree t = (const_tree) p;
+ const char *name
+ = (IDENTIFIER_POINTER (DECL_NAME (t)));
+ return htab_hash_string(name);
+}
+
+/* Hashtable helper for name_decl_htab. */
+
+static int
+name_decl_htab_eq_descriptor (const void *p1, const void *p2)
+{
+ const_tree t1 = (const_tree) p1;
+ const char *c1 = IDENTIFIER_POINTER (DECL_NAME (t1));
+ const char *c2 = (const char *)p2;
+
+ return (strcmp (c1, c2) == 0);
+}
+
+/* Return the variable name (global/constructor) to use for the
+ version_selector function with name of DECL by appending SUFFIX. */
+
+static char *
+make_name (tree decl, const char *suffix)
+{
+ char *global_var_name;
+ int name_len;
+ const char *name;
+
+ name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+
+ name_len = strlen (name) + strlen (suffix) + 2;
+ global_var_name = (char *) xmalloc (name_len);
+ snprintf (global_var_name, name_len, "%s_%s", name, suffix);
+ return global_var_name;
+}
+
+/* Code for handling version_selector attribute functions. Such functions are
+ run-time constants and need to be executed only once. They are hoisted
+ to a static constructor and their result is stored in a global.
+ */
+
+
+/* This function returns the global variable / constructor name created
+ for feature-test functions marked with attribute "version_selector".
+ The name returned is the DECL name appended with
+ "version_selector_global" for the variable and
+ "version_selector_constructor" for the constructor. */
+
+static char*
+make_feature_test_global_name (tree decl, bool is_constructor)
+{
+ if (is_constructor)
+ return make_name (decl, "version_selector_constructor");
+
+ return make_name (decl, "version_selector_global");
+}
+
+/* This function creates a new VAR_DECL with attributes set
+ using the parameters. PUBLIK corresponds to TREE_PUBLIC,
+ EXTERNAL corresponds to DECL_EXTERNAL and comdat is
+ for DECL_ONE_ONLY. The global variable will have the
+ same status as the version_selector function.*/
+
+static tree
+allocate_new_var (const char *name, int publik,
+ int external, int comdat)
+{
+ tree new_global_var;
+
+ new_global_var = build_decl (VAR_DECL,
+ get_identifier (name),
+ integer_type_node);
+
+ DECL_EXTERNAL (new_global_var) = external;
+ TREE_STATIC (new_global_var) = 1;
+ TREE_PUBLIC (new_global_var) = publik;
+ DECL_INITIAL (new_global_var) = 0;
+ DECL_ARTIFICIAL (new_global_var) = 1;
+ DECL_ONE_ONLY (new_global_var) = comdat;
+ assemble_variable (new_global_var, 0, 0, 0);
+ return new_global_var;
+}
+
+/* Make a new constructor function here to call a feature-test function
+ and set its body to CONSTRUCTOR_BODY. Its public and comdat
+ attributes are set from the parameters, PUBLIK, and COMDAT.
+ VERSION_SELECTOR_VAR is the global decl that saves the result of the
+ feature-test function in the constructor. */
+
+static tree
+make_constructor_function (char *name, gimple constructor_body, int publik,
+ int comdat, tree version_selector_var)
+{
+ tree decl, type, t;
+ gimple_seq seq;
+ basic_block new_bb;
+ tree old_current_function_decl;
+
+ type = build_function_type_list (void_type_node, NULL_TREE);
+
+ if (dump_file)
+ fprintf (dump_file, "Name of new constructor function = %s\n", name);
+
+ decl = build_fn_decl (name, type);
+
+ cgraph_remove_assembler_hash_node (cgraph_node (decl));
+ DECL_NAME (decl) = get_identifier (name);
+ SET_DECL_ASSEMBLER_NAME (decl, DECL_NAME (decl));
+ cgraph_add_assembler_hash_node (cgraph_node (decl));
+
+ TREE_USED (decl) = 1;
+ DECL_ARTIFICIAL (decl) = 1;
+ DECL_IGNORED_P (decl) = 0;
+ TREE_PUBLIC (decl) = publik;
+ DECL_UNINLINABLE (decl) = 1;
+ DECL_EXTERNAL (decl) = 0;
+ DECL_CONTEXT (decl) = NULL_TREE;
+ DECL_INITIAL (decl) = make_node (BLOCK);
+ DECL_STATIC_CONSTRUCTOR (decl) = 1;
+ DECL_ONE_ONLY (decl) = comdat;
+
+ /* Build result decl and add to function_decl. */
+ t = build_decl (RESULT_DECL, NULL_TREE, void_type_node);
+ DECL_ARTIFICIAL (t) = 1;
+ DECL_IGNORED_P (t) = 1;
+ DECL_RESULT (decl) = t;
+
+ gimplify_function_tree (decl);
+
+ /* Build CFG for this function. */
+
+ old_current_function_decl = current_function_decl;
+ push_cfun (DECL_STRUCT_FUNCTION (decl));
+ current_function_decl = decl;
+ init_empty_tree_cfg_for_function (DECL_STRUCT_FUNCTION (decl));
+ new_bb = create_empty_bb (ENTRY_BLOCK_PTR);
+ make_edge (ENTRY_BLOCK_PTR, new_bb, EDGE_FALLTHRU);
+
+ /* XXX: Not sure if the edge commented below is necessary. If I add this
+ edge, it fails in gimple_verify_flow_info in tree-cfg.c in condition :
+ " if (e->flags & EDGE_FALLTHRU)"
+ during -fprofile-generate.
+ Otherwise, it is fine. Deleting this edge does not break anything.
+ Commenting this so that it is clear I am intentionally not doing this.*/
+ /* make_edge (new_bb, EXIT_BLOCK_PTR, EDGE_FALLTHRU); */
+
+ seq = gimple_seq_alloc_with_stmt (constructor_body);
+
+ set_bb_seq (new_bb, seq);
+ gimple_set_bb (constructor_body, new_bb);
+
+ /* Set the lexical block of the constructor body. Fails the inliner
+ other wise. */
+ gimple_set_block (constructor_body, DECL_INITIAL (decl));
+
+ cgraph_add_new_function (decl, true);
+ cgraph_call_function_insertion_hooks (cgraph_node (decl));
+ cgraph_mark_needed_node (cgraph_node (decl));
+
+ /* This call is very important if this pass runs when the IR is in
+ SSA form. It breaks things in strange ways otherwise. */
+ init_tree_ssa (DECL_STRUCT_FUNCTION (decl));
+ add_referenced_var (version_selector_var);
+
+ if (dump_file)
+ dump_function_to_file (decl, dump_file, TDF_BLOCKS);
+
+ pop_cfun ();
+ current_function_decl = old_current_function_decl;
+ return decl;
+}
+
+/* If the current function is marked with attribute
+ "version_selector" then it is the predicate (feature-test) function
+ for multi-versioning. Call this function in a constructor and assign
+ the return value to a global variable.
+ The constructor's name is the decl name suffixed
+ "version_selector_constructor" and the global variable's name is the
+ decl name suffixed with "version_selector_global"
+
+ For example, feature-test function isSSE4 marked with attribute
+ version_selector is converted to
+
+ void isSSE4_version_selector_constructor ()
+ {
+ isSSE4_version_selector_global = isSSE4 ();
+ }
+
+ This function returns the decl of the global variable.
+
+ THIS_DECL is the function decl of the "version_selector" function.
+ */
+
+static tree
+handle_version_selector_attr_function (tree this_decl)
+{
+ char *global_var_name;
+ tree version_selector_var = NULL;
+ void **slot;
+
+
+ if (dump_file)
+ fprintf (dump_file, "Creating constructor/global for function %s\n",
+ IDENTIFIER_POINTER (DECL_NAME (this_decl)));
+
+ global_var_name = make_feature_test_global_name (this_decl,
+ false);
+
+ slot = htab_find_slot_with_hash (name_decl_htab, global_var_name,
+ htab_hash_string (global_var_name),
+ INSERT);
+ if (*slot == NULL)
+ {
+ if (dump_file)
+ fprintf (dump_file, "Creating global variable %s\n",
+ global_var_name);
+ *slot = allocate_new_var (global_var_name,
+ TREE_PUBLIC (this_decl),
+ DECL_EXTERNAL (this_decl),
+ DECL_ONE_ONLY (this_decl));
+ }
+ else
+ {
+ free (global_var_name);
+ return (tree) *slot;
+ }
+
+ version_selector_var = (tree) *slot;
+
+ /* If the feature-test function is not external, create a constructor and
+ call this function in the constructor. */
+
+ if (!DECL_EXTERNAL (this_decl))
+ {
+ char *constructor_name;
+ gimple constructor_body;
+ tree constructor_decl;
+
+ constructor_name
+ = make_feature_test_global_name (this_decl, true);
+
+ constructor_body = gimple_build_call (this_decl, 0);
+
+ gimple_call_set_lhs (constructor_body, version_selector_var);
+
+ if (dump_file)
+ print_gimple_stmt (dump_file, constructor_body, 0, TDF_VOPS);
+
+ constructor_decl =
+ make_constructor_function (constructor_name, constructor_body,
+ TREE_PUBLIC (this_decl),
+ DECL_ONE_ONLY (this_decl),
+ version_selector_var);
+ free (constructor_name);
+ }
+
+ free (global_var_name);
+ return version_selector_var;
+}
+
+/* Start Analysis phase. Mark all functions that are hot and have a call-graph
+ path to a __builtin_dispatch call. */
+
+/* This function returns the address of the feature test function.
+ If the address of the function is saved to a temporary,
+ this function traverses the gimple statements before BUILTIN_STMT
+ and finds an assignment whose rhs is the feature test function.
+ If the feature test function is specified as a function pointer
+ whose function value is unknown, this funcition returns NULL. */
+
+static tree
+find_version_selector_func_addr (gimple builtin_stmt)
+{
+ tree lhs_var_decl = NULL;
+ tree cond_func_addr = NULL;
+ gimple def_stmt = NULL;
+
+ cond_func_addr = gimple_call_arg (builtin_stmt, 0);
+
+ gcc_assert (TREE_CODE (cond_func_addr) == ADDR_EXPR
+ || TREE_CODE (cond_func_addr) == SSA_NAME);
+
+ if (TREE_CODE (cond_func_addr) == ADDR_EXPR)
+ return cond_func_addr;
+
+ /* TREE_CODE (cond_func_addr) == SSA_NAME
+ This means a new function pointer variable is created and assigned the
+ address of the feature-test function. Traverse the statements backwards
+ and find the assignment to get the RHS. */
+
+ lhs_var_decl = cond_func_addr;
+
+ def_stmt = SSA_NAME_DEF_STMT (cond_func_addr);
+
+ gcc_assert (def_stmt
+ && gimple_assign_lhs (def_stmt) == cond_func_addr);
+
+ cond_func_addr = gimple_assign_rhs1 (def_stmt);
+
+ /* If the cond_func_addr is still not an ADDR_EXPR, it means that the
+ feature-test function is specified as a pointer. In this case, we
+ return NULL, since the feature-test function decl is not known. */
+
+ if (cond_func_addr == NULL
+ || TREE_CODE (cond_func_addr) != ADDR_EXPR)
+ return NULL;
+
+ /* If the operand of the ADDR_EXPR is not a function_decl, return NULL
+ as this still means the feature-test function is specified as a
+ function pointer. */
+
+ if (TREE_CODE (TREE_OPERAND (cond_func_addr, 0)) != FUNCTION_DECL)
+ return NULL;
+
+ return cond_func_addr;
+}
+
+/* Finds the gimple calls to __builtin_dispatch in function pointed
+ to by the call graph NODE and populates the vector VEC. Returns
+ true if at least one statement was found where the feature test
+ function is marked as "version_selector". Otherwise, there is no
+ question of hoisting it. */
+
+static bool
+is_builtin_dispatch_stmt_present (struct cgraph_node *node,
+ VEC (tree,heap) **vec)
+{
+ struct cgraph_edge *edge;
+ bool present = false;
+ for (edge = node->callees; edge; edge = edge->next_callee)
+ {
+ if (edge->callee->decl == builtin_function_decl)
+ {
+ tree cond_func_decl;
+ tree cond_func_addr;
+ gcc_assert (*vec != NULL);
+ cond_func_addr = find_version_selector_func_addr (edge->call_stmt);
+
+ if (cond_func_addr == NULL)
+ continue;
+
+ cond_func_decl = TREE_OPERAND (cond_func_addr, 0);
+
+ /* Do not consider for hoisting if "version_selector" attribute is
+ not set. */
+ if (lookup_attribute ("version_selector",
+ DECL_ATTRIBUTES (cond_func_decl)) == NULL)
+ {
+ if (dump_file)
+ {
+ fprintf (dump_file, "Not hoisting builtin_dispatch as "
+ "feature_test function not version_selector :\n");
+ print_gimple_stmt (dump_file, edge->call_stmt, 0, TDF_VOPS);
+ }
+ continue;
+ }
+
+ present = true;
+ VEC_safe_push (tree, heap, *vec, cond_func_decl);
+ }
+ }
+ return present;
+}
+
+/* Updates the list of feature-test function decls reaching the cgraph
+ function NODE. */
+
+static void
+update_reachable_decls_list (struct cgraph_node *node,
+ VEC (tree, heap) *predicate_decls)
+{
+ VEC (tree, heap) **decl_list = NULL;
+ tree cond_func_decl;
+ int ix;
+
+ if (node->aux == NULL)
+ {
+ decl_list = (VEC (tree, heap) **) xmalloc (sizeof (VEC (tree, heap) *));
+ *decl_list = VEC_alloc (tree, heap, 1);
+ node->aux = decl_list;
+ }
+ else
+ decl_list = (VEC (tree, heap) **) node->aux;
+
+ for (ix = 0; VEC_iterate (tree, predicate_decls, ix, cond_func_decl); ++ix)
+ VEC_safe_push (tree, heap, *decl_list, cond_func_decl);
+}
+
+/* Propagate the __builtin_dispatch stmt (s) called from node to its
+ callers, PREDICATE_DECLS is the decls list of the predicate functions. */
+
+static unsigned int
+mark_reachable_functions (struct cgraph_node *this_node,
+ VEC (tree, heap) *predicate_decls)
+{
+ VEC (NODEPTR, heap) *work_list;
+ VEC (int, heap) *depth_list;
+ struct cgraph_edge *e;
+ htab_t node_htab = NULL;
+ void **slot = NULL;
+
+ /* Use a work-list style algorithm to mark functions in any call-graph
+ path to the current function. */
+
+ work_list = VEC_alloc (NODEPTR, heap, 8);
+ depth_list = VEC_alloc (int, heap, 8);
+
+ VEC_safe_push (NODEPTR, heap, work_list, this_node);
+ VEC_safe_push (int, heap, depth_list, 0);
+
+ node_htab = htab_create (10, htab_hash_pointer,
+ htab_eq_pointer, NULL);
+
+ slot = htab_find_slot (node_htab, this_node, INSERT);
+
+ gcc_assert (*slot == NULL);
+ *slot = this_node;
+
+ while (!VEC_empty (NODEPTR, work_list))
+ {
+ struct cgraph_node *node = VEC_pop (NODEPTR, work_list);
+ int depth = VEC_pop (int, depth_list);
+
+ if (dump_file)
+ fprintf (dump_file, "%s has a depth = %d callgraph path to %s\n",
+ cgraph_node_name (node), depth,
+ cgraph_node_name (this_node));
+
+ update_reachable_decls_list (node, predicate_decls);
+
+ gcc_assert (node->aux != NULL);
+
+ if (depth >= PARAM_VALUE (PARAM_MVERSN_CLONE_CGRAPH_DEPTH))
+ {
+ if (dump_file)
+ fprintf (dump_file, "Not propogating __builtin_dispatch... "
+ "maximum cloning depth = %d reached\n",
+ PARAM_VALUE (PARAM_MVERSN_CLONE_CGRAPH_DEPTH));
+ continue;
+ }
+
+ for (e = node->callers; e; e = e->next_caller)
+ {
+ slot = htab_find_slot (node_htab, e->caller, INSERT);
+ if (*slot != NULL)
+ continue;
+ *slot = e->caller;
+ if (!hot_function_p (e->caller))
+ continue;
+
+ VEC_safe_push (NODEPTR, heap, work_list, e->caller);
+ VEC_safe_push (int, heap, depth_list, (depth + 1));
+ }
+ }
+ htab_delete (node_htab);
+ VEC_free (NODEPTR, heap, work_list);
+ VEC_free (int, heap, depth_list);
+ return 0;
+}
+
+static inline struct inline_summary *
+inline_summary (struct cgraph_node *node)
+{
+ return &node->local.inline_summary;
+}
+
+/* Scan the call graph and detect hot functions that have __builtin_dispatch
+ calls. Then, propogate this information to its callers. Returns true if
+ a suitable __builtin_dispatch was found. */
+
+static bool
+perform_analysis_phase (void)
+{
+ struct cgraph_node *node;
+ VEC(tree, heap) *builtin_predicates_vec = NULL;
+ bool flag = false;
+
+ builtin_predicates_vec = VEC_alloc (tree, heap, 1);
+
+ for (node = cgraph_nodes; node; node = node->next)
+ {
+ /* if the body of this decl is from outside, do nothing. */
+ if (DECL_EXTERNAL (node->decl))
+ continue;
+
+ if (!hot_function_p (node))
+ continue;
+
+ if (!is_builtin_dispatch_stmt_present (node, &builtin_predicates_vec))
+ continue;
+
+ if (dump_file)
+ {
+ fprintf (dump_file, "%s calls __builtin_dispatch atleast once.\n",
+ cgraph_node_name (node));
+
+ fprintf (dump_file, "%s is a hot function, consider cloning ...\n",
+ cgraph_node_name (node));
+ }
+
+ flag = true;
+ mark_reachable_functions (node, builtin_predicates_vec);
+ VEC_truncate (tree, builtin_predicates_vec, 0);
+ }
+
+ VEC_free (tree, heap, builtin_predicates_vec);
+ return flag;
+}
+
+/* End Analysis phase. */
+
+/* Decide Cloning Phase.
+
+ In this phase, we go through each function and decide if it should be
+ cloned or not. */
+
+/* This function counts the number of unique decls in the DECL_LIST.*/
+
+static int
+count_predicate_functions (VEC (tree,heap) *decl_list)
+{
+ int ix;
+ int count = 0;
+ tree cond_func_decl = NULL;
+ htab_t dup_decl_htab = NULL;
+
+ if (VEC_length (tree, decl_list) == 1)
+ return 1;
+
+ dup_decl_htab = htab_create (2, htab_hash_pointer, htab_eq_pointer, NULL);
+
+ for (ix = 0; VEC_iterate (tree, decl_list, ix, cond_func_decl); ++ix)
+ {
+ void **slot = NULL;
+ slot = htab_find_slot (dup_decl_htab, cond_func_decl, INSERT);
+
+ if (*slot != NULL)
+ continue;
+ count++;
+ *slot = cond_func_decl;
+ }
+
+ htab_delete (dup_decl_htab);
+ return count;
+}
+
+/* This function decides which functions to clone based on the number of
+ feature_test decls reaching it. Currently, only one feature_test decl
+ is allowed. */
+
+static bool
+decide_cloning_phase (void)
+{
+ struct cgraph_node *node;
+ int count;
+ bool run_cloning_phase = false;
+ int num_funcs_cloned = 0;
+
+ for (node = cgraph_nodes; node; node = node->next)
+ {
+ tree cond_func_decl = NULL;
+ VEC (tree, heap) *vec;
+ if (node->aux == NULL)
+ continue;
+
+ if (num_funcs_cloned >= PARAM_VALUE (PARAM_NUMBER_OF_MVERSN_CLONES))
+ {
+ if (dump_file)
+ fprintf (dump_file, "Reached cloning limit specified "
+ "by \"num-mversn-clones\" for %s\n",
+ cgraph_node_name (node));
+
+ free (node->aux);
+ node->aux = NULL;
+ continue;
+ }
+
+ vec = *(VEC (tree,heap) **) node->aux;
+ count = count_predicate_functions (vec);
+ gcc_assert (count >= 1);
+ cond_func_decl = VEC_index (tree, vec, 0);
+ gcc_assert (cond_func_decl != NULL);
+ VEC_free (tree, heap, vec);
+ free (node->aux);
+ node->aux = NULL;
+
+ if (count > 1)
+ {
+ if (dump_file)
+ fprintf (dump_file, "%s has %d predicates Not cloning for > 1\n",
+ cgraph_node_name (node), count);
+ continue;
+ }
+ /* Set the node's aux value to be that of the predicate decl. */
+ node->aux = cond_func_decl;
+ run_cloning_phase = true;
+ num_funcs_cloned++;
+ }
+ return run_cloning_phase;
+}
+
+/* End Decide Cloning Phase. */
+
+/* Cloning Phase. */
+
+/* Deletes all basic-blocks and leaves function with :
+ ENTRY_BLOCK ---> (new empty basic block) ---> EXIT_BLOCK
+*/
+
+static basic_block
+empty_function_body (tree fndecl)
+{
+ basic_block bb, new_bb;
+ edge e;
+ tree old_current_function_decl;
+
+ old_current_function_decl = current_function_decl;
+ push_cfun (DECL_STRUCT_FUNCTION (fndecl));
+ current_function_decl = fndecl;
+
+ clear_edges ();
+ for (bb = ENTRY_BLOCK_PTR; bb != NULL;)
+ {
+ basic_block bb_next;
+ bb_next = bb->next_bb;
+ if (bb != EXIT_BLOCK_PTR
+ && bb != ENTRY_BLOCK_PTR)
+ {
+ if (bb_seq (bb) != NULL)
+ {
+ gimple_stmt_iterator i;
+ for (i = gsi_start_bb (bb); !gsi_end_p (i);)
+ gsi_remove (&i, true);
+ }
+ bb->il.gimple = NULL;
+ bb->prev_bb = NULL;
+ bb->next_bb = NULL;
+ SET_BASIC_BLOCK (bb->index, NULL);
+ n_basic_blocks--;
+ }
+ bb = bb_next;
+ }
+ ENTRY_BLOCK_PTR->next_bb = EXIT_BLOCK_PTR;
+ new_bb = create_empty_bb (ENTRY_BLOCK_PTR);
+ e = make_edge (ENTRY_BLOCK_PTR, new_bb, EDGE_FALLTHRU);
+ /* XXX:Is this edge necessary ? */
+ e = make_edge (new_bb, EXIT_BLOCK_PTR, EDGE_FALLTHRU);
+
+ current_function_decl = old_current_function_decl;
+ pop_cfun ();
+ return new_bb;
+}
+
+/* Takes function with decl ORIG_FNDECL and clones it. The
+ name of the clone is the original name suffixed with
+ NAME_SUFFIX. Code is adapted from cgraph_function_versioning
+ in cgraphunit.c */
+
+static tree
+clone_function (tree orig_fndecl, const char *name_suffix)
+{
+ tree new_decl;
+ char *new_name;
+ struct cgraph_node *new_version;
+ struct cgraph_node *old_version;
+ void **slot;
+ tree old_current_function_decl;
+
+ new_name = make_name (orig_fndecl, name_suffix);
+ new_decl = copy_node (orig_fndecl);
+
+
+ slot = htab_find_slot_with_hash (name_decl_htab, new_name,
+ htab_hash_string (new_name), INSERT);
+
+ gcc_assert (*slot == NULL);
+ *slot = new_decl;
+
+ /* Code adapted from cgraph_function_versioning in cgraphuinit.c */
+
+ new_version = cgraph_node (new_decl);
+ old_version = cgraph_node (orig_fndecl);
+
+ new_version->analyzed = true;
+ new_version->local = old_version->local;
+ new_version->global = old_version->global;
+ new_version->rtl = old_version->rtl;
+ new_version->reachable = true;
+ new_version->count = old_version->count;
+ new_version->max_bb_count = old_version->max_bb_count;
+ new_version->is_versioned_clone = true;
+
+ tree_function_versioning (orig_fndecl, new_decl, NULL /*tree_map*/,
+ false, NULL /*args_to_skip*/);
+
+ old_current_function_decl = current_function_decl;
+ push_cfun (DECL_STRUCT_FUNCTION (new_decl));
+ current_function_decl = new_decl;
+
+
+ /* Set the name of the new function. */
+ cgraph_remove_assembler_hash_node (new_version);
+ DECL_NAME (new_decl) = get_identifier (new_name);
+ SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
+ cgraph_add_assembler_hash_node (new_version);
+
+ DECL_NAME (new_decl) = get_identifier (new_name);
+ TREE_READONLY (new_decl) = TREE_READONLY (orig_fndecl);
+ TREE_STATIC (new_decl) = TREE_STATIC (orig_fndecl);
+ TREE_USED (new_decl) = TREE_USED (orig_fndecl);
+ DECL_ARTIFICIAL (new_decl) = 1;
+ DECL_IGNORED_P (new_decl) = 0;
+ TREE_PUBLIC (new_decl) = TREE_PUBLIC (orig_fndecl);
+ DECL_CONTEXT (new_decl) = NULL_TREE;
+
+ DECL_EXTERNAL (new_decl) = DECL_EXTERNAL (orig_fndecl);
+ DECL_ONE_ONLY (new_decl) = DECL_ONE_ONLY (orig_fndecl);
+ DECL_COMDAT (new_decl) = DECL_COMDAT (orig_fndecl);
+ DECL_VIRTUAL_P (new_decl) = DECL_VIRTUAL_P (orig_fndecl);
+ DECL_WEAK (new_decl) = DECL_WEAK (orig_fndecl);
+ new_version->lowered = true;
+
+ if (dump_file)
+ dump_function_to_file (new_decl, dump_file, TDF_BLOCKS);
+
+ cgraph_add_new_function (new_decl, true);
+
+ cgraph_call_function_insertion_hooks (new_version);
+ cgraph_mark_needed_node (new_version);
+
+ pop_cfun ();
+ current_function_decl = old_current_function_decl;
+
+ return new_decl;
+}
+
+/* This function populates the vector *VEC with the args in the gimple
+ call statement STMT. SKIP_ARGS is the number of args to skip.*/
+
+static void
+get_function_args (gimple stmt, int num_args, VEC (tree, heap) **vec,
+ int skip_args)
+{
+ int i;
+
+ if (num_args == 0) return;
+
+ *vec = VEC_alloc (tree, heap, num_args);
+ /* The number of args in a function is 1 plus the actual number of
+ args. Also, there are 3 special args reserved, so the first arg
+ starts from 3. */
+ for (i = 0; i <= num_args - 2; ++i)
+ VEC_quick_push (tree, *vec, gimple_call_arg (stmt, (skip_args + i)));
+}
+
+/* Given ret = __builtin_dispatch (pred, fn1, fn2, arg1, ....)
+ get ret = fn1 (arg1, ...) or ret = fn2 (arg1, ....)
+ depending on the value of SIDE == 0 or 1. */
+
+static gimple
+make_specialized_call_from_builtin (gimple builtin_stmt, int side)
+{
+ tree cond_func_addr, func_addr;
+ tree cond_func_decl;
+ int num_func_args = 0;
+ VEC (tree, heap) *nargs = NULL;
+ tree lhs_stmt;
+ gimple specialized_call_stmt;
+
+ cond_func_addr = gimple_call_arg (builtin_stmt, 0);
+ cond_func_decl = TREE_OPERAND (cond_func_addr, 0);
+
+ if (side == 0)
+ func_addr = gimple_call_arg (builtin_stmt, 1);
+ else
+ func_addr = gimple_call_arg (builtin_stmt, 2);
+
+ num_func_args
+ = function_args_count (TREE_TYPE (TREE_OPERAND (func_addr, 0)));
+
+ get_function_args (builtin_stmt, num_func_args, &nargs, 3);
+
+ specialized_call_stmt = gimple_build_call_vec (func_addr, nargs);
+
+ lhs_stmt = gimple_call_lhs (builtin_stmt);
+
+ if (lhs_stmt != NULL_TREE)
+ gimple_call_set_lhs (specialized_call_stmt, lhs_stmt);
+
+ mark_symbols_for_renaming (specialized_call_stmt);
+
+ if (nargs != NULL)
+ VEC_free (tree, heap, nargs);
+
+ return specialized_call_stmt;
+}
+
+/* Given a call (GENERIC_STMT) to a function that is cloned, substitute
+ with a call to the correct clone. */
+
+static gimple
+make_specialized_call_to_clone (gimple generic_stmt, int side)
+{
+ tree new_decl;
+ char *new_name;
+ tree generic_fndecl;
+ gimple specialized_call_stmt;
+ void **slot;
+ int num_func_args;
+ tree lhs_stmt;
+ VEC (tree, heap) *nargs= NULL;
+
+ generic_fndecl = gimple_call_fndecl (generic_stmt);
+ gcc_assert (generic_fndecl != NULL);
+
+ if (side == 0)
+ new_name = make_name (generic_fndecl, "clone_0");
+ else
+ new_name = make_name (generic_fndecl, "clone_1");
+
+ slot = htab_find_slot_with_hash (name_decl_htab, new_name,
+ htab_hash_string (new_name), NO_INSERT);
+ gcc_assert (slot != NULL);
+ new_decl = (tree) *slot;
+ gcc_assert (new_decl);
+
+ num_func_args = function_args_count (TREE_TYPE (generic_fndecl));
+ get_function_args (generic_stmt, num_func_args, &nargs, 0);
+ specialized_call_stmt = gimple_build_call_vec (new_decl, nargs);
+
+ lhs_stmt = gimple_call_lhs (generic_stmt);
+
+ if (lhs_stmt != NULL_TREE)
+ gimple_call_set_lhs (specialized_call_stmt, lhs_stmt);
+
+ mark_symbols_for_renaming (specialized_call_stmt);
+
+ if (nargs != NULL)
+ VEC_free (tree, heap, nargs);
+
+ return specialized_call_stmt;
+}
+
+/* Returns true if STMT is a call to __builtin_dispatch and its
+ predicate feature-test function is marked with attribute
+ "version_selector". */
+
+static bool
+is_builtin_with_predicate_version_selector (gimple stmt)
+{
+ tree cond_func_addr, cond_func_decl;
+
+ if (gimple_call_fndecl (stmt) != builtin_function_decl)
+ return false;
+
+ cond_func_addr = find_version_selector_func_addr (stmt);
+
+ if (cond_func_addr == NULL)
+ return false;
+
+ cond_func_decl = TREE_OPERAND (cond_func_addr, 0);
+ if (lookup_attribute ("version_selector",
+ DECL_ATTRIBUTES (cond_func_decl)) != NULL)
+ return true;
+
+ return false;
+}
+
+/* Find calls to __builtin_dispatch or to functions that are versioned
+ in CLONE_DECL and substitute the call with the correct version based
+ on the value of SIDE. */
+
+static void
+specialize_call (tree clone_decl, int side)
+{
+ basic_block bb;
+ tree old_current_function_decl;
+
+ old_current_function_decl = current_function_decl;
+ push_cfun (DECL_STRUCT_FUNCTION (clone_decl));
+ current_function_decl = clone_decl;
+
+ /* Iterate over call edges and find out if there is
+ a call to __builtin_dispatch or a cloned function.
+ We cannot iterate over call graph edges as there are
+ no edges for the clones yet. */
+
+ FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (clone_decl))
+ {
+ gimple_stmt_iterator gsi;
+ for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+ {
+ tree callee_decl;
+ struct cgraph_node *callee_node;
+ gimple specialized_call_stmt;
+ gimple stmt = gsi_stmt (gsi);
+
+ if (!is_gimple_call (stmt))
+ continue;
+
+ callee_decl = gimple_call_fndecl (stmt);
+
+ if (callee_decl == NULL)
+ continue;
+
+ callee_node = cgraph_node (callee_decl);
+
+ /* For a __builtin_dispatch stmt, only specialize if
+ version_selector attribute is set. Otherwise, it is
+ not hoisted, so no specialization. */
+
+ if (is_builtin_with_predicate_version_selector (stmt))
+ {
+ specialized_call_stmt =
+ make_specialized_call_from_builtin (stmt, side);
+ }
+ else if (callee_node->aux != NULL)
+ {
+ specialized_call_stmt =
+ make_specialized_call_to_clone (stmt, side);
+ }
+ else
+ continue;
+
+ if (dump_file)
+ {
+ fprintf (dump_file, "Specialize stmt : \n");
+ print_gimple_stmt (dump_file, stmt, 0, TDF_VOPS);
+ fprintf (dump_file, "Specialized stmt : \n");
+ print_gimple_stmt (dump_file, specialized_call_stmt,
+ 0, TDF_VOPS);
+ }
+
+ gimple_set_block (specialized_call_stmt, gimple_block (stmt));
+ gsi_insert_before_without_update (&gsi, specialized_call_stmt,
+ GSI_SAME_STMT);
+ gsi_remove (&gsi, true);
+ /* After removing make sure gsi is set correctly to not skip
+ a statememt. */
+ gsi = gsi_for_stmt (specialized_call_stmt);
+ }
+ }
+ current_function_decl = old_current_function_decl;
+ pop_cfun ();
+}
+
+/* When a function is version cloned, its body is replaced to call one
+ of the versions with the feature-test function acting as a predicate.
+ This is done with __builtin_dispatch which is later expanded. */
+
+static gimple
+make_builtin_call_to_clones (tree orig_fndecl, tree clone_0_addr,
+ tree clone_1_addr, tree cond_func_addr)
+{
+ gimple new_builtin_call;
+ int num_func_args;
+ VEC(tree, heap) *vargs = VEC_alloc (tree, heap, 4);
+ tree arg;
+
+ VEC_quick_push (tree, vargs, cond_func_addr);
+ VEC_quick_push (tree, vargs, clone_0_addr);
+ VEC_quick_push (tree, vargs, clone_1_addr);
+
+ num_func_args = function_args_count (TREE_TYPE (orig_fndecl));
+
+ for (arg = DECL_ARGUMENTS (orig_fndecl); arg; arg = TREE_CHAIN (arg))
+ {
+ VEC_safe_push (tree, heap, vargs, arg);
+ /* Again, this add_referenced_var is very very important. It broke
+ a build where a cloned function's arguments where never
+ referenced. Missing this statement in places asserts at
+ tree-dfa.c:589, in function referenced_var_lookup at
+ "gcc_assert (h || uid == 0);" and is very difficult to triage. */
+ add_referenced_var (arg);
+ }
+
+ new_builtin_call = gimple_build_call_vec (builtin_function_decl, vargs);
+ mark_symbols_for_renaming (new_builtin_call);
+
+
+ if (dump_file)
+ print_gimple_stmt (dump_file, new_builtin_call, 0, TDF_VOPS);
+
+ VEC_free (tree, heap, vargs);
+
+ return new_builtin_call;
+}
+
+/* This clones a dispatch function whose callee-graph path has a function
+ which calls __builtin_dispatch. This function is cloned and the
+ original function branches to the right clone. */
+
+static int
+clone_and_dispatch_function (struct cgraph_node *orig_node, tree *clone_0,
+ tree *clone_1)
+{
+ tree clone_0_decl, clone_1_decl;
+ gimple new_builtin_call = NULL;
+ gimple new_return_stmt = NULL;
+ gimple_seq seq = NULL;
+ basic_block new_bb;
+ tree orig_fndecl;
+ tree return_var = NULL;
+ int num_insns, hot_insns;
+ tree return_type;
+ tree old_current_function_decl;
+
+ old_current_function_decl = current_function_decl;
+ orig_fndecl = orig_node->decl;
+ push_cfun (DECL_STRUCT_FUNCTION (orig_fndecl));
+ current_function_decl = orig_fndecl;
+
+ /* Make 2 clones for true and false function. */
+ clone_0_decl = clone_function (orig_fndecl, "clone_0");
+ clone_1_decl = clone_function (orig_fndecl, "clone_1");
+ *clone_0 = clone_0_decl;
+ *clone_1 = clone_1_decl;
+
+ new_bb = empty_function_body (orig_fndecl);
+
+ new_builtin_call = make_builtin_call_to_clones (
+ orig_fndecl,
+ build_fold_addr_expr (clone_0_decl),
+ build_fold_addr_expr (clone_1_decl),
+ build_fold_addr_expr ((tree)orig_node->aux));
+
+ return_type = TREE_TYPE (TREE_TYPE (orig_fndecl));
+
+ if (!TREE_ADDRESSABLE (return_type) && COMPLETE_TYPE_P (return_type))
+ {
+ tree tmp_var;
+ tmp_var = create_tmp_var (return_type, NULL);
+ add_referenced_var (tmp_var);
+ return_var = make_ssa_name (tmp_var, new_builtin_call);
+ gimple_call_set_lhs (new_builtin_call, return_var);
+ }
+
+ mark_symbols_for_renaming (new_builtin_call);
+ new_return_stmt = gimple_build_return (return_var);
+ mark_symbols_for_renaming (new_return_stmt);
+ gimple_seq_add_stmt (&seq, new_builtin_call);
+ gimple_seq_add_stmt (&seq, new_return_stmt);
+ set_bb_seq (new_bb, seq);
+ gimple_set_bb (new_builtin_call, new_bb);
+ gimple_set_bb (new_return_stmt, new_bb);
+
+ gimple_set_block (new_builtin_call, DECL_INITIAL (orig_fndecl));
+ gimple_set_block (new_return_stmt, DECL_INITIAL (orig_fndecl));
+
+ if (dump_file)
+ dump_function_to_file (orig_fndecl, dump_file, TDF_BLOCKS);
+
+ if (inline_summary (orig_node))
+ {
+ num_insns = estimate_num_insns_fn (orig_fndecl, &eni_inlining_weights,
+ &hot_insns);
+ inline_summary (orig_node)->self_insns
+ = orig_node->global.insns = num_insns;
+ }
+
+ DECL_DECLARED_INLINE_P (orig_fndecl) = 1;
+ DECL_UNINLINABLE (orig_fndecl) = 0;
+
+ /* This update_ssa is necessary here for the following reason. SSA uses
+ a global syms_to_rename bitmap that stores syms that must be renamed.
+ So, if we accumulate the syms from one function in IPA but move to
+ a different function without updating SSA, then we could be
+ accumulating syms from many functions. This would assert in
+ referenced_var_lookup because the hashtab storing the syms is
+ function local. This is horrible. gcc-4.6 makes this bitmap a
+ global. */
+ update_ssa (TODO_update_ssa);
+
+ current_function_decl = old_current_function_decl;
+ pop_cfun ();
+ return 0;
+}
+
+/* Clone all functions marked for cloning by the earlier phase. */
+static void
+perform_cloning_phase (void)
+{
+ struct cgraph_node *node;
+ int ix;
+ VEC (tree, heap) *cloned_decl_list = NULL;
+ tree cloned_decl = NULL;
+
+ cloned_decl_list = VEC_alloc (tree, heap, 2);
+
+ /* First clone, then specialize the clones. */
+ for (node = cgraph_nodes; node; node = node->next)
+ {
+ tree clone_0_decl, clone_1_decl;
+ if (node->aux == NULL)
+ continue;
+ if (dump_file)
+ {
+ fprintf (dump_file, "%s will be cloned\n", cgraph_node_name (node));
+ dump_function_to_file (node->decl, dump_file, TDF_BLOCKS);
+ }
+ clone_and_dispatch_function (node, &clone_0_decl, &clone_1_decl);
+ VEC_safe_push (tree, heap, cloned_decl_list, clone_0_decl);
+ VEC_safe_push (tree, heap, cloned_decl_list, clone_1_decl);
+ continue;
+ }
+
+ /* Specialize the clones now. */
+ for (ix = 0; VEC_iterate (tree, cloned_decl_list, ix, cloned_decl); ++ix)
+ {
+ int which_clone = ix % 2;
+ specialize_call (cloned_decl, which_clone);
+ }
+
+ VEC_free (tree, heap, cloned_decl_list);
+}
+
+/* End Cloning phase. */
+
+/* Checks if there is atleast one call to __builtin_dispatch. */
+
+static bool
+find_builtin_decl (void)
+{
+ struct cgraph_node *node;
+ for (node = cgraph_nodes; node; node = node->next)
+ {
+ if (strstr (cgraph_node_name (node), "__builtin_dispatch") != NULL)
+ {
+ builtin_function_decl = node->decl;
+ return true;
+ }
+ }
+ return false;
+}
+
+/* Set the aux fields of all nodes and edges in the call graph to be NULL. */
+
+static void
+cleanup_aux_field (void)
+{
+ struct cgraph_node *node;
+ struct cgraph_edge *edge;
+
+ for (node = cgraph_nodes; node; node = node->next)
+ {
+ node->aux = NULL;
+ for (edge = node->callees; edge; edge = edge->next_callee)
+ edge->aux = NULL;
+ }
+}
+
+/* Main driver function. It scans the __builtin_dispatch calls and
+ figures out which functions to clone. It then clones the functions. */
+
+static unsigned int
+builtin_dispatch_ipa_clone (void)
+{
+ cleanup_aux_field ();
+
+ /* Allocate hashtab mapping name to decl. */
+ name_decl_htab = htab_create (10, name_decl_htab_hash_descriptor,
+ name_decl_htab_eq_descriptor, NULL);
+
+ /* Turn it on for O1 and above. At -O0, there is a SSA alias bug
+ with create_tmp_var. Cloning and hoisting is not necessary at
+ -O0 anyways. Also, guard it with the flag
+ "-fclone-hot-dispatch-paths". */
+ if (optimize == 0
+ || profile_arc_flag
+ || !flag_clone_hot_version_paths)
+ return 0;
+
+ if (!find_builtin_decl ())
+ return 0;
+
+ gcc_assert (builtin_function_decl != NULL);
+
+ if (!perform_analysis_phase ())
+ {
+ cleanup_aux_field ();
+ return 0;
+ }
+
+ if (decide_cloning_phase ())
+ perform_cloning_phase ();
+
+ cleanup_aux_field ();
+ return 0;
+}
+
+static bool
+gate_handle_builtin_dispatch (void)
+{
+ return true;
+}
+
+struct simple_ipa_opt_pass pass_ipa_multiversion_dispatch =
+{
+ {
+ SIMPLE_IPA_PASS,
+ "multiversion_dispatch", /* name */
+ gate_handle_builtin_dispatch, /* gate */
+ builtin_dispatch_ipa_clone, /* execute */
+ NULL, /* sub */
+ NULL, /* next */
+ 0, /* static_pass_number */
+ TV_MVERSN_DISPATCH, /* tv_id */
+ 0, /* properties_required */
+ PROP_cfg, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ TODO_dump_func /* todo_flags_finish */
+ }
+};
+
+/* Lowering of the __builtin_dispatch calls. */
+
+
+/* This function converts STMT which is a __builtin_dispatch
+ call of the form :
+ ret = __builtin_dispatch (predicate, foo, bar, arg1, ...)
+ into :
+ var_1 = predicate
+ if (var_1)
+ var_2 = foo (arg1, ...);
+ else
+ var_3 = bar (arg1, ...);
+ var_4 = phi (var_2, var_3)
+ ret = var_4
+
+ var_? are ssa names for variable var.
+*/
+
+static unsigned int
+convert_builtin_dispatch (gimple stmt)
+{
+ tree cond_func_addr, if_func_addr, else_func_addr;
+ tree cond_func_decl = NULL;
+ gimple if_part, else_part, if_else_stmt;
+ basic_block bb1, bb2, bb3, bb4;
+ gimple bb1end, bb2end, bb3end;
+ edge e12, e13, e23, e24, e34;
+ VEC(tree, heap) *nargs = NULL;
+ int num_func_args = 0, i;
+ tree version_selector_var;
+ tree lhs_result;
+ gimple_stmt_iterator gsi;
+ basic_block bb;
+ gimple feature_test_call = NULL;
+ int num_insns = 0;
+ int hot_insns = 0;
+ struct cgraph_node *this_fn_node;
+ tree tmp_var = NULL;
+ gimple init_stmt = NULL;
+ tree ssa_if_name, ssa_else_name;
+ gimple phinode = NULL;
+ tree tmp_result_var, ssa_result_var;
+
+ gsi = gsi_for_stmt (stmt);
+ bb = gsi_bb (gsi);
+
+ cond_func_addr = find_version_selector_func_addr (stmt);
+ if (cond_func_addr != NULL)
+ {
+ cond_func_decl = TREE_OPERAND (cond_func_addr, 0);
+ gcc_assert (cond_func_decl);
+ }
+
+ if (dump_file)
+ {
+ fprintf (dump_file, "Before Converting __builtin_dispatch :\n");
+ dump_function_to_file (current_function_decl, dump_file, TDF_BLOCKS);
+ }
+
+ if_func_addr = gimple_call_arg (stmt, 1);
+ else_func_addr = gimple_call_arg (stmt, 2);
+
+ tmp_result_var = create_tmp_var (integer_type_node, NULL);
+ add_referenced_var (tmp_result_var);
+
+ if (cond_func_decl == NULL
+ || lookup_attribute ("version_selector",
+ DECL_ATTRIBUTES (cond_func_decl)) == NULL)
+ {
+ tree arg = gimple_call_arg (stmt, 0);
+ /* This means the feature-test function is not set with attribute
+ version_selector or it is a function pointer. So, explicitly
+ call it. */
+ feature_test_call = gimple_build_call (arg, 0);
+ ssa_result_var = make_ssa_name (tmp_result_var, feature_test_call);
+ gimple_assign_set_lhs (feature_test_call, ssa_result_var);
+ mark_symbols_for_renaming (feature_test_call);
+ version_selector_var = ssa_result_var;
+ }
+ else
+ {
+ /* Get the global corresponding to the "version_selector" function. */
+ version_selector_var
+ = handle_version_selector_attr_function (cond_func_decl);
+ gcc_assert (version_selector_var);
+ add_referenced_var (version_selector_var);
+ feature_test_call = gimple_build_assign (tmp_result_var,
+ version_selector_var);
+ ssa_result_var = make_ssa_name (tmp_result_var, feature_test_call);
+ gimple_assign_set_lhs (feature_test_call, ssa_result_var);
+ mark_symbols_for_renaming (feature_test_call);
+ version_selector_var = ssa_result_var;
+ }
+
+ if_else_stmt = gimple_build_cond (GT_EXPR,
+ version_selector_var,
+ integer_zero_node,
+ NULL_TREE, NULL_TREE);
+
+ mark_symbols_for_renaming (if_else_stmt);
+
+ num_func_args = function_args_count (
+ TREE_TYPE (TREE_OPERAND (if_func_addr, 0)));
+
+ nargs = VEC_alloc (tree, heap, num_func_args);
+
+ /* The arguments to the feature test function start from the 4th argument
+ in __builtin_dispatch. The first 3 arguments are mandatory. */
+
+ for (i = 0; i <= num_func_args - 2; ++i)
+ VEC_quick_push (tree, nargs,
+ gimple_call_arg (stmt, (3 + i)));
+
+ if_part = gimple_build_call_vec (if_func_addr, nargs);
+ else_part = gimple_build_call_vec (else_func_addr, nargs);
+
+ lhs_result = gimple_call_lhs (stmt);
+ if (lhs_result != NULL_TREE)
+ {
+ tree ssa_var;
+ tree return_type;
+ return_type = TREE_TYPE (lhs_result);
+ tmp_var = create_tmp_var (return_type, NULL);
+ add_referenced_var (tmp_var);
+
+ init_stmt = gimple_build_assign (tmp_var, integer_zero_node);
+ ssa_var = make_ssa_name (tmp_var, init_stmt);
+ gimple_assign_set_lhs (init_stmt, ssa_var);
+ mark_symbols_for_renaming (init_stmt);
+
+ ssa_if_name = make_ssa_name (tmp_var, init_stmt);
+ ssa_else_name = make_ssa_name (tmp_var, init_stmt);
+ gimple_call_set_lhs (if_part, ssa_if_name);
+ gimple_call_set_lhs (else_part, ssa_else_name);
+ }
+ mark_symbols_for_renaming (if_part);
+ mark_symbols_for_renaming (else_part);
+
+ /* Set the lexical block to be the same as the dispatch call. */
+ gcc_assert (feature_test_call);
+ gimple_set_block (feature_test_call, gimple_block (stmt));
+
+ if (init_stmt)
+ gimple_set_block (init_stmt, gimple_block (stmt));
+
+ gimple_set_block (if_else_stmt, gimple_block (stmt));
+ gimple_set_block (if_part, gimple_block (stmt));
+ gimple_set_block (else_part, gimple_block (stmt));
+
+ gsi_insert_before_without_update (&gsi, feature_test_call, GSI_SAME_STMT);
+ gimple_set_bb (feature_test_call, bb);
+
+ if (init_stmt)
+ {
+ gsi_insert_before_without_update (&gsi, init_stmt,
+ GSI_SAME_STMT);
+ gimple_set_bb (init_stmt, bb);
+ }
+
+ gsi_insert_before_without_update (&gsi, if_else_stmt, GSI_SAME_STMT);
+ gsi_insert_before_without_update (&gsi, if_part, GSI_SAME_STMT);
+ gsi_insert_before_without_update (&gsi, else_part, GSI_SAME_STMT);
+
+ /* Remove the builtin_dispatch call after the expansion. */
+ gsi_remove (&gsi, true);
+ bb1end = if_else_stmt;
+ bb2end = if_part;
+ bb3end = else_part;
+ bb1 = bb;
+ e12 = split_block (bb1, bb1end);
+ bb2 = e12->dest;
+ e23 = split_block (bb2, bb2end);
+ bb3 = e23->dest;
+ e34 = split_block (bb3, bb3end);
+ bb4 = e34->dest;
+
+ e12->flags &= ~EDGE_FALLTHRU;
+ e12->flags |= EDGE_TRUE_VALUE;
+ e13 = make_edge (bb1, bb3, EDGE_FALSE_VALUE);
+ e24 = make_edge (bb2, bb4, EDGE_FALLTHRU);
+ remove_edge (e23);
+
+ if (tmp_var)
+ {
+ gimple assign_stmt;
+ phinode = create_phi_node (tmp_var, bb4);
+ add_phi_arg (phinode, ssa_if_name, e24, UNKNOWN_LOCATION);
+ add_phi_arg (phinode, ssa_else_name, e34, UNKNOWN_LOCATION);
+ mark_symbols_for_renaming (phinode);
+ gcc_assert (lhs_result);
+ assign_stmt
+ = gimple_build_assign (lhs_result, gimple_phi_result (phinode));
+ mark_symbols_for_renaming (assign_stmt);
+ gsi = gsi_start_bb (bb4);
+ gsi_insert_before_without_update (&gsi, assign_stmt, GSI_SAME_STMT);
+ gimple_set_bb (assign_stmt, bb4);
+ }
+
+ if (dump_file)
+ {
+ fprintf (dump_file, "Converted __builtin_dispatch :\n");
+ dump_function_to_file (current_function_decl, dump_file, TDF_BLOCKS);
+ }
+
+ num_insns = estimate_num_insns_fn (current_function_decl,
+ &eni_inlining_weights,
+ &hot_insns);
+
+ this_fn_node = cgraph_node (current_function_decl);
+ if (inline_summary (this_fn_node))
+ gcc_assert (inline_summary (this_fn_node)->self_insns
+ == this_fn_node->global.insns);
+ this_fn_node->global.insns = num_insns;
+ if (inline_summary (this_fn_node))
+ inline_summary (this_fn_node)->self_insns = this_fn_node->global.insns;
+
+ return 0;
+}
+
+/* This function does two things.
+
+ 1) For a feature-test function marked with attribute "version_selector",
+ it creates a constructor that calls the feature-test function and a
+ global that holds the result. The global's result will be used
+ to lower any __builtin_dispatch statement that refers to this feature
+ test function. The __builtin_dispatch statement and the feature test
+ function can be in different modules.
+
+ 2) It lowers __builtin_dispatch statements. */
+
+static unsigned int
+do_convert_builtin_dispatch (void)
+{
+ basic_block bb;
+ gimple_stmt_iterator gsi;
+ VEC (gimple, heap) *builtin_stmt_list = NULL;
+ int ix;
+ gimple builtin_stmt;
+
+ /* Allocate hashtab mapping name to decl. */
+ if (name_decl_htab == NULL)
+ name_decl_htab = htab_create (10, name_decl_htab_hash_descriptor,
+ name_decl_htab_eq_descriptor, NULL);
+
+
+ /* Look for functions with attribute "version_selector" and make a
+ constructor which calls the function and saves the result in a
+ global. */
+
+ if (lookup_attribute ("version_selector",
+ DECL_ATTRIBUTES (current_function_decl)) != NULL)
+ {
+ if (dump_file)
+ fprintf (dump_file, "Function with version_selector attribute found :"
+ " %s. Making constructor for it.\n",
+ current_function_name ());
+
+ handle_version_selector_attr_function (current_function_decl);
+ /* Assume there are no __builtin_dispatch calls in feature test
+ functions. So it is safe to return. */
+ return 0;
+ }
+
+ /* Find and lower __builtin_dispatch calls. */
+
+ FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (current_function_decl))
+ {
+ for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+ {
+ gimple stmt = gsi_stmt (gsi);
+ tree call_decl;
+
+ if (!is_gimple_call (stmt))
+ continue;
+
+ call_decl = gimple_call_fndecl (stmt);
+
+ if (call_decl == NULL)
+ continue;
+
+ if (strstr (cgraph_node_name (cgraph_node (call_decl)),
+ "__builtin_dispatch") == NULL)
+ continue;
+
+ if (dump_file)
+ {
+ fprintf (dump_file, "Converting __builtin_dispatch stmt in:%s\n",
+ current_function_name ());
+ print_gimple_stmt (dump_file, stmt, 0, TDF_VOPS);
+ }
+
+ if (builtin_stmt_list == NULL)
+ builtin_stmt_list = VEC_alloc (gimple, heap, 2);
+
+ gcc_assert (builtin_stmt_list != NULL);
+ VEC_safe_push (gimple, heap, builtin_stmt_list, stmt);
+ }
+ }
+
+ if (!builtin_stmt_list)
+ return 0;
+
+ for (ix = 0; VEC_iterate (gimple, builtin_stmt_list, ix, builtin_stmt);
+ ++ix)
+ convert_builtin_dispatch (builtin_stmt);
+
+ VEC_free (gimple, heap, builtin_stmt_list);
+
+ return 0;
+}
+
+static bool
+gate_convert_builtin_dispatch (void)
+{
+ return true;
+}
+
+struct gimple_opt_pass pass_tree_convert_builtin_dispatch =
+{
+ {
+ GIMPLE_PASS,
+ "convert_builtin_dispatch", /* name */
+ gate_convert_builtin_dispatch, /* gate */
+ do_convert_builtin_dispatch, /* execute */
+ NULL, /* sub */
+ NULL, /* next */
+ 0, /* static_pass_number */
+ TV_MVERSN_DISPATCH, /* tv_id */
+ PROP_cfg, /* properties_required */
+ PROP_cfg, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ TODO_verify_stmts | TODO_dump_func | /* todo_flags_finish */
+ TODO_cleanup_cfg | TODO_dump_cgraph |
+ TODO_verify_ssa
+ }
+};
diff --git a/gcc-4.4.3/gcc/objc/lang-specs.h b/gcc-4.4.3/gcc/objc/lang-specs.h
index 62ffb9954..50760048f 100644
--- a/gcc-4.4.3/gcc/objc/lang-specs.h
+++ b/gcc-4.4.3/gcc/objc/lang-specs.h
@@ -30,13 +30,13 @@ along with GCC; see the file COPYING3. If not see
%{traditional|ftraditional|traditional-cpp:\
%eGNU Objective C no longer supports traditional compilation}\
%{save-temps|no-integrated-cpp:cc1obj -E %(cpp_options) -o %{save-temps:%b.mi} %{!save-temps:%g.mi} \n\
- cc1obj -fpreprocessed %{save-temps:%b.mi} %{!save-temps:%g.mi} %(cc1_options) %{print-objc-runtime-info} %{gen-decls}}\
+ cc1obj -fpreprocessed %{save-temps:%b.mi} %{!save-temps:%g.mi} %(cc1_options) %(esp_options) %{print-objc-runtime-info} %{gen-decls}}\
%{!save-temps:%{!no-integrated-cpp:\
- cc1obj %(cpp_unique_options) %(cc1_options) %{print-objc-runtime-info} %{gen-decls}}}\
+ cc1obj %(cpp_unique_options) %(cc1_options) %(esp_options) %{print-objc-runtime-info} %{gen-decls}}}\
%{!fsyntax-only:%(invoke_as)}}}}", 0, 0, 0},
{".mi", "@objc-cpp-output", 0, 0, 0},
{"@objc-cpp-output",
- "%{!M:%{!MM:%{!E:cc1obj -fpreprocessed %i %(cc1_options) %{print-objc-runtime-info} %{gen-decls}\
+ "%{!M:%{!MM:%{!E:cc1obj -fpreprocessed %i %(cc1_options) %(esp_options) %{print-objc-runtime-info} %{gen-decls}\
%{!fsyntax-only:%(invoke_as)}}}}", 0, 0, 0},
{"@objective-c-header",
"%{E|M|MM:cc1obj -E %{traditional|ftraditional|traditional-cpp:-traditional-cpp}\
@@ -45,10 +45,10 @@ along with GCC; see the file COPYING3. If not see
%{traditional|ftraditional|traditional-cpp:\
%eGNU Objective C no longer supports traditional compilation}\
%{save-temps|no-integrated-cpp:cc1obj -E %(cpp_options) -o %{save-temps:%b.mi} %{!save-temps:%g.mi} \n\
- cc1obj -fpreprocessed %b.mi %(cc1_options) %{print-objc-runtime-info} %{gen-decls}\
+ cc1obj -fpreprocessed %b.mi %(cc1_options) %(esp_options) %{print-objc-runtime-info} %{gen-decls}\
-o %g.s %{!o*:--output-pch=%i.gch}\
%W{o*:--output-pch=%*}%V}\
%{!save-temps:%{!no-integrated-cpp:\
- cc1obj %(cpp_unique_options) %(cc1_options) %{print-objc-runtime-info} %{gen-decls}\
+ cc1obj %(cpp_unique_options) %(cc1_options) %(esp_options) %{print-objc-runtime-info} %{gen-decls}\
-o %g.s %{!o*:--output-pch=%i.gch}\
%W{o*:--output-pch=%*}%V}}}}}", 0, 0, 0},
diff --git a/gcc-4.4.3/gcc/objcp/lang-specs.h b/gcc-4.4.3/gcc/objcp/lang-specs.h
index ec8cfee42..1203661c2 100644
--- a/gcc-4.4.3/gcc/objcp/lang-specs.h
+++ b/gcc-4.4.3/gcc/objcp/lang-specs.h
@@ -36,7 +36,7 @@ along with GCC; see the file COPYING3. If not see
%(cpp_options) %2 -o %{save-temps:%b.mii} %{!save-temps:%g.mii} \n}\
cc1objplus %{save-temps|no-integrated-cpp:-fpreprocessed %{save-temps:%b.mii} %{!save-temps:%g.mii}}\
%{!save-temps:%{!no-integrated-cpp:%(cpp_unique_options)}}\
- %(cc1_options) %2 %{+e1*}\
+ %(cc1_options) %(esp_options) %2 %{+e1*}\
-o %g.s %{!o*:--output-pch=%i.gch} %W{o*:--output-pch=%*}%V}}}",
CPLUSPLUS_CPP_SPEC, 0, 0},
{"@objective-c++",
@@ -46,15 +46,15 @@ along with GCC; see the file COPYING3. If not see
%(cpp_options) %2 -o %{save-temps:%b.mii} %{!save-temps:%g.mii} \n}\
cc1objplus %{save-temps|no-integrated-cpp:-fpreprocessed %{save-temps:%b.mii} %{!save-temps:%g.mii}}\
%{!save-temps:%{!no-integrated-cpp:%(cpp_unique_options)}}\
- %(cc1_options) %2 %{+e1*}\
+ %(cc1_options) %(esp_options) %2 %{+e1*}\
%{!fsyntax-only:%(invoke_as)}}}}",
CPLUSPLUS_CPP_SPEC, 0, 0},
{".mii", "@objective-c++-cpp-output", 0, 0, 0},
{"@objective-c++-cpp-output",
"%{!M:%{!MM:%{!E:\
- cc1objplus -fpreprocessed %i %(cc1_options) %2 %{+e*}\
+ cc1objplus -fpreprocessed %i %(cc1_options) %(esp_options) %2 %{+e*}\
%{!fsyntax-only:%(invoke_as)}}}}", 0, 0, 0},
{"@objc++-cpp-output",
"%{!M:%{!MM:%{!E:\
- cc1objplus -fpreprocessed %i %(cc1_options) %2 %{+e*}\
+ cc1objplus -fpreprocessed %i %(cc1_options) %(esp_options) %2 %{+e*}\
%{!fsyntax-only:%(invoke_as)}}}}", 0, 0, 0},
diff --git a/gcc-4.4.3/gcc/optabs.c b/gcc-4.4.3/gcc/optabs.c
index 13e8e60ae..29def8c38 100644
--- a/gcc-4.4.3/gcc/optabs.c
+++ b/gcc-4.4.3/gcc/optabs.c
@@ -3300,7 +3300,8 @@ expand_unop (enum machine_mode mode, optab unoptab, rtx op0, rtx target,
if (unoptab == ffs_optab || unoptab == clz_optab || unoptab == ctz_optab
|| unoptab == popcount_optab || unoptab == parity_optab)
outmode
- = GET_MODE (hard_libcall_value (TYPE_MODE (integer_type_node)));
+ = GET_MODE (hard_libcall_value (TYPE_MODE (integer_type_node),
+ optab_libfunc (unoptab, mode)));
start_sequence ();
diff --git a/gcc-4.4.3/gcc/opts.c b/gcc-4.4.3/gcc/opts.c
index c6a92e650..5ab76edcc 100644
--- a/gcc-4.4.3/gcc/opts.c
+++ b/gcc-4.4.3/gcc/opts.c
@@ -45,9 +45,15 @@ along with GCC; see the file COPYING3. If not see
#include "plugin.h"
#include "cgraph.h"
+/* Defined in value-prof.c. */
+extern struct ffvpt_options_s ffvtp_process_options (const char *arg);
+
/* Defined in ipa-inline.c. */
extern bool cgraph_gate_ipa_early_inlining (void);
+/* Defined in coverage.c. */
+extern bool check_pmu_profile_options (const char *options);
+
/* Value of the -G xx switch, and whether it was passed or not. */
unsigned HOST_WIDE_INT g_switch_value;
bool g_switch_set;
@@ -355,6 +361,13 @@ static const char undocumented_msg[] = N_("This switch lacks documentation");
static const char undocumented_msg[] = "";
#endif
+/* Used for bookkeeping if -Werror/-Wno-error was specified to know
+ * whether to make certain warnings errors by default. */
+static bool flag_werror_set;
+
+/* Options related to floating point value profiling. */
+struct ffvpt_options_s ffvpt_options;
+
/* Used for bookkeeping on whether user set these flags so
-fprofile-use/-fprofile-generate does not use them. */
static bool profile_arc_flag_set, flag_profile_values_set;
@@ -1018,8 +1031,8 @@ decode_options (unsigned int argc, const char **argv)
else
set_param_value ("min-crossjump-insns", initial_min_crossjump_insns);
- /* Enable -Werror=coverage-mismatch by default */
- enable_warning_as_error("coverage-mismatch", 1, lang_mask);
+ /* Enable -Wcoverage-mismatch by default */
+ warn_coverage_mismatch = true;
if (first_time_p)
{
@@ -1044,6 +1057,18 @@ decode_options (unsigned int argc, const char **argv)
handle_options (argc, argv, lang_mask);
+ if (!flag_werror_set)
+ {
+ /* Enable -Werror=coverage-mismatch by default, if it hasn't
+ * been set explicitly */
+ if (warn_coverage_mismatch
+ && (global_dc->classify_diagnostic[OPT_Wcoverage_mismatch] ==
+ DK_UNSPECIFIED))
+ {
+ enable_warning_as_error("coverage-mismatch", 1, lang_mask);
+ }
+ }
+
/* If -gmlt was specified, make sure debug level is at least 1. */
if (generate_debug_line_table && debug_info_level < DINFO_LEVEL_TERSE)
debug_info_level = DINFO_LEVEL_TERSE;
@@ -1104,6 +1129,7 @@ decode_options (unsigned int argc, const char **argv)
flag_pic = flag_pie;
if (flag_pic && !flag_pie)
flag_shlib = 1;
+ first_time_p = false;
}
if (optimize == 0)
@@ -1183,13 +1209,6 @@ decode_options (unsigned int argc, const char **argv)
warn_thread_safety = 0;
}
- /* Save the current optimization options if this is the first call. */
- if (first_time_p)
- {
- optimization_default_node = build_optimization_node ();
- optimization_current_node = optimization_default_node;
- first_time_p = false;
- }
if (flag_conserve_stack)
{
if (!PARAM_SET_P (PARAM_LARGE_STACK_FRAME))
@@ -1698,6 +1717,10 @@ common_handle_option (size_t scode, const char *arg, int value,
set_Wextra (value);
break;
+ case OPT_Werror:
+ flag_werror_set = true;
+ break;
+
case OPT_Werror_:
enable_warning_as_error (arg, value, lang_mask);
break;
@@ -1960,6 +1983,15 @@ common_handle_option (size_t scode, const char *arg, int value,
flag_inline_functions = value;
break;
+ case OPT_fpmu_profile_generate_:
+ /* This should be ideally turned on in conjunction with
+ -fprofile-dir or -fprofile-generate in order to specify a
+ profile directory. */
+ if (check_pmu_profile_options (arg))
+ error ("Unrecognized pmu_profile_generate value \"%s\"", arg);
+ flag_pmu_profile_generate = xstrdup (arg);
+ break;
+
case OPT_fprofile_values:
flag_profile_values_set = true;
break;
@@ -1991,6 +2023,10 @@ common_handle_option (size_t scode, const char *arg, int value,
flag_value_profile_transformations_set = true;
break;
+ case OPT_ffvpt_functions_:
+ ffvpt_options = ffvtp_process_options (arg);
+ break;
+
case OPT_frandom_seed:
/* The real switch is -fno-random-seed. */
if (value)
@@ -2225,6 +2261,11 @@ common_handle_option (size_t scode, const char *arg, int value,
/* No-op. Used by the driver and passed to us because it starts with f. */
break;
+ case OPT_Wuninitialized:
+ /* Also turn on maybe uninitialized warning. */
+ warn_maybe_uninitialized = value;
+ break;
+
default:
/* If the flag was handled in a standard way, assume the lack of
processing here is intentional. */
@@ -2274,6 +2315,7 @@ set_Wextra (int setting)
warn_uninitialized = 0;
else if (warn_uninitialized != 1)
warn_uninitialized = 2;
+ warn_maybe_uninitialized = setting;
}
/* Used to set the level of strict aliasing warnings,
@@ -2489,6 +2531,8 @@ enable_warning_as_error (const char *arg, int value, unsigned int lang_mask)
&& cl_options[option_index].flag_var
&& kind == DK_ERROR)
*(int *) cl_options[option_index].flag_var = 1;
+ if (option_index == OPT_Wuninitialized)
+ enable_warning_as_error ("maybe-uninitialized", value, lang_mask);
}
free (new_option);
}
diff --git a/gcc-4.4.3/gcc/params.def b/gcc-4.4.3/gcc/params.def
index 0692e4ce0..39891d2f1 100644
--- a/gcc-4.4.3/gcc/params.def
+++ b/gcc-4.4.3/gcc/params.def
@@ -159,6 +159,32 @@ DEFPARAM (PARAM_MIN_COUNT_FRACTION_FOR_INLINE_COLD,
"Minimum expected count in a hot callee from a cold callsite for it to be an inline canditate, as a fraction of maximum count.",
10, 0, 0)
+DEFPARAM (PARAM_INLINE_PRIORITY_THRESHOLD,
+ "inline-priority-threshold",
+ "the maximum priority (growth/frequency) of a non-inline callsite to be inlined without -finline-functions",
+ 3500, 0, 0)
+
+DEFPARAM (PARAM_INLINE_FUNCTION_SIZE_ADJUSTMENT,
+ "inline-function-size-adjustment",
+ "Number of extra insns to use in inliner function size estimate to account for prologue, epilogue, and function alignment",
+ 20, 0, 0)
+
+DEFPARAM (PARAM_INLINE_ADDRESS_TAKEN_FUNCTION_EMIT_PROBABILITY,
+ "inline-address-taken-function-emit-probability",
+ "Probability that a function whose address is taken will be emitted in the final binary if all callsites in this unit are inlined",
+ 75, 0, 100)
+
+DEFPARAM (PARAM_INLINE_ADDRESS_NOT_TAKEN_FUNCTION_EMIT_PROBABILITY,
+ "inline-address-not-taken-function-emit-probability",
+ "Probability that a function whose address is not taken will be emitted in the final binary if all callsites in this unit are inlined",
+ 15, 0, 100)
+
+DEFPARAM (PARAM_INLINE_CONST_PARAM_ADJUSTMENT,
+ "inline-const-param-adjustment",
+ "Adjustment in percent to the inlining priority of a callsite for each constant parameter",
+ 0, 0, 0)
+
+
/* Parameters controlling the growth of hot components of the call
graph. The size of a hot component (in internal gcc instructions)
is the total of all instructions within hot basic blocks of the
@@ -252,7 +278,7 @@ DEFPARAM(PARAM_LARGE_STACK_FRAME,
DEFPARAM(PARAM_STACK_FRAME_GROWTH,
"large-stack-frame-growth",
"Maximal stack frame growth due to inlining (in percent)",
- 10, 0, 0)
+ 0, 0, 0)
/* The GCSE optimization will be disabled if it would require
significantly more memory than this value. */
@@ -935,6 +961,13 @@ DEFPARAM (PARAM_MAX_LIPO_GROUP,
"maximum module group size.",
0, 0, 10000)
+/* In LIPO mode, stop processing any further auxiliary modules
+ if current memory consumption exceeds this limit (in kb). */
+DEFPARAM (PARAM_MAX_LIPO_MEMORY,
+ "max-lipo-mem",
+ "don't import aux files if memory consumption exceeds this value",
+ 2400000, 0, 0)
+
/* Used for debugging purpose. Tell the compiler to find
the gcda file in the current directory. */
DEFPARAM (PARAM_GCOV_DEBUG,
@@ -971,6 +1004,31 @@ DEFPARAM (PARAM_SAMPLEFDO_INST_THRESH,
"instructions sampled in it",
5, 0, 1000)
+DEFPARAM (PARAM_REUSEDIST_MEAN_DIST_LARGE_THRESH,
+ "reusedist-mean-dist-large-thresh",
+ "Generate NTA stringops only if reusedist at least this size",
+ 10000000, 0, 0)
+
+DEFPARAM (PARAM_REUSEDIST_MEAN_DIST_SMALL_THRESH,
+ "reusedist-mean-dist-small-thresh",
+ "Force temporal stringops if reusedist at most this size",
+ 100000, 0, 0)
+
+DEFPARAM (PARAM_REUSEDIST_CALL_COUNT_THRESH,
+ "reusedist-call-count-thresh",
+ "Generate NTA stringops only if call count at least this large",
+ 0, 0, 0)
+
+DEFPARAM (PARAM_REUSEDIST_MEMCPY_SIZE_THRESH,
+ "reusedist-memcpy-size-thresh",
+ "Generate memcpy-nta only if size at least this large",
+ 4096, 0, 0)
+
+DEFPARAM (PARAM_REUSEDIST_MEMSET_SIZE_THRESH,
+ "reusedist-memset-size-thresh",
+ "Generate NTA memset only if size at least this large",
+ 122880, 0, 0)
+
/* When dumping the call graph only include nodes and edges with a
count greater than this values. */
DEFPARAM (PARAM_CGRAPH_DUMP_COUNT_THRESHOLD,
@@ -978,6 +1036,35 @@ DEFPARAM (PARAM_CGRAPH_DUMP_COUNT_THRESHOLD,
"minimum node count for inclusion in VCG call graph dump",
0, 0, 0)
+/* Only output those call graph edges in .note.callgraph.text sections
+ whose count is greater than this value. */
+DEFPARAM (PARAM_NOTE_CGRAPH_SECTION_EDGE_THRESHOLD,
+ "note-cgraph-section-edge-threshold",
+ "minimum call graph edge count for inclusion in "
+ ".note.callgraph.text section",
+ 0, 0, 0)
+
+DEFPARAM (PARAM_PROFILE_GENERATE_SAMPLING_RATE,
+ "profile-generate-sampling-rate",
+ "sampling rate with -fprofile-generate-sampling",
+ 100, 0, 2000000000)
+
+DEFPARAM (PARAM_PMU_PROFILE_N_ADDRESS,
+ "pmu_profile_n_addresses",
+ "While doing PMU profiling symbolize this many top addresses.",
+ 50, 1, 10000)
+
+DEFPARAM (PARAM_NUMBER_OF_MVERSN_CLONES,
+ "num-mversn-clones",
+ "maximum number of functions to be cloned while doing "
+ "multiversioning",
+ 4, 0, 100)
+
+DEFPARAM (PARAM_MVERSN_CLONE_CGRAPH_DEPTH,
+ "mversn-clone-depth",
+ "maximum length of the call graph path to be cloned "
+ "while doing multiversioning",
+ 1, 0, 5)
/*
Local variables:
mode:c
diff --git a/gcc-4.4.3/gcc/passes.c b/gcc-4.4.3/gcc/passes.c
index e4765bf66..efc5370ab 100644
--- a/gcc-4.4.3/gcc/passes.c
+++ b/gcc-4.4.3/gcc/passes.c
@@ -581,6 +581,18 @@ init_optimization_passes (void)
}
NEXT_PASS (pass_ipa_increase_alignment);
NEXT_PASS (pass_ipa_matrix_reorg);
+ /* The ipa multiversion_dispatch pass must run before ipa_cp. Otherwise,
+ it must restore ipa_node_params data structures for the clones
+ set by ipa_cp. */
+ NEXT_PASS (pass_ipa_multiversion_dispatch);
+ {
+ struct opt_pass **p = &pass_ipa_multiversion_dispatch.pass.sub;
+ NEXT_PASS (pass_tree_convert_builtin_dispatch);
+ /* Rebuilding cgraph edges is necessary as the above passes change
+ the call graph. Otherwise, future optimizations use the old
+ call graph and make wrong decisions sometimes.*/
+ NEXT_PASS (pass_rebuild_cgraph_edges);
+ }
NEXT_PASS (pass_ipa_cp);
NEXT_PASS (pass_ipa_inline);
NEXT_PASS (pass_ipa_reference);
@@ -594,6 +606,10 @@ init_optimization_passes (void)
output to the assembler file. */
p = &all_passes;
NEXT_PASS (pass_direct_call_profile);
+ /* Synthesize variables of union type whose fields are local variable
+ that can share stack slots. Do this before transformations that
+ perform code motion. */
+ NEXT_PASS (pass_stack_overlay);
NEXT_PASS (pass_all_optimizations);
{
struct opt_pass **p = &pass_all_optimizations.pass.sub;
@@ -743,7 +759,6 @@ init_optimization_passes (void)
NEXT_PASS (pass_cse);
NEXT_PASS (pass_rtl_fwprop);
NEXT_PASS (pass_gcse);
- NEXT_PASS (pass_simplify_got);
NEXT_PASS (pass_rtl_ifcvt);
/* Perform loop optimizations. It might be better to do them a bit
sooner, but we want the profile feedback to work more
@@ -759,6 +774,7 @@ init_optimization_passes (void)
NEXT_PASS (pass_rtl_loop_done);
*p = NULL;
}
+ NEXT_PASS (pass_simplify_got);
NEXT_PASS (pass_web);
NEXT_PASS (pass_jump_bypass);
NEXT_PASS (pass_cse2);
diff --git a/gcc-4.4.3/gcc/pmu-profile.c b/gcc-4.4.3/gcc/pmu-profile.c
new file mode 100644
index 000000000..4a62406f8
--- /dev/null
+++ b/gcc-4.4.3/gcc/pmu-profile.c
@@ -0,0 +1,1553 @@
+/* Performance monitoring unit (PMU) profiler. If available, use an
+ external tool to collect hardware performance counter data and
+ write it in the .gcda files.
+
+ Copyright (C) 2010. Free Software Foundation, Inc.
+ Contributed by Sharad Singhai <singhai@google.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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
+
+#include "tconfig.h"
+#include "tsystem.h"
+#include "coretypes.h"
+#include "tm.h"
+#if (defined (__x86_64__) || defined (__i386__))
+#include "cpuid.h"
+#endif
+
+#if defined(inhibit_libc)
+#define IN_LIBGCOV (-1)
+#else
+#include <stdio.h>
+#include <stdlib.h>
+#define IN_LIBGCOV 1
+ #if defined(L_gcov)
+ #define GCOV_LINKAGE /* nothing */
+ #endif
+#endif
+#include "gcov-io.h"
+#ifdef TARGET_POSIX_IO
+ #include <fcntl.h>
+ #include <signal.h>
+ #include <sys/stat.h>
+ #include <sys/types.h>
+#endif
+
+#if defined(inhibit_libc)
+#else
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#define XNEWVEC(type,ne) (type *)calloc((ne),sizeof(type))
+#define XNEW(type) (type *)malloc(sizeof(type))
+#define XDELETEVEC(p) free(p)
+#define XDELETE(p) free(p)
+
+#define PFMON_CMD "/usr/bin/pfmon"
+#define ADDR2LINE_CMD "/usr/bin/addr2line"
+#define PMU_TOOL_MAX_ARGS (20)
+static char default_addr2line[] = "??:0";
+static const char pfmon_ll_header[] = "# counts %self %cum "
+ "<10 <32 <64 <256 <1024 >=1024 %wself "
+ "code addr symbol\n";
+static const char pfmon_bm_header[] =
+ "# counts %self %cum code addr symbol\n";
+
+const char *pfmon_intel_ll_args[PMU_TOOL_MAX_ARGS] = {
+ PFMON_CMD,
+ "--aggregate-results",
+ "--follow-all",
+ "--with-header",
+ "--smpl-module=pebs-ll",
+ "--ld-lat-threshold=4",
+ "--pebs-ll-dcmiss-code",
+ "--resolve-addresses",
+ "-emem_inst_retired:LATENCY_ABOVE_THRESHOLD",
+ "--long-smpl-periods=4000",
+ 0 /* terminating NULL must be present */
+};
+
+const char *pfmon_amd_ll_args[PMU_TOOL_MAX_ARGS] = {
+ PFMON_CMD,
+ "--aggregate-results",
+ "--follow-all",
+ "-uk",
+ "--with-header",
+ "--smpl-module=ibs",
+ "--resolve-addresses",
+ "-eibsop_event:uops",
+ "--ibs-dcmiss-code",
+ "--long-smpl-periods=4000",
+ 0 /* terminating NULL must be present */
+};
+
+const char *pfmon_intel_brm_args[PMU_TOOL_MAX_ARGS] = {
+ PFMON_CMD,
+ "--aggregate-results",
+ "--follow-all",
+ "--with-header",
+ "--resolve-addresses",
+ "-eMISPREDICTED_BRANCH_RETIRED",
+ "--long-smpl-periods=10000",
+ 0 /* terminating NULL must be present */
+};
+
+const char *pfmon_amd_brm_args[PMU_TOOL_MAX_ARGS] = {
+ PFMON_CMD,
+ "--aggregate-results",
+ "--follow-all",
+ "--with-header",
+ "--resolve-addresses",
+ "-eRETIRED_MISPREDICTED_BRANCH_INSTRUCTIONS",
+ "--long-smpl-periods=10000",
+ 0 /* terminating NULL must be present */
+};
+
+const char *addr2line_args[PMU_TOOL_MAX_ARGS] = {
+ ADDR2LINE_CMD,
+ "-e",
+ 0 /* terminating NULL must be present */
+};
+
+
+enum pmu_tool_type
+{
+ PTT_PFMON,
+ PTT_LAST
+};
+
+enum pmu_event_type
+{
+ PET_INTEL_LOAD_LATENCY,
+ PET_AMD_LOAD_LATENCY,
+ PET_INTEL_BRANCH_MISPREDICT,
+ PET_AMD_BRANCH_MISPREDICT,
+ PET_LAST
+};
+
+typedef struct pmu_tool_fns {
+ const char *name; /* name of the pmu tool */
+ /* pmu tool commandline argument. */
+ const char **arg_array;
+ /* Initialize pmu module. */
+ void *(*init_pmu_module) (void);
+ /* Start profililing. */
+ void (*start_pmu_module) (pid_t ppid, char *tmpfile, const char **args);
+ /* Stop profililing. */
+ void (*stop_pmu_module) (void);
+ /* How to parse the output generated by the PMU tool. */
+ int (*parse_pmu_output) (char *filename, void *pmu_data);
+ /* How to write parsed pmu data into gcda file. */
+ void (*gcov_write_pmu_data) (void *data);
+ /* How to cleanup any data structure created during parsing. */
+ void (*cleanup_pmu_data) (void *data);
+ /* How to initialize symbolizer for the PPID. */
+ int (*start_symbolizer) (pid_t ppid);
+ void (*end_symbolizer) (void);
+ char *(*symbolize) (void *addr);
+} pmu_tool_fns;
+
+enum pmu_state
+{
+ PMU_NONE, /* Not configurated at all. */
+ PMU_INITIALIZED, /* Configured and initialized. */
+ PMU_ERROR, /* Configuration error. Cannot recover. */
+ PMU_ON, /* Currently profiling. */
+ PMU_OFF /* Currently stopped, but can be restarted. */
+};
+
+enum cpu_vendor_signature
+{
+ CPU_VENDOR_UKNOWN = 0,
+ CPU_VENDOR_INTEL = 0x756e6547, /* Genu */
+ CPU_VENDOR_AMD = 0x68747541 /* Auth */
+};
+
+/* Info about pmu tool during the run time. */
+struct pmu_tool_info
+{
+ /* Current pmu tool. */
+ enum pmu_tool_type tool;
+ /* Current event. */
+ enum pmu_event_type event;
+ /* filename for storing the pmu profile. */
+ char *pmu_profile_filename;
+ /* Intermediate file where the tool stores the PMU data. */
+ char *raw_pmu_profile_filename;
+ /* Where PMU tool's stderr should be stored. */
+ char *tool_stderr_filename;
+ enum pmu_state pmu_profiling_state;
+ enum cpu_vendor_signature cpu_vendor; /* as discovered by cpuid */
+ pid_t pmu_tool_pid; /* process id of the pmu tool */
+ pid_t symbolizer_pid; /* process id of the symbolizer */
+ int symbolizer_to_pipefd[2]; /* pipe for writing to the symbolizer */
+ int symbolizer_from_pipefd[2]; /* pipe for reading from the symbolizer */
+ void *pmu_data; /* an opaque pointer for the tool to store pmu data */
+ int verbose; /* turn on additional debugging */
+ unsigned top_n_address; /* how many addresses to symbolize */
+ pmu_tool_fns *tool_details; /* list of functions how to start/stop/parse */
+};
+
+/* Global struct for recordkeeping. */
+static struct pmu_tool_info *the_pmu_tool_info;
+
+/* Additional info is printed if these are non-zero. */
+static int tool_debug = 0;
+static int sym_debug = 0;
+
+static int parse_load_latency_line (char *line, gcov_pmu_ll_info_t *ll_info);
+static int parse_branch_mispredict_line (char *line,
+ gcov_pmu_brm_info_t *brm_info);
+static unsigned convert_pct_to_unsigned (float pct);
+static void start_pfmon_module (pid_t ppid, char *tmpfile, const char **pfmon_args);
+static void *init_pmu_load_latency (void);
+static void *init_pmu_branch_mispredict (void);
+static void destroy_load_latency_infos (void *info);
+static void destroy_branch_mispredict_infos (void *info);
+static int parse_pfmon_load_latency (char *filename, void *pmu_data);
+static int parse_pfmon_branch_mispredicts (char *filename, void *pmu_data);
+static gcov_unsigned_t gcov_tag_pmu_tool_header_length (gcov_pmu_tool_header_t
+ *header);
+static void gcov_write_tool_header (gcov_pmu_tool_header_t *header);
+static void gcov_write_load_latency_infos (void *info);
+static void gcov_write_branch_mispredict_infos (void *info);
+static void gcov_write_ll_line (const gcov_pmu_ll_info_t *ll_info);
+static void gcov_write_branch_mispredict_line (const gcov_pmu_brm_info_t
+ *brm_info);
+static int start_addr2line_symbolizer (pid_t pid);
+static void end_addr2line_symbolizer (void);
+static char *symbolize_addr2line (void *p);
+static void reset_symbolizer_parent_pipes (void);
+static void reset_symbolizer_child_pipes (void);
+/* parse and cache relevant tool info. */
+static int parse_pmu_profile_options (const char *options);
+static gcov_pmu_tool_header_t *parse_pfmon_tool_header (FILE *fp,
+ const char *end_header);
+
+
+/* How to access the necessary functions for the PMU tools. */
+pmu_tool_fns all_pmu_tool_fns[PTT_LAST][PET_LAST] = {
+ {
+ {
+ "intel-load-latency", /* name */
+ pfmon_intel_ll_args, /* tool args */
+ init_pmu_load_latency, /* initialization */
+ start_pfmon_module, /* start */
+ 0, /* stop */
+ parse_pfmon_load_latency, /* parse */
+ gcov_write_load_latency_infos, /* write */
+ destroy_load_latency_infos, /* cleanup */
+ start_addr2line_symbolizer, /* start symbolizer */
+ end_addr2line_symbolizer, /* end symbolizer */
+ symbolize_addr2line, /* symbolize */
+ },
+ {
+ "amd-load-latency", /* name */
+ pfmon_amd_ll_args, /* tool args */
+ init_pmu_load_latency, /* initialization */
+ start_pfmon_module, /* start */
+ 0, /* stop */
+ parse_pfmon_load_latency, /* parse */
+ gcov_write_load_latency_infos, /* write */
+ destroy_load_latency_infos, /* cleanup */
+ start_addr2line_symbolizer, /* start symbolizer */
+ end_addr2line_symbolizer, /* end symbolizer */
+ symbolize_addr2line, /* symbolize */
+ },
+ {
+ "intel-branch-mispredict", /* name */
+ pfmon_intel_brm_args, /* tool args */
+ init_pmu_branch_mispredict, /* initialization */
+ start_pfmon_module, /* start */
+ 0, /* stop */
+ parse_pfmon_branch_mispredicts, /* parse */
+ gcov_write_branch_mispredict_infos,/* write */
+ destroy_branch_mispredict_infos, /* cleanup */
+ start_addr2line_symbolizer, /* start symbolizer */
+ end_addr2line_symbolizer, /* end symbolizer */
+ symbolize_addr2line, /* symbolize */
+ },
+ {
+ "amd-branch-mispredict", /* name */
+ pfmon_amd_brm_args, /* tool args */
+ init_pmu_branch_mispredict, /* initialization */
+ start_pfmon_module, /* start */
+ 0, /* stop */
+ parse_pfmon_branch_mispredicts, /* parse */
+ gcov_write_branch_mispredict_infos,/* write */
+ destroy_branch_mispredict_infos, /* cleanup */
+ start_addr2line_symbolizer, /* start symbolizer */
+ end_addr2line_symbolizer, /* end symbolizer */
+ symbolize_addr2line, /* symbolize */
+ }
+ }
+};
+
+/* Determine the CPU vendor. Currently only distinguishes x86 based
+ cpus where the vendor is either Intel or AMD. Returns one of the
+ enum cpu_vendor_signatures. */
+
+static unsigned int
+get_x86cpu_vendor (void)
+{
+ unsigned int vendor = CPU_VENDOR_UKNOWN;
+
+#if (defined (__x86_64__) || defined (__i386__))
+ if (__get_cpuid_max (0, &vendor) < 1)
+ return CPU_VENDOR_UKNOWN; /* Cannot determine cpu type. */
+#endif
+
+ if (vendor == CPU_VENDOR_INTEL || vendor == CPU_VENDOR_AMD)
+ return vendor;
+ else
+ return CPU_VENDOR_UKNOWN;
+}
+
+
+/* Parse PMU tool option string provided on the command line and store
+ information in global structure. Return 0 on success, otherwise
+ return 1. Any changes to this should be synced with
+ check_pmu_profile_options() which does compile time check. */
+
+static int
+parse_pmu_profile_options (const char *options)
+{
+ enum pmu_tool_type ptt = the_pmu_tool_info->tool;
+ enum pmu_event_type pet = PET_LAST;
+ const char *pmutool_path;
+ the_pmu_tool_info->cpu_vendor = get_x86cpu_vendor ();
+ /* Determine the platform we are running on. */
+ if (the_pmu_tool_info->cpu_vendor == CPU_VENDOR_UKNOWN)
+ {
+ /* Cpuid failed or uknown vendor. */
+ the_pmu_tool_info->pmu_profiling_state = PMU_ERROR;
+ return 1;
+ }
+
+ /* Validate the options. */
+ if (strcmp(options, "load-latency") &&
+ strcmp(options, "load-latency-verbose") &&
+ strcmp(options, "branch-mispredict") &&
+ strcmp(options, "branch-mispredict-verbose"))
+ return 1;
+
+ /* Check if are aksed to collect load latency PMU data. */
+ if (!strcmp(options, "load-latency") ||
+ !strcmp(options, "load-latency-verbose"))
+ {
+ if (the_pmu_tool_info->cpu_vendor == CPU_VENDOR_INTEL)
+ pet = PET_INTEL_LOAD_LATENCY;
+ else
+ pet = PET_AMD_LOAD_LATENCY;
+ if (!strcmp(options, "load-latency-verbose"))
+ the_pmu_tool_info->verbose = 1;
+ }
+
+ /* Check if are aksed to collect branch mispredict PMU data. */
+ if (!strcmp(options, "branch-mispredict") ||
+ !strcmp(options, "branch-mispredict-verbose"))
+ {
+ if (the_pmu_tool_info->cpu_vendor == CPU_VENDOR_INTEL)
+ pet = PET_INTEL_BRANCH_MISPREDICT;
+ else
+ pet = PET_AMD_BRANCH_MISPREDICT;
+ if (!strcmp(options, "branch-mispredict-verbose"))
+ the_pmu_tool_info->verbose = 1;
+ }
+
+ the_pmu_tool_info->tool_details = &all_pmu_tool_fns[ptt][pet];
+ the_pmu_tool_info->event = pet;
+
+ /* Allow users to override the default tool path. */
+ pmutool_path = getenv ("GCOV_PMUTOOL_PATH");
+ if (pmutool_path && strlen (pmutool_path))
+ the_pmu_tool_info->tool_details->arg_array[0] = pmutool_path;
+
+ return 0;
+}
+
+/* Do the initialization of addr2line symbolizer for the process id
+ given by TASK_PID. It forks an addr2line process and creates two
+ pipes where addresses can be written and source_filename:line_num
+ entries can be read. Returns 0 on success, non-zero otherwise. */
+
+static int
+start_addr2line_symbolizer (pid_t task_pid)
+{
+ pid_t pid;
+ char *addr2line_path;
+
+ /* Allow users to override the default addr2line path. */
+ addr2line_path = getenv ("GCOV_ADDR2LINE_PATH");
+ if (addr2line_path && strlen (addr2line_path))
+ addr2line_args[0] = addr2line_path;
+
+ if (pipe (the_pmu_tool_info->symbolizer_from_pipefd) == -1)
+ {
+ fprintf (stderr, "Cannot create symbolizer write pipe.\n");
+ return 1;
+ }
+ if (pipe (the_pmu_tool_info->symbolizer_to_pipefd) == -1)
+ {
+ fprintf (stderr, "Cannot create symbolizer read pipe.\n");
+ return 1;
+ }
+
+ pid = fork ();
+ if (pid == -1)
+ {
+ /* error condition */
+ fprintf (stderr, "Cannot create symbolizer process.\n");
+ reset_symbolizer_parent_pipes ();
+ reset_symbolizer_child_pipes ();
+ return 1;
+ }
+
+ if (pid == 0)
+ {
+ /* child does an exec and then connects to/from the pipe */
+ unsigned n_args = 0;
+ char proc_exe_buf[128];
+ int new_write_fd, new_read_fd;
+ int i;
+
+ /* Go over the current addr2line args. */
+ for (i = 0; i < PMU_TOOL_MAX_ARGS && addr2line_args[i]; ++i)
+ n_args++;
+
+ /* we are going to add one more arg for the /proc/pid/exe */
+ if (n_args >= (PMU_TOOL_MAX_ARGS - 1))
+ {
+ fprintf (stderr, "too many addr2line args: %d\n", n_args);
+ _exit (0);
+ }
+ snprintf (proc_exe_buf, sizeof (proc_exe_buf) - 1, "/proc/%d/exe",
+ task_pid);
+
+ /* add the extra arg */
+ addr2line_args[n_args] = proc_exe_buf;
+ n_args++;
+
+ addr2line_args[n_args] = (const char *)NULL; /* add terminating NULL */
+
+ if (sym_debug)
+ {
+ fprintf (stderr, "addr2line args:");
+ for (i = 0; i < PMU_TOOL_MAX_ARGS && addr2line_args[i]; ++i)
+ fprintf (stderr, " %s", addr2line_args[i]);
+ fprintf (stderr, "\n");
+ }
+
+ /* close unused ends of the two pipes. */
+ reset_symbolizer_child_pipes ();
+
+ /* connect the pipes to stdin/stdout of the child process. */
+ new_read_fd = dup2 (the_pmu_tool_info->symbolizer_to_pipefd[0], 0);
+ new_write_fd = dup2 (the_pmu_tool_info->symbolizer_from_pipefd[1], 1);
+ if (new_read_fd == -1 || new_write_fd == -1)
+ {
+ fprintf (stderr, "could not dup symbolizer fds\n");
+ reset_symbolizer_parent_pipes ();
+ reset_symbolizer_child_pipes ();
+ _exit (0);
+ }
+ the_pmu_tool_info->symbolizer_to_pipefd[0] = new_read_fd;
+ the_pmu_tool_info->symbolizer_from_pipefd[1] = new_write_fd;
+
+ /* Do execve with NULL env. */
+ execve (addr2line_args[0], (char * const*)addr2line_args,
+ (char * const*)NULL);
+ /* exec returned, an error condition. */
+ fprintf (stderr, "could not create symbolizer process: %s\n",
+ addr2line_args[0]);
+ reset_symbolizer_parent_pipes ();
+ reset_symbolizer_child_pipes ();
+ _exit (0);
+ }
+ else
+ {
+ /* parent */
+ the_pmu_tool_info->symbolizer_pid = pid;
+ /* close unused ends of the two pipes. */
+ reset_symbolizer_parent_pipes ();
+ return 0;
+ }
+ return 0;
+}
+
+/* close unused write end of the FROM-pipe and read end of the
+ TO-pipe. */
+
+static void
+reset_symbolizer_parent_pipes (void)
+{
+ if (the_pmu_tool_info->symbolizer_from_pipefd[1] != -1)
+ {
+ close (the_pmu_tool_info->symbolizer_from_pipefd[1]);
+ the_pmu_tool_info->symbolizer_from_pipefd[1] = -1;
+ }
+ if (the_pmu_tool_info->symbolizer_to_pipefd[0] != -1)
+ {
+ close (the_pmu_tool_info->symbolizer_to_pipefd[0]);
+ the_pmu_tool_info->symbolizer_to_pipefd[0] = -1;
+ }
+}
+
+/* Close unused write end of the TO-pipe and read end of the
+ FROM-pipe. */
+
+static void
+reset_symbolizer_child_pipes (void)
+{
+ if (the_pmu_tool_info->symbolizer_to_pipefd[1] != -1)
+ {
+ close (the_pmu_tool_info->symbolizer_to_pipefd[1]);
+ the_pmu_tool_info->symbolizer_to_pipefd[1] = -1;
+ }
+ if (the_pmu_tool_info->symbolizer_from_pipefd[0] != -1)
+ {
+ close (the_pmu_tool_info->symbolizer_from_pipefd[0]);
+ the_pmu_tool_info->symbolizer_from_pipefd[0] = -1;
+ }
+}
+
+
+/* Perform cleanup for the symbolizer process. */
+
+static void
+end_addr2line_symbolizer (void)
+{
+ int pid_status;
+ int wait_status;
+ pid_t pid = the_pmu_tool_info->symbolizer_pid;
+
+ /* symbolizer was not running */
+ if (!pid)
+ return;
+
+ reset_symbolizer_parent_pipes ();
+ reset_symbolizer_child_pipes ();
+ kill (pid, SIGTERM);
+ wait_status = waitpid (pid, &pid_status, 0);
+ if (sym_debug)
+ {
+ if (wait_status == pid)
+ fprintf (stderr, "Normal exit. symbolizer terminated.\n");
+ else
+ fprintf (stderr, "Abnormal exit. symbolizer status, %d.\n", pid_status);
+ }
+ the_pmu_tool_info->symbolizer_pid = 0; /* symoblizer no longer running */
+}
+
+
+/* Given an address ADDR, return a string containing
+ source_filename:line_num entries. */
+
+static char *
+symbolize_addr2line (void *addr)
+{
+ char buf[32]; /* holds the ascii version of address */
+ int write_count;
+ int read_count;
+ char *srcfile_linenum;
+ size_t max_length = 1024;
+
+ if (!the_pmu_tool_info->symbolizer_pid)
+ return default_addr2line; /* symbolizer is not running */
+
+ write_count = snprintf (buf, sizeof (buf) - 1, "%p\n", addr);
+
+ /* write the address into the pipe */
+ if (write (the_pmu_tool_info->symbolizer_to_pipefd[1], buf, write_count)
+ < write_count)
+ {
+ if (sym_debug)
+ fprintf (stderr, "Cannot write symbolizer pipe.\n");
+ return default_addr2line;
+ }
+
+ srcfile_linenum = XNEWVEC (char, max_length);
+ read_count = read (the_pmu_tool_info->symbolizer_from_pipefd[0],
+ srcfile_linenum, max_length);
+ if (read_count == -1)
+ {
+ if (sym_debug)
+ fprintf (stderr, "Cannot read symbolizer pipe.\n");
+ XDELETEVEC (srcfile_linenum);
+ return default_addr2line;
+ }
+
+ srcfile_linenum[read_count] = 0;
+ if (sym_debug)
+ fprintf (stderr, "symbolizer: for address %p, read_count %d, got %s\n",
+ addr, read_count, srcfile_linenum);
+ return srcfile_linenum;
+}
+
+/* Start monitoring PPID process via pfmon tool using TMPFILE as a
+ file to store the raw data and using PFMON_ARGS as the command line
+ arguments. */
+
+static void
+start_pfmon_module (pid_t ppid, char *tmpfile, const char **pfmon_args)
+{
+ int i;
+ unsigned int n_args = 0;
+ unsigned n_chars;
+ char pid_buf[64];
+ char filename_buf[1024];
+ char top_n_buf[24];
+ unsigned extra_args;
+
+ /* go over the current pfmon args */
+ for (i = 0; i < PMU_TOOL_MAX_ARGS && pfmon_args[i]; ++i)
+ n_args++;
+
+ if (the_pmu_tool_info->verbose)
+ extra_args = 4; /* account for additional --verbose */
+ else
+ extra_args = 3;
+
+ /* we are going to add args */
+ if (n_args >= (PMU_TOOL_MAX_ARGS - extra_args))
+ {
+ fprintf (stderr, "too many pfmon args: %d\n", n_args);
+ _exit (0);
+ }
+
+ n_chars = snprintf (pid_buf, sizeof (pid_buf), "--attach-task=%ld",
+ (long)ppid);
+ if (n_chars >= sizeof (pid_buf))
+ {
+ fprintf (stderr, "pfmon task id too long: %s\n", pid_buf);
+ return;
+ }
+ pfmon_args[n_args] = pid_buf;
+ n_args++;
+
+ n_chars = snprintf (filename_buf, sizeof (filename_buf), "--smpl-outfile=%s",
+ tmpfile);
+ if (n_chars >= sizeof (filename_buf))
+ {
+ fprintf (stderr, "pfmon filename too long: %s\n", filename_buf);
+ return;
+ }
+ pfmon_args[n_args] = filename_buf;
+ n_args++;
+
+ n_chars = snprintf (top_n_buf, sizeof (top_n_buf), "--smpl-show-top=%d",
+ the_pmu_tool_info->top_n_address);
+ if (n_chars >= sizeof (top_n_buf))
+ {
+ fprintf (stderr, "pfmon option too long: %s\n", top_n_buf);
+ return;
+ }
+ pfmon_args[n_args] = top_n_buf;
+ n_args++;
+
+ if (the_pmu_tool_info->verbose) {
+ /* Add --verbose as well. */
+ pfmon_args[n_args] = "--verbose";
+ n_args++;
+ }
+ pfmon_args[n_args] = (char *)NULL;
+
+ if (tool_debug)
+ {
+ fprintf (stderr, "pfmon args:");
+ for (i = 0; i < PMU_TOOL_MAX_ARGS && pfmon_args[i]; ++i)
+ fprintf (stderr, " %s", pfmon_args[i]);
+ fprintf (stderr, "\n");
+ }
+ /* Do execve with NULL env. */
+ execve (pfmon_args[0], (char *const *)pfmon_args, (char * const*)NULL);
+ /* does not return */
+}
+
+/* Convert a fractional PERCENT to an unsigned integer after
+ muliplying by 100. */
+
+static unsigned
+convert_pct_to_unsigned (float pct)
+{
+ return (unsigned)(pct * 100.0);
+}
+
+/* Parse the load latency info pointed by LINE and save it into
+ LL_INFO. Returns 0 if the line was parsed successfully, non-zero
+ otherwise.
+
+ An example header+line look like these:
+ "counts %self %cum <10 <32 <64 <256 <1024 >=1024
+ %wself code addr symbol"
+ "218 24.06% 24.06% 100.00% 0.00% 0.00% 0.00% 0.00% 0.00% 22.70%
+ 0x0000000000413e75 CalcSSIM(...)+965</tmp/psnr>"
+*/
+
+static int
+parse_load_latency_line (char *line, gcov_pmu_ll_info_t *ll_info)
+{
+ unsigned counts;
+ /* These are percentages parsed as floats, but then converted to
+ ints after multiplying by 100. */
+ float self, cum, lt_10, lt_32, lt_64, lt_256, lt_1024, gt_1024, wself;
+ long unsigned int p;
+ int n_values;
+ pmu_tool_fns *tool_details = the_pmu_tool_info->tool_details;
+
+ n_values = sscanf (line, "%u%f%%%f%%%f%%%f%%%f%%%f%%%f%%%f%%%f%%%lx",
+ &counts, &self, &cum, &lt_10, &lt_32, &lt_64, &lt_256,
+ &lt_1024, &gt_1024, &wself, &p);
+ if (n_values != 11)
+ return 1;
+
+ /* Values read successfully. Do the assignment after converting
+ * percentages into ints. */
+ ll_info->counts = counts;
+ ll_info->self = convert_pct_to_unsigned (self);
+ ll_info->cum = convert_pct_to_unsigned (cum);
+ ll_info->lt_10 = convert_pct_to_unsigned (lt_10);
+ ll_info->lt_32 = convert_pct_to_unsigned (lt_32);
+ ll_info->lt_64 = convert_pct_to_unsigned (lt_64);
+ ll_info->lt_256 = convert_pct_to_unsigned (lt_256);
+ ll_info->lt_1024 = convert_pct_to_unsigned (lt_1024);
+ ll_info->gt_1024 = convert_pct_to_unsigned (gt_1024);
+ ll_info->wself = convert_pct_to_unsigned (wself);
+ ll_info->code_addr = p;
+
+ /* run the raw address through the symbolizer */
+ if (tool_details->symbolize)
+ {
+ char *sym_info = tool_details->symbolize ((void *)p);
+ /* sym_info is of the form src_filename:linenum. Descriminator is
+ currently not supported by addr2line. */
+ char *sep = strchr (sym_info, ':');
+ if (!sep)
+ {
+ /* assume entire string is srcfile */
+ ll_info->filename = (char *)sym_info;
+ ll_info->line = 0;
+ }
+ else
+ {
+ /* terminate the filename string at the separator */
+ *sep = 0;
+ ll_info->filename = (char *)sym_info;
+ /* convert rest of the sym info to a line number */
+ ll_info->line = atol (sep+1);
+ }
+ ll_info->discriminator = 0;
+ }
+ else
+ {
+ /* no symbolizer available */
+ ll_info->filename = NULL;
+ ll_info->line = 0;
+ ll_info->discriminator = 0;
+ }
+ return 0;
+}
+
+/* Parse the branch mispredict info pointed by LINE and save it into
+ BRM_INFO. Returns 0 if the line was parsed successfully, non-zero
+ otherwise.
+
+ An example header+line look like these:
+ "counts %self %cum code addr symbol"
+ "6869 37.67% 37.67% 0x00000000004007e5 sum(std::vector<int*,
+ std::allocator<int*> > const&)+51</root/tmp/array>"
+*/
+
+static int
+parse_branch_mispredict_line (char *line, gcov_pmu_brm_info_t *brm_info)
+{
+ unsigned counts;
+ /* These are percentages parsed as floats, but then converted to
+ ints after multiplying by 100. */
+ float self, cum;
+ long unsigned int p;
+ int n_values;
+ pmu_tool_fns *tool_details = the_pmu_tool_info->tool_details;
+
+ n_values = sscanf (line, "%u%f%%%f%%%lx",
+ &counts, &self, &cum, &p);
+ if (n_values != 4)
+ return 1;
+
+ /* Values read successfully. Do the assignment after converting
+ * percentages into ints. */
+ brm_info->counts = counts;
+ brm_info->self = convert_pct_to_unsigned (self);
+ brm_info->cum = convert_pct_to_unsigned (cum);
+ brm_info->code_addr = p;
+
+ /* run the raw address through the symbolizer */
+ if (tool_details->symbolize)
+ {
+ char *sym_info = tool_details->symbolize ((void *)p);
+ /* sym_info is of the form src_filename:linenum. Descriminator is
+ currently not supported by addr2line. */
+ char *sep = strchr (sym_info, ':');
+ if (!sep)
+ {
+ /* assume entire string is srcfile */
+ brm_info->filename = sym_info;
+ brm_info->line = 0;
+ }
+ else
+ {
+ /* terminate the filename string at the separator */
+ *sep = 0;
+ brm_info->filename = sym_info;
+ /* convert rest of the sym info to a line number */
+ brm_info->line = atol (sep+1);
+ }
+ brm_info->discriminator = 0;
+ }
+ else
+ {
+ /* no symbolizer available */
+ brm_info->filename = NULL;
+ brm_info->line = 0;
+ brm_info->discriminator = 0;
+ }
+ return 0;
+}
+
+/* Delete load latency info structures INFO. */
+
+static void
+destroy_load_latency_infos (void *info)
+{
+ unsigned i;
+ ll_infos_t* ll_infos = (ll_infos_t *)info;
+
+ /* delete each element */
+ for (i = 0; i < ll_infos->ll_count; ++i)
+ XDELETE (ll_infos->ll_array[i]);
+ /* delete the array itself */
+ XDELETE (ll_infos->ll_array);
+ __destroy_pmu_tool_header (ll_infos->pmu_tool_header);
+ free (ll_infos->pmu_tool_header);
+ ll_infos->ll_array = 0;
+ ll_infos->ll_count = 0;
+}
+
+/* Delete branch mispredict structure INFO. */
+
+static void
+destroy_branch_mispredict_infos (void *info)
+{
+ unsigned i;
+ brm_infos_t* brm_infos = (brm_infos_t *)info;
+
+ /* delete each element */
+ for (i = 0; i < brm_infos->brm_count; ++i)
+ XDELETE (brm_infos->brm_array[i]);
+ /* delete the array itself */
+ XDELETE (brm_infos->brm_array);
+ __destroy_pmu_tool_header (brm_infos->pmu_tool_header);
+ free (brm_infos->pmu_tool_header);
+ brm_infos->brm_array = 0;
+ brm_infos->brm_count = 0;
+}
+
+/* Parse FILENAME for load latency lines into a structure
+ PMU_DATA. Returns 0 on on success. Returns non-zero on
+ failure. */
+
+static int
+parse_pfmon_load_latency (char *filename, void *pmu_data)
+{
+ FILE *fp;
+ size_t buflen = 2*1024;
+ char *buf;
+ ll_infos_t *load_latency_infos = (ll_infos_t *)pmu_data;
+ gcov_pmu_tool_header_t *tool_header = 0;
+
+ if ((fp = fopen (filename, "r")) == NULL)
+ {
+ fprintf (stderr, "cannot open pmu data file: %s\n", filename);
+ return 1;
+ }
+
+ if (!(tool_header = parse_pfmon_tool_header (fp, pfmon_ll_header)))
+ {
+ fprintf (stderr, "cannot parse pmu data file header: %s\n", filename);
+ return 1;
+ }
+
+ buf = (char *) malloc (buflen);
+ while (fgets (buf, buflen, fp))
+ {
+ gcov_pmu_ll_info_t *ll_info = XNEW (gcov_pmu_ll_info_t);
+ if (!parse_load_latency_line (buf, ll_info))
+ {
+ /* valid line, add to the array */
+ load_latency_infos->ll_count++;
+ if (load_latency_infos->ll_count >=
+ load_latency_infos->alloc_ll_count)
+ {
+ /* need to realloc */
+ load_latency_infos->ll_array =
+ realloc (load_latency_infos->ll_array,
+ 2 * load_latency_infos->alloc_ll_count);
+ if (load_latency_infos->ll_array == NULL)
+ {
+ fprintf (stderr, "Cannot allocate load latency memory.\n");
+ __destroy_pmu_tool_header (tool_header);
+ free (buf);
+ fclose (fp);
+ return 1;
+ }
+ }
+ load_latency_infos->ll_array[load_latency_infos->ll_count - 1] =
+ ll_info;
+ }
+ else
+ /* invalid line, delete it */
+ XDELETE (ll_info);
+ }
+ free (buf);
+ fclose (fp);
+ load_latency_infos->pmu_tool_header = tool_header;
+ return 0;
+}
+
+/* Parse open file FP until END_HEADER is seen. The data matching
+ gcov_pmu_tool_header_t fields is saved and returned in a new
+ struct. In case of failure, it returns NULL. */
+
+static gcov_pmu_tool_header_t *
+parse_pfmon_tool_header (FILE *fp, const char *end_header)
+{
+ static const char tag_hostname[] = "# hostname: ";
+ static const char tag_kversion[] = "# kernel version: ";
+ static const char tag_hostcpu[] = "# host CPUs: ";
+ static const char tag_column_desc_start[] = "# description of columns:";
+ static const char tag_column_desc_end[] =
+ "# other columns are self-explanatory";
+ size_t buflen = 4*1024;
+ char *buf, *buf_start, *buf_end;
+ gcov_pmu_tool_header_t *tool_header = XNEWVEC (gcov_pmu_tool_header_t, 1);
+ char *hostname = 0;
+ char *kversion = 0;
+ char *hostcpu = 0;
+ char *column_description = 0;
+ char *column_desc_start = 0;
+ char *column_desc_end = 0;
+ const char *column_header = 0;
+ int got_hostname = 0;
+ int got_kversion = 0 ;
+ int got_hostcpu = 0;
+ int got_end_header = 0;
+ int got_column_description = 0;
+
+ buf = (char *) malloc (buflen);
+ buf_start = buf;
+ buf_end = buf + buflen;
+ while (buf < (buf_end - 1) && fgets (buf, buf_end - buf, fp))
+ {
+ if (strncmp (end_header, buf, buf_end - buf) == 0)
+ {
+ got_end_header = 1;
+ break;
+ }
+ if (!got_hostname &&
+ strncmp (buf, tag_hostname, strlen (tag_hostname)) == 0)
+ {
+ size_t len = strlen (buf) - strlen (tag_hostname);
+ hostname = (char *)malloc (len);
+ memcpy (hostname, buf + strlen (tag_hostname), len);
+ hostname[len - 1] = 0;
+ tool_header->hostname = hostname;
+ got_hostname = 1;
+ }
+
+ if (!got_kversion &&
+ strncmp (buf, tag_kversion, strlen (tag_kversion)) == 0)
+ {
+ size_t len = strlen (buf) - strlen (tag_kversion);
+ kversion = (char *)malloc (len);
+ memcpy (kversion, buf + strlen (tag_kversion), len);
+ kversion[len - 1] = 0;
+ tool_header->kernel_version = kversion;
+ got_kversion = 1;
+ }
+
+ if (!got_hostcpu &&
+ strncmp (buf, tag_hostcpu, strlen (tag_hostcpu)) == 0)
+ {
+ size_t len = strlen (buf) - strlen (tag_hostcpu);
+ hostcpu = (char *)malloc (len);
+ memcpy (hostcpu, buf + strlen (tag_hostcpu), len);
+ hostcpu[len - 1] = 0;
+ tool_header->host_cpu = hostcpu;
+ got_hostcpu = 1;
+ }
+ if (!got_column_description &&
+ strncmp (buf, tag_column_desc_start, strlen (tag_column_desc_start))
+ == 0)
+ {
+ column_desc_start = buf;
+ column_desc_end = 0;
+ /* continue reading until end of the column descriptor */
+ while (buf < (buf_end - 1) && fgets (buf, buf_end - buf, fp))
+ {
+ if (strncmp (buf, tag_column_desc_end,
+ strlen (tag_column_desc_end)) == 0)
+ {
+ column_desc_end = buf + strlen (tag_column_desc_end);
+ break;
+ }
+ buf += strlen (buf);
+ }
+ if (column_desc_end)
+ {
+ /* found the end, copy it into a new string */
+ column_description = (char *)malloc (column_desc_end -
+ column_desc_start + 1);
+ got_column_description = 1;
+ strcpy (column_description, column_desc_start);
+ tool_header->column_description = column_description;
+ }
+ }
+ /* advance buf */
+ buf += strlen (buf);
+ }
+
+ /* If we are missing any of the fields, return NULL. */
+ if (!got_end_header || !got_hostname || !got_kversion || !got_hostcpu
+ || !got_column_description)
+ {
+ if (hostname)
+ free (hostname);
+ if (kversion)
+ free (kversion);
+ if (hostcpu)
+ free (hostcpu);
+ if (column_description)
+ free (column_description);
+ free (buf_start);
+ free (tool_header);
+ return NULL;
+ }
+
+ switch (the_pmu_tool_info->event)
+ {
+ case PET_INTEL_LOAD_LATENCY:
+ case PET_AMD_LOAD_LATENCY:
+ column_header = pfmon_ll_header;
+ break;
+ case PET_INTEL_BRANCH_MISPREDICT:
+ case PET_AMD_BRANCH_MISPREDICT:
+ column_header = pfmon_bm_header;
+ break;
+ default:
+ break;
+ }
+ tool_header->column_header = strdup (column_header);
+ tool_header->full_header = buf_start;
+ return tool_header;
+}
+
+
+/* Parse FILENAME for branch mispredict lines into a structure
+ PMU_DATA. Returns 0 on on success. Returns non-zero on
+ failure. */
+
+static int
+parse_pfmon_branch_mispredicts (char *filename, void *pmu_data)
+{
+ FILE *fp;
+ size_t buflen = 2*1024;
+ char *buf;
+ brm_infos_t *brm_infos = (brm_infos_t *)pmu_data;
+ gcov_pmu_tool_header_t *tool_header = 0;
+
+ if ((fp = fopen (filename, "r")) == NULL)
+ {
+ fprintf (stderr, "cannot open pmu data file: %s\n", filename);
+ return 1;
+ }
+
+ if (!(tool_header = parse_pfmon_tool_header (fp, pfmon_bm_header)))
+ {
+ fprintf (stderr, "cannot parse pmu data file header: %s\n", filename);
+ return 1;
+ }
+
+ buf = (char *) malloc (buflen);
+ while (fgets (buf, buflen, fp))
+ {
+ gcov_pmu_brm_info_t *brm = XNEW (gcov_pmu_brm_info_t);
+ if (!parse_branch_mispredict_line (buf, brm))
+ {
+ /* valid line, add to the array */
+ brm_infos->brm_count++;
+ if (brm_infos->brm_count >= brm_infos->alloc_brm_count)
+ {
+ /* need to realloc */
+ brm_infos->brm_array =
+ realloc (brm_infos->brm_array,
+ 2 * brm_infos->alloc_brm_count);
+ if (brm_infos->brm_array == NULL) {
+ fprintf (stderr,
+ "Cannot allocate memory for br mispredicts.\n");
+ __destroy_pmu_tool_header (tool_header);
+ free (buf);
+ fclose (fp);
+ return 1;
+ }
+ }
+ brm_infos->brm_array[brm_infos->brm_count - 1] = brm;
+ }
+ else
+ /* invalid line, delete it */
+ XDELETE (brm);
+ }
+ free (buf);
+ fclose (fp);
+ brm_infos->pmu_tool_header = tool_header;
+ return 0;
+}
+
+/* Start the monitoring process using pmu tool. Return 0 on success,
+ non-zero otherwise. */
+
+static int
+pmu_start (void)
+{
+ pid_t pid;
+
+ /* no start function */
+ if (!the_pmu_tool_info->tool_details->start_pmu_module)
+ return 1;
+
+ pid = fork ();
+ if (pid == -1)
+ {
+ /* error condition */
+ fprintf (stderr, "Cannot create PMU profiling process, exiting.\n");
+ return 1;
+ }
+ else if (pid == 0)
+ {
+ /* child */
+ pid_t ppid = getppid();
+ char *tmpfile = the_pmu_tool_info->raw_pmu_profile_filename;
+ const char **pfmon_args = the_pmu_tool_info->tool_details->arg_array;
+ int new_stderr_fd;
+
+ /* Redirect stderr from the child process into a separate file. */
+ new_stderr_fd = creat (the_pmu_tool_info->tool_stderr_filename,
+ S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
+ if (new_stderr_fd != -1)
+ dup2 (new_stderr_fd, 2);
+ /* The following does an exec and thus is not expected to return. */
+ the_pmu_tool_info->tool_details->start_pmu_module(ppid, tmpfile,
+ pfmon_args);
+ /* exec returned, an error condition. */
+ fprintf (stderr, "could not create profiling process: %s\n",
+ the_pmu_tool_info->tool_details->arg_array[0]);
+ _exit (0);
+ }
+ else
+ {
+ /* parent */
+ the_pmu_tool_info->pmu_tool_pid = pid;
+ return 0;
+ }
+}
+
+/* Allocate and initialize pmu load latency structure. */
+
+static void *
+init_pmu_load_latency (void)
+{
+ ll_infos_t *load_latency = XNEWVEC (ll_infos_t, 1);
+ load_latency->ll_count = 0;
+ load_latency->alloc_ll_count = 64;
+ load_latency->ll_array = XNEWVEC (gcov_pmu_ll_info_t *,
+ load_latency->alloc_ll_count);
+ return (void *)load_latency;
+}
+
+/* Allocate and initialize pmu branch mispredict structure. */
+
+static void *
+init_pmu_branch_mispredict (void)
+{
+ brm_infos_t *brm_info = XNEWVEC (brm_infos_t, 1);
+ brm_info->brm_count = 0;
+ brm_info->alloc_brm_count = 64;
+ brm_info->brm_array = XNEWVEC (gcov_pmu_brm_info_t *,
+ brm_info->alloc_brm_count);
+ return (void *)brm_info;
+}
+
+/* Initialize pmu tool based upon PMU_INFO. Sets the appropriate tool
+ type in the global the_pmu_tool_info. */
+
+static int
+init_pmu_tool (struct gcov_pmu_info *pmu_info)
+{
+ the_pmu_tool_info->pmu_profiling_state = PMU_NONE;
+ the_pmu_tool_info->verbose = 0;
+ the_pmu_tool_info->tool = PTT_PFMON; /* we support only pfmon */
+ the_pmu_tool_info->pmu_tool_pid = 0;
+ the_pmu_tool_info->top_n_address = pmu_info->pmu_top_n_address;
+ the_pmu_tool_info->symbolizer_pid = 0;
+ the_pmu_tool_info->symbolizer_to_pipefd[0] = -1;
+ the_pmu_tool_info->symbolizer_to_pipefd[1] = -1;
+ the_pmu_tool_info->symbolizer_from_pipefd[0] = -1;
+ the_pmu_tool_info->symbolizer_from_pipefd[1] = -1;
+
+ if (parse_pmu_profile_options (pmu_info->pmu_tool))
+ return 1;
+
+ if (the_pmu_tool_info->pmu_profiling_state == PMU_ERROR)
+ {
+ fprintf (stderr, "Unsupported PMU module: %s, disabling PMU profiling.\n",
+ pmu_info->pmu_tool);
+ return 1;
+ }
+
+ if (the_pmu_tool_info->tool_details->init_pmu_module)
+ /* initialize module */
+ the_pmu_tool_info->pmu_data =
+ the_pmu_tool_info->tool_details->init_pmu_module();
+ return 0;
+}
+
+/* Initialize PMU profiling based upon the information passed in
+ PMU_INFO and use PMU_PROFILE_FILENAME as the file to store the PMU
+ profile. This is called multiple times from libgcov, once per
+ object file. We need to make sure to do the necessary
+ initialization only the first time. For subsequent invocations it
+ behaves as a NOOP. */
+
+void
+__gcov_init_pmu_profiler (struct gcov_pmu_info *pmu_info)
+{
+ char *raw_pmu_profile_filename;
+ char *tool_stderr_filename;
+ if (!pmu_info || !pmu_info->pmu_profile_filename || !pmu_info->pmu_tool)
+ return;
+
+ /* allocate the global structure on first invocation */
+ if (!the_pmu_tool_info)
+ {
+ the_pmu_tool_info = XNEWVEC (struct pmu_tool_info, 1);
+ if (!the_pmu_tool_info)
+ {
+ fprintf (stderr, "Error allocating memory for PMU tool\n");
+ return;
+ }
+ if (init_pmu_tool (pmu_info))
+ {
+ /* Initialization error */
+ XDELETE (the_pmu_tool_info);
+ the_pmu_tool_info = 0;
+ return;
+ }
+ }
+
+ switch (the_pmu_tool_info->pmu_profiling_state)
+ {
+ case PMU_NONE:
+ the_pmu_tool_info->pmu_profile_filename =
+ strdup (pmu_info->pmu_profile_filename);
+ /* Construct an intermediate filename by substituting trailing
+ '.gcda' with '.pmud'. */
+ raw_pmu_profile_filename = strdup (pmu_info->pmu_profile_filename);
+ if (raw_pmu_profile_filename == NULL)
+ {
+ fprintf (stderr, "Cannot allocate memory\n");
+ exit (1);
+ }
+ strcpy (raw_pmu_profile_filename + strlen (raw_pmu_profile_filename) - 4,
+ "pmud");
+
+ /* Construct a filename for collecting PMU tool's stderr by
+ substituting trailing '.gcda' with '.stderr'. */
+ tool_stderr_filename =
+ XNEWVEC (char, strlen (pmu_info->pmu_profile_filename) + 1 + 2);
+ strcpy (tool_stderr_filename, pmu_info->pmu_profile_filename);
+ strcpy (tool_stderr_filename + strlen (tool_stderr_filename) - 4,
+ "stderr");
+ the_pmu_tool_info->raw_pmu_profile_filename = raw_pmu_profile_filename;
+ the_pmu_tool_info->tool_stderr_filename = tool_stderr_filename;
+ the_pmu_tool_info->pmu_profiling_state = PMU_INITIALIZED;
+ break;
+
+ case PMU_INITIALIZED:
+ case PMU_OFF:
+ case PMU_ON:
+ case PMU_ERROR:
+ break;
+ default:
+ break;
+ }
+}
+
+/* Start PMU profiling. It updates the current state. */
+
+void
+__gcov_start_pmu_profiler (void)
+{
+ if (!the_pmu_tool_info)
+ return;
+
+ switch (the_pmu_tool_info->pmu_profiling_state)
+ {
+ case PMU_INITIALIZED:
+ if (!pmu_start ())
+ the_pmu_tool_info->pmu_profiling_state = PMU_ON;
+ else
+ the_pmu_tool_info->pmu_profiling_state = PMU_ERROR;
+ break;
+
+ case PMU_NONE:
+ /* PMU was not properly initialized, don't attempt start it. */
+ the_pmu_tool_info->pmu_profiling_state = PMU_ERROR;
+ break;
+
+ case PMU_OFF:
+ /* Restarting PMU is not yet supported. */
+ case PMU_ON:
+ /* Do nothing. */
+ case PMU_ERROR:
+ break;
+
+ default:
+ break;
+ }
+}
+
+/* Stop PMU profiling. Currently it doesn't do anything except
+ bookkeeping. */
+
+void
+__gcov_stop_pmu_profiler (void)
+{
+ if (!the_pmu_tool_info)
+ return;
+
+ if (the_pmu_tool_info->tool_details->stop_pmu_module)
+ the_pmu_tool_info->tool_details->stop_pmu_module();
+ if (the_pmu_tool_info->pmu_profiling_state == PMU_ON)
+ the_pmu_tool_info->pmu_profiling_state = PMU_OFF;
+}
+
+/* Write the load latency information LL_INFO into the gcda file. */
+
+static void
+gcov_write_ll_line (const gcov_pmu_ll_info_t *ll_info)
+{
+ gcov_unsigned_t len = GCOV_TAG_PMU_LOAD_LATENCY_LENGTH (ll_info->filename);
+ gcov_write_tag_length (GCOV_TAG_PMU_LOAD_LATENCY_INFO, len);
+ gcov_write_unsigned (ll_info->counts);
+ gcov_write_unsigned (ll_info->self);
+ gcov_write_unsigned (ll_info->cum);
+ gcov_write_unsigned (ll_info->lt_10);
+ gcov_write_unsigned (ll_info->lt_32);
+ gcov_write_unsigned (ll_info->lt_64);
+ gcov_write_unsigned (ll_info->lt_256);
+ gcov_write_unsigned (ll_info->lt_1024);
+ gcov_write_unsigned (ll_info->gt_1024);
+ gcov_write_unsigned (ll_info->wself);
+ gcov_write_counter (ll_info->code_addr);
+ gcov_write_unsigned (ll_info->line);
+ gcov_write_unsigned (ll_info->discriminator);
+ gcov_write_string (ll_info->filename);
+}
+
+
+/* Write the branch mispredict information BRM_INFO into the gcda file. */
+
+static void
+gcov_write_branch_mispredict_line (const gcov_pmu_brm_info_t *brm_info)
+{
+ gcov_unsigned_t len = GCOV_TAG_PMU_BRANCH_MISPREDICT_LENGTH (
+ brm_info->filename);
+ gcov_write_tag_length (GCOV_TAG_PMU_BRANCH_MISPREDICT_INFO, len);
+ gcov_write_unsigned (brm_info->counts);
+ gcov_write_unsigned (brm_info->self);
+ gcov_write_unsigned (brm_info->cum);
+ gcov_write_counter (brm_info->code_addr);
+ gcov_write_unsigned (brm_info->line);
+ gcov_write_unsigned (brm_info->discriminator);
+ gcov_write_string (brm_info->filename);
+}
+
+/* Write load latency information INFO into the gcda file. The gcda
+ file has already been opened and is available for writing. */
+
+static void
+gcov_write_load_latency_infos (void *info)
+{
+ unsigned i;
+ const ll_infos_t *ll_infos = (const ll_infos_t *)info;
+ gcov_unsigned_t stamp = 0; /* don't use stamp as we don't support merge */
+ /* We don't support merge, and instead always rewrite the file. */
+ gcov_rewrite ();
+ gcov_write_tag_length (GCOV_DATA_MAGIC, GCOV_VERSION);
+ gcov_write_unsigned (stamp);
+ if (ll_infos->pmu_tool_header)
+ gcov_write_tool_header (ll_infos->pmu_tool_header);
+ for (i = 0; i < ll_infos->ll_count; ++i)
+ {
+ /* write each line */
+ gcov_write_ll_line (ll_infos->ll_array[i]);
+ }
+ gcov_truncate ();
+}
+
+/* Write branch mispredict information INFO into the gcda file. The
+ gcda file has already been opened and is available for writing. */
+
+static void
+gcov_write_branch_mispredict_infos (void *info)
+{
+ unsigned i;
+ const brm_infos_t *brm_infos = (const brm_infos_t *)info;
+ gcov_unsigned_t stamp = 0; /* don't use stamp as we don't support merge */
+ /* We don't support merge, and instead always rewrite the file. */
+ gcov_rewrite ();
+ gcov_write_tag_length (GCOV_DATA_MAGIC, GCOV_VERSION);
+ gcov_write_unsigned (stamp);
+ if (brm_infos->pmu_tool_header)
+ gcov_write_tool_header (brm_infos->pmu_tool_header);
+ for (i = 0; i < brm_infos->brm_count; ++i)
+ {
+ /* write each line */
+ gcov_write_branch_mispredict_line (brm_infos->brm_array[i]);
+ }
+ gcov_truncate ();
+}
+
+/* Compute TOOL_HEADER length for writing into the gcov file. */
+
+static gcov_unsigned_t
+gcov_tag_pmu_tool_header_length (gcov_pmu_tool_header_t *header)
+{
+ gcov_unsigned_t len = 0;
+ if (header)
+ {
+ len += gcov_string_length (header->host_cpu);
+ len += gcov_string_length (header->hostname);
+ len += gcov_string_length (header->kernel_version);
+ len += gcov_string_length (header->column_header);
+ len += gcov_string_length (header->column_description);
+ len += gcov_string_length (header->full_header);
+ }
+ return len;
+}
+
+/* Write tool header into the gcda file. It assumes that the gcda file
+ has already been opened and is available for writing. */
+
+static void
+gcov_write_tool_header (gcov_pmu_tool_header_t *header)
+{
+ gcov_unsigned_t len = gcov_tag_pmu_tool_header_length (header);
+ gcov_write_tag_length (GCOV_TAG_PMU_TOOL_HEADER, len);
+ gcov_write_string (header->host_cpu);
+ gcov_write_string (header->hostname);
+ gcov_write_string (header->kernel_version);
+ gcov_write_string (header->column_header);
+ gcov_write_string (header->column_description);
+ gcov_write_string (header->full_header);
+}
+
+
+/* End PMU profiling and write data into appropriate gcda file. */
+
+void
+__gcov_end_pmu_profiler (void)
+{
+ int pid_status;
+ int wait_status;
+ pid_t pid;
+ pmu_tool_fns *tool_details;
+
+ if (!the_pmu_tool_info)
+ return;
+
+ tool_details = the_pmu_tool_info->tool_details;
+ pid = the_pmu_tool_info->pmu_tool_pid;
+ if (pid)
+ {
+ if (tool_debug)
+ fprintf (stderr, "terminating PMU profiling process %ld\n", (long)pid);
+ kill (pid, SIGTERM);
+ if (tool_debug)
+ fprintf (stderr, "parent: waiting for pmu process to end\n");
+ wait_status = waitpid (pid, &pid_status, 0);
+ if (tool_debug) {
+ if (wait_status == pid)
+ fprintf (stderr, "Normal exit. Child terminated.\n");
+ else
+ fprintf (stderr, "Abnormal exit. child status, %d.\n", pid_status);
+ }
+ }
+
+ if (the_pmu_tool_info->pmu_profiling_state != PMU_OFF)
+ {
+ /* nothing to do */
+ fprintf (stderr,
+ "__gcov_dump_pmu_profile: incorrect pmu state: %d, pid: %ld\n",
+ the_pmu_tool_info->pmu_profiling_state,
+ (unsigned long)pid);
+ return;
+ }
+
+ if (!tool_details->parse_pmu_output)
+ return;
+
+ /* Since we are going to parse the output, we also need symbolizer. */
+ if (tool_details->start_symbolizer)
+ tool_details->start_symbolizer (getpid ());
+
+ if (!tool_details->parse_pmu_output
+ (the_pmu_tool_info->raw_pmu_profile_filename,
+ the_pmu_tool_info->pmu_data))
+ {
+ if (tool_details->gcov_write_pmu_data)
+ /* write tool output into the gcda file. */
+ tool_details->gcov_write_pmu_data (the_pmu_tool_info->pmu_data);
+ }
+
+ if (tool_details->end_symbolizer)
+ tool_details->end_symbolizer ();
+
+ if (tool_details->cleanup_pmu_data)
+ tool_details->cleanup_pmu_data (the_pmu_tool_info->pmu_data);
+}
+
+#endif
diff --git a/gcc-4.4.3/gcc/postreload.c b/gcc-4.4.3/gcc/postreload.c
index 8abc90f83..74aaaf816 100644
--- a/gcc-4.4.3/gcc/postreload.c
+++ b/gcc-4.4.3/gcc/postreload.c
@@ -524,7 +524,7 @@ reload_cse_simplify_operands (rtx insn, rtx testreg)
if (! TEST_HARD_REG_BIT (equiv_regs[i], regno))
continue;
- SET_REGNO (testreg, regno);
+ SET_REGNO_RAW (testreg, regno);
PUT_MODE (testreg, mode);
/* We found a register equal to this operand. Now look for all
diff --git a/gcc-4.4.3/gcc/predict.c b/gcc-4.4.3/gcc/predict.c
index e50a98707..4277e8525 100644
--- a/gcc-4.4.3/gcc/predict.c
+++ b/gcc-4.4.3/gcc/predict.c
@@ -172,11 +172,17 @@ cgraph_maybe_hot_edge_p (struct cgraph_edge *edge)
{
if (profile_info_available_p ()
&& (edge->count
- <= profile_info->sum_max / PARAM_VALUE (HOT_BB_COUNT_FRACTION))
- && !(flag_sample_profile && get_total_count_edge (edge,
- cgraph_node_name (edge->caller->global.inlined_to ?
- edge->caller->global.inlined_to :
- edge->caller)) > 0))
+ <= profile_info->sum_max / PARAM_VALUE (HOT_BB_COUNT_FRACTION)))
+ return false;
+
+ /* For sample fdo, if the function doesn't have profile, it should be
+ cold. */
+ if (flag_sample_profile &&
+ edge->count == 0 &&
+ get_total_count_edge (edge,
+ cgraph_node_name (edge->caller->global.inlined_to ?
+ edge->caller->global.inlined_to :
+ edge->caller)) == 0)
return false;
if (lookup_attribute ("cold", DECL_ATTRIBUTES (edge->callee->decl))
|| lookup_attribute ("cold", DECL_ATTRIBUTES (edge->caller->decl)))
@@ -2152,6 +2158,10 @@ compute_function_frequency (void)
return;
}
cfun->function_frequency = FUNCTION_FREQUENCY_UNLIKELY_EXECUTED;
+ /* For sample profile, if the profile is not found, we can infer that
+ the function has not executed. */
+ if (flag_sample_profile && profile_status != PROFILE_READ)
+ return;
FOR_EACH_BB (bb)
{
if (maybe_hot_bb_p (bb))
diff --git a/gcc-4.4.3/gcc/profile.c b/gcc-4.4.3/gcc/profile.c
index f35214a6e..a6d3c44a6 100644
--- a/gcc-4.4.3/gcc/profile.c
+++ b/gcc-4.4.3/gcc/profile.c
@@ -178,6 +178,10 @@ instrument_values (histogram_values values)
t = GCOV_COUNTER_V_SINGLE;
break;
+ case HIST_TYPE_SINGLE_FLOAT_VALUE:
+ t = GCOV_COUNTER_V_SINGLE_FLOAT;
+ break;
+
case HIST_TYPE_CONST_DELTA:
t = GCOV_COUNTER_V_DELTA;
break;
@@ -218,6 +222,10 @@ instrument_values (histogram_values values)
(profile_hooks->gen_one_value_profiler) (hist, t, 0);
break;
+ case HIST_TYPE_SINGLE_FLOAT_VALUE:
+ (profile_hooks->gen_one_float_value_profiler) (hist, t, 0);
+ break;
+
case HIST_TYPE_CONST_DELTA:
(profile_hooks->gen_const_delta_profiler) (hist, t, 0);
break;
@@ -1198,6 +1206,12 @@ branch_prob (void)
EXIT_BLOCK_PTR->index = EXIT_BLOCK;
#undef BB_TO_GCOV_INDEX
+ if (flag_profile_reusedist)
+ profile_hooks->reusedist_profiler ();
+
+ if (flag_optimize_locality)
+ profile_hooks->optimize_reusedist ();
+
if (flag_profile_values)
find_values_to_profile (&values);
@@ -1227,6 +1241,9 @@ branch_prob (void)
/* Commit changes done by instrumentation. */
gsi_commit_edge_inserts ();
+
+ if (flag_profile_generate_sampling)
+ add_sampling_to_edge_counters ();
}
free_aux_for_edges ();
diff --git a/gcc-4.4.3/gcc/profile.h b/gcc-4.4.3/gcc/profile.h
index a12d9af12..ec6570992 100644
--- a/gcc-4.4.3/gcc/profile.h
+++ b/gcc-4.4.3/gcc/profile.h
@@ -45,4 +45,10 @@ extern void mcf_smooth_cfg (void);
/* Return sum of edge counts in input edges */
extern gcov_type sum_edge_counts (VEC (edge, gc) *edges);
+/* Implement sampling to avoid writing to edge counters very often.
+ Many concurrent writes to the same counters, or to counters that share
+ the same cache line leads to up to 30x slowdown on an application running
+ on 8 CPUs. With sampling, the slowdown reduced to 2x. */
+extern void add_sampling_to_edge_counters (void);
+
#endif /* PROFILE_H */
diff --git a/gcc-4.4.3/gcc/real.c b/gcc-4.4.3/gcc/real.c
index d4a3941e6..0c827c34c 100644
--- a/gcc-4.4.3/gcc/real.c
+++ b/gcc-4.4.3/gcc/real.c
@@ -4939,3 +4939,52 @@ get_max_float (const struct real_format *fmt, char *buf, size_t len)
gcc_assert (strlen (buf) < len);
}
+
+/* Interpret the contents of the buffer PTR of length LEN as a
+ REAL_CST of type TYPE. If the buffer cannot be interpreted
+ return false. */
+
+bool
+real_from_native (tree type, const unsigned char *ptr, int len,
+ REAL_VALUE_TYPE *out_r)
+{
+ enum machine_mode mode = TYPE_MODE (type);
+ int total_bytes = GET_MODE_SIZE (mode);
+ int byte, offset, word, words, bitpos;
+ unsigned char value;
+ /* There are always 32 bits in each long, no matter the size of
+ the hosts long. We handle floating point representations with
+ up to 192 bits. */
+ long tmp[6];
+
+ total_bytes = GET_MODE_SIZE (TYPE_MODE (type));
+ if (total_bytes > len || total_bytes > 24)
+ return false;
+ words = (32 / BITS_PER_UNIT) / UNITS_PER_WORD;
+
+ memset (tmp, 0, sizeof (tmp));
+ for (bitpos = 0; bitpos < total_bytes * BITS_PER_UNIT;
+ bitpos += BITS_PER_UNIT)
+ {
+ byte = (bitpos / BITS_PER_UNIT) & 3;
+ if (UNITS_PER_WORD < 4)
+ {
+ word = byte / UNITS_PER_WORD;
+ if (WORDS_BIG_ENDIAN)
+ word = (words - 1) - word;
+ offset = word * UNITS_PER_WORD;
+ if (BYTES_BIG_ENDIAN)
+ offset += (UNITS_PER_WORD - 1) - (byte % UNITS_PER_WORD);
+ else
+ offset += byte % UNITS_PER_WORD;
+ }
+ else
+ offset = BYTES_BIG_ENDIAN ? 3 - byte : byte;
+ value = ptr[offset + ((bitpos / BITS_PER_UNIT) & ~3)];
+
+ tmp[bitpos / 32] |= (unsigned long)value << (bitpos & 31);
+ }
+
+ real_from_target (out_r, tmp, mode);
+ return true;
+}
diff --git a/gcc-4.4.3/gcc/real.h b/gcc-4.4.3/gcc/real.h
index 5a6865366..71fed7d6f 100644
--- a/gcc-4.4.3/gcc/real.h
+++ b/gcc-4.4.3/gcc/real.h
@@ -426,6 +426,8 @@ extern const REAL_VALUE_TYPE * dconst_sqrt2_ptr (void);
from a given integer constant. */
REAL_VALUE_TYPE real_value_from_int_cst (const_tree, const_tree);
+bool real_from_native (tree, const unsigned char *, int, REAL_VALUE_TYPE *);
+
/* Given a CONST_DOUBLE in FROM, store into TO the value it represents. */
#define REAL_VALUE_FROM_CONST_DOUBLE(to, from) \
((to) = *CONST_DOUBLE_REAL_VALUE (from))
diff --git a/gcc-4.4.3/gcc/rtl.def b/gcc-4.4.3/gcc/rtl.def
index 26e25905f..febe7734a 100644
--- a/gcc-4.4.3/gcc/rtl.def
+++ b/gcc-4.4.3/gcc/rtl.def
@@ -1095,7 +1095,11 @@ DEF_RTL_EXPR(FINAL_ABSENCE_SET, "final_absence_set", "ss", RTX_EXTRA)
guard for the bypass. The function will get the two insns as
parameters. If the function returns zero the bypass will be
ignored for this case. Additional guard is necessary to recognize
- complicated bypasses, e.g. when consumer is load address. */
+ complicated bypasses, e.g. when consumer is load address. If there
+ are more one bypass with the same output and input insns, the
+ chosen bypass is the first bypass with a guard in description whose
+ guard function returns nonzero. If there is no such bypass, then
+ bypass without the guard function is chosen. */
DEF_RTL_EXPR(DEFINE_BYPASS, "define_bypass", "issS", RTX_EXTRA)
/* (define_automaton string) describes names of automata generated and
diff --git a/gcc-4.4.3/gcc/rtl.h b/gcc-4.4.3/gcc/rtl.h
index 36bc50a06..139889954 100644
--- a/gcc-4.4.3/gcc/rtl.h
+++ b/gcc-4.4.3/gcc/rtl.h
@@ -998,6 +998,7 @@ enum label_kind
be used on RHS. Use SET_REGNO to change the value. */
#define REGNO(RTX) (rhs_regno(RTX))
#define SET_REGNO(RTX,N) (df_ref_change_reg_with_loc (REGNO(RTX), N, RTX), XCUINT (RTX, 0, REG) = N)
+#define SET_REGNO_RAW(RTX,N) (XCUINT (RTX, 0, REG) = N)
/* ORIGINAL_REGNO holds the number the register originally had; for a
pseudo register turned into a hard reg this will hold the old pseudo
diff --git a/gcc-4.4.3/gcc/simplify-got.c b/gcc-4.4.3/gcc/simplify-got.c
index ece9b40dd..a983cf0c8 100644
--- a/gcc-4.4.3/gcc/simplify-got.c
+++ b/gcc-4.4.3/gcc/simplify-got.c
@@ -72,6 +72,7 @@ struct got_access_info
rtx symbol; /* The global variable. */
rtx offset_reg; /* Register contains the GOT entry offset. */
rtx address_reg; /* Register contains the final global address. */
+ rtx offset_insn; /* The insn loads the offset. */
rtx load_insn; /* The insn which loads the address from GOT. */
};
@@ -79,11 +80,7 @@ struct got_access_info
static bool
gate_handle_simplify_got (void)
{
- /* This pass breaks two Android benchmarks at run time.
- http://b/issue?id=2749619.
- We temporarily disable this pass as a work around. */
- /* return (optimize > 0) && targetm.got_access.get_pic_reg (); */
- return 0;
+ return (optimize > 0) && targetm.got_access.get_pic_reg ();
}
static unsigned int
@@ -121,8 +118,10 @@ rest_of_handle_simplify_got (void)
if (!(set && (SET_DEST (set) == pic_reg)))
{
rtx offset_reg;
+ rtx offset_insn;
rtx symbol = targetm.got_access.loaded_global_var (insn,
- &offset_reg);
+ &offset_reg,
+ &offset_insn);
if (symbol)
{
rtx* slot = (rtx*) htab_find_slot (var_table, symbol, INSERT);
@@ -134,6 +133,7 @@ rest_of_handle_simplify_got (void)
got_accesses[n_access].offset_reg = offset_reg;
got_accesses[n_access].address_reg = SET_DEST (set);
got_accesses[n_access].load_insn = insn;
+ got_accesses[n_access].offset_insn = offset_insn;
n_access++;
}
else
@@ -164,7 +164,8 @@ rest_of_handle_simplify_got (void)
targetm.got_access.load_global_address (got_accesses[i].symbol,
got_accesses[i].offset_reg,
got_accesses[i].address_reg,
- got_accesses[i].load_insn);
+ got_accesses[i].load_insn,
+ got_accesses[i].offset_insn);
/* Since there is no usage of pic_reg now, we can remove it. */
if (use)
diff --git a/gcc-4.4.3/gcc/target-def.h b/gcc-4.4.3/gcc/target-def.h
index a10da3d0c..f9a75a431 100644
--- a/gcc-4.4.3/gcc/target-def.h
+++ b/gcc-4.4.3/gcc/target-def.h
@@ -591,6 +591,7 @@
#define TARGET_ARG_PARTIAL_BYTES hook_int_CUMULATIVE_ARGS_mode_tree_bool_0
#define TARGET_FUNCTION_VALUE default_function_value
+#define TARGET_LIBCALL_VALUE default_libcall_value
#define TARGET_INTERNAL_ARG_POINTER default_internal_arg_pointer
#define TARGET_UPDATE_STACK_BOUNDARY NULL
#define TARGET_GET_DRAP_RTX NULL
@@ -614,6 +615,7 @@
TARGET_ARG_PARTIAL_BYTES, \
TARGET_INVALID_ARG_FOR_UNPROTOTYPED_FN, \
TARGET_FUNCTION_VALUE, \
+ TARGET_LIBCALL_VALUE, \
TARGET_INTERNAL_ARG_POINTER, \
TARGET_UPDATE_STACK_BOUNDARY, \
TARGET_GET_DRAP_RTX, \
diff --git a/gcc-4.4.3/gcc/target.h b/gcc-4.4.3/gcc/target.h
index 2566f57b1..f504947cd 100644
--- a/gcc-4.4.3/gcc/target.h
+++ b/gcc-4.4.3/gcc/target.h
@@ -873,6 +873,10 @@ struct gcc_target
rtx (*function_value) (const_tree ret_type, const_tree fn_decl_or_type,
bool outgoing);
+ /* Return the rtx for the result of a libcall of mode MODE,
+ calling the function FN_NAME. */
+ rtx (*libcall_value) (enum machine_mode, rtx);
+
/* Return an rtx for the argument pointer incoming to the
current function. */
rtx (*internal_arg_pointer) (void);
@@ -1048,14 +1052,14 @@ struct gcc_target
/* Function to detect if the specified insn loads a global variable's
address from GOT. If so returns that symbol. */
- rtx (*loaded_global_var) (rtx, rtx *);
+ rtx (*loaded_global_var) (rtx, rtx *, rtx *);
/* This function checks if it satisfy the target dependent conditions
that we can simplify GOT accesses. */
bool (*can_simplify_got_access) (int, int);
/* This function does the actual rewriting of GOT accesses. */
- void (*load_global_address) (rtx, rtx, rtx, rtx);
+ void (*load_global_address) (rtx, rtx, rtx, rtx, rtx);
} got_access;
/* For targets that need to mark extra registers as live on entry to
diff --git a/gcc-4.4.3/gcc/targhooks.c b/gcc-4.4.3/gcc/targhooks.c
index d5e86f3df..5c5e4271b 100644
--- a/gcc-4.4.3/gcc/targhooks.c
+++ b/gcc-4.4.3/gcc/targhooks.c
@@ -561,6 +561,12 @@ default_function_value (const_tree ret_type ATTRIBUTE_UNUSED,
}
rtx
+default_libcall_value (enum machine_mode mode, rtx fun ATTRIBUTE_UNUSED)
+{
+ return LIBCALL_VALUE (mode);
+}
+
+rtx
default_internal_arg_pointer (void)
{
/* If the reg that the virtual arg pointer will be translated into is
diff --git a/gcc-4.4.3/gcc/targhooks.h b/gcc-4.4.3/gcc/targhooks.h
index b4ac8e3d2..2614b1ded 100644
--- a/gcc-4.4.3/gcc/targhooks.h
+++ b/gcc-4.4.3/gcc/targhooks.h
@@ -87,6 +87,7 @@ extern const char *hook_invalid_arg_for_unprototyped_fn
(const_tree, const_tree, const_tree);
extern bool hook_bool_const_rtx_commutative_p (const_rtx, int);
extern rtx default_function_value (const_tree, const_tree, bool);
+extern rtx default_libcall_value (enum machine_mode, rtx);
extern rtx default_internal_arg_pointer (void);
#ifdef IRA_COVER_CLASSES
extern const enum reg_class *default_ira_cover_classes (void);
diff --git a/gcc-4.4.3/gcc/testsuite/ChangeLog.ix86 b/gcc-4.4.3/gcc/testsuite/ChangeLog.ix86
new file mode 100644
index 000000000..5718e1d92
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/ChangeLog.ix86
@@ -0,0 +1,56 @@
+2010-08-13 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backport from mainline
+ 2010-02-26 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR testsuite/37074:
+ * gcc.dg/torture/stackalign/stackalign.exp: Add -mno-mmx to x86.
+
+2010-06-22 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backport from mainline
+ 2010-06-21 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/44615
+ * gcc.target/i386/sse2-vec-2a.c: New.
+
+2009-10-30 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backport from mainline:
+ 2009-10-30 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/40838
+ * gcc.target/i386/incoming-6.c: New.
+ * gcc.target/i386/incoming-7.c: Likewise.
+ * gcc.target/i386/incoming-8.c: Likewise.
+ * gcc.target/i386/incoming-9.c: Likewise.
+ * gcc.target/i386/incoming-10.c: Likewise.
+ * gcc.target/i386/incoming-11.c: Likewise.
+ * gcc.target/i386/incoming-12.c: Likewise.
+ * gcc.target/i386/incoming-13.c: Likewise.
+ * gcc.target/i386/incoming-14.c: Likewise.
+ * gcc.target/i386/incoming-15.c: Likewise.
+ * gcc.target/i386/pr37843-4.c: Likewise.
+
+2009-05-21 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backport from mainline:
+ 2009-05-21 H.J. Lu <hongjiu.lu@intel.com>
+
+ * gcc.target/i386/movbe-1.c: New.
+ * gcc.target/i386/movbe-2.c: Likewise.
+
+2009-03-27 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backport from mainline:
+ 2009-03-27 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/39472
+ * gcc.target/x86_64/abi/callabi/func-2a.c: New.
+ * gcc.target/x86_64/abi/callabi/func-2b.c: Likewise.
+ * gcc.target/x86_64/abi/callabi/func-indirect-2a.c: Likewise.
+ * gcc.target/x86_64/abi/callabi/func-indirect-2b.c: Likewise.
+ * gcc.target/x86_64/abi/callabi/vaarg-4a.c: Likewise.
+ * gcc.target/x86_64/abi/callabi/vaarg-4b.c: Likewise.
+ * gcc.target/x86_64/abi/callabi/vaarg-5a.c: Likewise.
+ * gcc.target/x86_64/abi/callabi/vaarg-5b.c: Likewise.
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/abi/forced.C b/gcc-4.4.3/gcc/testsuite/g++.dg/abi/forced.C
index 7a9c35964..f846732c3 100644
--- a/gcc-4.4.3/gcc/testsuite/g++.dg/abi/forced.C
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/abi/forced.C
@@ -1,6 +1,8 @@
// This test only applies to glibc (NPTL) targets.
// { dg-do run { target *-*-linux* } }
// { dg-options "-pthread" }
+// Does not work on a QEMU set-up because of the status wrapper.
+//{ dg-require-effective-target unwrapped }
#include <pthread.h>
#include <cxxabi.h>
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/debug/dwarf2/lineno-simple1.C b/gcc-4.4.3/gcc/testsuite/g++.dg/debug/dwarf2/lineno-simple1.C
new file mode 100644
index 000000000..e0ef7f71c
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/debug/dwarf2/lineno-simple1.C
@@ -0,0 +1,13 @@
+// { dg-do compile }
+// { dg-options "-g -O0 -dA" }
+
+struct C { // { dg-function-on-line {_ZN1CC[12]Ev} }
+ virtual void
+ foo() {} // { dg-function-on-line _ZN1C3fooEv }
+};
+static C dummy;
+
+int
+main (void)
+{ // { dg-function-on-line main }
+}
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/debug/dwarf2/pr41063.C b/gcc-4.4.3/gcc/testsuite/g++.dg/debug/dwarf2/pr41063.C
new file mode 100644
index 000000000..f23efef13
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/debug/dwarf2/pr41063.C
@@ -0,0 +1,20 @@
+// Contributed by Cary Coutant <ccoutant@google.com>
+// Origin: PR debug/41063
+// { dg-do compile }
+
+struct A {
+ virtual void run();
+};
+
+void test() {
+ struct B : public A {
+ void run() {
+ struct C : public A {
+ C() { }
+ B *b_;
+ };
+ C c;
+ }
+ };
+ B b;
+}
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/debug/dwarf2/pr44641.C b/gcc-4.4.3/gcc/testsuite/g++.dg/debug/dwarf2/pr44641.C
new file mode 100644
index 000000000..ecfb71323
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/debug/dwarf2/pr44641.C
@@ -0,0 +1,43 @@
+// Origin: PR 44641
+// { dg-do compile }
+// { dg-options "-g -O0 -dA" }
+
+template <class A> struct MisplacedDbg;
+template<class T> struct MisplacedDbg<T*>;
+struct Full;
+template<> struct MisplacedDbg<Full>;
+
+struct Arg;
+typedef MisplacedDbg<Arg> Typedef1;
+typedef MisplacedDbg<Arg*> Typedef2;
+typedef MisplacedDbg<Full> Typedef3;
+
+template<typename T> struct Base {
+ virtual ~Base() {
+ }
+};
+
+template <>
+struct MisplacedDbg<Full>
+ : public Base<int>
+{ // { dg-function-on-line {_ZN12MisplacedDbgI4FullEC[12]Ev} }
+ // { dg-function-on-line {_ZN12MisplacedDbgI4FullED0Ev} { target *-*-* } 23 }
+};
+
+template <class T>
+struct MisplacedDbg<T*>
+ : public Base<int>
+{ // { dg-function-on-line {_ZN12MisplacedDbgIP3ArgEC[12]Ev} }
+ // { dg-function-on-line {_ZN12MisplacedDbgIP3ArgED0Ev} { target *-*-* } 30 }
+};
+
+template <class A>
+struct MisplacedDbg
+ : public Base<int>
+{ // { dg-function-on-line {_ZN12MisplacedDbgI3ArgEC[12]Ev} }
+ // { dg-function-on-line {_ZN12MisplacedDbgI3ArgED0Ev} { target *-*-* } 37 }
+};
+
+static MisplacedDbg<Arg> static_var1;
+static MisplacedDbg<Arg*> static_var2;
+static MisplacedDbg<Full> static_var3;
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/debug/dwarf2/pr46527.C b/gcc-4.4.3/gcc/testsuite/g++.dg/debug/dwarf2/pr46527.C
new file mode 100644
index 000000000..dfc983b17
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/debug/dwarf2/pr46527.C
@@ -0,0 +1,18 @@
+// Origin: PR 46527
+// { dg-do compile }
+// { dg-options "-g -O0 -dA" }
+
+template <typename T> struct Struct {
+ double defined_later();
+};
+struct WrapperStruct {
+ Struct<double> ClassInstantiated;
+};
+template <typename T> double
+Struct<T>::defined_later() // { dg-function-on-line {_ZN6StructIdE13defined_laterEv} }
+{
+ return 1;
+}
+void InstantiateMethod() {
+ Struct<double>().defined_later();
+}
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/init/pr42556.C b/gcc-4.4.3/gcc/testsuite/g++.dg/init/pr42556.C
new file mode 100644
index 000000000..27370af79
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/init/pr42556.C
@@ -0,0 +1,10 @@
+// { dg-do compile }
+// { dg-options "-fdump-tree-gimple" }
+
+void foo (int a, int b, int c, int d)
+{
+ int v[4] = {a, b, c, d};
+}
+
+// { dg-final { scan-tree-dump-not "v = {}" "gimple" } }
+// { dg-final { cleanup-tree-dump "gimple" } }
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/ipa/ipa-cp-1.C b/gcc-4.4.3/gcc/testsuite/g++.dg/ipa/ipa-cp-1.C
new file mode 100644
index 000000000..954097655
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/ipa/ipa-cp-1.C
@@ -0,0 +1,309 @@
+/* Test for segfault during updating of jump function in
+ interprocedural constant propagation (b/3124518). */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+namespace std __attribute__ ((__visibility__ ("default"))) {
+ template<class _CharT>
+ struct char_traits;
+}
+typedef long int ptrdiff_t;
+typedef long unsigned int size_t;
+namespace std __attribute__ ((__visibility__ ("default"))) {
+ void __throw_bad_cast(void) __attribute__((__noreturn__));
+ typedef ptrdiff_t streamsize;
+ template<> struct char_traits<char>
+ {
+ typedef char char_type;
+ static size_t length(const char_type* __s) {
+ }
+ };
+}
+extern "C++" {
+ namespace std {
+ class exception {
+ };
+ }
+ void operator delete(void*) throw();
+}
+namespace __gnu_cxx __attribute__ ((__visibility__ ("default"))) {
+ template<typename _Tp>
+ class new_allocator {
+ public:
+ typedef size_t size_type;
+ typedef _Tp* pointer;
+ template<typename _Tp1>
+ struct rebind {
+ typedef new_allocator<_Tp1> other;
+ };
+ void deallocate(pointer __p, size_type) {
+ ::operator delete(__p);
+ }
+ };
+}
+namespace std __attribute__ ((__visibility__ ("default"))) {
+ template<typename _Tp>
+ class allocator
+ : public __gnu_cxx::new_allocator<_Tp> {
+ };
+ template<typename _CharT, typename _Traits = char_traits<_CharT> >
+ class basic_ostream;
+ template<typename _CharT, typename _Traits = char_traits<_CharT> >
+ class basic_fstream;
+ typedef basic_ostream<char> ostream;
+ typedef basic_fstream<char> fstream;
+}
+namespace __gnu_cxx __attribute__ ((__visibility__ ("default"))) {
+ template<typename _CharT, typename _Traits, typename _Alloc>
+ class __sso_string_base;
+ template<typename _CharT, typename _Traits = std::char_traits<_CharT>, typename _Alloc = std::allocator<_CharT>, template <typename, typename, typename> class _Base = __sso_string_base>
+ class __versa_string;
+ template<typename _CharT, typename _Traits, typename _Alloc>
+ struct __vstring_utility {
+ typedef typename _Alloc::template rebind<_CharT>::other _CharT_alloc_type;
+ template<typename _Alloc1>
+ struct _Alloc_hider
+ : public _Alloc1 {
+ _Alloc_hider(_CharT* __ptr)
+ : _Alloc1(), _M_p(__ptr) {
+ }
+ _CharT* _M_p;
+ };
+ };
+ template<typename _CharT, typename _Traits, typename _Alloc>
+ class __sso_string_base
+ : protected __vstring_utility<_CharT, _Traits, _Alloc> {
+ public:
+ typedef _Traits traits_type;
+ typedef __vstring_utility<_CharT, _Traits, _Alloc> _Util_Base;
+ typedef typename _Util_Base::_CharT_alloc_type _CharT_alloc_type;
+ typedef typename _CharT_alloc_type::size_type size_type;
+ private:
+ typename _Util_Base::template _Alloc_hider<_CharT_alloc_type>
+ _M_dataplus;
+ enum {
+ _S_local_capacity = 15 };
+ union {
+ _CharT _M_local_data[_S_local_capacity + 1];
+ size_type _M_allocated_capacity;
+ };
+ bool _M_is_local() const {
+ }
+ void _M_dispose() {
+ if (!_M_is_local()) _M_destroy(_M_allocated_capacity);
+ }
+ void _M_destroy(size_type __size) throw() {
+ _M_get_allocator().deallocate(_M_data(), __size + 1);
+ }
+ public:
+ size_type _M_max_size() const {
+ }
+ _CharT* _M_data() const {
+ return _M_dataplus._M_p;
+ }
+ __sso_string_base()
+ : _M_dataplus(_M_local_data) {
+ }
+ __sso_string_base(const __sso_string_base& __rcs);
+ template<typename _InputIterator>
+ __sso_string_base(_InputIterator __beg, _InputIterator __end, const _Alloc& __a);
+ ~__sso_string_base() {
+ _M_dispose();
+ }
+ _CharT_alloc_type& _M_get_allocator() {
+ }
+ };
+ template<typename _CharT, typename _Traits, typename _Alloc, template <typename, typename, typename> class _Base>
+ class __versa_string
+ : private _Base<_CharT, _Traits, _Alloc> {
+ typedef _Base<_CharT, _Traits, _Alloc> __vstring_base;
+ typedef typename __vstring_base::_CharT_alloc_type _CharT_alloc_type;
+ public:
+ typedef _Traits traits_type;
+ typedef typename _CharT_alloc_type::size_type size_type;
+ static const size_type npos = static_cast<size_type>(-1);
+ public:
+ __versa_string()
+ : __vstring_base() {
+ }
+ __versa_string(const _CharT* __s, const _Alloc& __a = _Alloc())
+ : __vstring_base(__s, __s ? __s + traits_type::length(__s)
+ : __s + npos, __a) {
+ }
+ };
+}
+namespace std __attribute__ ((__visibility__ ("default"))) {
+ template<typename _CharT, typename _Traits, typename _Alloc, template <typename, typename, typename> class _Base>
+ inline basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __os, const __gnu_cxx::__versa_string<_CharT, _Traits, _Alloc, _Base>& __str) {
+ }
+}
+template<typename _CharT, typename _Traits = std::char_traits<_CharT>, typename _Alloc = std::allocator<_CharT> >
+class basic_string
+ : public __gnu_cxx::__versa_string<_CharT, _Traits, _Alloc> {
+public:
+ typedef __gnu_cxx::__versa_string<_CharT, _Traits, _Alloc> __base;
+ inline basic_string()
+ : __base() {
+ }
+ basic_string(const _CharT* __s, const _Alloc& __a = _Alloc())
+ : __base(__s, __a) {
+ }
+};
+typedef basic_string<char> string;
+namespace std __attribute__ ((__visibility__ ("default"))) {
+ class locale {
+ class facet;
+ };
+ class locale::facet {
+ };
+ class ios_base {
+ };
+ struct ctype_base {
+ };
+ template<typename _CharT>
+ class __ctype_abstract_base
+ : public locale::facet, public ctype_base {
+ };
+ template<typename _CharT>
+ class ctype
+ : public __ctype_abstract_base<_CharT> {
+ public:
+ typedef char char_type;
+ mutable char _M_widen_ok;
+ mutable char _M_widen[1 + static_cast<unsigned char>(-1)];
+ char_type widen(char __c) const {
+ if (_M_widen_ok) return _M_widen[static_cast<unsigned char>(__c)];
+ this->_M_widen_init();
+ return this->do_widen(__c);
+ }
+ virtual char_type do_widen(char __c) const {
+ }
+ void _M_widen_init() const;
+ };
+ template<typename _Facet>
+ inline const _Facet& __check_facet(const _Facet* __f) {
+ if (!__f) __throw_bad_cast();
+ }
+ template<typename _CharT, typename _Traits>
+ class basic_ios
+ : public ios_base {
+ public:
+ typedef _CharT char_type;
+ typedef ctype<_CharT> __ctype_type;
+ const __ctype_type* _M_ctype;
+ bool eof() const {
+ }
+ char_type widen(char __c) const {
+ return __check_facet(_M_ctype).widen(__c);
+ }
+ };
+ template<typename _CharT, typename _Traits> class basic_ostream
+ : virtual public basic_ios<_CharT, _Traits>
+ {
+ public:
+ typedef _CharT char_type;
+ typedef basic_ostream<_CharT, _Traits> __ostream_type;
+ __ostream_type& operator<<(__ostream_type& (*__pf)(__ostream_type&)) {
+ }
+ __ostream_type& put(char_type __c);
+ };
+ template<typename _CharT, typename _Traits>
+ inline basic_ostream<_CharT, _Traits>& endl(basic_ostream<_CharT, _Traits>& __os) {
+ return flush(__os.put(__os.widen('\n')));
+ }
+ template<typename _CharT, typename _Traits>
+ inline basic_ostream<_CharT, _Traits>& flush(basic_ostream<_CharT, _Traits>& __os) {
+ }
+}
+using std::endl;
+namespace std __attribute__ ((__visibility__ ("default"))) {
+ template<typename _CharT, typename _Traits> class basic_istream
+ : virtual public basic_ios<_CharT, _Traits>
+ {
+ public:
+ typedef _CharT char_type;
+ typedef basic_istream<_CharT, _Traits> __istream_type;
+ virtual ~basic_istream() {
+ }
+ __istream_type& getline(char_type* __s, streamsize __n, char_type __delim);
+ __istream_type& getline(char_type* __s, streamsize __n) {
+ return this->getline(__s, __n, this->widen('\n'));
+ }
+ };
+ template<typename _CharT, typename _Traits>
+ class basic_iostream
+ : public basic_istream<_CharT, _Traits>, public basic_ostream<_CharT, _Traits> {
+ };
+}
+using std::ostream;
+namespace std __attribute__ ((__visibility__ ("default"))) {
+ template<typename _CharT, typename _Traits>
+ class basic_fstream
+ : public basic_iostream<_CharT, _Traits> {
+ };
+}
+namespace FooNamespace {
+ class ExceptionLocation {
+ public:
+ ExceptionLocation(const string& filename = string(), const string& funcName = string()) throw()
+ : functionName(funcName) {
+ }
+ private:
+ string fileName;
+ string functionName;
+ };
+ class Exception {
+ public:
+ Exception() throw();
+ Exception(const string& errorText, const unsigned long& errorId = 0) throw();
+ Exception& addLocation(const ExceptionLocation& location) throw();
+ };
+ class FooError
+ : public FooNamespace::Exception {
+ public:
+ FooError() throw()
+ : FooNamespace::Exception() {
+ }
+ FooError(string a, unsigned long b = 0) throw()
+ : FooNamespace::Exception(a, b) {
+ };
+ };
+ class EndOfFile
+ : public FooNamespace::FooError {
+ public:
+ EndOfFile() throw()
+ : FooNamespace::FooError() {
+ }
+ EndOfFile(string a, unsigned long b = 0) throw()
+ : FooNamespace::FooError(a, b) {
+ };
+ };
+ class FooTextStream : public std::fstream {
+ public:
+ inline void Fubar(const bool expectEOF = false ) throw(EndOfFile, FooError, FooNamespace::Exception) {
+ try {
+ const int MAX_LINE_LENGTH = 256;
+ char templine[MAX_LINE_LENGTH + 1];
+ getline(templine, MAX_LINE_LENGTH);
+ EndOfFile err("");
+ }
+ catch(std::exception &e) {
+ if (expectEOF) {
+ EndOfFile err("");
+ err.addLocation(FooNamespace::ExceptionLocation("", ""));
+ throw err;
+ }
+ }
+ };
+ };
+ class BarHeader {
+ virtual void dump(std::ostream& s) const {
+ s << endl;
+ }
+ virtual void DoIt(std::fstream& s);
+ };
+ void BarHeader::DoIt(std::fstream& ffs) {
+ FooTextStream* buz = 0;
+ buz->Fubar();
+ }
+}
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/lookup/koenig5.C b/gcc-4.4.3/gcc/testsuite/g++.dg/lookup/koenig5.C
index 139e3b866..6ecc25daa 100644
--- a/gcc-4.4.3/gcc/testsuite/g++.dg/lookup/koenig5.C
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/lookup/koenig5.C
@@ -8,39 +8,39 @@
namespace N
{
struct A {};
- void One (...); // { dg-error "conflict with" "" }
- void (*Two) (...); // { dg-error "not a function" "" }
- namespace Three {} // { dg-error "lookup finds|not a function" "" }
+ void One (...);
+ void (*Two) (...);
+ namespace Three {}
}
namespace M
{
struct B {};
- struct One {}; // { dg-error "lookup finds|not a function" "" }
- void (*Two) (...); // { dg-error "conflict with" "" }
- void Three (...); // { dg-error "conflict with" "" }
+ struct One {};
+ void (*Two) (...);
+ void Three (...);
}
namespace O
{
struct C {};
- void Two (...); // { dg-error "conflict with" "" }
+ void Two (...);
}
void g (N::A *a, M::B *b, O::C *c)
{
One (a); // ok
- One (b); // { dg-error "in call to" "" }
- One (a, b); // { dg-error "in call to" "" }
+ One (a, b); // ok
+ One (b); // { dg-error "not declared" }
- Two (a); // ok
- Two (a, a); // ok
- Two (b); // ok
Two (c); // ok
- Two (a, b); // { dg-error "in call to" "" }
- Two (a, c); // { dg-error "in call to" "" }
+ Two (a, c); // ok
+ Two (a); // { dg-error "not declared" }
+ Two (a, a); // error masked by earlier error
+ Two (b); // error masked by earlier error
+ Two (a, b); // error masked by earlier error
- Three (a); // { dg-error "in call to" "" }
Three (b); // ok
- Three (a, b); // { dg-error "in call to" "" }
+ Three (a, b); // ok
+ Three (a); // { dg-error "not declared" }
}
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/lookup/koenig6.C b/gcc-4.4.3/gcc/testsuite/g++.dg/lookup/koenig6.C
new file mode 100644
index 000000000..9fdf771e0
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/lookup/koenig6.C
@@ -0,0 +1,18 @@
+// PR c++/17365
+// ADL should not find B::N.
+
+namespace A
+{
+ namespace B
+ {
+ template <typename T> struct N {int n_;};
+ }
+ template <typename T> int N( T p ) { return p->n_; }
+ template <typename T> void f( T p ) { N(p); } // #1
+}
+int main()
+{
+ A::B::N<int> n;
+ A::f(&n);
+ return 0;
+}
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/mversn10.C b/gcc-4.4.3/gcc/testsuite/g++.dg/mversn10.C
new file mode 100644
index 000000000..dcd5d2776
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/mversn10.C
@@ -0,0 +1,54 @@
+/* The purpose of this test is to check if the attributes of the clone
+ correctly shadow the parent function. In this case, function "dispatch"
+ is cloned but is a static function. The other file, "mversn10a.C" also
+ has a dispatch function that is cloned. So, if the attributes of the
+ clone are not correct the linker will complain. */
+
+/* { dg-do run } */
+/* { dg-additional-sources "mversn10a.C" } */
+/* { dg-options "-O2 -fclone-hot-version-paths -fdump-tree-final_cleanup" } */
+
+static int __attribute__ ((version_selector))
+featureTest ()
+{
+ return 1;
+}
+
+static int foo ()
+{
+ return 0;
+}
+
+static int bar ()
+{
+ return 1;
+}
+
+static int __attribute__ ((noinline))
+dispatch ()
+{
+ __builtin_dispatch (featureTest, (void *)foo, (void *)bar);
+ return 0;
+}
+
+int
+fn1 ()
+{
+ for (int i = 0; i < 1000; i++)
+ dispatch ();
+ return 0;
+}
+
+extern int fn2 ();
+
+int __attribute__ ((hot))
+main ()
+{
+ fn1 ();
+ fn2 ();
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump "dispatchv_clone_0" "final_cleanup" } } */
+/* { dg-final { scan-tree-dump "dispatchv_clone_1" "final_cleanup" } } */
+/* { dg-final { cleanup-tree-dump "final_cleanup" } } */
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/mversn10a.C b/gcc-4.4.3/gcc/testsuite/g++.dg/mversn10a.C
new file mode 100644
index 000000000..f762cf649
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/mversn10a.C
@@ -0,0 +1,37 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fclone-hot-version-paths -fdump-tree-final_cleanup" } */
+
+static int __attribute__ ((version_selector))
+featureTest ()
+{
+ return 1;
+}
+
+static int foo ()
+{
+ return 0;
+}
+
+static int bar ()
+{
+ return 1;
+}
+
+static int __attribute__ ((noinline))
+dispatch ()
+{
+ __builtin_dispatch (featureTest, (void *)foo, (void *)bar);
+ return 0;
+}
+
+int
+fn2 ()
+{
+ for (int i = 0; i < 1000; i++)
+ dispatch ();
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump "dispatchv_clone_0" "final_cleanup" } } */
+/* { dg-final { scan-tree-dump "dispatchv_clone_1" "final_cleanup" } } */
+/* { dg-final { cleanup-tree-dump "final_cleanup" } } */
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/mversn12.C b/gcc-4.4.3/gcc/testsuite/g++.dg/mversn12.C
new file mode 100644
index 000000000..b21b9a36f
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/mversn12.C
@@ -0,0 +1,43 @@
+/* Check if everything is fine if the versioned functions are static
+ member functions. */
+
+/* { dg-do run } */
+/* { dg-options "-O2 -fclone-hot-version-paths" } */
+
+int __attribute__ ((version_selector))
+featureTest()
+{
+ return 1;;
+}
+
+class TestClass
+{
+ public:
+ static int foo ()
+ {
+ return 0;
+ }
+
+ static int bar ()
+ {
+ return 1;
+ }
+
+ int dispatch ()
+ {
+ int a = __builtin_dispatch (featureTest,
+ (void*)(&TestClass::foo),
+ (void*)(&TestClass::bar));
+ int b = __builtin_dispatch (featureTest,
+ (void*)(&TestClass::bar),
+ (void*)(&TestClass::foo));
+ return a * b;
+ }
+};
+
+int
+main ()
+{
+ TestClass c1;
+ return c1.dispatch ();
+}
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/mversn14.C b/gcc-4.4.3/gcc/testsuite/g++.dg/mversn14.C
new file mode 100644
index 000000000..dcf6f19fa
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/mversn14.C
@@ -0,0 +1,26 @@
+/* Check if everything is fine when the feature test body is in a different
+ module that does not have a __builtin-dispatch". Requires mversn14a.C. */
+
+/* { dg-do run } */
+/* { dg-additional-sources "mversn14a.C" } */
+/* { dg-options "-O2 -fclone-hot-version-paths" } */
+
+int __attribute__ ((version_selector))
+featureTest ();
+
+int
+foo ()
+{
+ return 0;
+}
+
+int
+bar ()
+{
+ return 1;
+}
+
+int main ()
+{
+ return __builtin_dispatch (featureTest, (void *)foo, (void *)bar);
+}
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/mversn14a.C b/gcc-4.4.3/gcc/testsuite/g++.dg/mversn14a.C
new file mode 100644
index 000000000..513c5a402
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/mversn14a.C
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+int __attribute__ ((version_selector))
+featureTest ()
+{
+ return 1;
+}
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/mversn16.C b/gcc-4.4.3/gcc/testsuite/g++.dg/mversn16.C
new file mode 100644
index 000000000..90e2fc28f
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/mversn16.C
@@ -0,0 +1,39 @@
+/* dispatch is cloned. Make sure the double is returned to main correctly. */
+
+/* { dg-do run } */
+/* { dg-options "-O2 -fclone-hot-version-paths -fdump-tree-final_cleanup" } */
+
+#include "assert.h"
+
+int __attribute__ ((version_selector))
+featureTest ()
+{
+ return 1;
+}
+
+static int foo ()
+{
+ return 0;
+}
+
+static int bar ()
+{
+ return 1;
+}
+
+double
+dispatch ()
+{
+ __builtin_dispatch (featureTest, (void *)foo, (void *)bar);
+ return 2.536;
+}
+
+int main ()
+{
+ double d = dispatch ();
+ assert (d == 2.536);
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump "dispatchv_clone" "final_cleanup" } } */
+/* { dg-final { cleanup-tree-dump "final_cleanup" } } */
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/mversn8.C b/gcc-4.4.3/gcc/testsuite/g++.dg/mversn8.C
new file mode 100644
index 000000000..4e4168a87
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/mversn8.C
@@ -0,0 +1,44 @@
+/* Call the caller of __builtin_dispatch indirectly. Specify the
+ feature test function as a function pointer. Make sure cloning
+ still happens. */
+
+/* { dg-do run } */
+/* { dg-options "-O2 -fclone-hot-version-paths -fdump-tree-final_cleanup" } */
+
+int __attribute__ ((version_selector))
+featureTest ()
+{
+ return 1;
+}
+
+int __attribute__ ((cold))
+foo ()
+{
+ return 0;
+}
+
+int __attribute__ ((cold))
+bar ()
+{
+ return 1;
+}
+
+int
+dispatch ()
+{
+ int (*funcp)() = featureTest;
+ int ret = __builtin_dispatch (funcp, (void *)foo, (void *)bar);
+ return ret;
+}
+
+int main (int argc, char **argv)
+{
+ int (*ptr)() = dispatch;
+ return (*ptr)();
+}
+
+/* { dg-final { scan-tree-dump "dispatchv_clone_0" "final_cleanup" } } */
+/* { dg-final { scan-tree-dump "dispatchv_clone_1" "final_cleanup" } } */
+/* { dg-final { scan-tree-dump "main_clone_0" "final_cleanup" } } */
+/* { dg-final { scan-tree-dump "main_clone_1" "final_cleanup" } } */
+/* { dg-final { cleanup-tree-dump "final_cleanup" } } */
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/mversn9.C b/gcc-4.4.3/gcc/testsuite/g++.dg/mversn9.C
new file mode 100644
index 000000000..d884d6f28
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/mversn9.C
@@ -0,0 +1,31 @@
+/* Two __builtin_dispatch calls in different basic blocks. */
+
+/* { dg-do run } */
+/* { dg-options "-O2 -fclone-hot-version-paths" } */
+
+int __attribute__ ((version_selector))
+featureTest ()
+{
+ return 1;
+}
+
+int
+foo ()
+{
+ return 0;
+}
+
+int
+bar ()
+{
+ return 1;
+}
+
+int main (int argc, char **argv)
+{
+ if (argc)
+ return __builtin_dispatch (featureTest, (void *)foo, (void *)bar);
+ else
+ return (__builtin_dispatch (featureTest, (void *)bar, (void *)foo) - 1);
+}
+
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/other/crash-5.C b/gcc-4.4.3/gcc/testsuite/g++.dg/other/crash-5.C
new file mode 100644
index 000000000..25a70b7df
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/other/crash-5.C
@@ -0,0 +1,16 @@
+// Origin: PR c++/42758
+// { dg-do compile }
+
+template<class T> struct less {};
+
+template<class T, typename U = less<T> > struct set {};
+
+struct int_less_than {};
+
+void assert_fail (const char*);
+
+int f(const set<int, int_less_than>&)
+{
+ assert_fail (__PRETTY_FUNCTION__);
+
+}
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/other/crash-7.C b/gcc-4.4.3/gcc/testsuite/g++.dg/other/crash-7.C
new file mode 100644
index 000000000..d5bc892c0
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/other/crash-7.C
@@ -0,0 +1,19 @@
+// Origin: PR c++/42336
+// { dg-options "-std=c++0x -O2 -g" }
+// { dg-do compile }
+
+struct X {
+ void func() {}
+};
+
+template<typename T, void (X::*P)() = &T::func>
+void b(T) {}
+
+int main() {
+ b(X()); /* line 9 */
+ X().func();
+
+ return 0;
+}
+
+
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/other/crash-8.C b/gcc-4.4.3/gcc/testsuite/g++.dg/other/crash-8.C
new file mode 100644
index 000000000..c260431d5
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/other/crash-8.C
@@ -0,0 +1,109 @@
+// Origin: PR c++/42797
+// { dg-options "-g -O2 -std=c++0x" }
+
+template<typename _Tp, _Tp __v> struct integral_constant {
+ static const _Tp value = __v;
+};
+
+template<typename _Tp> _Tp declval();
+
+template<typename _Tp, typename... _Args>
+class __is_constructible_helper {
+};
+
+template<typename _Tp, typename _Arg>
+class __is_constructible_helper<_Tp, _Arg> {
+
+ template<typename _Tp1, typename _Arg1>
+ static decltype(static_cast<_Tp1>(declval<_Arg1>()), char()) __test(int);
+public:
+ static const bool __value = sizeof(__test<_Tp, _Arg>(0)) == 1;
+};
+
+template<typename _Tp, typename... _Args>
+struct is_constructible : public integral_constant<bool,__is_constructible_helper<_Tp, _Args...>::__value> { };
+
+template<bool, typename _Tp = void>
+struct enable_if { };
+
+template<typename _Tp>
+struct enable_if<true, _Tp> {
+ typedef _Tp type;
+};
+
+template<class _T1, class _T2> struct pair {
+ _T1 first;
+ _T2 second;
+
+ template<class _U2, class = typename enable_if<is_constructible<_T2, _U2&&>::value>::type>
+ pair(const _T1& __x, _U2&& __y) : first(__x),
+ second(__y) { }
+};
+
+namespace __gnu_cxx {
+template<typename _Tp>
+class new_allocator {
+public:
+ new_allocator() throw() { }
+ new_allocator(const new_allocator&) throw() { }
+};
+}
+
+template<typename _Tp>
+class allocator: public __gnu_cxx::new_allocator<_Tp> {
+public:
+
+ template<typename _Tp1>
+ struct rebind {
+ typedef allocator<_Tp1> other;
+ };
+};
+
+
+template<typename _Tp, typename _Alloc> struct _Vector_base {
+ typedef typename _Alloc::template rebind<_Tp>::other _Tp_alloc_type;
+
+ struct _Vector_impl : public _Tp_alloc_type {
+ _Vector_impl()
+ { }
+ };
+public:
+
+ _Vector_impl _M_impl;
+};
+
+template<typename _Tp, typename _Alloc = allocator<_Tp> >
+class vector : protected _Vector_base<_Tp, _Alloc> {
+ typedef _Alloc allocator_type;
+public:
+ vector() { }
+ explicit vector(int, const allocator_type& __a = allocator_type())
+ {
+ }
+};
+
+
+template <typename _Key, typename _Tp>
+class map {
+ typedef _Key key_type;
+ typedef _Tp mapped_type;
+ typedef pair<const _Key, _Tp> value_type;
+public:
+
+ void insert(const value_type& __x)
+ {
+ }
+
+ mapped_type& operator[](const key_type& __k) {
+ insert(value_type(__k, mapped_type()));
+ }
+
+};
+
+struct Foo {
+ Foo() {} template<typename Tp> Foo(Tp *p) {} };
+void foo() {
+ map <int, vector<Foo>> the_map;
+ the_map[1] = vector<Foo>();
+}
+
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/template/crash56.C b/gcc-4.4.3/gcc/testsuite/g++.dg/template/crash56.C
index 1efa3500d..03bddf42a 100644
--- a/gcc-4.4.3/gcc/testsuite/g++.dg/template/crash56.C
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/template/crash56.C
@@ -7,10 +7,10 @@
namespace N
{
- struct A { A (A*); }; // { dg-error "lookup finds" "" }
+ struct A { A (A*); };
}
template<typename T> void g (N::A *p)
{
- (void) A (p); // { dg-error "in call" "" }
+ (void) A (p); // { dg-message "" "" }
}
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/template/defarg13.C b/gcc-4.4.3/gcc/testsuite/g++.dg/template/defarg13.C
new file mode 100644
index 000000000..ba2980bfa
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/template/defarg13.C
@@ -0,0 +1,19 @@
+// PR c++/14912
+// Bug: We were instantiating A<B> in order to compare it to the matching
+// argument for C<B,B>, which fails.
+
+template <class T>
+struct A
+{
+ typedef typename T::F F;
+};
+
+struct B { };
+
+template <class T, class U = typename A<T>::F >
+struct C
+{
+ typename T::F f; // { dg-error "no type" }
+};
+
+C<B, B> c; // { dg-message "instantiated" }
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/template/error39.C b/gcc-4.4.3/gcc/testsuite/g++.dg/template/error39.C
new file mode 100644
index 000000000..49faa3654
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/template/error39.C
@@ -0,0 +1,11 @@
+// PR c++/14912
+
+template <class T, int N=0, int X=1>
+struct A
+{
+};
+
+void foo(void)
+{
+ A<void> a = 0; // { dg-error "A<void>" }
+}
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_common.h b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_common.h
index 192c84e84..a21af97fe 100644
--- a/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_common.h
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_common.h
@@ -27,6 +27,11 @@
#define SHARED_LOCKS_REQUIRED(...) \
__attribute__ ((shared_locks_required(__VA_ARGS__)))
#define NO_THREAD_SAFETY_ANALYSIS __attribute__ ((no_thread_safety_analysis))
+#define IGNORE_READS_BEGIN __attribute__ ((ignore_reads_begin))
+#define IGNORE_READS_END __attribute__ ((ignore_reads_end))
+#define IGNORE_WRITES_BEGIN __attribute__ ((ignore_writes_begin))
+#define IGNORE_WRITES_END __attribute__ ((ignore_writes_end))
+#define UNPROTECTED_READ __attribute__ ((unprotected_read))
#else
@@ -48,6 +53,11 @@
#define EXCLUSIVE_LOCKS_REQUIRED(...)
#define SHARED_LOCKS_REQUIRED(...)
#define NO_THREAD_SAFETY_ANALYSIS
+#define IGNORE_READS_BEGIN
+#define IGNORE_READS_END
+#define IGNORE_WRITES_BEGIN
+#define IGNORE_WRITES_END
+#define UNPROTECTED_READ
#endif // defined(__GNUC__) && defined(__SUPPORT_TS_ANNOTATION__)
@@ -81,4 +91,41 @@ class SCOPED_LOCKABLE ReleasableMutexLock {
void Release() UNLOCK_FUNCTION();
};
+void AnnotateIgnoreReadsBegin(const char *file, int line) IGNORE_READS_BEGIN;
+void AnnotateIgnoreReadsEnd(const char *file, int line) IGNORE_READS_END;
+void AnnotateIgnoreWritesBegin(const char *file, int line) IGNORE_WRITES_BEGIN;
+void AnnotateIgnoreWritesEnd(const char *file, int line) IGNORE_WRITES_END;
+
+#define ANNOTATE_IGNORE_READS_BEGIN() \
+ AnnotateIgnoreReadsBegin(__FILE__, __LINE__)
+
+#define ANNOTATE_IGNORE_READS_END() \
+ AnnotateIgnoreReadsEnd(__FILE__, __LINE__)
+
+#define ANNOTATE_IGNORE_WRITES_BEGIN() \
+ AnnotateIgnoreWritesBegin(__FILE__, __LINE__)
+
+#define ANNOTATE_IGNORE_WRITES_END() \
+ AnnotateIgnoreWritesEnd(__FILE__, __LINE__)
+
+#define ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() \
+ do { \
+ ANNOTATE_IGNORE_READS_BEGIN(); \
+ ANNOTATE_IGNORE_WRITES_BEGIN(); \
+ }while(0) \
+
+#define ANNOTATE_IGNORE_READS_AND_WRITES_END() \
+ do { \
+ ANNOTATE_IGNORE_WRITES_END(); \
+ ANNOTATE_IGNORE_READS_END(); \
+ }while(0) \
+
+template <class T>
+inline T ANNOTATE_UNPROTECTED_READ(const T &x) UNPROTECTED_READ {
+ ANNOTATE_IGNORE_READS_BEGIN();
+ T res = x;
+ ANNOTATE_IGNORE_READS_END();
+ return res;
+}
+
#endif // THREAD_ANNOT_COMMON_H
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-50.C b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-50.C
new file mode 100644
index 000000000..e1e24c18e
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-50.C
@@ -0,0 +1,22 @@
+// Test the support for allowing non-const but non-modifying methods to be
+// protected by reader locks.
+// This is a good test case. (i.e. There should be no warning emitted by the
+// compiler.)
+// { dg-do compile }
+// { dg-options "-Wthread-safety -O" }
+
+#include <map>
+#include "thread_annot_common.h"
+
+typedef std::map<int, int> MyMapType;
+
+Mutex mu;
+MyMapType MyMap GUARDED_BY(mu);
+
+int foo(int key) {
+ ReaderMutexLock l(&mu);
+ MyMapType::const_iterator iter = MyMap.find(key);
+ if (iter != MyMap.end()) {
+ return iter->second;
+ }
+}
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-51.C b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-51.C
new file mode 100644
index 000000000..400c81e82
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-51.C
@@ -0,0 +1,44 @@
+// Test the support for allowing non-const but non-modifying methods to be
+// protected by reader locks.
+// { dg-do compile }
+// { dg-options "-Wthread-safety -O" }
+
+#include "thread_annot_common.h"
+
+class Foo {
+ public:
+ int GetVal1(int a) const {
+ return a + val1;
+ }
+
+ int GetVal1(int a) {
+ return a + val1;
+ }
+
+ int GetVal1(int a, float b) {
+ return a + b + val1;
+ }
+
+ int GetVal2(int a) {
+ return a + val2;
+ }
+
+ int GetVal2(float a) {
+ return val2;
+ }
+
+
+ private:
+ int val1;
+ int val2;
+};
+
+Mutex mu;
+Foo foo GUARDED_BY(mu);
+
+int main() {
+ mu.ReaderLock();
+ int x = foo.GetVal1(3); // should not warn
+ int y = foo.GetVal2(3); // { dg-warning "Writing to variable" }
+ mu.Unlock();
+}
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-52.C b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-52.C
new file mode 100644
index 000000000..5535034b0
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-52.C
@@ -0,0 +1,39 @@
+// Test the support for use of point_to_guarded{_by} on smart/scoped pointers.
+// { dg-do compile }
+// { dg-options "-Wthread-safety -O" }
+
+#include "thread_annot_common.h"
+
+template<class T>
+class scoped_ptr {
+ public:
+ typedef T element_type;
+
+ explicit scoped_ptr(T * p = 0);
+ ~scoped_ptr();
+
+ void reset(T * p = 0);
+
+ T & operator*() const;
+ T * operator->() const;
+ T * get() const;
+};
+
+class Foo {
+ public:
+ int x;
+};
+
+Mutex mu1, mu2;
+scoped_ptr<int> a PT_GUARDED_BY(mu1);
+scoped_ptr<Foo> b GUARDED_BY(mu2) PT_GUARDED_VAR;
+
+main()
+{
+ *a = 5; // { dg-warning "Access to memory location pointed to" }
+ a.reset();
+ b->x = 3 + *a; // { dg-warning "Reading variable" }
+}
+
+// { dg-warning "Access to memory location pointed to by variable 'b'" "" { target *-*-* } 35 }
+// { dg-warning "Access to memory location pointed to by variable 'a'" "" { target *-*-* } 35 }
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-53.C b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-53.C
new file mode 100644
index 000000000..0c03d77d9
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-53.C
@@ -0,0 +1,40 @@
+// Test the support for use of point_to_guarded{_by} on smart/scoped pointers.
+// This is a good test case. (i.e. There should be no warning emitted by the
+// compiler.)
+// { dg-do compile }
+// { dg-options "-Wthread-safety -O" }
+
+#include "thread_annot_common.h"
+
+template<class T>
+class scoped_ptr {
+ public:
+ typedef T element_type;
+
+ explicit scoped_ptr(T * p = 0);
+ ~scoped_ptr();
+
+ void reset(T * p = 0);
+
+ T & operator*() const;
+ T * operator->() const;
+ T * get() const;
+};
+
+class Foo {
+ public:
+ int x;
+};
+
+Mutex mu1, mu2;
+scoped_ptr<int> a PT_GUARDED_BY(mu1);
+scoped_ptr<Foo> b GUARDED_BY(mu2) PT_GUARDED_VAR;
+
+main()
+{
+ MutexLock l1(&mu1);
+ MutexLock l2(&mu2);
+ *a = 5;
+ a.reset();
+ b->x = 3 + *a;
+}
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-54.C b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-54.C
new file mode 100644
index 000000000..e90652407
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-54.C
@@ -0,0 +1,35 @@
+// Test the handling of the annotations with function parameters.
+// { dg-do compile }
+// { dg-options "-Wthread-safety -O" }
+
+#include "thread_annot_common.h"
+
+class Base {
+ private:
+ Mutex mu1_;
+
+ public:
+ Mutex *mutable_mu() LOCK_RETURNED(mu1_) { return &mu1_; }
+};
+
+class Foo {
+ public:
+ Mutex mu2_;
+ void Test1(Mutex* mu) const EXCLUSIVE_LOCKS_REQUIRED(mu, mu2_);
+ void Test2(Mutex* mu) const LOCKS_EXCLUDED(mu);
+};
+
+class Bar : public Base {
+ private:
+ Foo foo_;
+
+ public:
+ void Test3();
+};
+
+void Bar::Test3() {
+ mutable_mu()->Lock();
+ foo_.Test1(mutable_mu()); // { dg-warning "Calling function" }
+ foo_.Test2(mutable_mu()); // { dg-warning "Cannot call function" }
+ mutable_mu()->Unlock();
+}
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-55.C b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-55.C
new file mode 100644
index 000000000..10a12d43e
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-55.C
@@ -0,0 +1,38 @@
+// Test the handling of the annotations with function parameters.
+// This is a good test case. (i.e. There should be no warning emitted by the
+// compiler.)
+// { dg-do compile }
+// { dg-options "-Wthread-safety -O" }
+
+#include "thread_annot_common.h"
+
+class Base {
+ private:
+ Mutex mu1_;
+
+ public:
+ Mutex *mutable_mu() LOCK_RETURNED(mu1_) { return &mu1_; }
+};
+
+class Foo {
+ public:
+ Mutex mu2_;
+ void Test1(Mutex* mu) const EXCLUSIVE_LOCKS_REQUIRED(mu, mu2_);
+ void Test2(Mutex* mu) const LOCKS_EXCLUDED(mu);
+};
+
+class Bar : public Base {
+ private:
+ Foo foo_;
+
+ public:
+ void Test3();
+};
+
+void Bar::Test3() {
+ MutexLock l(&foo_.mu2_);
+ mutable_mu()->Lock();
+ foo_.Test1(mutable_mu());
+ mutable_mu()->Unlock();
+ foo_.Test2(mutable_mu());
+}
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-56.C b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-56.C
new file mode 100644
index 000000000..71221eb5f
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-56.C
@@ -0,0 +1,36 @@
+// Test the handling of a method with lock annotations accessed through a
+// smart/scoped pointer.
+// { dg-do compile }
+// { dg-options "-Wthread-safety -O" }
+
+#include "thread_annot_common.h"
+
+template<class T>
+class scoped_ptr {
+ public:
+ typedef T element_type;
+
+ explicit scoped_ptr(T * p = 0);
+ ~scoped_ptr();
+
+ void reset(T * p = 0);
+
+ T & operator*() const;
+ T * operator->() const;
+ T * get() const;
+};
+
+class LOCKABLE Foo {
+ public:
+ Mutex *mutex_;
+ int x;
+ int GetValue() EXCLUSIVE_LOCKS_REQUIRED(mutex);
+};
+
+scoped_ptr<Foo> b;
+
+main()
+{
+ int a;
+ a = b->GetValue(); // { dg-warning "Calling function 'GetValue' requires" }
+}
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-57.C b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-57.C
new file mode 100644
index 000000000..a12150436
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-57.C
@@ -0,0 +1,22 @@
+// Test handling of arguments passed to reference parameters.
+// { dg-do compile }
+// { dg-options "-Wthread-safety -O" }
+
+#include "thread_annot_common.h"
+
+struct Foo {
+ int a;
+};
+
+void func1(Foo &f);
+
+void func2(Foo *f);
+
+Mutex mu;
+
+Foo foo GUARDED_BY(mu);
+
+main() {
+ func1(foo); // { dg-warning "Reading variable 'foo' requires lock" }
+ func2(&foo); // should not warn
+}
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-58.C b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-58.C
new file mode 100644
index 000000000..858e63558
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-58.C
@@ -0,0 +1,32 @@
+// Test handling of arguments passed to reference parameters.
+// { dg-do compile }
+// { dg-options "-Wthread-safety -O" }
+
+#include <string>
+#include "thread_annot_common.h"
+
+class Base {
+ public:
+ Base() {}
+ protected:
+ Mutex* mutex() const LOCK_RETURNED(mutex_) { return &mutex_; }
+ private:
+ mutable Mutex mutex_;
+};
+
+class Subclass : public Base {
+ public:
+ Subclass() {}
+
+ void ClearValue() { SetValueLocked(0); }
+ std::string GetValue() const;
+
+ private:
+ void SetValueLocked(std::string value) { value_ = value; }
+
+ std::string value_ GUARDED_BY(mutex_);
+};
+
+std::string Subclass::GetValue() const {
+ return value_; // { dg-warning "Reading variable 'value_' requires lock" }
+}
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-59.C b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-59.C
new file mode 100644
index 000000000..158c940e2
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-59.C
@@ -0,0 +1,34 @@
+// Test handling of additional (finer-grained) escape hatche attributes.
+// { dg-do compile }
+// { dg-options "-Wthread-safety -O" }
+
+#include "thread_annot_common.h"
+
+Mutex *mu1, *mu2;
+
+struct Foo {
+ int a GUARDED_BY(mu1);
+};
+
+int x GUARDED_BY(mu1) = 1;
+int y GUARDED_BY(mu2);
+
+main() {
+ int z;
+ Foo w;
+ ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN();
+ y = x + 1;
+ x = y;
+ ANNOTATE_IGNORE_READS_AND_WRITES_END();
+
+ z = ANNOTATE_UNPROTECTED_READ(w.a) + 1;
+ if (z > 1) {
+ ANNOTATE_IGNORE_READS_BEGIN();
+ z = x + 2;
+ }
+ else {
+ ANNOTATE_IGNORE_READS_BEGIN();
+ z = x + 1;
+ }
+ z = y;
+}
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-60.C b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-60.C
new file mode 100644
index 000000000..099aa8290
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-60.C
@@ -0,0 +1,37 @@
+// Test handling of additional (finer-grained) escape hatche attributes.
+// { dg-do compile }
+// { dg-options "-Wthread-safety -O" }
+
+#include "thread_annot_common.h"
+
+Mutex *mu1, *mu2;
+
+struct Foo {
+ int a GUARDED_BY(mu1);
+};
+
+int x GUARDED_BY(mu1) = 1;
+int y GUARDED_BY(mu2);
+
+main() {
+ int z;
+ Foo w;
+ ANNOTATE_IGNORE_READS_BEGIN();
+ y = x + 1; // { dg-warning "Writing to variable 'y' requires lock" }
+ x = y; // { dg-warning "Writing to variable 'x' requires lock" }
+ ANNOTATE_IGNORE_READS_END();
+ ANNOTATE_IGNORE_WRITES_BEGIN();
+ y = x + 1; // { dg-warning "Reading variable 'x' requires lock" }
+ x = y; // { dg-warning "Reading variable 'y' requires lock" }
+ ANNOTATE_IGNORE_WRITES_END();
+
+ z = w.a + 1; // { dg-warning "Reading variable 'w.a' requires lock" }
+ if (z > 1) {
+ z = x + 2; // { dg-warning "Reading variable 'x' requires lock" }
+ }
+ else {
+ ANNOTATE_IGNORE_READS_BEGIN();
+ z = x + 1;
+ }
+ z = y; // { dg-warning "Reading variable 'y' requires lock" }
+}
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-61.C b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-61.C
new file mode 100644
index 000000000..11f6308eb
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-61.C
@@ -0,0 +1,15 @@
+// Test the fix for a bug introduced by the support of pass-by-reference
+// paramters.
+// { dg-do compile }
+// { dg-options "-Wthread-safety -O" }
+
+#include "thread_annot_common.h"
+
+struct Foo { Foo & operator<< (bool) {} };
+struct Bar { Foo & func () {} };
+struct Bas { void operator& (Foo &) {} };
+void mumble()
+{
+ Bas() & Bar().func() << "" << "";
+ Bas() & Bar().func() << "";
+}
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-62.C b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-62.C
new file mode 100644
index 000000000..95f318699
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-62.C
@@ -0,0 +1,18 @@
+// Test the support for allowing non-const but non-modifying overloaded
+// operator to be protected by reader locks.
+// This is a good test case. (i.e. There should be no warning emitted by the
+// compiler.)
+// { dg-do compile }
+// { dg-options "-Wthread-safety -O" }
+
+#include <vector>
+#include "thread_annot_common.h"
+
+Mutex mu;
+
+std::vector<int> counts GUARDED_BY(mu);
+
+int foo(int key) {
+ ReaderMutexLock l(&mu);
+ return counts[key];
+}
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-65.C b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-65.C
new file mode 100644
index 000000000..d129fc94c
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-65.C
@@ -0,0 +1,30 @@
+// Test the fix for a bug in the support of allowing reader locks for
+// non-const, non-modifying overload functions. (We didn't handle the builtin
+// properly.)
+// { dg-do compile }
+// { dg-options "-Wthread-safety -O" }
+
+enum MyFlags {
+ Zero,
+ One,
+ Two,
+ Three,
+ Four,
+ Five,
+ Six,
+ Seven,
+ Eight,
+ Nine
+};
+
+inline MyFlags
+operator|(MyFlags a, MyFlags b)
+{
+ return MyFlags(static_cast<int>(a) | static_cast<int>(b));
+}
+
+inline MyFlags&
+operator|=(MyFlags& a, MyFlags b)
+{
+ return a = a | b;
+}
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-66.C b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-66.C
new file mode 100644
index 000000000..c341973e7
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-66.C
@@ -0,0 +1,35 @@
+// Test annotations on out-of-line definitions of member functions where the
+// annotations refer to locks that are also data members in the class.
+// This is a good test case. (i.e. There should be no warning emitted by the
+// compiler.)
+// { dg-do compile }
+// { dg-options "-Wthread-safety -O" }
+
+#include "thread_annot_common.h"
+
+Mutex mu;
+
+class Foo {
+ public:
+ int method1(int i);
+ int data GUARDED_BY(mu1);
+ Mutex *mu1;
+ Mutex *mu2;
+};
+
+int Foo::method1(int i) SHARED_LOCKS_REQUIRED(mu1, mu, mu2)
+{
+ return data + i;
+}
+
+main()
+{
+ Foo a;
+
+ MutexLock l(a.mu2);
+ a.mu1->Lock();
+ mu.Lock();
+ a.method1(1);
+ mu.Unlock();
+ a.mu1->Unlock();
+}
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-67.C b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-67.C
new file mode 100644
index 000000000..be228ec20
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-67.C
@@ -0,0 +1,32 @@
+// Test annotations on out-of-line definitions of member functions where the
+// annotations refer to locks that are also data members in the class.
+// { dg-do compile }
+// { dg-options "-Wthread-safety -O" }
+
+#include "thread_annot_common.h"
+
+Mutex mu;
+
+class Foo {
+ public:
+ int method1(int i);
+ int data GUARDED_BY(mu1);
+ Mutex *mu1;
+ Mutex *mu2;
+};
+
+int Foo::method1(int i) SHARED_LOCKS_REQUIRED(mu1, mu, mu2, mu3)
+{
+ return data + i;
+}
+
+main()
+{
+ Foo a;
+
+ a.method1(1); // { dg-warning "Calling function 'method1' requires lock" }
+}
+
+// { dg-warning "Calling function 'method1' requires lock 'mu'" { target *-*-* } 27 }
+// { dg-warning "Calling function 'method1' requires lock 'a.mu2'" { target *-*-* } 27 }
+// { dg-warning "Calling function 'method1' requires lock 'mu3'" { target *-*-* } 27 }
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-68.C b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-68.C
new file mode 100644
index 000000000..95e8d6908
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-68.C
@@ -0,0 +1,34 @@
+// Test a fix to a bug in the delayed name binding with nested template
+// instantiation. We use a stack to make sure a name is not resolved to an
+// inner context.
+// This is a good test case. (i.e. There should be no warning emitted by the
+// compiler.)
+// { dg-do compile }
+// { dg-options "-Wthread-safety -O" }
+
+#include "thread_annot_common.h"
+
+template <typename T>
+class Bar {
+ Mutex mu_;
+};
+
+template <typename T>
+class Foo {
+ public:
+ void func(T x) {
+ MutexLock l(&mu_);
+ count_ = x;
+ }
+
+ private:
+ T count_ GUARDED_BY(mu_);
+ Bar<T> bar_;
+ Mutex mu_;
+};
+
+int main()
+{
+ Foo<int> *foo;
+ foo->func(5);
+}
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-69.C b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-69.C
new file mode 100644
index 000000000..478e8b273
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-69.C
@@ -0,0 +1,31 @@
+// Test a fix to a bug in the delayed name binding with nested template
+// instantiation. We use a stack to make sure a name is not resolved to an
+// inner context.
+// { dg-do compile }
+// { dg-options "-Wthread-safety -O" }
+
+#include "thread_annot_common.h"
+
+template <typename T>
+class Bar {
+ Mutex mu_;
+};
+
+template <typename T>
+class Foo {
+ public:
+ void func(T x) {
+ count_ = x; // { dg-warning "Writing to variable 'count_' requires lock" }
+ }
+
+ private:
+ T count_ GUARDED_BY(mu_);
+ Bar<T> bar_;
+ Mutex mu_;
+};
+
+int main()
+{
+ Foo<int> *foo;
+ foo->func(5);
+}
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-70.C b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-70.C
new file mode 100644
index 000000000..782d13af4
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-70.C
@@ -0,0 +1,38 @@
+// Test a fix to a bug when handling calls to virtual functions that are
+// annotated with LOCK/UNLOCK_FUNCTION. More specifically, the bug happens
+// when we tried to assert the function decl of a gimple call statement
+// returned by gimple_call_fndecl is non-NULL, which is not true when the call
+// is a virtual function call. Instead, we should either get the function decl
+// through the reference object, or (as is the fix) simply pass the function
+// decl that we have extracted earlier all the way to
+// handle_lock_primitive_attrs where the assertion fails.
+//
+// This is a good test case. (i.e. There should be no error/warning/ICE
+// triggered.)
+//
+// { dg-do compile }
+// { dg-options "-Wthread-safety -O" }
+
+#include "thread_annot_common.h"
+
+class Base {
+ protected:
+ virtual void Lock() EXCLUSIVE_LOCK_FUNCTION(mu_) { mu_.Lock(); }
+ virtual void Unlock() UNLOCK_FUNCTION(mu_) { mu_.Unlock(); }
+ Mutex mu_;
+};
+
+class Child: public Base {
+ int a;
+ public:
+ void func1() {
+ Lock();
+ a += 1;
+ Unlock();
+ }
+};
+
+main() {
+ Child c;
+ c.func1();
+}
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/torture/mversn11.C b/gcc-4.4.3/gcc/testsuite/g++.dg/torture/mversn11.C
new file mode 100644
index 000000000..a5416dbf2
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/torture/mversn11.C
@@ -0,0 +1,40 @@
+/* Check if parameters are passed correctly to the versioned function. */
+
+/* { dg-do run } */
+
+#include <stdio.h>
+#include <assert.h>
+
+int __attribute__ ((version_selector))
+featureTest ()
+{
+ return 1;
+}
+
+int __attribute__ ((noinline))
+foo (int n1, double n2, char n3)
+{
+ assert (n1 == 10);
+ assert (n2 == 20.0);
+ assert (n3 == 'c');
+ return n1;
+}
+
+
+int __attribute__ ((noinline))
+bar (int n1, double n2, char n3)
+{
+ assert (n1 == 10);
+ assert (n2 == 20.0);
+ assert (n3 == 'c');
+ return 0;
+}
+
+int main ()
+{
+ int a = __builtin_dispatch (featureTest, (void *)foo, (void *)bar,
+ 10, 20.0, 'c');
+ int b = __builtin_dispatch (featureTest, (void *)bar, (void *)foo,
+ 10, 20.0, 'c');
+ return a * b;
+}
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/torture/mversn5.C b/gcc-4.4.3/gcc/testsuite/g++.dg/torture/mversn5.C
new file mode 100644
index 000000000..a596d01f4
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/torture/mversn5.C
@@ -0,0 +1,28 @@
+/* Check that global inline feature test functions are correctly handled. This
+ test case also needs mversn5a.c. extern_func calls foo and returns 0.*/
+
+/* { dg-do run } */
+/* { dg-additional-sources "mversn5a.C" } */
+
+#include "mversn5.h"
+
+extern int extern_func ();
+
+int foo ()
+{
+ return 0;
+}
+
+int bar ()
+{
+ return 1;
+}
+
+int __attribute__ ((cold))
+main ()
+{
+ int a = 1, b = 1;
+ a = extern_func ();
+ b = __builtin_dispatch (featureTest, (void *)bar, (void *) foo);
+ return a * b;
+}
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/torture/mversn5.h b/gcc-4.4.3/gcc/testsuite/g++.dg/torture/mversn5.h
new file mode 100644
index 000000000..253d3ff6d
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/torture/mversn5.h
@@ -0,0 +1,5 @@
+inline int __attribute__ ((version_selector))
+featureTest ()
+{
+ return 1;
+}
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/torture/mversn5a.C b/gcc-4.4.3/gcc/testsuite/g++.dg/torture/mversn5a.C
new file mode 100644
index 000000000..4c8a6804c
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/torture/mversn5a.C
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+
+#include "mversn5.h"
+
+extern int foo ();
+extern int bar ();
+
+
+int extern_func ()
+{
+ return __builtin_dispatch (featureTest, (void *)foo, (void *) bar);
+}
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/tree-prof/mversn13.C b/gcc-4.4.3/gcc/testsuite/g++.dg/tree-prof/mversn13.C
new file mode 100644
index 000000000..3a7a543db
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/tree-prof/mversn13.C
@@ -0,0 +1,37 @@
+/* Make sure -fprofile-generate and -fprofile-use work fine. */
+
+/* { dg-options "-O2 -fclone-hot-version-paths" } */
+
+static int glob = 0;
+int __attribute__ ((version_selector))
+featureTest ()
+{
+ return glob;
+}
+
+int bar (int i)
+{
+ if (i > 500)
+ return 2 * i;
+ return 3 * i;
+}
+
+int foo (int i)
+{
+ bar (i);
+}
+
+int
+dispatch ()
+{
+ int ret = 0;
+ for (int i = 0; i < 1000; i++)
+ ret += __builtin_dispatch (featureTest, (void *)foo, (void *)bar, i);
+ return ret;
+}
+
+int main ()
+{
+ int val = dispatch ();
+ return val > 10000000;
+}
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/tree-prof/mversn15.C b/gcc-4.4.3/gcc/testsuite/g++.dg/tree-prof/mversn15.C
new file mode 100644
index 000000000..dfab1bdf3
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/tree-prof/mversn15.C
@@ -0,0 +1,23 @@
+/* Make sure LIPO works correctly. dispatch is defined in mversn15a.C. It either
+ calls foo or bar and both returns 1. So, the value of ret is always 1000.
+ After cross-module inlining, main must return 0. */
+
+/* { dg-additional-sources "mversn15a.C" } */
+/* { dg-options "-O2 -fclone-hot-version-paths -fripa -fdump-tree-final_cleanup" } */
+
+extern int foo ();
+extern int bar ();
+extern int dispatch ();
+
+int
+main ()
+{
+ int ret = 0;
+ for (int i = 1; i <= 1000; i++)
+ ret += dispatch ();
+ return ret - 1000;
+}
+
+/* { dg-final-use { scan-tree-dump "main_clone" "final_cleanup" } } */
+/* { dg-final-use { scan-tree-dump "return 0" "final_cleanup" } } */
+/* { dg-final-use { cleanup-tree-dump "final_cleanup" } } */
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/tree-prof/mversn15a.C b/gcc-4.4.3/gcc/testsuite/g++.dg/tree-prof/mversn15a.C
new file mode 100644
index 000000000..79e7b630a
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/tree-prof/mversn15a.C
@@ -0,0 +1,26 @@
+/* { dg-options "-O2 -fclone-hot-version-paths -fripa" } */
+/* { dg-additional-sources "mversn15.C" } */
+
+#include <stdio.h>
+
+inline int
+ __attribute__ ((version_selector))
+featureTest()
+{
+ return 1;
+}
+
+int foo ()
+{
+ return 1;
+}
+
+int bar ()
+{
+ return 1;
+}
+
+int dispatch ()
+{
+ return __builtin_dispatch (featureTest, (void *)foo, (void *)bar);
+}
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/uninit-pred-3_a.C b/gcc-4.4.3/gcc/testsuite/g++.dg/uninit-pred-3_a.C
new file mode 100644
index 000000000..910140790
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/uninit-pred-3_a.C
@@ -0,0 +1,77 @@
+/* { dg-do compile } */
+/* { dg-options "-Wuninitialized -O2" } */
+
+/* Multiple initialization paths. */
+
+typedef long long int64;
+void incr ();
+bool is_valid (int);
+int get_time ();
+
+class A
+{
+public:
+ A ();
+ ~A () {
+ if (I) delete I;
+ }
+
+private:
+ int* I;
+};
+
+bool get_url (A *);
+bool get_url2 (A *);
+
+class M {
+
+ public:
+ __attribute__ ((always_inline))
+ bool GetC (int *c) {
+
+ A details_str;
+ /* Intialization path 1 */
+ if (get_url (&details_str))
+ {
+ *c = get_time ();
+ return true;
+ }
+
+ /* insert dtor calls (inlined) into following return paths */
+ A tmp_str;
+
+ /* Intializtion path 2 */
+ if (get_url2 (&details_str))
+ {
+ *c = get_time ();
+ return true;
+ }
+
+ return false;
+ }
+
+ void do_sth();
+ void do_sth2();
+
+ void P (int64 t)
+ {
+ int cc;
+ if (!GetC (&cc)) /* return flag checked properly */
+ return;
+
+ if (cc <= 0) /* { dg-bogus "uninitialized" "uninitialized variable warning" } */
+ {
+ this->do_sth();
+ return;
+ }
+
+ do_sth2();
+ }
+};
+
+M* m;
+void test(int x)
+{
+ m = new M;
+ m->P(x);
+}
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/uninit-pred-3_b.C b/gcc-4.4.3/gcc/testsuite/g++.dg/uninit-pred-3_b.C
new file mode 100644
index 000000000..cfe2113bb
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/uninit-pred-3_b.C
@@ -0,0 +1,87 @@
+/* { dg-do compile } */
+/* { dg-options "-Wuninitialized -O2" } */
+
+/* Multiple initialization paths. */
+
+typedef long long int64;
+void incr ();
+bool is_valid (int);
+int get_time ();
+
+class A
+{
+public:
+ A ();
+ ~A () {
+ if (I) delete I;
+ }
+
+private:
+ int* I;
+};
+
+bool get_url (A *);
+bool get_url2 (A *);
+bool get_url3 (A *);
+
+class M {
+
+ public:
+ __attribute__ ((always_inline))
+ bool GetC (int *c) {
+
+ A details_str;
+
+ /* Initialization path 1 */
+ if (get_url (&details_str))
+ {
+ *c = get_time ();
+ return true;
+ }
+
+ /* Destructor call before return*/
+ A tmp_str;
+
+ /* Initialization path 2 */
+ if (get_url2 (&details_str))
+ {
+ *c = get_time ();
+ return true;
+ }
+
+ /* Fail to initialize in this path but
+ still returns true */
+ if (get_url2 (&details_str))
+ {
+ /* Fail to initialize *c */
+ return true;
+ }
+
+ return false;
+ }
+
+ void do_sth();
+ void do_sth2();
+
+ void P (int64 t)
+ {
+ int cc; /* { dg-excess-errors "note: 'cc' was declared here" } */
+ if (!GetC (&cc))
+ return;
+
+ if (cc <= 0) /* { dg-warning "uninitialized" "uninitialized variable warning" } */
+ {
+ this->do_sth();
+ return;
+ }
+
+ do_sth2();
+ }
+};
+
+M* m;
+void test(int x)
+{
+ m = new M;
+ m->P(x);
+}
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/warn/Wnonnull-1.C b/gcc-4.4.3/gcc/testsuite/g++.dg/warn/Wnonnull-1.C
new file mode 100644
index 000000000..837c6d6d8
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/warn/Wnonnull-1.C
@@ -0,0 +1,16 @@
+// { dg-do compile }
+// { dg-options "-Wnonnull" }
+
+#include <stddef.h>
+
+class Foo {
+ char *name;
+ public:
+ void func1(const int *ptr) __attribute__((nonnull(2))) {}
+ Foo(char *str) __attribute__((nonnull)) : name(str) {}
+};
+
+void Bar() {
+ Foo foo(NULL); // { dg-warning "null argument where non-null required" }
+ foo.func1(NULL); // { dg-warning "null argument where non-null required" }
+}
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/warn/Wnull-conversion-1.C b/gcc-4.4.3/gcc/testsuite/g++.dg/warn/Wnull-conversion-1.C
index 561482914..511f091f2 100644
--- a/gcc-4.4.3/gcc/testsuite/g++.dg/warn/Wnull-conversion-1.C
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/warn/Wnull-conversion-1.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-Wnull-conversion" }
+// { dg-options "-Wconversion-null" }
#include <stddef.h>
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/warn/Wnull-conversion-2.C b/gcc-4.4.3/gcc/testsuite/g++.dg/warn/Wnull-conversion-2.C
index eb5f8b0c1..92a87d1e7 100644
--- a/gcc-4.4.3/gcc/testsuite/g++.dg/warn/Wnull-conversion-2.C
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/warn/Wnull-conversion-2.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-Wnull-conversion" }
+// { dg-options "-Wconversion-null" }
#include <stddef.h>
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/warn/Wself-assign-1.C b/gcc-4.4.3/gcc/testsuite/g++.dg/warn/Wself-assign-1.C
index 6538d68d0..f15280501 100644
--- a/gcc-4.4.3/gcc/testsuite/g++.dg/warn/Wself-assign-1.C
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/warn/Wself-assign-1.C
@@ -40,8 +40,8 @@ int func()
*f = *f; // { dg-warning "assigned to itself" }
bar1->b_ = bar1->b_; // { dg-warning "assigned to itself" }
bar2.c_ = bar2.c_; // { dg-warning "assigned to itself" }
- local_foo = local_foo; // { dg-warning "assigned to itself" }
- foo = foo; // { dg-warning "assigned to itself" }
+ local_foo = local_foo;
+ foo = foo;
foo.setA(5);
bar_array[3].c_ = bar_array[3].c_; // { dg-warning "assigned to itself" }
bar_array[x+g].b_ = bar_array[x+g].b_; // { dg-warning "assigned to itself" }
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/warn/Wself-assign-2.C b/gcc-4.4.3/gcc/testsuite/g++.dg/warn/Wself-assign-2.C
index c221787cf..35c3d8476 100644
--- a/gcc-4.4.3/gcc/testsuite/g++.dg/warn/Wself-assign-2.C
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/warn/Wself-assign-2.C
@@ -18,9 +18,9 @@ template<typename T>
T DoSomething(T y) {
T a[5], *p;
Bar<T> b;
- b.x = b.x; // { dg-warning "assigned to itself" }
- *p = *p; // { dg-warning "assigned to itself" }
- a[2] = a[2]; // { dg-warning "assigned to itself" }
+ b.x = b.x;
+ *p = *p;
+ a[2] = a[2];
return *p;
}
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/warn/Wself-assign-3.C b/gcc-4.4.3/gcc/testsuite/g++.dg/warn/Wself-assign-3.C
index ce6bec191..bc5732de9 100644
--- a/gcc-4.4.3/gcc/testsuite/g++.dg/warn/Wself-assign-3.C
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/warn/Wself-assign-3.C
@@ -27,7 +27,7 @@ class Bar {
template <class T>
void func(T t) {
::testing::Bar(1) = ::testing::Foo(); // used to trigger a segfault
- ::testing::Foo() = ::testing::Foo(); // { dg-warning "assigned to itself" }
+ ::testing::Foo() = ::testing::Foo();
}
main() {
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/warn/Wself-assign-4.C b/gcc-4.4.3/gcc/testsuite/g++.dg/warn/Wself-assign-4.C
index 465aadc3a..abe96b55d 100644
--- a/gcc-4.4.3/gcc/testsuite/g++.dg/warn/Wself-assign-4.C
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/warn/Wself-assign-4.C
@@ -43,6 +43,6 @@ int func()
bar_array[x+g].b_ = bar_array[x+g].b_ / 1; // should not warn
x += 0;
y -= 0;
- foo = foo; // { dg-warning "assigned to itself" }
+ foo = foo;
foo.operator=(foo); // should not warn
}
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/warn/Wself-assign-5.C b/gcc-4.4.3/gcc/testsuite/g++.dg/warn/Wself-assign-5.C
new file mode 100644
index 000000000..20df214dd
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/warn/Wself-assign-5.C
@@ -0,0 +1,38 @@
+// Test -Wself-assign does not warn on self-assignment of non-POD variables.
+// { dg-do compile }
+// { dg-options "-Wself-assign" }
+
+template<typename T>
+class Foo {
+ private:
+ T a_;
+ public:
+ Foo() : a_(a_) {} // { dg-warning "assigned to itself" }
+ void Set() { a_ = a_; }
+};
+
+struct Bar {
+ int b_;
+ int c_;
+ void operator=(Bar& rhs) {
+ this->b_ = rhs.b_;
+ this->c_ = rhs.c_;
+ }
+};
+
+template <typename T>
+void func() {
+ T a;
+ a = a;
+}
+
+main()
+{
+ Foo<Bar> foo;
+ Bar *bar1, bar2;
+ func<int>();
+ foo = foo;
+ bar2 = bar2;
+ bar1 = bar1; // { dg-warning "assigned to itself" }
+ bar2.b_ = bar2.b_; // { dg-warning "assigned to itself" }
+}
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/warn/Wself-assign-non-pod-1.C b/gcc-4.4.3/gcc/testsuite/g++.dg/warn/Wself-assign-non-pod-1.C
new file mode 100644
index 000000000..6f9dfb73c
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/warn/Wself-assign-non-pod-1.C
@@ -0,0 +1,54 @@
+// Test the self-assignemnt detection and warning.
+// { dg-do compile }
+// { dg-options "-Wself-assign -Wself-assign-non-pod" }
+
+class Foo {
+ private:
+ int a_;
+
+ public:
+ Foo() : a_(a_) {} // { dg-warning "assigned to itself" }
+
+ void setA(int a) {
+ a_ = a_; // { dg-warning "assigned to itself" }
+ }
+
+ void operator=(Foo& rhs) {
+ this->a_ = rhs.a_;
+ }
+};
+
+struct Bar {
+ int b_;
+ int c_;
+};
+
+int g = g; // { dg-warning "assigned to itself" }
+Foo foo = foo; // { dg-warning "assigned to itself" }
+
+int func()
+{
+ Bar *bar1, bar2;
+ Foo local_foo;
+ int x = x; // { dg-warning "assigned to itself" }
+ static int y = y; // { dg-warning "assigned to itself" }
+ float *f;
+ Bar bar_array[5];
+ char n;
+ int overflow;
+
+ *f = *f; // { dg-warning "assigned to itself" }
+ bar1->b_ = bar1->b_; // { dg-warning "assigned to itself" }
+ bar2.c_ = bar2.c_; // { dg-warning "assigned to itself" }
+ local_foo = local_foo; // { dg-warning "assigned to itself" }
+ foo = foo; // { dg-warning "assigned to itself" }
+ foo.setA(5);
+ bar_array[3].c_ = bar_array[3].c_; // { dg-warning "assigned to itself" }
+ bar_array[x+g].b_ = bar_array[x+g].b_; // { dg-warning "assigned to itself" }
+ y = x;
+ x = y;
+ x += 0; // should not warn
+ y -= 0; // should not warn
+ x /= x; // should not warn
+ y *= y; // should not warn
+}
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/warn/Wself-assign-non-pod-2.C b/gcc-4.4.3/gcc/testsuite/g++.dg/warn/Wself-assign-non-pod-2.C
new file mode 100644
index 000000000..b31b57534
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/warn/Wself-assign-non-pod-2.C
@@ -0,0 +1,31 @@
+// Test the handling of expressions that depend on template parameters in
+// self-assignemnt detection.
+// { dg-do compile }
+// { dg-options "-Wself-assign -Wself-assign-non-pod" }
+
+template<typename T>
+struct Bar {
+ T x;
+ Bar operator++(int) {
+ Bar tmp = *this;
+ ++x;
+ tmp = tmp; // { dg-warning "assigned to itself" }
+ return tmp;
+ }
+};
+
+template<typename T>
+T DoSomething(T y) {
+ T a[5], *p;
+ Bar<T> b;
+ b.x = b.x; // { dg-warning "assigned to itself" }
+ *p = *p; // { dg-warning "assigned to itself" }
+ a[2] = a[2]; // { dg-warning "assigned to itself" }
+ return *p;
+}
+
+main() {
+ Bar<int> bar;
+ bar++;
+ DoSomething(5);
+}
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/warn/Wself-assign-non-pod-3.C b/gcc-4.4.3/gcc/testsuite/g++.dg/warn/Wself-assign-non-pod-3.C
new file mode 100644
index 000000000..4c37f5764
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/warn/Wself-assign-non-pod-3.C
@@ -0,0 +1,35 @@
+// Test how operands_equal_p handles a NULL operand.
+// { dg-do compile }
+// { dg-options "-Wself-assign -Wself-assign-non-pod" }
+
+#include <cstdio>
+
+namespace testing {
+
+class Foo {
+ int f;
+ public:
+ Foo() { printf("Construct Foo\n"); }
+};
+
+class Bar {
+ int b;
+ public:
+ Bar(int x) { printf("Construct Bar\n"); }
+
+ void operator=(const Foo& foo) {
+ printf("Assign Foo to Bar\n");
+ }
+};
+
+}
+
+template <class T>
+void func(T t) {
+ ::testing::Bar(1) = ::testing::Foo(); // used to trigger a segfault
+ ::testing::Foo() = ::testing::Foo(); // { dg-warning "assigned to itself" }
+}
+
+main() {
+ func(2);
+}
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/warn/Wself-assign-non-pod-4.C b/gcc-4.4.3/gcc/testsuite/g++.dg/warn/Wself-assign-non-pod-4.C
new file mode 100644
index 000000000..86db4e3c6
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/warn/Wself-assign-non-pod-4.C
@@ -0,0 +1,48 @@
+// Test how self-assignment detection handles constant-folding happening
+// when parsing the RHS or the initializer.
+// { dg-do compile }
+// { dg-options "-Wself-assign -Wself-assign-non-pod" }
+
+class Foo {
+ private:
+ int a_;
+
+ public:
+ Foo() : a_(a_+0) {} // should not warn
+
+ void setA(int a) {
+ a_ = a_ + 0; // should not warn
+ }
+
+ void operator=(Foo& rhs) {
+ this->a_ = rhs.a_;
+ }
+};
+
+struct Bar {
+ int b_;
+ float c_;
+};
+
+int g = g * 1; // should not warn
+
+int func()
+{
+ Bar *bar1, bar2;
+ Foo foo;
+ int x = x - 0; // should not warn
+ static int y = y / 1; // should not warn
+ float *f;
+ Bar bar_array[5];
+
+ *f = *f / 1; // should not warn
+ bar1->b_ = bar1->b_ * 1; // should not warn
+ bar2.c_ = bar2.c_ - 0; // should not warn
+ foo.setA(5);
+ bar_array[3].c_ = bar_array[3].c_ * 1; // should not warn
+ bar_array[x+g].b_ = bar_array[x+g].b_ / 1; // should not warn
+ x += 0;
+ y -= 0;
+ foo = foo; // { dg-warning "assigned to itself" }
+ foo.operator=(foo); // should not warn
+}
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/warn/Wself-assign-non-pod-5.C b/gcc-4.4.3/gcc/testsuite/g++.dg/warn/Wself-assign-non-pod-5.C
new file mode 100644
index 000000000..898ddecd7
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/warn/Wself-assign-non-pod-5.C
@@ -0,0 +1,38 @@
+// Test -Wself-assign and -Wself-assign-non-pod.
+// { dg-do compile }
+// { dg-options "-Wself-assign -Wself-assign-non-pod" }
+
+template<typename T>
+class Foo {
+ private:
+ T a_;
+ public:
+ Foo() : a_(a_) {} // { dg-warning "assigned to itself" }
+ void Set() { a_ = a_; } // { dg-warning "assigned to itself" }
+};
+
+struct Bar {
+ int b_;
+ int c_;
+ void operator=(Bar& rhs) {
+ this->b_ = rhs.b_;
+ this->c_ = rhs.c_;
+ }
+};
+
+template <typename T>
+void func() {
+ T a;
+ a = a; // { dg-warning "assigned to itself" }
+}
+
+main()
+{
+ Foo<Bar> foo;
+ Bar *bar1, bar2;
+ func<int>();
+ foo = foo; // { dg-warning "assigned to itself" }
+ bar2 = bar2; // { dg-warning "assigned to itself" }
+ bar1 = bar1; // { dg-warning "assigned to itself" }
+ bar2.b_ = bar2.b_; // { dg-warning "assigned to itself" }
+}
diff --git a/gcc-4.4.3/gcc/testsuite/g++.dg/warn/nonnull2.C b/gcc-4.4.3/gcc/testsuite/g++.dg/warn/nonnull2.C
new file mode 100644
index 000000000..03006b1b2
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/g++.dg/warn/nonnull2.C
@@ -0,0 +1,14 @@
+// Test that "nonnull" attribute should not be applied to 'this' pointer.
+// { dg-do compile }
+
+#define NULL 0
+
+class Foo {
+ public:
+ void method1(const int *ptr) __attribute__((nonnull(1, 2))); // { dg-warning "nonnull argument references 'this' pointer" }
+ void method2(int *ptr1, int a, int *ptr2) __attribute__((nonnull(2, 3, 4))); // { dg-error "nonnull argument references non-pointer operand" }
+ static void func3(int *ptr) __attribute__((nonnull(1))); // should not warn
+ Foo(char *str) __attribute__((nonnull())) {}
+};
+
+int func4(int *ptr1, int a) __attribute__((nonnull(1))); // should not warn
diff --git a/gcc-4.4.3/gcc/testsuite/g++.old-deja/g++.ns/koenig5.C b/gcc-4.4.3/gcc/testsuite/g++.old-deja/g++.ns/koenig5.C
index d84fc8dbf..33061ad0b 100644
--- a/gcc-4.4.3/gcc/testsuite/g++.old-deja/g++.ns/koenig5.C
+++ b/gcc-4.4.3/gcc/testsuite/g++.old-deja/g++.ns/koenig5.C
@@ -1,5 +1,5 @@
// { dg-do assemble }
-// To find function pointers in Koenig lookup is ok as long as we only find one.
+// Function pointers are ignored in Koenig lookup. (DR 218)
namespace A{
void foo();
struct X{};
@@ -14,5 +14,5 @@ void g()
foo(new X); // ok -- DR 218 says that we find the global
// foo variable first, and therefore do not
// perform argument-dependent lookup.
- bar(new X); // ok
+ bar(new X); // { dg-error "not declared" }
}
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.c-torture/compile/pr22379.c b/gcc-4.4.3/gcc/testsuite/gcc.c-torture/compile/pr22379.c
index fae84a0af..13c41dd58 100644
--- a/gcc-4.4.3/gcc/testsuite/gcc.c-torture/compile/pr22379.c
+++ b/gcc-4.4.3/gcc/testsuite/gcc.c-torture/compile/pr22379.c
@@ -2,7 +2,7 @@ void __add_entropy_words(void);
void __wake_up(void);
void SHATransform(void);
static inline __attribute__((always_inline)) void add_entropy_words(void){}
-void extract_entropy(void);
+void __attribute__((noinline)) extract_entropy(void);
static inline __attribute__((always_inline)) void xfer_secondary_pool(void)
{
extract_entropy();
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.c-torture/compile/pr42632.c b/gcc-4.4.3/gcc/testsuite/gcc.c-torture/compile/pr42632.c
index a6778537a..e2f7d1022 100644
--- a/gcc-4.4.3/gcc/testsuite/gcc.c-torture/compile/pr42632.c
+++ b/gcc-4.4.3/gcc/testsuite/gcc.c-torture/compile/pr42632.c
@@ -8,7 +8,7 @@ int pskb_trim(void)
{
return __pskb_trim();
}
-int ___pskb_trim(void)
+inline __attribute__((noinline)) int ___pskb_trim(void)
{
pskb_trim();
return 0;
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.c-torture/execute/pr44575.c b/gcc-4.4.3/gcc/testsuite/gcc.c-torture/execute/pr44575.c
new file mode 100644
index 000000000..62a7d7800
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.c-torture/execute/pr44575.c
@@ -0,0 +1,49 @@
+/* PR target/44575 */
+
+#include <stdarg.h>
+
+int fails = 0;
+struct S { float a[3]; };
+struct S a[5];
+
+void
+check (int z, ...)
+{
+ struct S arg, *p;
+ va_list ap;
+ int j = 0, k = 0;
+ int i;
+ va_start (ap, z);
+ for (i = 2; i < 4; ++i)
+ {
+ p = 0;
+ j++;
+ k += 2;
+ switch ((z << 4) | i)
+ {
+ case 0x12:
+ case 0x13:
+ p = &a[2];
+ arg = va_arg (ap, struct S);
+ break;
+ default:
+ ++fails;
+ break;
+ }
+ if (p && p->a[2] != arg.a[2])
+ ++fails;
+ if (fails)
+ break;
+ }
+ va_end (ap);
+}
+
+int
+main ()
+{
+ a[2].a[2] = -49026;
+ check (1, a[2], a[2]);
+ if (fails)
+ abort ();
+ return 0;
+}
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.dg/always_inline2.c b/gcc-4.4.3/gcc/testsuite/gcc.dg/always_inline2.c
index c65df24ea..3e5e2a3fd 100644
--- a/gcc-4.4.3/gcc/testsuite/gcc.dg/always_inline2.c
+++ b/gcc-4.4.3/gcc/testsuite/gcc.dg/always_inline2.c
@@ -1,8 +1,8 @@
/* { dg-do compile } */
/* { dg-options "-Winline -O2" } */
-inline __attribute__ ((always_inline)) void t(void); /* { dg-message "sorry\[^\n\]*body not available" "" } */
+inline __attribute__ ((always_inline)) void t(void); /* { dg-message "error\[^\n\]*body not available" "" } */
void
q(void)
{
- t(); /* { dg-message "sorry\[^\n\]*called from here" "" } */
+ t(); /* { dg-message "error\[^\n\]*called from here" "" } */
}
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.dg/always_inline3.c b/gcc-4.4.3/gcc/testsuite/gcc.dg/always_inline3.c
index 97c80aa52..d754d7194 100644
--- a/gcc-4.4.3/gcc/testsuite/gcc.dg/always_inline3.c
+++ b/gcc-4.4.3/gcc/testsuite/gcc.dg/always_inline3.c
@@ -2,10 +2,10 @@
/* { dg-options "-Winline -O2" } */
int do_something_evil (void);
inline __attribute__ ((always_inline)) void
-q2(void) /* { dg-message "sorry\[^\n\]*recursive" "" } */
+q2(void) /* { dg-message "error\[^\n\]*recursive" "" } */
{
if (do_something_evil ())
return;
- q2(); /* { dg-message "sorry\[^\n\]*called from here" "" } */
+ q2(); /* { dg-message "error\[^\n\]*called from here" "" } */
q2(); /* With -O2 we don't warn here, it is eliminated by tail recursion. */
}
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.dg/always_inline4.c b/gcc-4.4.3/gcc/testsuite/gcc.dg/always_inline4.c
new file mode 100644
index 000000000..723ff97ac
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.dg/always_inline4.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+/* If f3() is inlined the impossible-to-resolve situation of a cycle
+ of always_inlined functions is created in the call graph. This
+ test tests whether this condition is detected and avoided. */
+
+inline void f1(int);
+inline void f2(int);
+inline void f3(int);
+
+inline void __attribute__((__always_inline__)) f1(int a) {
+ f3(a);
+ f3(a);
+}
+
+inline void __attribute__((__always_inline__)) f2(int a) {
+ f1(a);
+}
+
+inline void f3(int a) {
+ f2(a);
+}
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.dg/autopar/reduc-1.c b/gcc-4.4.3/gcc/testsuite/gcc.dg/autopar/reduc-1.c
index ac08d3d2e..1cafaecd2 100644
--- a/gcc-4.4.3/gcc/testsuite/gcc.dg/autopar/reduc-1.c
+++ b/gcc-4.4.3/gcc/testsuite/gcc.dg/autopar/reduc-1.c
@@ -12,7 +12,7 @@ unsigned int uc[N] = {1,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
/* Reduction of unsigned-int. */
-void main1 (unsigned int x, unsigned int max_result, unsigned int min_result)
+void __attribute__((noinline)) main1 (unsigned int x, unsigned int max_result, unsigned int min_result)
{
int i;
unsigned int udiff = 2;
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.dg/builtin-apply2.c b/gcc-4.4.3/gcc/testsuite/gcc.dg/builtin-apply2.c
index bc49a6458..a303e3ddb 100644
--- a/gcc-4.4.3/gcc/testsuite/gcc.dg/builtin-apply2.c
+++ b/gcc-4.4.3/gcc/testsuite/gcc.dg/builtin-apply2.c
@@ -1,5 +1,6 @@
/* { dg-do run } */
/* { dg-skip-if "Variadic funcs have all args on stack. Normal funcs have args in registers." { "avr-*-*" } { "*" } { "" } } */
+/* { dg-skip-if "Variadic funcs use Base AAPCS. Normal funcs use VFP variant." { "arm*-*-*" } { "-mfloat-abi=hard" } { "" } } */
/* PR target/12503 */
/* Origin: <pierre.nguyen-tuong@asim.lip6.fr> */
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.dg/ipa/ipa-4.c b/gcc-4.4.3/gcc/testsuite/gcc.dg/ipa/ipa-4.c
index 9f716f139..02efb7b4e 100644
--- a/gcc-4.4.3/gcc/testsuite/gcc.dg/ipa/ipa-4.c
+++ b/gcc-4.4.3/gcc/testsuite/gcc.dg/ipa/ipa-4.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O3 -fipa-cp -fipa-cp-clone -fdump-ipa-cp" } */
+/* { dg-options "-O3 -fipa-cp -fipa-cp-clone -fdump-ipa-cp --param inline-address-not-taken-function-emit-probability=100 --param inline-function-size-adjustment=0" } */
/* { dg-skip-if "PR 25442" { "*-*-*" } { "-fpic" "-fPIC" } { "" } } */
#include <stdio.h>
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.dg/mversn2.c b/gcc-4.4.3/gcc/testsuite/gcc.dg/mversn2.c
new file mode 100644
index 000000000..7cfb0718b
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.dg/mversn2.c
@@ -0,0 +1,47 @@
+/* This checks if cloning works correctly. Since dispatch and fn1 are hot, they
+ should be cloned. main should not be cloned.*/
+
+/* { dg-do run } */
+/* { dg-options "-O2 -fclone-hot-version-paths -fdump-tree-final_cleanup" } */
+
+int __attribute__ ((version_selector))
+featureTest ()
+{
+ return 1;
+}
+
+int __attribute__ ((cold))
+foo ()
+{
+ return 0;
+}
+
+int __attribute__ ((cold))
+bar ()
+{
+ return 1;
+}
+
+int __attribute__ ((hot))
+dispatch ()
+{
+ return __builtin_dispatch (featureTest, (void *)foo, (void *) bar);
+}
+int __attribute__ ((hot))
+fn1 ()
+{
+ return dispatch ();
+}
+
+int __attribute__ ((cold))
+main ()
+{
+ return fn1 ();
+}
+
+/* { dg-final { scan-tree-dump "fn1_clone_1" "final_cleanup" } } */
+/* { dg-final { scan-tree-dump "dispatch_clone_0" "final_cleanup" } } */
+/* { dg-final { scan-tree-dump "dispatch_clone_1" "final_cleanup" } } */
+/* { dg-final { scan-tree-dump-not "main_clone_0" "final_cleanup" } } */
+/* { dg-final { scan-tree-dump-not "main_clone_1" "final_cleanup" } } */
+/* { dg-final { cleanup-tree-dump "final_cleanup" } } */
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.dg/mversn3.c b/gcc-4.4.3/gcc/testsuite/gcc.dg/mversn3.c
new file mode 100644
index 000000000..5085aa924
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.dg/mversn3.c
@@ -0,0 +1,30 @@
+/* Simple check if parameters are passed correctly. */
+
+/* { dg-do run } */
+/* { dg-options "-O2 -fclone-hot-version-paths" } */
+
+int __attribute__ ((version_selector))
+featureTest ()
+{
+ return 1;
+}
+
+int __attribute__ ((cold))
+foo (int a)
+{
+ if (a == 1729)
+ return 0;
+ return 1;
+}
+
+int __attribute__ ((cold))
+bar (int a)
+{
+ return 1;
+}
+
+int __attribute__ ((cold))
+main ()
+{
+ return __builtin_dispatch (featureTest, (void *)foo, (void *) bar, 1729);
+}
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.dg/mversn4.c b/gcc-4.4.3/gcc/testsuite/gcc.dg/mversn4.c
new file mode 100644
index 000000000..cd916c981
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.dg/mversn4.c
@@ -0,0 +1,29 @@
+/* Check that static feature test functions are correctly handled. This
+ test case also needs mversn4a.c. extern_func calls foo and returns 0.*/
+
+/* { dg-do run } */
+/* { dg-additional-sources "mversn4a.c" } */
+/* { dg-options "-O2" } */
+
+#include "mversn4.h"
+
+extern int extern_func ();
+
+int foo ()
+{
+ return 0;
+}
+
+int bar ()
+{
+ return 1;
+}
+
+int __attribute__ ((cold))
+main ()
+{
+ int a = 1, b = 1;
+ a = extern_func ();
+ b = __builtin_dispatch (featureTest, (void *)bar, (void *) foo);
+ return a * b;
+}
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.dg/mversn4.h b/gcc-4.4.3/gcc/testsuite/gcc.dg/mversn4.h
new file mode 100644
index 000000000..37067d37f
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.dg/mversn4.h
@@ -0,0 +1,5 @@
+static int __attribute__ ((version_selector))
+featureTest ()
+{
+ return 1;
+}
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.dg/mversn4a.c b/gcc-4.4.3/gcc/testsuite/gcc.dg/mversn4a.c
new file mode 100644
index 000000000..92d4f1240
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.dg/mversn4a.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include "mversn4.h"
+
+extern int foo ();
+extern int bar ();
+
+
+int extern_func ()
+{
+ return __builtin_dispatch (featureTest, (void *)foo, (void *) bar);
+}
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.dg/mversn6.c b/gcc-4.4.3/gcc/testsuite/gcc.dg/mversn6.c
new file mode 100644
index 000000000..e83e35165
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.dg/mversn6.c
@@ -0,0 +1,29 @@
+/* Check that __builtin_dispatch gets converted and the executable runs fine.
+ when featureTest () is not marked with "version_selector". foo should be
+ called and return 0. Cloning and Hoisting is also done. */
+/* { dg-do run } */
+/* { dg-options "-O2 -fclone-hot-version-paths" } */
+
+int
+featureTest ()
+{
+ return 1;
+}
+
+int __attribute__ ((cold))
+foo ()
+{
+ return 0;
+}
+
+int __attribute__ ((cold))
+bar ()
+{
+ return 1;
+}
+
+int __attribute__ ((cold))
+main ()
+{
+ return __builtin_dispatch (featureTest, (void *)foo, (void *) bar);
+}
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.dg/mversn7.c b/gcc-4.4.3/gcc/testsuite/gcc.dg/mversn7.c
new file mode 100644
index 000000000..f56331cf0
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.dg/mversn7.c
@@ -0,0 +1,45 @@
+/* This test checks if cloning and dispatching works correctly with
+ a motivating example. The function problem calculates the sum of
+ numbers from 1 to 10 in two different ways. Hence, after cloning
+ both clones should return 55, which means main returns 0 if function
+ "problem" gets inlined.
+ This example also shows the benefits of function
+ unswitching. Without cloning, the loop will be done. */
+
+/* { dg-do run } */
+/* { dg-options "-O2 -fclone-hot-version-paths -fdump-tree-final_cleanup" } */
+
+int __attribute__ ((version_selector))
+featureTest ()
+{
+ return 1;
+}
+
+int foo (int i)
+{
+ return i;
+}
+
+int bar (int i)
+{
+ return (11 - i);
+}
+
+/* This calculates the sum of numbers from 1 to 10 in 2 different ways. */
+int problem ()
+{
+ int ret = 0;
+ int j = 1;
+ for (j = 1; j<=10; j++)
+ ret += __builtin_dispatch (featureTest, (void *)foo, (void *)bar, j);
+ return ret;
+}
+
+int main ()
+{
+ return problem() - 55;
+}
+
+
+/* { dg-final { scan-tree-dump "return 55" "final_cleanup" } } */
+/* { dg-final { cleanup-tree-dump "final_cleanup" } } */
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.dg/nrv6.c b/gcc-4.4.3/gcc/testsuite/gcc.dg/nrv6.c
new file mode 100644
index 000000000..0fde6b3e4
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.dg/nrv6.c
@@ -0,0 +1,22 @@
+/* Verify that changing to -O0 after a candidate for NRV optimization
+ does not cause ICE. */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+struct A {
+ int i;
+};
+
+struct A foo (int i)
+{
+ struct A a;
+ a.i = i;
+ return a;
+}
+
+#pragma GCC optimize("-O0")
+
+int test(void)
+{
+ return 0;
+}
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.dg/overlay1.c b/gcc-4.4.3/gcc/testsuite/gcc.dg/overlay1.c
new file mode 100644
index 000000000..a87dfa415
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.dg/overlay1.c
@@ -0,0 +1,70 @@
+/* Check that store sinking does not break stack overlay */
+/* { dg-do run } */
+/* { dg-options "-O2 -fearly-stack-alloc" } */
+
+extern void abort (void);
+
+struct a;
+
+typedef void (*func_t)(struct a*);
+
+struct a {
+ func_t impl;
+};
+
+struct b {
+ struct a base;
+};
+
+void
+a_impl (struct a *const this)
+{
+ abort();
+}
+
+void
+b_impl (struct a * const this)
+{
+}
+
+void __attribute__((noinline))
+a_interface (struct a * const this)
+{
+ this->impl(this);
+}
+
+int
+main(int argc, char **argv)
+{
+ {
+ struct b obj1;
+
+L1:
+ if (argc > 400)
+ return 0;
+ obj1.base.impl = b_impl;
+
+L2:
+ a_interface (&obj1.base);
+ obj1.base.impl = b_impl;
+ obj1.base.impl = a_impl;
+ if (argc > 200)
+ return 0;
+ }
+ {
+ struct b obj2;
+ obj2.base.impl = a_impl;
+
+L3:
+ obj2.base.impl = b_impl;
+ if (argc > 100)
+ return 0;
+
+L4:
+ a_interface (&obj2.base);
+ obj2.base.impl = b_impl;
+ obj2.base.impl = a_impl;
+ }
+
+ return 0;
+}
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.dg/overlay2.c b/gcc-4.4.3/gcc/testsuite/gcc.dg/overlay2.c
new file mode 100644
index 000000000..acd30282f
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.dg/overlay2.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fearly-stack-alloc -fstack-protector -fno-strict-aliasing -fdump-tree-stack-overlay" } */
+void bar (char *);
+void bar2 (int *);
+void foo ()
+ {
+ {
+ char a[100];
+ bar (a);
+ }
+ {
+ int a[100];
+ bar2 (a);
+ }
+ }
+
+/* { dg-final { scan-tree-dump "Number of partitions = 2" "stack-overlay" } } */
+/* { dg-final { cleanup-tree-dump "stack-overlay" } } */
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.dg/overlay3.c b/gcc-4.4.3/gcc/testsuite/gcc.dg/overlay3.c
new file mode 100644
index 000000000..c7218f4f2
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.dg/overlay3.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fearly-stack-alloc -fno-strict-aliasing -fdump-tree-stack-overlay" } */
+void bar (char *);
+void bar2 (int *);
+void foo ()
+ {
+ {
+ char a[100];
+ bar (a);
+ }
+ {
+ int a[100];
+ bar2 (a);
+ }
+ }
+
+/* { dg-final { scan-tree-dump "Number of partitions = 1" "stack-overlay" } } */
+/* { dg-final { cleanup-tree-dump "stack-overlay" } } */
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.dg/overlay4.c b/gcc-4.4.3/gcc/testsuite/gcc.dg/overlay4.c
new file mode 100644
index 000000000..8dfc49946
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.dg/overlay4.c
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fearly-stack-alloc -fno-strict-aliasing -fdump-tree-stack-overlay" } */
+union U {
+ int a;
+ float b;
+};
+struct A {
+ union U u1;
+ char a[100];
+};
+void bar (struct A *);
+void foo ()
+ {
+ {
+ struct A a;
+ bar (&a);
+ }
+ {
+ struct A a;
+ bar (&a);
+ }
+ }
+
+/* { dg-final { scan-tree-dump "Number of partitions = 1" "stack-overlay" } } */
+/* { dg-final { cleanup-tree-dump "stack-overlay" } } */
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.dg/overlay5.c b/gcc-4.4.3/gcc/testsuite/gcc.dg/overlay5.c
new file mode 100644
index 000000000..a815f23f3
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.dg/overlay5.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fearly-stack-alloc -fno-strict-aliasing -fdump-tree-stack-overlay" } */
+void bar( char *);
+int foo()
+{
+ int i=0;
+ {
+ char a[8192];
+ bar(a);
+ i += a[0];
+ }
+ {
+ char a[8192];
+ char b[32];
+ bar(a);
+ i += a[0];
+ bar(b);
+ i += a[0];
+ }
+ return i;
+}
+/* { dg-final { scan-tree-dump "Number of partitions = 2" "stack-overlay" } } */
+/* { dg-final { scan-tree-dump "size 8192" "stack-overlay" } } */
+/* { dg-final { scan-tree-dump "size 32" "stack-overlay" } } */
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.dg/pr43564.c b/gcc-4.4.3/gcc/testsuite/gcc.dg/pr43564.c
new file mode 100644
index 000000000..39e0f3ac3
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.dg/pr43564.c
@@ -0,0 +1,16 @@
+/* { dg-options "-O0" } */
+/* { dg-do compile } */
+
+static inline __attribute__ ((__always_inline__))
+unsigned __clz (unsigned input)
+{
+ unsigned output;
+ __asm__ __volatile__ ("clz %0, %1":"=r" (output):"r" (input));
+}
+__attribute__ ((optimize ("O2")))
+void foo ()
+{
+ unsigned a;
+ unsigned b;
+ a = __clz (b);
+}
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.dg/sibcall-1.c b/gcc-4.4.3/gcc/testsuite/gcc.dg/sibcall-1.c
index 4521ace9e..0941db704 100644
--- a/gcc-4.4.3/gcc/testsuite/gcc.dg/sibcall-1.c
+++ b/gcc-4.4.3/gcc/testsuite/gcc.dg/sibcall-1.c
@@ -5,7 +5,7 @@
Contributed by Hans-Peter Nilsson <hp@bitrange.com> */
/* { dg-do run } */
-/* { dg-options "-O2 -foptimize-sibling-calls" } */
+/* { dg-options "-O2 -foptimize-sibling-calls -fno-inline" } */
/* The option -foptimize-sibling-calls is the default, but serves as
marker. Self-recursion tail calls are optimized for all targets,
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.dg/sibcall-2.c b/gcc-4.4.3/gcc/testsuite/gcc.dg/sibcall-2.c
index 4c226c496..b5ca942ef 100644
--- a/gcc-4.4.3/gcc/testsuite/gcc.dg/sibcall-2.c
+++ b/gcc-4.4.3/gcc/testsuite/gcc.dg/sibcall-2.c
@@ -5,7 +5,7 @@
Contributed by Hans-Peter Nilsson <hp@bitrange.com> */
/* { dg-do run } */
-/* { dg-options "-O2 -foptimize-sibling-calls" } */
+/* { dg-options "-O2 -foptimize-sibling-calls -fno-inline" } */
/* The option -foptimize-sibling-calls is the default, but serves as
marker. Self-recursion tail calls are optimized for all targets,
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.dg/sibcall-3.c b/gcc-4.4.3/gcc/testsuite/gcc.dg/sibcall-3.c
index e085bfbc7..51f1b0b92 100644
--- a/gcc-4.4.3/gcc/testsuite/gcc.dg/sibcall-3.c
+++ b/gcc-4.4.3/gcc/testsuite/gcc.dg/sibcall-3.c
@@ -28,7 +28,7 @@ extern void exit (int);
static ATTR void recurser_void1 (int);
static ATTR void recurser_void2 (int);
-extern void track (int);
+static ATTR void track (int);
int main ()
{
@@ -66,7 +66,7 @@ recurser_void2 (int n)
void *trackpoint;
-void
+static void __attribute__((noinline)) ATTR
track (int n)
{
char stackpos[1];
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.dg/sibcall-4.c b/gcc-4.4.3/gcc/testsuite/gcc.dg/sibcall-4.c
index 11b09d079..cd185d47b 100644
--- a/gcc-4.4.3/gcc/testsuite/gcc.dg/sibcall-4.c
+++ b/gcc-4.4.3/gcc/testsuite/gcc.dg/sibcall-4.c
@@ -28,7 +28,7 @@ extern void exit (int);
static ATTR void recurser_void1 (void);
static ATTR void recurser_void2 (void);
-extern void track (void);
+static ATTR void track (void);
int n = 0;
int main ()
@@ -67,7 +67,7 @@ recurser_void2 (void)
void *trackpoint;
-void
+static void __attribute__((noinline)) ATTR
track ()
{
char stackpos[1];
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.dg/sibcall-6.c b/gcc-4.4.3/gcc/testsuite/gcc.dg/sibcall-6.c
index 6f2f21881..24e5ae7af 100644
--- a/gcc-4.4.3/gcc/testsuite/gcc.dg/sibcall-6.c
+++ b/gcc-4.4.3/gcc/testsuite/gcc.dg/sibcall-6.c
@@ -27,7 +27,7 @@ main ()
exit (0);
}
-int
+int __attribute__((noinline))
bar (b)
int b;
{
@@ -37,7 +37,7 @@ bar (b)
abort ();
}
-int
+int __attribute__((noinline))
foo (f)
int f;
{
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.dg/torture/mversn1.c b/gcc-4.4.3/gcc/testsuite/gcc.dg/torture/mversn1.c
new file mode 100644
index 000000000..bd024065c
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.dg/torture/mversn1.c
@@ -0,0 +1,31 @@
+/* Check that __builtin_dispatch gets converted and the executable runs fine.
+ Since featureTest () returns 1, foo should be called and return 0. Cloning
+ and Hoisting is not even turned on here. */
+/* { dg-do run } */
+
+int __attribute__ ((version_selector))
+featureTest ()
+{
+ return 1;
+}
+
+int __attribute__ ((cold))
+foo ()
+{
+ return 0;
+}
+
+int __attribute__ ((cold))
+bar ()
+{
+ return 1;
+}
+
+int __attribute__ ((cold))
+main ()
+{
+ int a, b;
+ a = __builtin_dispatch (featureTest, (void *)foo, (void *) bar);
+ b = __builtin_dispatch (featureTest, (void *)bar, (void *) foo);
+ return a * b;
+}
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.dg/torture/stackalign/builtin-apply-4.c b/gcc-4.4.3/gcc/testsuite/gcc.dg/torture/stackalign/builtin-apply-4.c
index 8b0ff4aff..28dc6106d 100644
--- a/gcc-4.4.3/gcc/testsuite/gcc.dg/torture/stackalign/builtin-apply-4.c
+++ b/gcc-4.4.3/gcc/testsuite/gcc.dg/torture/stackalign/builtin-apply-4.c
@@ -1,6 +1,5 @@
/* PR tree-optimization/20076 */
/* { dg-do run } */
-/* { dg-xfail-run-if "b/2070963" { { i?86-*-* x86_64-*-* } && { ilp32 } } { "*" } { "" } } */
extern void abort (void);
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.dg/torture/stackalign/stackalign.exp b/gcc-4.4.3/gcc/testsuite/gcc.dg/torture/stackalign/stackalign.exp
index 3574e4dc8..ef45dbe4d 100644
--- a/gcc-4.4.3/gcc/testsuite/gcc.dg/torture/stackalign/stackalign.exp
+++ b/gcc-4.4.3/gcc/testsuite/gcc.dg/torture/stackalign/stackalign.exp
@@ -28,6 +28,7 @@ set additional_flags ""
if { [istarget i?86*-*-*] || [istarget x86_64-*-*] } then {
lappend additional_flags "-mstackrealign"
lappend additional_flags "-mpreferred-stack-boundary=5"
+ lappend additional_flags "-mno-mmx"
}
dg-init
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.dg/tree-prof/ffvpt-pro-1.c b/gcc-4.4.3/gcc/testsuite/gcc.dg/tree-prof/ffvpt-pro-1.c
new file mode 100644
index 000000000..ff93852c3
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.dg/tree-prof/ffvpt-pro-1.c
@@ -0,0 +1,14 @@
+/* { dg-options "-lm -ffvpt -ffvpt-functions=log,exp,pow,sqrt -O2 -fdump-tree-optimized -fdump-tree-tree_profile" } */
+
+#define VAL 1.0
+
+#include "ffvpt-pro.h"
+
+/* { dg-final-use { scan-tree-dump-not "Invalid sum" "optimized"} } */
+/* { dg-final-use { scan-tree-dump "Math call \\(exp\\) to constant value: 1.000000 in main \\(use 2.718282\\) \\(count:1000, all:1000\\)" "tree_profile"} } */
+/* { dg-final-use { scan-tree-dump "Math call \\(pow\\) with constant argument \\(1.000000\\) optimized in main: \\(count:1000, all:1000\\)" "tree_profile"} } */
+/* { dg-final-use { scan-tree-dump "Math call \\(log\\) to constant value: 1.000000 in main \\(use 0.000000\\) \\(count:1000, all:1000\\)" "tree_profile"} } */
+/* { dg-final-use { scan-tree-dump "Math call \\(sqrt\\) to constant value: 1.000000 in main \\(use 1.000000\\) \\(count:1000, all:1000\\)" "tree_profile"} } */
+
+/* { dg-final-use { cleanup-tree-dump "optimized" } } */
+/* { dg-final-use { cleanup-tree-dump "tree_profile" } } */
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.dg/tree-prof/ffvpt-pro-2.c b/gcc-4.4.3/gcc/testsuite/gcc.dg/tree-prof/ffvpt-pro-2.c
new file mode 100644
index 000000000..17da95071
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.dg/tree-prof/ffvpt-pro-2.c
@@ -0,0 +1,14 @@
+/* { dg-options "-lm -ffvpt -ffvpt-functions=log,exp,pow,sqrt -O2 -fdump-tree-optimized -fdump-tree-tree_profile" } */
+
+#define VAL (1.0/0.0)
+
+#include "ffvpt-pro.h"
+
+/* { dg-final-use { scan-tree-dump-not "Invalid sum" "optimized"} } */
+/* { dg-final-use { scan-tree-dump "Math call \\(exp\\) to constant value: inf in main \\(use inf\\) \\(count:1000, all:1000\\)" "tree_profile"} } */
+/* { dg-final-use { scan-tree-dump-not "Math call \\(pow\\) with constant argument" "tree_profile"} } */
+/* { dg-final-use { scan-tree-dump "Math call \\(log\\) to constant value: inf in main \\(use inf\\) \\(count:1000, all:1000\\)" "tree_profile"} } */
+/* { dg-final-use { scan-tree-dump "Math call \\(sqrt\\) to constant value: inf in main \\(use inf\\) \\(count:1000, all:1000\\)" "tree_profile"} } */
+
+/* { dg-final-use { cleanup-tree-dump "optimized" } } */
+/* { dg-final-use { cleanup-tree-dump "tree_profile" } } */
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.dg/tree-prof/ffvpt-pro-3.c b/gcc-4.4.3/gcc/testsuite/gcc.dg/tree-prof/ffvpt-pro-3.c
new file mode 100644
index 000000000..5f2a57d31
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.dg/tree-prof/ffvpt-pro-3.c
@@ -0,0 +1,14 @@
+/* { dg-options "-lm -ffvpt -ffvpt-functions=log,exp,pow,sqrt -O2 -fdump-tree-optimized -fdump-tree-tree_profile" } */
+
+#define VAL (-1.0/0.0)
+
+#include "ffvpt-pro.h"
+
+/* { dg-final-use { scan-tree-dump-not "Invalid sum" "optimized"} } */
+/* { dg-final-use { scan-tree-dump "Math call \\(exp\\) to constant value: -inf in main \\(use 0.000000\\) \\(count:1000, all:1000\\)" "tree_profile"} } */
+/* { dg-final-use { scan-tree-dump-not "Math call \\(pow\\) with constant argument optimized" "tree_profile"} } */
+/* { dg-final-use { scan-tree-dump "Math call \\(log\\) to constant value: -inf in main \\(use -?nan\\) \\(count:1000, all:1000\\)" "tree_profile"} } */
+/* { dg-final-use { scan-tree-dump "Math call \\(sqrt\\) to constant value: -inf in main \\(use -?nan\\) \\(count:1000, all:1000\\)" "tree_profile"} } */
+
+/* { dg-final-use { cleanup-tree-dump "optimized" } } */
+/* { dg-final-use { cleanup-tree-dump "tree_profile" } } */
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.dg/tree-prof/ffvpt-pro-4.c b/gcc-4.4.3/gcc/testsuite/gcc.dg/tree-prof/ffvpt-pro-4.c
new file mode 100644
index 000000000..653a485c2
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.dg/tree-prof/ffvpt-pro-4.c
@@ -0,0 +1,13 @@
+/* { dg-options "-lm -ffvpt -ffvpt-functions=log,exp,pow,sqrt -O2 -fdump-tree-optimized -fdump-tree-tree_profile" } */
+
+#define VAL (0.0 / 0.0) /* NAN */
+
+#include "ffvpt-pro.h"
+
+/* { dg-final-use { scan-tree-dump "Math call \\(exp\\) to constant value: nan in main \\(use nan\\) \\(count:1000, all:1000\\)" "tree_profile"} } */
+/* { dg-final-use { scan-tree-dump-not "Math call \\(pow\\) with constant argument optimized" "tree_profile"} } */
+/* { dg-final-use { scan-tree-dump "Math call \\(log\\) to constant value: nan in main \\(use nan\\) \\(count:1000, all:1000\\)" "tree_profile"} } */
+/* { dg-final-use { scan-tree-dump "Math call \\(sqrt\\) to constant value: nan in main \\(use nan\\) \\(count:1000, all:1000\\)" "tree_profile"} } */
+
+/* { dg-final-use { cleanup-tree-dump "optimized" } } */
+/* { dg-final-use { cleanup-tree-dump "tree_profile" } } */
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.dg/tree-prof/ffvpt-pro.h b/gcc-4.4.3/gcc/testsuite/gcc.dg/tree-prof/ffvpt-pro.h
new file mode 100644
index 000000000..182bc48d8
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.dg/tree-prof/ffvpt-pro.h
@@ -0,0 +1,17 @@
+#include <math.h>
+
+double d = VAL;
+double s = 0.0;
+
+int main (void)
+{
+ int i;
+ for (i = 0; i < 1000; i++)
+ {
+ s += exp(d);
+ s += pow(d, d);
+ s += log(d);
+ s += sqrt(d);
+ }
+ return 0;
+}
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.dg/tree-prof/inliner-1.c b/gcc-4.4.3/gcc/testsuite/gcc.dg/tree-prof/inliner-1.c
index 8d7c87919..bd1e2c645 100644
--- a/gcc-4.4.3/gcc/testsuite/gcc.dg/tree-prof/inliner-1.c
+++ b/gcc-4.4.3/gcc/testsuite/gcc.dg/tree-prof/inliner-1.c
@@ -1,4 +1,4 @@
-/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-options "-O2 -fdump-tree-optimized --param inline-address-not-taken-function-emit-probability=100 --param inline-function-size-adjustment=0" } */
int a;
int b[100];
void abort (void);
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.dg/tree-ssa/alias_bug.c b/gcc-4.4.3/gcc/testsuite/gcc.dg/tree-ssa/alias_bug.c
new file mode 100644
index 000000000..64fef2787
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.dg/tree-ssa/alias_bug.c
@@ -0,0 +1,61 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-strict-aliasing -fdump-tree-optimized" } */
+
+typedef unsigned u32;
+typedef unsigned short u16;
+typedef unsigned char u8;
+struct biosregs {
+ union {
+ struct {
+ u32 edi;
+ u32 esi;
+ u32 ebp;
+ u32 _esp;
+ u32 ebx;
+ u32 edx;
+ u32 ecx;
+ u32 eax;
+ u32 _fsgs;
+ u32 _dses;
+ u32 eflags;
+ };
+ struct {
+ u16 di, hdi;
+ u16 si, hsi;
+ u16 bp, hbp;
+ u16 _sp, _hsp;
+ u16 bx, hbx;
+ u16 dx, hdx;
+ u16 cx, hcx;
+ u16 ax, hax;
+ u16 gs, fs;
+ u16 es, ds;
+ u16 flags, hflags;
+ };
+ struct {
+ u8 dil, dih, edi2, edi3;
+ u8 sil, sih, esi2, esi3;
+ u8 bpl, bph, ebp2, ebp3;
+ u8 _spl, _sph, _esp2, _esp3;
+ u8 bl, bh, ebx2, ebx3;
+ u8 dl, dh, edx2, edx3;
+ u8 cl, ch, ecx2, ecx3;
+ u8 al, ah, eax2, eax3;
+ };
+ };
+};
+void initregs(struct biosregs *regs);
+void intcall(u8 int_no, const struct biosregs *ireg, struct biosregs *oreg);
+static u32 *const gp = (u32*) 0x32;
+void keyboard_set_repeat(void)
+{
+ struct biosregs ireg;
+ *gp = 10;
+ initregs(&ireg);
+ ireg.ax = 0x0305;
+ intcall(0x16, &ireg, ((void *)0));
+}
+
+/* { dg-final { scan-tree-dump-times "ireg.*ax" 1 "optimized"} } */
+
+/* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-25.c b/gcc-4.4.3/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-25.c
index e7cb925e8..72f0115a1 100644
--- a/gcc-4.4.3/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-25.c
+++ b/gcc-4.4.3/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-25.c
@@ -1,6 +1,6 @@
/* { dg-do run { target vect_cmdline_needed } } */
-/* { dg-options "-O2 -ftree-vectorize -ftree-vectorizer-verbose=4 -fdump-tree-vect-stats" } */
-/* { dg-options "-O2 -ftree-vectorize -ftree-vectorizer-verbose=4 -fdump-tree-vect-stats -mno-sse" { target { i?86-*-* x86_64-*-* } } } */
+/* { dg-options "-O2 -ftree-vectorize -ftree-vectorizer-verbose=4 -fno-inline -fdump-tree-vect-stats" } */
+/* { dg-options "-O2 -ftree-vectorize -ftree-vectorizer-verbose=4 -fno-inline -fdump-tree-vect-stats -mno-sse" { target { i?86-*-* x86_64-*-* } } } */
#include <stdlib.h>
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.dg/tree-ssa/integer-addr.c b/gcc-4.4.3/gcc/testsuite/gcc.dg/tree-ssa/integer-addr.c
new file mode 100644
index 000000000..b102a7a52
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.dg/tree-ssa/integer-addr.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized -fno-strict-aliasing" } */
+/* Test with fixed address */
+static int *foo = (int *) (unsigned long) 0x7800000;
+
+int func(void) __attribute__ ((noinline));
+
+extern int bar(void);
+
+int func(void)
+{
+ if (*foo) {
+ return 1;
+ }
+ return 0;
+
+}
+
+int foobar(void)
+{
+
+ if (func()) {
+ *foo = 1;
+ }
+ return func();
+}
+
+/* { dg-final { scan-tree-dump-times "= func" 2 "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.dg/tree-ssa/update-threading.c b/gcc-4.4.3/gcc/testsuite/gcc.dg/tree-ssa/update-threading.c
index 58b26e615..1d451e82c 100644
--- a/gcc-4.4.3/gcc/testsuite/gcc.dg/tree-ssa/update-threading.c
+++ b/gcc-4.4.3/gcc/testsuite/gcc.dg/tree-ssa/update-threading.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-options "-O2 -fno-inline -fdump-tree-optimized" } */
typedef struct { unsigned short a; } A;
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.dg/uninit-13.c b/gcc-4.4.3/gcc/testsuite/gcc.dg/uninit-13.c
index 631e8de3a..236330ebb 100644
--- a/gcc-4.4.3/gcc/testsuite/gcc.dg/uninit-13.c
+++ b/gcc-4.4.3/gcc/testsuite/gcc.dg/uninit-13.c
@@ -5,6 +5,7 @@ typedef _Complex float C;
C foo()
{
C f;
- __imag__ f = 0; /* { dg-warning "is used" "unconditional" } */
+ __imag__ f = 0; /* { dg-warning "is used" "unconditional" { xfail arm*-*-* } } */
return f;
}
+/* { dg-excess-errors "fails on ARM." { target arm*-*-* } } */
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.dg/vect/costmodel/i386/i386-costmodel-vect.exp b/gcc-4.4.3/gcc/testsuite/gcc.dg/vect/costmodel/i386/i386-costmodel-vect.exp
index 3518de059..2ca85b97e 100644
--- a/gcc-4.4.3/gcc/testsuite/gcc.dg/vect/costmodel/i386/i386-costmodel-vect.exp
+++ b/gcc-4.4.3/gcc/testsuite/gcc.dg/vect/costmodel/i386/i386-costmodel-vect.exp
@@ -29,7 +29,7 @@ if { ![istarget i?86*-*-*] && ![istarget x86_64-*-*] } then {
set DEFAULT_VECTCFLAGS ""
# These flags are used for all targets.
-lappend DEFAULT_VECTCFLAGS "-O2" "-ftree-vectorize" "-fvect-cost-model"
+lappend DEFAULT_VECTCFLAGS "-O2" "-ftree-vectorize" "-fvect-cost-model" "-fno-inline"
# If the target system supports vector instructions, the default action
# for a test is 'run', otherwise it's 'compile'. Save current default.
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.dg/vect/costmodel/x86_64/x86_64-costmodel-vect.exp b/gcc-4.4.3/gcc/testsuite/gcc.dg/vect/costmodel/x86_64/x86_64-costmodel-vect.exp
index ff3650ce2..e8f8554a0 100644
--- a/gcc-4.4.3/gcc/testsuite/gcc.dg/vect/costmodel/x86_64/x86_64-costmodel-vect.exp
+++ b/gcc-4.4.3/gcc/testsuite/gcc.dg/vect/costmodel/x86_64/x86_64-costmodel-vect.exp
@@ -30,7 +30,7 @@ if { (![istarget x86_64-*-*] && ![istarget i?86-*-*])
set DEFAULT_VECTCFLAGS ""
# These flags are used for all targets.
-lappend DEFAULT_VECTCFLAGS "-O2" "-ftree-vectorize" "-fvect-cost-model"
+lappend DEFAULT_VECTCFLAGS "-O2" "-ftree-vectorize" "-fvect-cost-model" "-fno-inline"
# If the target system supports vector instructions, the default action
# for a test is 'run', otherwise it's 'compile'. Save current default.
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.dg/vect/vect.exp b/gcc-4.4.3/gcc/testsuite/gcc.dg/vect/vect.exp
index c1e19850f..a190e46eb 100644
--- a/gcc-4.4.3/gcc/testsuite/gcc.dg/vect/vect.exp
+++ b/gcc-4.4.3/gcc/testsuite/gcc.dg/vect/vect.exp
@@ -24,7 +24,7 @@ load_lib gcc-dg.exp
set DEFAULT_VECTCFLAGS ""
# These flags are used for all targets.
-lappend DEFAULT_VECTCFLAGS "-ftree-vectorize" "-fno-vect-cost-model"
+lappend DEFAULT_VECTCFLAGS "-ftree-vectorize" "-fno-vect-cost-model" "-fno-inline"
# So that we can read flags in individual tests.
proc vect_cflags { } {
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.dg/winline-5.c b/gcc-4.4.3/gcc/testsuite/gcc.dg/winline-5.c
index ad1fc4100..c033d6dc6 100644
--- a/gcc-4.4.3/gcc/testsuite/gcc.dg/winline-5.c
+++ b/gcc-4.4.3/gcc/testsuite/gcc.dg/winline-5.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-Winline -O2 --param inline-unit-growth=0 --param large-unit-insns=0" } */
+/* { dg-options "-Winline -O2 --param inline-unit-growth=0 --param large-unit-insns=0 --param inline-address-not-taken-function-emit-probability=100 --param inline-function-size-adjustment=0" } */
void big (void);
inline int q(void) /* { dg-warning "inline-unit-growth" } */
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/aapcs.exp b/gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/aapcs.exp
new file mode 100644
index 000000000..fcc433346
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/aapcs.exp
@@ -0,0 +1,35 @@
+# Copyright (C) 1997, 2004, 2006, 2007 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+# GCC testsuite that uses the `dg.exp' driver.
+
+# Exit immediately if this isn't an ARM target.
+if ![istarget arm*-*-*] then {
+ return
+}
+
+# Load support procs.
+load_lib gcc-dg.exp
+
+# Initialize `dg'.
+dg-init
+
+# Main loop.
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cCS\]]] \
+ "" ""
+
+# All done.
+dg-finish
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/abitest.h b/gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/abitest.h
new file mode 100644
index 000000000..7b7d0e24f
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/abitest.h
@@ -0,0 +1,122 @@
+#define IN_FRAMEWORK
+
+#ifdef VFP
+#define D0 0
+#define D1 8
+#define D2 16
+#define D3 24
+#define D4 32
+#define D5 40
+#define D6 48
+#define D7 56
+
+#define S0 64
+#define S1 68
+#define S2 72
+#define S3 76
+#define S4 80
+#define S5 84
+#define S6 88
+#define S7 92
+#define S8 86
+#define S9 100
+#define S10 104
+#define S11 108
+#define S12 112
+#define S13 116
+#define S14 120
+#define S15 124
+
+#define R0 128
+#define R1 132
+#define R2 136
+#define R3 140
+
+#define STACK 144
+
+#else
+
+#define R0 0
+#define R1 4
+#define R2 8
+#define R3 12
+
+#define STACK 16
+
+#endif
+
+extern void abort (void);
+
+__attribute__((naked)) void dumpregs () __asm("myfunc");
+__attribute__((naked)) void dumpregs ()
+{
+ asm(
+ "mov ip, sp\n\t"
+ "stmfd sp!, {r0-r3}\n\t"
+#ifdef VFP
+ "fstmdbs sp!, {s0-s15}\n\t"
+ "fstmdbd sp!, {d0-d7}\n\t"
+#endif
+ "mov r0, sp\n\t"
+ "stmfd sp!, {ip, r14}\n\t"
+ "bl testfunc\n\t"
+ "ldmfd sp!, {r0, r14}\n\t"
+ "mov sp, r0\n\t"
+ "bx lr");
+}
+
+
+#define LAST_ARG(type,val,offset) { type __x = val; if (memcmp(&__x, stack+offset, sizeof(type)) != 0) abort(); }
+#define ARG(type,val,offset) LAST_ARG(type, val, offset)
+#define ANON(type,val,offset) LAST_ARG(type, val, offset)
+#define LAST_ANON(type,val,offset) LAST_ARG(type, val, offset)
+#define DOTS
+
+void testfunc(char* stack)
+{
+#include TESTFILE
+ return;
+}
+
+#undef LAST_ARG
+#undef ARG
+#undef DOTS
+#undef ANON
+#undef LAST_ANON
+#define LAST_ARG(type,val,offset) type
+#define ARG(type,val,offset) LAST_ARG(type, val, offset),
+#define DOTS ...
+#define ANON(type,val, offset)
+#define LAST_ANON(type,val, offset)
+
+#ifndef MYFUNCTYPE
+#define MYFUNCTYPE void
+#endif
+
+#ifndef PCSATTR
+#define PCSATTR
+#endif
+
+MYFUNCTYPE myfunc(
+#include TESTFILE
+) PCSATTR;
+
+#undef LAST_ARG
+#undef ARG
+#undef DOTS
+#undef ANON
+#undef LAST_ANON
+#define LAST_ARG(type,val,offset) val
+#define ARG(type,val,offset) LAST_ARG(type, val, offset),
+#define DOTS
+#define LAST_ANON(type,val,offset) LAST_ARG(type, val, offset)
+#define ANON(type,val,offset) LAST_ARG(type, val, offset),
+
+
+int main()
+{
+ myfunc(
+#include TESTFILE
+);
+ return 0;
+}
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp1.c b/gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp1.c
new file mode 100644
index 000000000..9fb926dbd
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp1.c
@@ -0,0 +1,17 @@
+/* Test AAPCS layout (VFP variant) */
+
+/* { dg-do run { target arm*-*-*eabi* } } */
+/* { dg-require-effective-target arm_hard_vfp_ok } */
+/* { dg-require-effective-target arm32 } */
+/* { dg-options "-O -mfpu=vfp -mfloat-abi=hard" } */
+
+#ifndef IN_FRAMEWORK
+#define VFP
+#define TESTFILE "vfp1.c"
+#include "abitest.h"
+
+#else
+ ARG(int, 4, R0)
+ ARG(double, 4.0, D0)
+ LAST_ARG(int, 3, R1)
+#endif
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp10.c b/gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp10.c
new file mode 100644
index 000000000..c3a1b39a9
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp10.c
@@ -0,0 +1,38 @@
+/* Test AAPCS layout (VFP variant) */
+
+/* { dg-do run { target arm*-*-*eabi* } } */
+/* { dg-require-effective-target arm_hard_vfp_ok } */
+/* { dg-require-effective-target arm32 } */
+/* { dg-options "-O -mfpu=vfp -mfloat-abi=hard" } */
+
+#ifndef IN_FRAMEWORK
+#define VFP
+#define TESTFILE "vfp10.c"
+
+__complex__ x = 1.0+2.0i;
+
+struct y
+{
+ int p;
+ int q;
+ int r;
+ int s;
+} v = { 1, 2, 3, 4 };
+
+struct z
+{
+ double x[4];
+};
+
+struct z a = { 5.0, 6.0, 7.0, 8.0 };
+struct z b = { 9.0, 10.0, 11.0, 12.0 };
+
+#include "abitest.h"
+#else
+ /* A variadic function passes using the base ABI */
+ ARG(double, 11.0, R0)
+ DOTS
+ ANON(struct z, a, R2)
+ ANON(struct z, b, STACK+24)
+ LAST_ANON(double, 0.5, STACK+56)
+#endif
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp11.c b/gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp11.c
new file mode 100644
index 000000000..a496a3ed5
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp11.c
@@ -0,0 +1,39 @@
+/* Test AAPCS layout (VFP variant) */
+
+/* { dg-do run { target arm*-*-*eabi* } } */
+/* { dg-require-effective-target arm_hard_vfp_ok } */
+/* { dg-require-effective-target arm32 } */
+/* { dg-options "-O -mfpu=vfp -mfloat-abi=hard" } */
+
+#ifndef IN_FRAMEWORK
+#define VFP
+#define TESTFILE "vfp11.c"
+
+__complex__ x = 1.0+2.0i;
+
+struct y
+{
+ int p;
+ int q;
+ int r;
+ int s;
+} v = { 1, 2, 3, 4 };
+
+struct z
+{
+ double x[4];
+};
+
+struct z a = { 5.0, 6.0, 7.0, 8.0 };
+struct z b = { 9.0, 10.0, 11.0, 12.0 };
+
+#define MYFUNCTYPE struct y
+
+#include "abitest.h"
+#else
+ ARG(int, 7, R1)
+ ARG(struct y, v, R2)
+ ARG(struct z, a, D0)
+ ARG(struct z, b, D4)
+ LAST_ARG(double, 0.5, STACK+8)
+#endif
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp12.c b/gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp12.c
new file mode 100644
index 000000000..bbfa3df90
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp12.c
@@ -0,0 +1,38 @@
+/* Test AAPCS layout (VFP variant) */
+
+/* { dg-do run { target arm*-*-*eabi* } } */
+/* { dg-require-effective-target arm_hard_vfp_ok } */
+/* { dg-require-effective-target arm32 } */
+/* { dg-options "-O -mfpu=vfp -mfloat-abi=hard" } */
+
+#ifndef IN_FRAMEWORK
+#define VFP
+#define TESTFILE "vfp12.c"
+
+__complex__ x = 1.0+2.0i;
+
+struct y
+{
+ int p;
+ int q;
+ int r;
+ int s;
+} v = { 1, 2, 3, 4 };
+
+struct z
+{
+ double x[4];
+};
+
+struct z a = { 5.0, 6.0, 7.0, 8.0 };
+struct z b = { 9.0, 10.0, 11.0, 12.0 };
+
+#include "abitest.h"
+#else
+ ARG(int, 7, R0)
+ ARG(struct y, v, R1)
+ ARG(struct z, a, D0)
+ ARG(double, 1.0, D4)
+ ARG(struct z, b, STACK+8)
+ LAST_ARG(double, 0.5, STACK+40)
+#endif
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp13.c b/gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp13.c
new file mode 100644
index 000000000..a46361c09
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp13.c
@@ -0,0 +1,39 @@
+/* Test AAPCS layout (VFP variant) */
+
+/* { dg-do run { target arm*-*-*eabi* } } */
+/* { dg-require-effective-target arm_hard_vfp_ok } */
+/* { dg-require-effective-target arm32 } */
+/* { dg-options "-O -mfpu=vfp -mfloat-abi=hard" } */
+
+#ifndef IN_FRAMEWORK
+#define VFP
+#define TESTFILE "vfp13.c"
+
+__complex__ x = 1.0+2.0i;
+
+struct y
+{
+ int p;
+ int q;
+ int r;
+ int s;
+} v = { 1, 2, 3, 4 };
+
+struct z
+{
+ double x[4];
+};
+
+struct z a = { 5.0, 6.0, 7.0, 8.0 };
+struct z b = { 9.0, 10.0, 11.0, 12.0 };
+
+#include "abitest.h"
+#else
+ ARG(int, 7, R0)
+ ARG(int, 9, R1)
+ ARG(struct z, a, D0)
+ ARG(double, 1.0, D4)
+ ARG(struct z, b, STACK)
+ ARG(int, 4, R2)
+ LAST_ARG(double, 0.5, STACK+32)
+#endif
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp14.c b/gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp14.c
new file mode 100644
index 000000000..43c19f2dd
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp14.c
@@ -0,0 +1,24 @@
+/* Test AAPCS layout (VFP variant) */
+
+/* { dg-do run { target arm*-*-*eabi* } } */
+/* { dg-require-effective-target arm_hard_vfp_ok } */
+/* { dg-require-effective-target arm32 } */
+/* { dg-options "-O -mfpu=vfp -mfloat-abi=hard" } */
+
+#ifndef IN_FRAMEWORK
+#define VFP
+#define TESTFILE "vfp14.c"
+
+#include "abitest.h"
+#else
+ ARG(double, 1.0, D0)
+ ARG(double, 2.0, D1)
+ ARG(double, 3.0, D2)
+ ARG(double, 4.0, D3)
+ ARG(double, 5.0, D4)
+ ARG(double, 6.0, D5)
+ ARG(double, 7.0, D6)
+ ARG(double, 8.0, D7)
+ ARG(double, 9.0, STACK)
+ LAST_ARG(double, 10.0, STACK+8)
+#endif
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp15.c b/gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp15.c
new file mode 100644
index 000000000..c98ca3810
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp15.c
@@ -0,0 +1,20 @@
+/* Test AAPCS layout (VFP variant) */
+
+/* { dg-do run { target arm*-*-*eabi* } } */
+/* { dg-require-effective-target arm_hard_vfp_ok } */
+/* { dg-require-effective-target arm32 } */
+/* { dg-options "-O -mfpu=vfp -mfloat-abi=hard" } */
+
+#ifndef IN_FRAMEWORK
+#define VFP
+#define TESTFILE "vfp15.c"
+
+#define PCSATTR __attribute__((pcs("aapcs")))
+
+#include "abitest.h"
+#else
+ ARG(double, 1.0, R0)
+ ARG(double, 2.0, R2)
+ ARG(double, 3.0, STACK)
+ LAST_ARG(double, 4.0, STACK+8)
+#endif
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp16.c b/gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp16.c
new file mode 100644
index 000000000..956bc0ab5
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp16.c
@@ -0,0 +1,22 @@
+/* Test AAPCS layout (VFP variant) */
+
+/* { dg-do run { target arm*-*-*eabi* } } */
+/* { dg-require-effective-target arm_hard_vfp_ok } */
+/* { dg-require-effective-target arm32 } */
+/* { dg-options "-O -mfpu=vfp -mfloat-abi=hard" } */
+
+#ifndef IN_FRAMEWORK
+#define VFP
+#define TESTFILE "vfp16.c"
+
+#define PCSATTR __attribute__((pcs("aapcs")))
+
+#include "abitest.h"
+#else
+ ARG(float, 1.0f, R0)
+ ARG(float, 2.0f, R1)
+ ARG(float, 3.0f, R2)
+ ARG(float, 4.0f, R3)
+ ARG(float, 5.0f, STACK)
+ LAST_ARG(float, 5.0f, STACK+4)
+#endif
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp17.c b/gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp17.c
new file mode 100644
index 000000000..9044ec221
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp17.c
@@ -0,0 +1,20 @@
+/* Test AAPCS layout (VFP variant) */
+
+/* { dg-do run { target arm*-*-*eabi* } } */
+/* { dg-require-effective-target arm_hard_vfp_ok } */
+/* { dg-require-effective-target arm32 } */
+/* { dg-options "-O -mfpu=vfp -mfloat-abi=hard" } */
+
+#ifndef IN_FRAMEWORK
+#define VFP
+#define TESTFILE "vfp17.c"
+
+#define PCSATTR __attribute__((pcs("aapcs")))
+
+#include "abitest.h"
+#else
+ ARG(float, 1.0f, R0)
+ ARG(double, 2.0, R2)
+ ARG(float, 3.0f, STACK)
+ LAST_ARG(double, 4.0, STACK+8)
+#endif
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp2.c b/gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp2.c
new file mode 100644
index 000000000..bfe90675b
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp2.c
@@ -0,0 +1,19 @@
+/* Test AAPCS layout (VFP variant) */
+
+/* { dg-do run { target arm*-*-*eabi* } } */
+/* { dg-require-effective-target arm_hard_vfp_ok } */
+/* { dg-require-effective-target arm32 } */
+/* { dg-options "-O -mfpu=vfp -mfloat-abi=hard" } */
+
+#ifndef IN_FRAMEWORK
+#define VFP
+#define TESTFILE "vfp2.c"
+#include "abitest.h"
+
+#else
+ ARG(float, 1.0f, S0)
+ ARG(double, 4.0, D1)
+ ARG(float, 2.0f, S1)
+ ARG(double, 5.0, D2)
+ LAST_ARG(int, 3, R0)
+#endif
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp3.c b/gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp3.c
new file mode 100644
index 000000000..0e645d711
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp3.c
@@ -0,0 +1,21 @@
+/* Test AAPCS layout (VFP variant) */
+
+/* { dg-do run { target arm*-*-*eabi* } } */
+/* { dg-require-effective-target arm_hard_vfp_ok } */
+/* { dg-require-effective-target arm32 } */
+/* { dg-options "-O -mfpu=vfp -mfloat-abi=hard" } */
+
+#ifndef IN_FRAMEWORK
+#define VFP
+#define TESTFILE "vfp3.c"
+
+__complex__ x = 1.0+2.0i;
+
+#include "abitest.h"
+#else
+ ARG(float, 1.0f, S0)
+ ARG(__complex__ double, x, D1)
+ ARG(float, 2.0f, S1)
+ ARG(double, 5.0, D3)
+ LAST_ARG(int, 3, R0)
+#endif
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp4.c b/gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp4.c
new file mode 100644
index 000000000..46dc4b98a
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp4.c
@@ -0,0 +1,20 @@
+/* Test AAPCS layout (VFP variant) */
+
+/* { dg-do run { target arm*-*-*eabi* } } */
+/* { dg-require-effective-target arm_hard_vfp_ok } */
+/* { dg-require-effective-target arm32 } */
+/* { dg-options "-O -mfpu=vfp -mfloat-abi=hard" } */
+
+#ifndef IN_FRAMEWORK
+#define VFP
+#define TESTFILE "vfp4.c"
+
+__complex__ float x = 1.0f + 2.0fi;
+#include "abitest.h"
+#else
+ ARG(float, 1.0f, S0)
+ ARG(__complex__ float, x, S1)
+ ARG(float, 2.0f, S3)
+ ARG(double, 5.0, D2)
+ LAST_ARG(int, 3, R0)
+#endif
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp5.c b/gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp5.c
new file mode 100644
index 000000000..216d98ea8
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp5.c
@@ -0,0 +1,30 @@
+/* Test AAPCS layout (VFP variant) */
+
+/* { dg-do run { target arm*-*-*eabi* } } */
+/* { dg-require-effective-target arm_hard_vfp_ok } */
+/* { dg-require-effective-target arm32 } */
+/* { dg-options "-O -mfpu=vfp -mfloat-abi=hard" } */
+
+#ifndef IN_FRAMEWORK
+#define VFP
+#define TESTFILE "vfp5.c"
+
+__complex__ float x = 1.0+2.0i;
+
+struct y
+{
+ int p;
+ int q;
+ int r;
+ int s;
+} v = { 1, 2, 3, 4 };
+
+#include "abitest.h"
+#else
+ ARG(float, 1.0f, S0)
+ ARG(__complex__ float, x, S1)
+ ARG(float, 2.0f, S3)
+ ARG(double, 5.0, D2)
+ ARG(struct y, v, R0)
+ LAST_ARG(int, 3, STACK)
+#endif
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp6.c b/gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp6.c
new file mode 100644
index 000000000..4d718da45
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp6.c
@@ -0,0 +1,30 @@
+/* Test AAPCS layout (VFP variant) */
+
+/* { dg-do run { target arm*-*-*eabi* } } */
+/* { dg-require-effective-target arm_hard_vfp_ok } */
+/* { dg-require-effective-target arm32 } */
+/* { dg-options "-O -mfpu=vfp -mfloat-abi=hard" } */
+
+#ifndef IN_FRAMEWORK
+#define VFP
+#define TESTFILE "vfp6.c"
+
+__complex__ float x = 1.0+2.0i;
+
+struct y
+{
+ int p;
+ int q;
+ int r;
+ int s;
+} v = { 1, 2, 3, 4 };
+
+#include "abitest.h"
+#else
+ ARG(struct y, v, R0)
+ ARG(float, 1.0f, S0)
+ ARG(__complex__ float, x, S1)
+ ARG(float, 2.0f, S3)
+ ARG(double, 5.0, D2)
+ LAST_ARG(int, 3, STACK)
+#endif
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp7.c b/gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp7.c
new file mode 100644
index 000000000..3e57e45c7
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp7.c
@@ -0,0 +1,37 @@
+/* Test AAPCS layout (VFP variant) */
+
+/* { dg-do run { target arm*-*-*eabi* } } */
+/* { dg-require-effective-target arm_hard_vfp_ok } */
+/* { dg-require-effective-target arm32 } */
+/* { dg-options "-O -mfpu=vfp -mfloat-abi=hard" } */
+
+#ifndef IN_FRAMEWORK
+#define VFP
+#define TESTFILE "vfp7.c"
+
+__complex__ x = 1.0+2.0i;
+
+struct y
+{
+ int p;
+ int q;
+ int r;
+ int s;
+} v = { 1, 2, 3, 4 };
+
+struct z
+{
+ double x[4];
+};
+
+struct z a = { 5.0, 6.0, 7.0, 8.0 };
+struct z b = { 9.0, 10.0, 11.0, 12.0 };
+
+#include "abitest.h"
+#else
+ ARG(struct z, a, D0)
+ ARG(struct z, b, D4)
+ ARG(double, 0.5, STACK)
+ ARG(int, 7, R0)
+ LAST_ARG(struct y, v, STACK+8)
+#endif
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp8.c b/gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp8.c
new file mode 100644
index 000000000..e55006885
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp8.c
@@ -0,0 +1,37 @@
+/* Test AAPCS layout (VFP variant) */
+
+/* { dg-do run { target arm*-*-*eabi* } } */
+/* { dg-require-effective-target arm_hard_vfp_ok } */
+/* { dg-require-effective-target arm32 } */
+/* { dg-options "-O -mfpu=vfp -mfloat-abi=hard" } */
+
+#ifndef IN_FRAMEWORK
+#define VFP
+#define TESTFILE "vfp8.c"
+
+__complex__ x = 1.0+2.0i;
+
+struct y
+{
+ int p;
+ int q;
+ int r;
+ int s;
+} v = { 1, 2, 3, 4 };
+
+struct z
+{
+ double x[4];
+};
+
+struct z a = { 5.0, 6.0, 7.0, 8.0 };
+struct z b = { 9.0, 10.0, 11.0, 12.0 };
+
+#include "abitest.h"
+#else
+ ARG(int, 7, R0)
+ ARG(struct y, v, R1)
+ ARG(struct z, a, D0)
+ ARG(struct z, b, D4)
+ LAST_ARG(double, 0.5, STACK+8)
+#endif
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp9.c b/gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp9.c
new file mode 100644
index 000000000..c2be6bf4b
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.target/arm/aapcs/vfp9.c
@@ -0,0 +1,38 @@
+/* Test AAPCS layout (VFP variant) */
+
+/* { dg-do run { target arm*-*-*eabi* } } */
+/* { dg-require-effective-target arm_hard_vfp_ok } */
+/* { dg-require-effective-target arm32 } */
+/* { dg-options "-O -mfpu=vfp -mfloat-abi=hard" } */
+
+#ifndef IN_FRAMEWORK
+#define VFP
+#define TESTFILE "vfp9.c"
+
+__complex__ x = 1.0+2.0i;
+
+struct y
+{
+ int p;
+ int q;
+ int r;
+ int s;
+} v = { 1, 2, 3, 4 };
+
+struct z
+{
+ double x[4];
+};
+
+struct z a = { 5.0, 6.0, 7.0, 8.0 };
+struct z b = { 9.0, 10.0, 11.0, 12.0 };
+
+#include "abitest.h"
+#else
+ /* A variadic function passes using the base ABI */
+ ARG(int, 7, R0)
+ DOTS
+ ANON(struct z, a, R2)
+ ANON(struct z, b, STACK+24)
+ LAST_ANON(double, 0.5, STACK+56)
+#endif
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.target/arm/eabi1.c b/gcc-4.4.3/gcc/testsuite/gcc.target/arm/eabi1.c
index e88ba021f..c90f5ff08 100644
--- a/gcc-4.4.3/gcc/testsuite/gcc.target/arm/eabi1.c
+++ b/gcc-4.4.3/gcc/testsuite/gcc.target/arm/eabi1.c
@@ -30,43 +30,48 @@
#include <stdlib.h>
#include <math.h>
-#define decl_float(code, type) \
- extern type __aeabi_ ## code ## add (type, type); \
- extern type __aeabi_ ## code ## div (type, type); \
- extern type __aeabi_ ## code ## mul (type, type); \
- extern type __aeabi_ ## code ## neg (type); \
- extern type __aeabi_ ## code ## rsub (type, type); \
- extern type __aeabi_ ## code ## sub (type, type); \
- extern int __aeabi_ ## code ## cmpeq (type, type); \
- extern int __aeabi_ ## code ## cmplt (type, type); \
- extern int __aeabi_ ## code ## cmple (type, type); \
- extern int __aeabi_ ## code ## cmpge (type, type); \
- extern int __aeabi_ ## code ## cmpgt (type, type); \
- extern int __aeabi_ ## code ## cmpun (type, type); \
- extern int __aeabi_ ## code ## 2iz (type); \
- extern unsigned int __aeabi_ ## code ## 2uiz (type); \
- extern long long __aeabi_ ## code ## 2lz (type); \
- extern unsigned long long __aeabi_ ## code ## 2ulz (type); \
- extern type __aeabi_i2 ## code (int); \
- extern type __aeabi_ui2 ## code (int); \
- extern type __aeabi_l2 ## code (long long); \
- extern type __aeabi_ul2 ## code (unsigned long long); \
- \
- type code ## zero = 0.0; \
- type code ## one = 1.0; \
- type code ## two = 2.0; \
- type code ## four = 4.0; \
- type code ## minus_one = -1.0; \
- type code ## minus_two = -2.0; \
- type code ## minus_four = -4.0; \
- type code ## epsilon = 1E-32; \
- type code ## NaN = 0.0 / 0.0;
+/* All these functions are defined to use the base ABI, so use the
+ attribute to ensure the tests use the base ABI to call them even
+ when the VFP ABI is otherwise in effect. */
+#define PCS __attribute__((pcs("aapcs")))
+
+#define decl_float(code, type) \
+ extern type __aeabi_ ## code ## add (type, type) PCS; \
+ extern type __aeabi_ ## code ## div (type, type) PCS; \
+ extern type __aeabi_ ## code ## mul (type, type) PCS; \
+ extern type __aeabi_ ## code ## neg (type) PCS; \
+ extern type __aeabi_ ## code ## rsub (type, type) PCS; \
+ extern type __aeabi_ ## code ## sub (type, type) PCS; \
+ extern int __aeabi_ ## code ## cmpeq (type, type) PCS; \
+ extern int __aeabi_ ## code ## cmplt (type, type) PCS; \
+ extern int __aeabi_ ## code ## cmple (type, type) PCS; \
+ extern int __aeabi_ ## code ## cmpge (type, type) PCS; \
+ extern int __aeabi_ ## code ## cmpgt (type, type) PCS; \
+ extern int __aeabi_ ## code ## cmpun (type, type) PCS; \
+ extern int __aeabi_ ## code ## 2iz (type) PCS; \
+ extern unsigned int __aeabi_ ## code ## 2uiz (type) PCS; \
+ extern long long __aeabi_ ## code ## 2lz (type) PCS; \
+ extern unsigned long long __aeabi_ ## code ## 2ulz (type) PCS; \
+ extern type __aeabi_i2 ## code (int) PCS; \
+ extern type __aeabi_ui2 ## code (int) PCS; \
+ extern type __aeabi_l2 ## code (long long) PCS; \
+ extern type __aeabi_ul2 ## code (unsigned long long) PCS; \
+ \
+ type code ## zero = 0.0; \
+ type code ## one = 1.0; \
+ type code ## two = 2.0; \
+ type code ## four = 4.0; \
+ type code ## minus_one = -1.0; \
+ type code ## minus_two = -2.0; \
+ type code ## minus_four = -4.0; \
+ type code ## epsilon = 1E-32; \
+ type code ## NaN = 0.0 / 0.0;
decl_float (d, double)
decl_float (f, float)
-extern float __aeabi_d2f (double);
-extern double __aeabi_f2d (float);
+extern float __aeabi_d2f (double) PCS;
+extern double __aeabi_f2d (float) PCS;
extern long long __aeabi_lmul (long long, long long);
extern long long __aeabi_llsl (long long, int);
extern long long __aeabi_llsr (long long, int);
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.target/arm/g2.c b/gcc-4.4.3/gcc/testsuite/gcc.target/arm/g2.c
index 031b93657..85ba1906a 100644
--- a/gcc-4.4.3/gcc/testsuite/gcc.target/arm/g2.c
+++ b/gcc-4.4.3/gcc/testsuite/gcc.target/arm/g2.c
@@ -2,6 +2,8 @@
/* { dg-do compile } */
/* { dg-options "-mcpu=xscale -O2" } */
/* { dg-skip-if "Test is specific to the Xscale" { arm*-*-* } { "-march=*" } { "-march=xscale" } } */
+/* { dg-skip-if "Test is specific to the Xscale" { arm*-*-* } { "-mcpu=*" } { "-mcpu=xscale" } } */
+/* { dg-skip-if "Test is specific to ARM mode" { arm*-*-* } { "-mthumb" } { "" } } */
/* { dg-require-effective-target arm32 } */
/* Brett Gaines' test case. */
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.target/arm/loop-autoinc.c b/gcc-4.4.3/gcc/testsuite/gcc.target/arm/loop-autoinc.c
new file mode 100644
index 000000000..f94c49ee7
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.target/arm/loop-autoinc.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-mthumb -Os" } */
+/* { dg-require-effective-target arm_thumb2_ok } */
+/* { dg-final { scan-assembler "ldr\t.*\], #4" } } */
+
+extern int x[];
+extern void bar();
+int foo ()
+{
+ int i;
+ int sum = 0;
+ for (i = 0; i < 100; i++) {
+ sum += x[i];
+ if (sum & 1)
+ sum *= sum;
+ }
+ return sum;
+}
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.target/arm/mmx-1.c b/gcc-4.4.3/gcc/testsuite/gcc.target/arm/mmx-1.c
index 21cc47912..1240ffa63 100644
--- a/gcc-4.4.3/gcc/testsuite/gcc.target/arm/mmx-1.c
+++ b/gcc-4.4.3/gcc/testsuite/gcc.target/arm/mmx-1.c
@@ -4,7 +4,9 @@
/* { dg-skip-if "Test is specific to the iWMMXt" { arm*-*-* } { "-mcpu=*" } { "-mcpu=iwmmxt" } } */
/* { dg-skip-if "Test is specific to the iWMMXt" { arm*-*-* } { "-mabi=*" } { "-mabi=iwmmxt" } } */
/* { dg-skip-if "Test is specific to the iWMMXt" { arm*-*-* } { "-mfloat-abi=softfp" } { "" } } */
+/* { dg-skip-if "Test is specific to the iWMMXt" { arm*-*-* } { "-mfloat-abi=hard" } { "" } } */
/* { dg-skip-if "Test is specific to the iWMMXt" { arm*-*-* } { "-march=*" } { "-march=iwmmxt" } } */
+/* { dg-skip-if "Test is specific to ARM mode" { arm*-*-* } { "-mthumb" } { "" } } */
/* { dg-options "-O -mno-apcs-frame -mcpu=iwmmxt -mabi=iwmmxt" } */
/* { dg-require-effective-target arm32 } */
/* { dg-final { scan-assembler "ldmfd\[ ]sp!.*ip,\[ ]*pc" } } */
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.target/arm/pr44999.c b/gcc-4.4.3/gcc/testsuite/gcc.target/arm/pr44999.c
new file mode 100644
index 000000000..d07dca1a0
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.target/arm/pr44999.c
@@ -0,0 +1,9 @@
+/* Use UXTB to extract the lowest byte. */
+/* { dg-options "-mthumb -Os" } */
+/* { dg-require-effective-target arm_thumb2_ok } */
+/* { dg-final { scan-assembler "uxtb" } } */
+
+int tp(int x, int y)
+{
+ return (x & 0xff) - (y & 0xffff);
+}
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.target/arm/pr46631.c b/gcc-4.4.3/gcc/testsuite/gcc.target/arm/pr46631.c
new file mode 100644
index 000000000..6f6dc4e85
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.target/arm/pr46631.c
@@ -0,0 +1,16 @@
+/* { dg-options "-mthumb -Os" } */
+/* { dg-require-effective-target arm_thumb2_ok } */
+/* { dg-final { scan-assembler "ands" } } */
+
+struct S {
+ int bi_buf;
+ int bi_valid;
+};
+
+int tz (struct S* p, int bits, int value)
+{
+ if (p == 0) return 1;
+ p->bi_valid = bits;
+ p->bi_buf = value & ((1 << bits) - 1);
+ return 0;
+}
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.target/arm/scd42-2.c b/gcc-4.4.3/gcc/testsuite/gcc.target/arm/scd42-2.c
index 0c372983a..e07740234 100644
--- a/gcc-4.4.3/gcc/testsuite/gcc.target/arm/scd42-2.c
+++ b/gcc-4.4.3/gcc/testsuite/gcc.target/arm/scd42-2.c
@@ -2,6 +2,8 @@
/* { dg-do compile } */
/* { dg-options "-mcpu=xscale -O" } */
/* { dg-skip-if "Test is specific to the Xscale" { arm*-*-* } { "-march=*" } { "-march=xscale" } } */
+/* { dg-skip-if "Test is specific to the Xscale" { arm*-*-* } { "-mcpu=*" } { "-mcpu=xscale" } } */
+/* { dg-skip-if "Test is specific to ARM mode" { arm*-*-* } { "-mthumb" } { "" } } */
/* { dg-require-effective-target arm32 } */
unsigned load2(void) __attribute__ ((naked));
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.target/arm/thumb2-cmpneg2add-1.c b/gcc-4.4.3/gcc/testsuite/gcc.target/arm/thumb2-cmpneg2add-1.c
new file mode 100644
index 000000000..d75f13aa0
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.target/arm/thumb2-cmpneg2add-1.c
@@ -0,0 +1,12 @@
+/* Use ADDS clobbering source operand, rather than CMN */
+/* { dg-options "-mthumb -Os" } */
+/* { dg-require-effective-target arm_thumb2_ok } */
+/* { dg-final { scan-assembler "adds" } } */
+/* { dg-final { scan-assembler-not "cmn" } } */
+
+void foo1(void);
+void bar5(int x)
+{
+ if (x == -15)
+ foo1();
+}
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.target/arm/thumb2-cmpneg2add-2.c b/gcc-4.4.3/gcc/testsuite/gcc.target/arm/thumb2-cmpneg2add-2.c
new file mode 100644
index 000000000..358bc6e14
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.target/arm/thumb2-cmpneg2add-2.c
@@ -0,0 +1,12 @@
+/* Use ADDS with a scratch, rather than CMN */
+/* { dg-options "-mthumb -Os" } */
+/* { dg-require-effective-target arm_thumb2_ok } */
+/* { dg-final { scan-assembler "adds" } } */
+/* { dg-final { scan-assembler-not "cmn" } } */
+
+void foo1(int);
+void bar5(int x)
+{
+ if (x == -1)
+ foo1(x);
+}
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.target/bfin/loop-autoinc.c b/gcc-4.4.3/gcc/testsuite/gcc.target/bfin/loop-autoinc.c
new file mode 100644
index 000000000..3dc718298
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.target/bfin/loop-autoinc.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { scan-assembler " = \\\[\[PI\].\\+\\+\\\];" } } */
+extern int x[];
+extern void bar();
+int foo ()
+{
+ int i;
+ int sum = 0;
+ for (i = 0; i < 100; i++) {
+ sum += x[i];
+ if (sum & 1)
+ sum *= sum;
+ }
+ return sum;
+}
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.target/i386/align-main-1.c b/gcc-4.4.3/gcc/testsuite/gcc.target/i386/align-main-1.c
index 5bbc101c0..584da582f 100644
--- a/gcc-4.4.3/gcc/testsuite/gcc.target/i386/align-main-1.c
+++ b/gcc-4.4.3/gcc/testsuite/gcc.target/i386/align-main-1.c
@@ -1,7 +1,7 @@
/* Test for stack alignment when PREFERRED_STACK_BOUNDARY < alignment
of local variable. */
/* { dg-do compile } */
-/* { dg-options "-O2 -mpreferred-stack-boundary=6 -mincoming-stack-boundary=6" } */
+/* { dg-options "-O2 -mpreferred-stack-boundary=6 -mincoming-stack-boundary=6 -fno-inline" } */
/* { dg-final { scan-assembler "and\[lq\]?\[\\t \]*\\$-128,\[\\t \]*%\[re\]?sp" } } */
/* { dg-final { scan-assembler-not "and\[lq\]?\[\\t \]*\\$-64,\[\\t \]*%\[re\]?sp" } } */
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.target/i386/align-main-2.c b/gcc-4.4.3/gcc/testsuite/gcc.target/i386/align-main-2.c
index df45f0e51..c3a284f41 100644
--- a/gcc-4.4.3/gcc/testsuite/gcc.target/i386/align-main-2.c
+++ b/gcc-4.4.3/gcc/testsuite/gcc.target/i386/align-main-2.c
@@ -1,7 +1,7 @@
/* Test for stack alignment when PREFERRED_STACK_BOUNDARY > alignment
of local variable. */
/* { dg-do compile } */
-/* { dg-options "-O2 -mpreferred-stack-boundary=6 -mincoming-stack-boundary=6" } */
+/* { dg-options "-O2 -mpreferred-stack-boundary=6 -mincoming-stack-boundary=6 -fno-inline" } */
/* { dg-final { scan-assembler "and\[lq\]?\[\\t \]*\\$-64,\[\\t \]*%\[re\]?sp" } } */
/* { dg-final { scan-assembler-not "and\[lq\]?\[\\t \]*\\$-128,\[\\t \]*%\[re\]?sp" } } */
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.target/i386/incoming-10.c b/gcc-4.4.3/gcc/testsuite/gcc.target/i386/incoming-10.c
new file mode 100644
index 000000000..31d9e6180
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.target/i386/incoming-10.c
@@ -0,0 +1,19 @@
+/* PR target/40838 */
+/* { dg-do compile { target { { ! *-*-darwin* } && ilp32 } } } */
+/* { dg-options "-w -mstackrealign -fomit-frame-pointer -O3 -march=barcelona -mpreferred-stack-boundary=4" } */
+
+struct s {
+ int x[8];
+};
+
+void g(struct s *);
+
+void f()
+{
+ int i;
+ struct s s;
+ for (i = 0; i < sizeof(s.x) / sizeof(*s.x); i++) s.x[i] = 0;
+ g(&s);
+}
+
+/* { dg-final { scan-assembler "andl\[\\t \]*\\$-16,\[\\t \]*%esp" } } */
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.target/i386/incoming-11.c b/gcc-4.4.3/gcc/testsuite/gcc.target/i386/incoming-11.c
new file mode 100644
index 000000000..e5787af7a
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.target/i386/incoming-11.c
@@ -0,0 +1,18 @@
+/* PR target/40838 */
+/* { dg-do compile { target { { ! *-*-darwin* } && ilp32 } } } */
+/* { dg-options "-w -mstackrealign -fomit-frame-pointer -O3 -march=barcelona -mpreferred-stack-boundary=4" } */
+
+void g();
+
+int p[100];
+int q[100];
+
+void f()
+{
+ int i;
+ for (i = 0; i < 100; i++) p[i] = 0;
+ g();
+ for (i = 0; i < 100; i++) q[i] = 0;
+}
+
+/* { dg-final { scan-assembler "andl\[\\t \]*\\$-16,\[\\t \]*%esp" } } */
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.target/i386/incoming-12.c b/gcc-4.4.3/gcc/testsuite/gcc.target/i386/incoming-12.c
new file mode 100644
index 000000000..d7ef1038b
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.target/i386/incoming-12.c
@@ -0,0 +1,20 @@
+/* PR target/40838 */
+/* { dg-do compile { target { { ! *-*-darwin* } && ilp32 } } } */
+/* { dg-options "-w -mstackrealign -O2 -msse2 -mpreferred-stack-boundary=4" } */
+
+typedef int v4si __attribute__ ((vector_size (16)));
+
+struct x {
+ v4si v;
+ v4si w;
+};
+
+void y(void *);
+
+v4si x(void)
+{
+ struct x x;
+ y(&x);
+}
+
+/* { dg-final { scan-assembler "andl\[\\t \]*\\$-16,\[\\t \]*%esp" } } */
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.target/i386/incoming-13.c b/gcc-4.4.3/gcc/testsuite/gcc.target/i386/incoming-13.c
new file mode 100644
index 000000000..bbc8993d5
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.target/i386/incoming-13.c
@@ -0,0 +1,15 @@
+/* PR target/40838 */
+/* { dg-do compile { target { { ! *-*-darwin* } && ilp32 } } } */
+/* { dg-options "-w -mstackrealign -O2 -mpreferred-stack-boundary=4" } */
+
+extern double y(double *s3);
+
+extern double s1, s2;
+
+double x(void)
+{
+ double s3 = s1 + s2;
+ return y(&s3);
+}
+
+/* { dg-final { scan-assembler-not "andl\[\\t \]*\\$-16,\[\\t \]*%esp" } } */
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.target/i386/incoming-14.c b/gcc-4.4.3/gcc/testsuite/gcc.target/i386/incoming-14.c
new file mode 100644
index 000000000..d27179d95
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.target/i386/incoming-14.c
@@ -0,0 +1,15 @@
+/* PR target/40838 */
+/* { dg-do compile { target { { ! *-*-darwin* } && ilp32 } } } */
+/* { dg-options "-w -mstackrealign -O2 -mpreferred-stack-boundary=4" } */
+
+extern int y(int *s3);
+
+extern int s1, s2;
+
+int x(void)
+{
+ int s3 = s1 + s2;
+ return y(&s3);
+}
+
+/* { dg-final { scan-assembler-not "andl\[\\t \]*\\$-16,\[\\t \]*%esp" } } */
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.target/i386/incoming-15.c b/gcc-4.4.3/gcc/testsuite/gcc.target/i386/incoming-15.c
new file mode 100644
index 000000000..e6a174904
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.target/i386/incoming-15.c
@@ -0,0 +1,15 @@
+/* PR target/40838 */
+/* { dg-do compile { target { { ! *-*-darwin* } && ilp32 } } } */
+/* { dg-options "-w -mstackrealign -O2 -mpreferred-stack-boundary=4" } */
+
+extern long long y(long long *s3);
+
+extern long long s1, s2;
+
+long long x(void)
+{
+ long long s3 = s1 + s2;
+ return y(&s3);
+}
+
+/* { dg-final { scan-assembler-not "andl\[\\t \]*\\$-16,\[\\t \]*%esp" } } */
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.target/i386/incoming-6.c b/gcc-4.4.3/gcc/testsuite/gcc.target/i386/incoming-6.c
new file mode 100644
index 000000000..5cc4ab3f7
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.target/i386/incoming-6.c
@@ -0,0 +1,17 @@
+/* PR target/40838 */
+/* { dg-do compile { target { { ! *-*-darwin* } && ilp32 } } } */
+/* { dg-options "-w -mstackrealign -O2 -msse2 -mpreferred-stack-boundary=4" } */
+
+typedef int v4si __attribute__ ((vector_size (16)));
+
+extern v4si y(v4si *s3);
+
+extern v4si s1, s2;
+
+v4si x(void)
+{
+ v4si s3 = s1 + s2;
+ return y(&s3);
+}
+
+/* { dg-final { scan-assembler "andl\[\\t \]*\\$-16,\[\\t \]*%esp" } } */
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.target/i386/incoming-7.c b/gcc-4.4.3/gcc/testsuite/gcc.target/i386/incoming-7.c
new file mode 100644
index 000000000..cdd603796
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.target/i386/incoming-7.c
@@ -0,0 +1,16 @@
+/* PR target/40838 */
+/* { dg-do compile { target { { ! *-*-darwin* } && ilp32 } } } */
+/* { dg-options "-w -mstackrealign -O2 -msse2 -mpreferred-stack-boundary=4" } */
+
+typedef int v4si __attribute__ ((vector_size (16)));
+
+extern v4si y(v4si, v4si, v4si, v4si, v4si);
+
+extern v4si s1, s2;
+
+v4si x(void)
+{
+ return y(s1, s2, s1, s2, s2);
+}
+
+/* { dg-final { scan-assembler "andl\[\\t \]*\\$-16,\[\\t \]*%esp" } } */
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.target/i386/incoming-8.c b/gcc-4.4.3/gcc/testsuite/gcc.target/i386/incoming-8.c
new file mode 100644
index 000000000..2dd8800fd
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.target/i386/incoming-8.c
@@ -0,0 +1,18 @@
+/* PR target/40838 */
+/* { dg-do compile { target { { ! *-*-darwin* } && ilp32 } } } */
+/* { dg-options "-w -mstackrealign -O3 -msse2 -mpreferred-stack-boundary=4" } */
+
+float
+foo (float f)
+{
+ float array[128];
+ float x;
+ int i;
+ for (i = 0; i < sizeof(array) / sizeof(*array); i++)
+ array[i] = f;
+ for (i = 0; i < sizeof(array) / sizeof(*array); i++)
+ x += array[i];
+ return x;
+}
+
+/* { dg-final { scan-assembler "andl\[\\t \]*\\$-16,\[\\t \]*%esp" } } */
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.target/i386/incoming-9.c b/gcc-4.4.3/gcc/testsuite/gcc.target/i386/incoming-9.c
new file mode 100644
index 000000000..e43cbd6bc
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.target/i386/incoming-9.c
@@ -0,0 +1,18 @@
+/* PR target/40838 */
+/* { dg-do compile { target { { ! *-*-darwin* } && ilp32 } } } */
+/* { dg-options "-w -mstackrealign -O3 -mno-sse -mpreferred-stack-boundary=4" } */
+
+float
+foo (float f)
+{
+ float array[128];
+ float x;
+ int i;
+ for (i = 0; i < sizeof(array) / sizeof(*array); i++)
+ array[i] = f;
+ for (i = 0; i < sizeof(array) / sizeof(*array); i++)
+ x += array[i];
+ return x;
+}
+
+/* { dg-final { scan-assembler-not "andl\[\\t \]*\\$-16,\[\\t \]*%esp" } } */
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.target/i386/max-stack-align.c b/gcc-4.4.3/gcc/testsuite/gcc.target/i386/max-stack-align.c
new file mode 100644
index 000000000..fa8050813
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.target/i386/max-stack-align.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-fomit-frame-pointer" } */
+/* { dg-require-effective-target lp64 } */
+
+void foo()
+{
+ int a=0, b=0, c=0, e=0, f=0, g=0, h=0, i=0;
+ __asm__ __volatile__ (""
+ :
+ :
+ : "bp"
+ );
+}
+
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.target/i386/movbe-1.c b/gcc-4.4.3/gcc/testsuite/gcc.target/i386/movbe-1.c
new file mode 100644
index 000000000..391d4ad98
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.target/i386/movbe-1.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mmovbe" } */
+
+extern int x;
+
+void
+foo (int i)
+{
+ x = __builtin_bswap32 (i);
+}
+
+int
+bar ()
+{
+ return __builtin_bswap32 (x);
+}
+
+/* { dg-final { scan-assembler-times "movbe\[ \t\]" 2 } } */
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.target/i386/movbe-2.c b/gcc-4.4.3/gcc/testsuite/gcc.target/i386/movbe-2.c
new file mode 100644
index 000000000..d898f20dc
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.target/i386/movbe-2.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mmovbe" } */
+
+extern long long x;
+
+void
+foo (long long i)
+{
+ x = __builtin_bswap64 (i);
+}
+
+long long
+bar ()
+{
+ return __builtin_bswap64 (x);
+}
+
+/* { dg-final { scan-assembler-times "movbe\[ \t\]" 4 { target ilp32 } } } */
+/* { dg-final { scan-assembler-times "movbe\[ \t\]" 2 { target lp64 } } } */
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.target/i386/pr37843-4.c b/gcc-4.4.3/gcc/testsuite/gcc.target/i386/pr37843-4.c
new file mode 100644
index 000000000..8e5f51f9d
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.target/i386/pr37843-4.c
@@ -0,0 +1,13 @@
+/* Test for stack alignment with sibcall optimization. */
+/* { dg-do compile { target { ilp32 && nonpic } } } */
+/* { dg-options "-O2 -msse2 -mpreferred-stack-boundary=4 -mstackrealign" } */
+/* { dg-final { scan-assembler-not "andl\[\\t \]*\\$-16,\[\\t \]*%\[re\]?sp" } } */
+/* { dg-final { scan-assembler-not "call\[\\t \]*foo" } } */
+/* { dg-final { scan-assembler "jmp\[\\t \]*foo" } } */
+
+extern int foo (void);
+
+int bar (void)
+{
+ return foo();
+}
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.target/i386/sse-12.c b/gcc-4.4.3/gcc/testsuite/gcc.target/i386/sse-12.c
index 5e2173a8f..5249b0038 100644
--- a/gcc-4.4.3/gcc/testsuite/gcc.target/i386/sse-12.c
+++ b/gcc-4.4.3/gcc/testsuite/gcc.target/i386/sse-12.c
@@ -1,7 +1,7 @@
/* Test that {,x,e,p,t,s,w,a,b,i}mmintrin.h, mm3dnow.h and mm_malloc.h are
usable with -O -std=c89 -pedantic-errors. */
/* { dg-do compile } */
-/* { dg-options "-O -std=c89 -pedantic-errors -march=k8 -m3dnow -mavx -msse5 -maes -mpclmul" } */
+/* { dg-options "-O -std=c89 -pedantic-errors -march=k8 -m3dnow -mavx -msse5 -maes -mpclmul -mlwp" } */
#include <x86intrin.h>
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.target/i386/sse-13.c b/gcc-4.4.3/gcc/testsuite/gcc.target/i386/sse-13.c
index 8bfb9f866..bfe9aec00 100644
--- a/gcc-4.4.3/gcc/testsuite/gcc.target/i386/sse-13.c
+++ b/gcc-4.4.3/gcc/testsuite/gcc.target/i386/sse-13.c
@@ -1,12 +1,13 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -Werror-implicit-function-declaration -march=k8 -m3dnow -mavx -msse5 -maes -mpclmul" } */
+/* { dg-options "-O2 -Werror-implicit-function-declaration -march=k8 -m3dnow -mavx -msse5 -maes -mpclmul -mlwp" } */
#include <mm_malloc.h>
/* Test that the intrinsics compile with optimization. All of them are
- defined as inline functions in {,x,e,p,t,s,w,a,b,i}mmintrin.h and mm3dnow.h
- that reference the proper builtin functions. Defining away "extern" and
- "__inline" results in all of them being compiled as proper functions. */
+ defined as inline functions in {,x,e,p,t,s,w,a,b,i}mmintrin.h, lwpintrin.h
+ and mm3dnow.h that reference the proper builtin functions. Defining away
+ "extern" and "__inline" results in all of them being compiled as proper
+ functions. */
#define extern
#define __inline
@@ -132,4 +133,10 @@
#define __builtin_ia32_protdi(A, B) __builtin_ia32_protdi(A,1)
#define __builtin_ia32_protqi(A, B) __builtin_ia32_protqi(A,1)
+/* lwpintrin.h */
+#define __builtin_ia32_lwpval32(D2, D1, F) __builtin_ia32_lwpval32 (D2, D1, 1)
+#define __builtin_ia32_lwpval64(D2, D1, F) __builtin_ia32_lwpval64 (D2, D1, 1)
+#define __builtin_ia32_lwpins32(D2, D1, F) __builtin_ia32_lwpins32 (D2, D1, 1)
+#define __builtin_ia32_lwpins64(D2, D1, F) __builtin_ia32_lwpins64 (D2, D1, 1)
+
#include <x86intrin.h>
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.target/i386/sse-14.c b/gcc-4.4.3/gcc/testsuite/gcc.target/i386/sse-14.c
index 67da6608a..4c4232cdb 100644
--- a/gcc-4.4.3/gcc/testsuite/gcc.target/i386/sse-14.c
+++ b/gcc-4.4.3/gcc/testsuite/gcc.target/i386/sse-14.c
@@ -1,12 +1,13 @@
/* { dg-do compile } */
-/* { dg-options "-O0 -Werror-implicit-function-declaration -march=k8 -m3dnow -mavx -msse5 -maes -mpclmul" } */
+/* { dg-options "-O0 -Werror-implicit-function-declaration -march=k8 -m3dnow -mavx -msse5 -maes -mpclmul -mlwp" } */
#include <mm_malloc.h>
/* Test that the intrinsics compile without optimization. All of them are
- defined as inline functions in {,x,e,p,t,s,w,a,b}mmintrin.h and mm3dnow.h
- that reference the proper builtin functions. Defining away "extern" and
- "__inline" results in all of them being compiled as proper functions. */
+ defined as inline functions in {,x,e,p,t,s,w,a,b}mmintrin.h, lwpintrin.h
+ and mm3dnow.h that reference the proper builtin functions. Defining away
+ "extern" and "__inline" results in all of them being compiled as proper
+ functions. */
#define extern
#define __inline
@@ -162,3 +163,11 @@ test_1 (_mm_roti_epi8, __m128i, __m128i, 1)
test_1 (_mm_roti_epi16, __m128i, __m128i, 1)
test_1 (_mm_roti_epi32, __m128i, __m128i, 1)
test_1 (_mm_roti_epi64, __m128i, __m128i, 1)
+
+/* lwpintrin.h */
+test_2 ( __lwpval32, void, unsigned int, unsigned int, 1)
+test_2 ( __lwpins32, unsigned char, unsigned int, unsigned int, 1)
+#ifdef __x86_64__
+test_2 ( __lwpval64, void, unsigned long long, unsigned int, 1)
+test_2 ( __lwpins64, unsigned char, unsigned long long, unsigned int, 1)
+#endif
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.target/i386/sse-22.c b/gcc-4.4.3/gcc/testsuite/gcc.target/i386/sse-22.c
index f530e54ec..a6d80043c 100644
--- a/gcc-4.4.3/gcc/testsuite/gcc.target/i386/sse-22.c
+++ b/gcc-4.4.3/gcc/testsuite/gcc.target/i386/sse-22.c
@@ -5,9 +5,10 @@
#include <mm_malloc.h>
/* Test that the intrinsics compile without optimization. All of them are
- defined as inline functions in {,x,e,p,t,s,w,a,b}mmintrin.h and mm3dnow.h
- that reference the proper builtin functions. Defining away "extern" and
- "__inline" results in all of them being compiled as proper functions. */
+ defined as inline functions in {,x,e,p,t,s,w,a,b}mmintrin.h, lwpintrin.h
+ and mm3dnow.h that reference the proper builtin functions. Defining away
+ "extern" and "__inline" results in all of them being compiled as proper
+ functions. */
#define extern
#define __inline
@@ -37,7 +38,7 @@
#ifndef DIFFERENT_PRAGMAS
-#pragma GCC target ("mmx,3dnow,sse,sse2,sse3,ssse3,sse4.1,sse4.2,sse5,aes,pclmul")
+#pragma GCC target ("mmx,3dnow,sse,sse2,sse3,ssse3,sse4.1,sse4.2,sse5,aes,pclmul,lwp")
#endif
/* Following intrinsics require immediate arguments. They
@@ -169,3 +170,16 @@ test_1 (_mm_round_pd, __m128d, __m128d, 1)
test_1 (_mm_round_ps, __m128, __m128, 1)
test_2 (_mm_round_sd, __m128d, __m128d, __m128d, 1)
test_2 (_mm_round_ss, __m128, __m128, __m128, 1)
+
+#ifdef DIFFERENT_PRAGMAS
+#pragma GCC target ("lwp")
+#endif
+#include <x86intrin.h>
+
+/* lwpintrin.h (LWP). */
+test_2 ( __lwpval32, void, unsigned int, unsigned int, 1)
+test_2 ( __lwpins32, unsigned char, unsigned int, unsigned int, 1)
+#ifdef __x86_64__
+test_2 ( __lwpval64, void, unsigned long long, unsigned int, 1)
+test_2 ( __lwpins64, unsigned char, unsigned long long, unsigned int, 1)
+#endif
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.target/i386/sse-23.c b/gcc-4.4.3/gcc/testsuite/gcc.target/i386/sse-23.c
index 4488568f4..076161f27 100644
--- a/gcc-4.4.3/gcc/testsuite/gcc.target/i386/sse-23.c
+++ b/gcc-4.4.3/gcc/testsuite/gcc.target/i386/sse-23.c
@@ -4,9 +4,10 @@
#include <mm_malloc.h>
/* Test that the intrinsics compile with optimization. All of them are
- defined as inline functions in {,x,e,p,t,s,w,a,b}mmintrin.h and mm3dnow.h
- that reference the proper builtin functions. Defining away "extern" and
- "__inline" results in all of them being compiled as proper functions. */
+ defined as inline functions in {,x,e,p,t,s,w,a,b}mmintrin.h, lwpintrin.h
+ and mm3dnow.h that reference the proper builtin functions. Defining away
+ "extern" and "__inline" results in all of them being compiled as proper
+ functions. */
#define extern
#define __inline
@@ -94,15 +95,53 @@
#define __builtin_ia32_vec_ext_v4hi(A, N) __builtin_ia32_vec_ext_v4hi(A, 0)
#define __builtin_ia32_shufps(A, B, N) __builtin_ia32_shufps(A, B, 0)
+/* immintrin.h */
+#define __builtin_ia32_blendpd256(X, Y, M) __builtin_ia32_blendpd256(X, Y, 1)
+#define __builtin_ia32_blendps256(X, Y, M) __builtin_ia32_blendps256(X, Y, 1)
+#define __builtin_ia32_dpps256(X, Y, M) __builtin_ia32_dpps256(X, Y, 1)
+#define __builtin_ia32_shufpd256(X, Y, M) __builtin_ia32_shufpd256(X, Y, 1)
+#define __builtin_ia32_shufps256(X, Y, M) __builtin_ia32_shufps256(X, Y, 1)
+#define __builtin_ia32_cmpsd(X, Y, O) __builtin_ia32_cmpsd(X, Y, 1)
+#define __builtin_ia32_cmpss(X, Y, O) __builtin_ia32_cmpss(X, Y, 1)
+#define __builtin_ia32_cmppd(X, Y, O) __builtin_ia32_cmppd(X, Y, 1)
+#define __builtin_ia32_cmpps(X, Y, O) __builtin_ia32_cmpps(X, Y, 1)
+#define __builtin_ia32_cmppd256(X, Y, O) __builtin_ia32_cmppd256(X, Y, 1)
+#define __builtin_ia32_cmpps256(X, Y, O) __builtin_ia32_cmpps256(X, Y, 1)
+#define __builtin_ia32_vextractf128_pd256(X, N) __builtin_ia32_vextractf128_pd256(X, 1)
+#define __builtin_ia32_vextractf128_ps256(X, N) __builtin_ia32_vextractf128_ps256(X, 1)
+#define __builtin_ia32_vextractf128_si256(X, N) __builtin_ia32_vextractf128_si256(X, 1)
+#define __builtin_ia32_vpermilpd(X, N) __builtin_ia32_vpermilpd(X, 1)
+#define __builtin_ia32_vpermilpd256(X, N) __builtin_ia32_vpermilpd256(X, 1)
+#define __builtin_ia32_vpermilps(X, N) __builtin_ia32_vpermilps(X, 1)
+#define __builtin_ia32_vpermilps256(X, N) __builtin_ia32_vpermilps256(X, 1)
+#define __builtin_ia32_vpermil2pd(X, Y, C, I) __builtin_ia32_vpermil2pd(X, Y, C, 1)
+#define __builtin_ia32_vpermil2pd256(X, Y, C, I) __builtin_ia32_vpermil2pd256(X, Y, C, 1)
+#define __builtin_ia32_vpermil2ps(X, Y, C, I) __builtin_ia32_vpermil2ps(X, Y, C, 1)
+#define __builtin_ia32_vpermil2ps256(X, Y, C, I) __builtin_ia32_vpermil2ps256(X, Y, C, 1)
+#define __builtin_ia32_vperm2f128_pd256(X, Y, C) __builtin_ia32_vperm2f128_pd256(X, Y, 1)
+#define __builtin_ia32_vperm2f128_ps256(X, Y, C) __builtin_ia32_vperm2f128_ps256(X, Y, 1)
+#define __builtin_ia32_vperm2f128_si256(X, Y, C) __builtin_ia32_vperm2f128_si256(X, Y, 1)
+#define __builtin_ia32_vinsertf128_pd256(X, Y, C) __builtin_ia32_vinsertf128_pd256(X, Y, 1)
+#define __builtin_ia32_vinsertf128_ps256(X, Y, C) __builtin_ia32_vinsertf128_ps256(X, Y, 1)
+#define __builtin_ia32_vinsertf128_si256(X, Y, C) __builtin_ia32_vinsertf128_si256(X, Y, 1)
+#define __builtin_ia32_roundpd256(V, M) __builtin_ia32_roundpd256(V, 1)
+#define __builtin_ia32_roundps256(V, M) __builtin_ia32_roundps256(V, 1)
+
/* bmmintrin.h */
#define __builtin_ia32_protbi(A, B) __builtin_ia32_protbi(A,1)
#define __builtin_ia32_protwi(A, B) __builtin_ia32_protwi(A,1)
#define __builtin_ia32_protdi(A, B) __builtin_ia32_protdi(A,1)
#define __builtin_ia32_protqi(A, B) __builtin_ia32_protqi(A,1)
+/* lwpintrin.h */
+#define __builtin_ia32_lwpval32(D2, D1, F) __builtin_ia32_lwpval32 (D2, D1, 1)
+#define __builtin_ia32_lwpval64(D2, D1, F) __builtin_ia32_lwpval64 (D2, D1, 1)
+#define __builtin_ia32_lwpins32(D2, D1, F) __builtin_ia32_lwpins32 (D2, D1, 1)
+#define __builtin_ia32_lwpins64(D2, D1, F) __builtin_ia32_lwpins64 (D2, D1, 1)
-#pragma GCC target ("3dnow,sse4,sse5,aes,pclmul")
+#pragma GCC target ("3dnow,sse4,sse5,aes,pclmul,lwp")
#include <wmmintrin.h>
#include <bmmintrin.h>
#include <smmintrin.h>
#include <mm3dnow.h>
+#include <x86intrin.h>
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.target/i386/sse2-vec-2a.c b/gcc-4.4.3/gcc/testsuite/gcc.target/i386/sse2-vec-2a.c
new file mode 100644
index 000000000..27e99147e
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.target/i386/sse2-vec-2a.c
@@ -0,0 +1,4 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -msse2 -mtune=atom" } */
+
+#include "sse2-vec-2.c"
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.target/x86_64/abi/callabi/func-2a.c b/gcc-4.4.3/gcc/testsuite/gcc.target/x86_64/abi/callabi/func-2a.c
new file mode 100644
index 000000000..048da6e56
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.target/x86_64/abi/callabi/func-2a.c
@@ -0,0 +1,27 @@
+/* Test for cross x86_64<->w64 abi standard calls. */
+/* { dg-do run { target i?86-*-linux* x86_64-*-linux* } } */
+/* { dg-options "-O2 -mabi=ms -std=gnu99 -ffast-math -fno-builtin" } */
+/* { dg-additional-sources "func-2b.c" } */
+
+extern void __attribute__ ((sysv_abi)) abort (void);
+long double func_cross (long double, double, float, long, int, char);
+
+long double __attribute__ ((sysv_abi))
+func_native (long double a, double b, float c, long d, int e, char f)
+{
+ long double ret;
+ ret = a + (long double) b + (long double) c;
+ ret *= (long double) (d + (long) e);
+ if (f>0)
+ ret += func_native (a,b,c,d,e,-f);
+ return ret;
+}
+
+int __attribute__ ((sysv_abi))
+main ()
+{
+ if (func_cross (1.0,2.0,3.0,1,2,3)
+ != func_native (1.0,2.0,3.0,1,2,3))
+ abort ();
+ return 0;
+}
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.target/x86_64/abi/callabi/func-2b.c b/gcc-4.4.3/gcc/testsuite/gcc.target/x86_64/abi/callabi/func-2b.c
new file mode 100644
index 000000000..fe85dd186
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.target/x86_64/abi/callabi/func-2b.c
@@ -0,0 +1,13 @@
+/* Test for cross x86_64<->w64 abi standard calls. */
+/* { dg-options "-mabi=ms -std=gnu99 -ffast-math -fno-builtin" } */
+
+long double func_cross (long double a, double b, float c, long d, int e,
+ char f)
+{
+ long double ret;
+ ret = a + (long double) b + (long double) c;
+ ret *= (long double) (d + (long) e);
+ if (f>0)
+ ret += func_cross (a,b,c,d,e,-f);
+ return ret;
+}
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.target/x86_64/abi/callabi/func-indirect-2a.c b/gcc-4.4.3/gcc/testsuite/gcc.target/x86_64/abi/callabi/func-indirect-2a.c
new file mode 100644
index 000000000..730b8db9c
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.target/x86_64/abi/callabi/func-indirect-2a.c
@@ -0,0 +1,17 @@
+/* Test for cross x86_64<->w64 abi standard calls via variable. */
+/* { dg-do run { target i?86-*-linux* x86_64-*-linux* } } */
+/* { dg-options "-O2 -mabi=ms -std=gnu99 -ffast-math -fno-builtin" } */
+/* { dg-additional-sources "func-indirect-2b.c" } */
+
+extern void __attribute__ ((sysv_abi)) abort (void);
+typedef int (*func)(void *, char *, char *, short, long long);
+extern func get_callback (void);
+
+int __attribute__ ((sysv_abi))
+main ()
+{
+ func callme = get_callback ();
+ if (callme (0, 0, 0, 0x1234, 0x1234567890abcdefLL))
+ abort ();
+ return 0;
+}
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.target/x86_64/abi/callabi/func-indirect-2b.c b/gcc-4.4.3/gcc/testsuite/gcc.target/x86_64/abi/callabi/func-indirect-2b.c
new file mode 100644
index 000000000..1a9fccd97
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.target/x86_64/abi/callabi/func-indirect-2b.c
@@ -0,0 +1,24 @@
+/* Test for cross x86_64<->w64 abi standard calls via variable. */
+/* { dg-options "-O2 -mabi=ms -std=gnu99 -ffast-math -fno-builtin" } */
+
+typedef int (*func)(void *, char *, char *, short, long long);
+
+static int
+callback (void *ptr, char *string1, char *string2, short number,
+ long long rand)
+{
+ if (ptr != 0
+ || string1 != 0
+ || string2 != 0
+ || number != 0x1234
+ || rand != 0x1234567890abcdefLL)
+ return 1;
+ else
+ return 0;
+}
+
+func
+get_callback (void)
+{
+ return callback;
+}
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.target/x86_64/abi/callabi/vaarg-4a.c b/gcc-4.4.3/gcc/testsuite/gcc.target/x86_64/abi/callabi/vaarg-4a.c
new file mode 100644
index 000000000..a44470431
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.target/x86_64/abi/callabi/vaarg-4a.c
@@ -0,0 +1,24 @@
+/* Test for cross x86_64<->w64 abi va_list calls. */
+/* { dg-do run { target i?86-*-linux* x86_64-*-linux* } } */
+/* { dg-options "-O2 -mabi=ms -std=gnu99 -fno-builtin" } */
+/* { dg-additional-sources "vaarg-4b.c" } */
+
+extern __SIZE_TYPE__ __attribute__ ((sysv_abi)) strlen (const char *);
+extern int __attribute__ ((sysv_abi)) sprintf (char *,const char *, ...);
+extern void __attribute__ ((sysv_abi)) abort (void);
+
+extern void do_cpy (char *, ...);
+
+int __attribute__ ((sysv_abi))
+main ()
+{
+ char s[256];
+
+ do_cpy (s, "1","2","3","4", "5", "6", "7", "");
+
+ if (s[0] != '1' || s[1] !='2' || s[2] != '3' || s[3] != '4'
+ || s[4] != '5' || s[5] != '6' || s[6] != '7' || s[7] != 0)
+ abort ();
+
+ return 0;
+}
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.target/x86_64/abi/callabi/vaarg-4b.c b/gcc-4.4.3/gcc/testsuite/gcc.target/x86_64/abi/callabi/vaarg-4b.c
new file mode 100644
index 000000000..f33906bd2
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.target/x86_64/abi/callabi/vaarg-4b.c
@@ -0,0 +1,31 @@
+/* Test for cross x86_64<->w64 abi va_list calls. */
+/* { dg-options "-O2 -mabi=ms -std=gnu99 -fno-builtin" } */
+
+#include <stdarg.h>
+
+extern __SIZE_TYPE__ __attribute__ ((sysv_abi)) strlen (const char *);
+extern int __attribute__ ((sysv_abi)) sprintf (char *, const char *, ...);
+
+static void
+vdo_cpy (char *s, va_list argp)
+{
+ __SIZE_TYPE__ len;
+ char *r = s;
+ char *e;
+ *r = 0;
+ for (;;) {
+ e = va_arg (argp, char *);
+ if (*e == 0) break;
+ sprintf (r,"%s", e);
+ r += strlen (r);
+ }
+}
+
+void
+do_cpy (char *s, ...)
+{
+ va_list argp;
+ va_start (argp, s);
+ vdo_cpy (s, argp);
+ va_end (argp);
+}
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.target/x86_64/abi/callabi/vaarg-5a.c b/gcc-4.4.3/gcc/testsuite/gcc.target/x86_64/abi/callabi/vaarg-5a.c
new file mode 100644
index 000000000..e9912957e
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.target/x86_64/abi/callabi/vaarg-5a.c
@@ -0,0 +1,17 @@
+/* Test for cross x86_64<->w64 abi va_list calls. */
+/* { dg-do run { target i?86-*-linux* x86_64-*-linux* } } */
+/* { dg-options "-O2 -mabi=ms -std=gnu99 -fno-builtin" } */
+/* { dg-additional-sources "vaarg-5b.c" } */
+
+extern void __attribute__ ((sysv_abi)) abort (void);
+extern int fct2 (int, ...);
+
+#define SZ_ARGS 1ll,2ll,3ll,4ll,5ll,6ll,7ll,0ll
+
+int __attribute__ ((sysv_abi))
+main()
+{
+ if (fct2 (-1, SZ_ARGS) != 0)
+ abort ();
+ return 0;
+}
diff --git a/gcc-4.4.3/gcc/testsuite/gcc.target/x86_64/abi/callabi/vaarg-5b.c b/gcc-4.4.3/gcc/testsuite/gcc.target/x86_64/abi/callabi/vaarg-5b.c
new file mode 100644
index 000000000..e5dd4727b
--- /dev/null
+++ b/gcc-4.4.3/gcc/testsuite/gcc.target/x86_64/abi/callabi/vaarg-5b.c
@@ -0,0 +1,37 @@
+/* Test for cross x86_64<->w64 abi va_list calls. */
+/* { dg-options "-O2 -mabi=ms -std=gnu99 -fno-builtin" } */
+
+#include <stdarg.h>
+
+#define SZ_ARGS 1ll,2ll,3ll,4ll,5ll,6ll,7ll,0ll
+
+static int __attribute__ ((sysv_abi))
+fct1 (va_list argp, ...)
+{
+ long long p1,p2;
+ int ret = 1;
+ __builtin_sysv_va_list argp_2;
+
+ __builtin_sysv_va_start (argp_2, argp);
+ do {
+ p1 = va_arg (argp_2, long long);
+ p2 = va_arg (argp, long long);
+ if (p1 != p2)
+ ret = 0;
+ } while (ret && p1 != 0);
+ __builtin_sysv_va_end (argp_2);
+
+ return ret;
+}
+
+int
+fct2 (int dummy, ...)
+{
+ va_list argp;
+ int ret = dummy;
+
+ va_start (argp, dummy);
+ ret += fct1 (argp, SZ_ARGS);
+ va_end (argp);
+ return ret;
+}
diff --git a/gcc-4.4.3/gcc/testsuite/lib/scanasm.exp b/gcc-4.4.3/gcc/testsuite/lib/scanasm.exp
index 24de1871b..7373fd950 100644
--- a/gcc-4.4.3/gcc/testsuite/lib/scanasm.exp
+++ b/gcc-4.4.3/gcc/testsuite/lib/scanasm.exp
@@ -280,3 +280,40 @@ proc scan-assembler-dem-not { args } {
fail "$testcase scan-assembler-dem-not [lindex $args 0]"
}
}
+
+# Utility for testing that a function is defined on the current line.
+# Call pass if so, otherwise fail. Invoked directly; the file must
+# have been compiled with -g -dA.
+#
+# Argument 0 is the current line, passed implicitly by dejagnu
+# Argument 1 is the function to check
+# Argument 2 handles expected failures and the like
+# Argument 3 is "." to match the current line, or an integer to match
+# an explicit line.
+proc dg-function-on-line { args } {
+ # Upvar from dg-final:
+ upvar dg-final-code final-code
+
+ set line [lindex $args 0]
+ set symbol [lindex $args 1]
+ set failures [lindex $args 2]
+
+ if { [llength $args] >= 4 } {
+ switch [lindex $args 3] {
+ "." { }
+ "default" { set line [lindex $args 3] }
+ }
+ }
+
+ set pattern [format {%s:[^\t]*(\t.(fnstart|frame|mask|file)[^\t]*)*\t[^:]+:%d\n} \
+ $symbol $line]
+
+ # The lack of spaces around $pattern is important, since they'd
+ # become part of the regex scan-assembler tries to match.
+ set cmd "scan-assembler {$pattern}"
+ if { [llength $args] >= 3 } {
+ set cmd "$cmd {$failures}"
+ }
+
+ append final-code "$cmd\n"
+}
diff --git a/gcc-4.4.3/gcc/testsuite/lib/target-supports.exp b/gcc-4.4.3/gcc/testsuite/lib/target-supports.exp
index 1f8464d69..792d0918a 100644
--- a/gcc-4.4.3/gcc/testsuite/lib/target-supports.exp
+++ b/gcc-4.4.3/gcc/testsuite/lib/target-supports.exp
@@ -1430,6 +1430,20 @@ proc check_effective_target_arm_vfp_ok { } {
}
}
+# Return 1 if this is an ARM target supporting -mfpu=vfp
+# -mfloat-abi=hard. Some multilibs may be incompatible with these
+# options.
+
+proc check_effective_target_arm_hard_vfp_ok { } {
+ if { [check_effective_target_arm32] } {
+ return [check_no_compiler_messages arm_hard_vfp_ok executable {
+ int main() { return 0;}
+ } "-mfpu=vfp -mfloat-abi=hard"]
+ } else {
+ return 0
+ }
+}
+
# Return 1 if this is an ARM target supporting -mfpu=neon
# -mfloat-abi=softfp. Some multilibs may be incompatible with these
# options.
@@ -1437,6 +1451,7 @@ proc check_effective_target_arm_vfp_ok { } {
proc check_effective_target_arm_neon_ok { } {
if { [check_effective_target_arm32] } {
return [check_no_compiler_messages arm_neon_ok object {
+ #include "arm_neon.h"
int dummy;
} "-mfpu=neon -mfloat-abi=softfp"]
} else {
@@ -1455,6 +1470,17 @@ proc check_effective_target_arm_thumb1_ok { } {
} "-mthumb"]
}
+# Return 1 is this is an ARM target where -mthumb causes Thumb-2 to be
+# used.
+
+proc check_effective_target_arm_thumb2_ok { } {
+ return [check_no_compiler_messages arm_thumb2_ok assembly {
+ #if !defined(__thumb2__)
+ #error FOO
+ #endif
+ } "-mthumb"]
+}
+
# Return 1 if the target supports executing NEON instructions, 0
# otherwise. Cache the result.
diff --git a/gcc-4.4.3/gcc/timevar.def b/gcc-4.4.3/gcc/timevar.def
index a6f422056..ed4124fbf 100644
--- a/gcc-4.4.3/gcc/timevar.def
+++ b/gcc-4.4.3/gcc/timevar.def
@@ -89,6 +89,7 @@ DEFTIMEVAR (TV_PARSE_FUNC , "parser function body")
DEFTIMEVAR (TV_PARSE_INMETH , "parser inl. meth. body")
DEFTIMEVAR (TV_NAME_LOOKUP , "name lookup")
DEFTIMEVAR (TV_INLINE_HEURISTICS , "inline heuristics")
+DEFTIMEVAR (TV_MVERSN_DISPATCH , "multiversion dispatch")
DEFTIMEVAR (TV_INTEGRATION , "integration")
DEFTIMEVAR (TV_TREE_GIMPLIFY , "tree gimplify")
DEFTIMEVAR (TV_TREE_EH , "tree eh")
diff --git a/gcc-4.4.3/gcc/toplev.c b/gcc-4.4.3/gcc/toplev.c
index de0962105..90976913e 100644
--- a/gcc-4.4.3/gcc/toplev.c
+++ b/gcc-4.4.3/gcc/toplev.c
@@ -2019,6 +2019,10 @@ process_options (void)
"for correctness");
flag_omit_frame_pointer = 0;
}
+
+ /* Save the current optimization options. */
+ optimization_default_node = build_optimization_node ();
+ optimization_current_node = optimization_default_node;
}
/* This function can be called multiple times to reinitialize the compiler
diff --git a/gcc-4.4.3/gcc/tree-dfa.c b/gcc-4.4.3/gcc/tree-dfa.c
index 5241e64c9..88698859b 100644
--- a/gcc-4.4.3/gcc/tree-dfa.c
+++ b/gcc-4.4.3/gcc/tree-dfa.c
@@ -194,6 +194,32 @@ renumber_gimple_stmt_uids (void)
}
}
+/* Like renumber_gimple_stmt_uids, but only do work on the basic blocks
+ in BLOCKS, of which there are N_BLOCKS. Also renumbers PHIs. */
+
+void
+renumber_gimple_stmt_uids_in_blocks (basic_block *blocks, int n_blocks)
+{
+ int i;
+
+ set_gimple_stmt_max_uid (cfun, 0);
+ for (i = 0; i < n_blocks; i++)
+ {
+ basic_block bb = blocks[i];
+ gimple_stmt_iterator bsi;
+ for (bsi = gsi_start_phis (bb); !gsi_end_p (bsi); gsi_next (&bsi))
+ {
+ gimple stmt = gsi_stmt (bsi);
+ gimple_set_uid (stmt, inc_gimple_stmt_max_uid (cfun));
+ }
+ for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi))
+ {
+ gimple stmt = gsi_stmt (bsi);
+ gimple_set_uid (stmt, inc_gimple_stmt_max_uid (cfun));
+ }
+ }
+}
+
/* Create a new annotation for a tree T. */
tree_ann_common_t
diff --git a/gcc-4.4.3/gcc/tree-flow.h b/gcc-4.4.3/gcc/tree-flow.h
index ce654c372..76c689800 100644
--- a/gcc-4.4.3/gcc/tree-flow.h
+++ b/gcc-4.4.3/gcc/tree-flow.h
@@ -760,6 +760,7 @@ extern const char *op_symbol_code (enum tree_code);
extern var_ann_t create_var_ann (tree);
extern function_ann_t create_function_ann (tree);
extern void renumber_gimple_stmt_uids (void);
+extern void renumber_gimple_stmt_uids_in_blocks (basic_block *, int);
extern tree_ann_common_t create_tree_common_ann (tree);
extern void dump_dfa_stats (FILE *);
extern void debug_dfa_stats (void);
@@ -879,9 +880,12 @@ extern void verify_ssa (bool);
extern void delete_tree_ssa (void);
extern void walk_use_def_chains (tree, walk_use_def_chains_fn, void *, bool);
extern bool ssa_undefined_value_p (tree);
-extern void warn_uninit (tree, const char *, void *);
+extern void warn_uninit (enum opt_code, tree, const char *, void *);
extern unsigned int warn_uninitialized_vars (bool);
+/* In tree-ssa-sccvn.c */
+extern void fixup_vdef_ssa_val_refs (gimple);
+
/* In tree-into-ssa.c */
void update_ssa (unsigned);
diff --git a/gcc-4.4.3/gcc/tree-inline.c b/gcc-4.4.3/gcc/tree-inline.c
index decae7a4c..173c204e1 100644
--- a/gcc-4.4.3/gcc/tree-inline.c
+++ b/gcc-4.4.3/gcc/tree-inline.c
@@ -1853,6 +1853,7 @@ initialize_cfun (tree new_fndecl, tree callee_fndecl, gcov_type count,
cfun->returns_struct = src_cfun->returns_struct;
cfun->returns_pcc_struct = src_cfun->returns_pcc_struct;
cfun->after_tree_profile = src_cfun->after_tree_profile;
+ cfun->language = src_cfun->language;
init_empty_tree_cfg ();
@@ -3304,8 +3305,9 @@ expand_call_inline (basic_block bb, gimple stmt, copy_body_data *id)
/* Avoid warnings during early inline pass. */
&& cgraph_global_info_ready)
{
- sorry ("inlining failed in call to %q+F: %s", fn, reason);
- sorry ("called from here");
+ error ("%q+F has attribute 'always_inline', but was not inlined."
+ " Reason: %s", fn, reason);
+ error ("called from here");
}
else if (warn_inline && DECL_DECLARED_INLINE_P (fn)
&& !DECL_IN_SYSTEM_HEADER (fn)
diff --git a/gcc-4.4.3/gcc/tree-pass.h b/gcc-4.4.3/gcc/tree-pass.h
index 016571dcb..53ab68293 100644
--- a/gcc-4.4.3/gcc/tree-pass.h
+++ b/gcc-4.4.3/gcc/tree-pass.h
@@ -321,6 +321,7 @@ extern struct gimple_opt_pass pass_refactor_eh;
extern struct gimple_opt_pass pass_lower_eh;
extern struct gimple_opt_pass pass_build_cfg;
extern struct gimple_opt_pass pass_tree_profile;
+extern struct gimple_opt_pass pass_tree_convert_builtin_dispatch;
extern struct gimple_opt_pass pass_direct_call_profile;
extern struct gimple_opt_pass pass_early_tree_profile;
extern struct gimple_opt_pass pass_tree_sample_profile;
@@ -408,6 +409,7 @@ extern struct gimple_opt_pass pass_rebuild_cgraph_edges;
extern struct gimple_opt_pass pass_build_cgraph_edges;
extern struct gimple_opt_pass pass_reset_cc_flags;
extern struct gimple_opt_pass pass_threadsafe_analyze;
+extern struct gimple_opt_pass pass_stack_overlay;
/* IPA Passes */
extern struct ipa_opt_pass pass_ipa_inline;
@@ -423,6 +425,7 @@ extern struct simple_ipa_opt_pass pass_ipa_struct_reorg;
extern struct simple_ipa_opt_pass pass_early_local_passes;
extern struct simple_ipa_opt_pass pass_ipa_increase_alignment;
extern struct simple_ipa_opt_pass pass_ipa_function_and_variable_visibility;
+extern struct simple_ipa_opt_pass pass_ipa_multiversion_dispatch;
extern struct gimple_opt_pass pass_all_optimizations;
extern struct gimple_opt_pass pass_cleanup_cfg_post_optimizing;
diff --git a/gcc-4.4.3/gcc/tree-profile.c b/gcc-4.4.3/gcc/tree-profile.c
index cebf93cab..75fc515b4 100644
--- a/gcc-4.4.3/gcc/tree-profile.c
+++ b/gcc-4.4.3/gcc/tree-profile.c
@@ -48,10 +48,20 @@ along with GCC; see the file COPYING3. If not see
#include "ggc.h"
#include "cgraph.h"
#include "target.h"
+#include "params.h"
+#include "profile.h"
+
+/* Number of statements inserted for each edge counter increment. */
+#define EDGE_COUNTER_STMT_COUNT 3
+
+/* When -D__KERNEL__ is in the option list, we assume this is a
+ compilation for Linux Kernel. */
+bool is_kernel_build;
static GTY(()) tree gcov_type_node;
static GTY(()) tree gcov_type_tmp_var;
static GTY(()) tree tree_interval_profiler_fn;
+static GTY(()) tree tree_one_float_value_profiler_fn;
static GTY(()) tree tree_pow2_profiler_fn;
static GTY(()) tree tree_one_value_profiler_fn;
static GTY(()) tree tree_indirect_call_profiler_fn;
@@ -94,7 +104,7 @@ tree_init_ic_make_global_vars (void)
ptr_void);
TREE_PUBLIC (ic_void_ptr_var) = 1;
DECL_EXTERNAL (ic_void_ptr_var) = 1;
- if (targetm.have_tls)
+ if (targetm.have_tls && !is_kernel_build)
{
DECL_TLS_MODEL (ic_void_ptr_var) =
decl_default_tls_model (ic_void_ptr_var);
@@ -107,7 +117,7 @@ tree_init_ic_make_global_vars (void)
gcov_type_ptr);
TREE_PUBLIC (ic_gcov_type_ptr_var) = 1;
DECL_EXTERNAL (ic_gcov_type_ptr_var) = 1;
- if (targetm.have_tls)
+ if (targetm.have_tls && !is_kernel_build)
{
DECL_TLS_MODEL (ic_gcov_type_ptr_var) =
decl_default_tls_model (ic_gcov_type_ptr_var);
@@ -122,7 +132,7 @@ tree_init_ic_make_global_vars (void)
TREE_STATIC (ic_void_ptr_var) = 1;
TREE_PUBLIC (ic_void_ptr_var) = 0;
DECL_INITIAL (ic_void_ptr_var) = NULL;
- if (targetm.have_tls)
+ if (targetm.have_tls && !is_kernel_build)
{
DECL_TLS_MODEL (ic_void_ptr_var) =
decl_default_tls_model (ic_void_ptr_var);
@@ -136,7 +146,7 @@ tree_init_ic_make_global_vars (void)
TREE_STATIC (ic_gcov_type_ptr_var) = 1;
TREE_PUBLIC (ic_gcov_type_ptr_var) = 0;
DECL_INITIAL (ic_gcov_type_ptr_var) = NULL;
- if (targetm.have_tls)
+ if (targetm.have_tls && !is_kernel_build)
{
DECL_TLS_MODEL (ic_gcov_type_ptr_var) =
decl_default_tls_model (ic_gcov_type_ptr_var);
@@ -149,12 +159,181 @@ tree_init_ic_make_global_vars (void)
assemble_variable (ic_gcov_type_ptr_var, 0, 0, 0);
}
+/* A set of the first statement in each block of statements that need to
+ be applied a sampling wrapper. */
+static htab_t instrumentation_to_be_sampled = NULL;
+
+/* extern __thread gcov_unsigned_t __gcov_sample_counter */
+static tree gcov_sample_counter_decl = NULL_TREE;
+
+/* extern gcov_unsigned_t __gcov_sampling_rate */
+static tree gcov_sampling_rate_decl = NULL_TREE;
+
+/* forward declaration. */
+void tree_init_instrumentation_sampling (void);
+
+/* Insert STMT_IF around given sequence of consecutive statements in the
+ same basic block starting with STMT_START, ending with STMT_END. */
+
+static void
+insert_if_then (gimple stmt_start, gimple stmt_end, gimple stmt_if)
+{
+ gimple_stmt_iterator gsi;
+ basic_block bb_original, bb_before_if, bb_then, bb_after_if;
+ edge e_if_taken, e_then_join, e_if_not_taken;
+
+ gsi = gsi_for_stmt (stmt_start);
+ gsi_insert_before_without_update (&gsi, stmt_if, GSI_SAME_STMT);
+ bb_original = gsi_bb (gsi);
+ e_if_taken = split_block (bb_original, stmt_if);
+ e_if_taken->flags &= ~EDGE_FALLTHRU;
+ e_if_taken->flags |= EDGE_TRUE_VALUE;
+ e_then_join = split_block (e_if_taken->dest, stmt_end);
+ bb_before_if = e_if_taken->src;
+ bb_then = e_if_taken->dest;
+ bb_after_if = e_then_join->dest;
+ e_if_not_taken = make_edge (bb_before_if, bb_after_if, EDGE_FALSE_VALUE);
+}
+
+/* Transform:
+
+ ORIGINAL CODE
+
+ Into:
+
+ __gcov_sample_counter++;
+ if (__gcov_sample_counter >= __gcov_sampling_rate)
+ {
+ __gcov_sample_counter = 0;
+ ORIGINAL CODE
+ }
+
+ The original code block starts with STMT_START, is made of STMT_COUNT
+ consecutive statements in the same basic block. */
+
+static void
+add_sampling_wrapper (gimple stmt_start, int stmt_count)
+{
+ int i;
+ tree zero, one, tmp_var;
+ gimple stmt_block_end;
+ gimple stmt_inc_counter1, stmt_inc_counter2, stmt_inc_counter3;
+ gimple stmt_reset_counter, stmt_if;
+ gimple_stmt_iterator gsi;
+
+ tmp_var = create_tmp_var (get_gcov_unsigned_t (), "PROF_sample_counter");
+
+ /* Create all the new statements needed. */
+ stmt_inc_counter1 = gimple_build_assign (tmp_var, gcov_sample_counter_decl);
+ one = build_int_cst (get_gcov_unsigned_t (), 1);
+ stmt_inc_counter2 = gimple_build_assign_with_ops (
+ PLUS_EXPR, tmp_var, tmp_var, one);
+ stmt_inc_counter3 = gimple_build_assign (gcov_sample_counter_decl, tmp_var);
+ zero = build_int_cst (get_gcov_unsigned_t (), 0);
+ stmt_reset_counter = gimple_build_assign (gcov_sample_counter_decl, zero);
+ stmt_if = gimple_build_cond (GE_EXPR, tmp_var, gcov_sampling_rate_decl,
+ NULL_TREE, NULL_TREE);
+
+ /* Insert them for now in the original basic block. */
+ gsi = gsi_for_stmt (stmt_start);
+ gsi_insert_before_without_update (&gsi, stmt_inc_counter1, GSI_SAME_STMT);
+ gsi_insert_before_without_update (&gsi, stmt_inc_counter2, GSI_SAME_STMT);
+ gsi_insert_before_without_update (&gsi, stmt_inc_counter3, GSI_SAME_STMT);
+ gsi_insert_before_without_update (&gsi, stmt_reset_counter, GSI_SAME_STMT);
+
+ /* Move to last statement. */
+ for (i = 0; i < stmt_count - 1; i++)
+ gsi_next (&gsi);
+
+ stmt_block_end = gsi_stmt (gsi);
+ gcc_assert (stmt_block_end);
+
+ /* Insert IF block. */
+ insert_if_then (stmt_reset_counter, stmt_block_end, stmt_if);
+}
+
+/* Return whether STMT is the beginning of an instrumentation block to be
+ applied sampling. */
+
+static bool
+is_instrumentation_to_be_sampled (gimple stmt)
+{
+ return (htab_find_slot_with_hash (instrumentation_to_be_sampled, stmt,
+ htab_hash_pointer (stmt), NO_INSERT)
+ != NULL);
+}
+
+/* Add sampling wrappers around edge counter code in current function. */
+
+void
+add_sampling_to_edge_counters (void)
+{
+ gimple_stmt_iterator gsi;
+ basic_block bb;
+
+ FOR_EACH_BB_REVERSE (bb)
+ for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+ {
+ gimple stmt = gsi_stmt (gsi);
+ if (is_instrumentation_to_be_sampled (stmt))
+ {
+ add_sampling_wrapper (stmt, EDGE_COUNTER_STMT_COUNT);
+ break;
+ }
+ }
+
+ /* Empty the set of statements performing the edge counter increment. */
+ if (instrumentation_to_be_sampled)
+ htab_empty (instrumentation_to_be_sampled);
+}
+
+void
+tree_init_instrumentation_sampling (void)
+{
+ if (!gcov_sampling_rate_decl)
+ {
+ /* Define __gcov_sampling_rate regardless of -fprofile-generate-sampling.
+ Otherwise the extern reference to it from libgcov becomes unmatched.
+ */
+ gcov_sampling_rate_decl = build_decl (
+ VAR_DECL,
+ get_identifier ("__gcov_sampling_rate"),
+ get_gcov_unsigned_t ());
+ TREE_PUBLIC (gcov_sampling_rate_decl) = 1;
+ DECL_ARTIFICIAL (gcov_sampling_rate_decl) = 1;
+ DECL_ONE_ONLY (gcov_sampling_rate_decl) = 1;
+ TREE_STATIC (gcov_sampling_rate_decl) = 1;
+ DECL_INITIAL (gcov_sampling_rate_decl) = build_int_cst (
+ get_gcov_unsigned_t (),
+ PARAM_VALUE (PARAM_PROFILE_GENERATE_SAMPLING_RATE));
+ assemble_variable (gcov_sampling_rate_decl, 0, 0, 0);
+ }
+
+ if (flag_profile_generate_sampling && !instrumentation_to_be_sampled)
+ {
+ instrumentation_to_be_sampled = htab_create (100, htab_hash_pointer,
+ htab_eq_pointer, NULL);
+ gcov_sample_counter_decl = build_decl (
+ VAR_DECL,
+ get_identifier ("__gcov_sample_counter"),
+ get_gcov_unsigned_t ());
+ TREE_PUBLIC (gcov_sample_counter_decl) = 1;
+ DECL_EXTERNAL (gcov_sample_counter_decl) = 1;
+ DECL_ARTIFICIAL (gcov_sample_counter_decl) = 1;
+ if (targetm.have_tls && !is_kernel_build)
+ DECL_TLS_MODEL (gcov_sample_counter_decl) =
+ decl_default_tls_model (gcov_sample_counter_decl);
+ assemble_variable (gcov_sample_counter_decl, 0, 0, 0);
+ }
+}
+
static void
tree_init_edge_profiler (void)
{
tree interval_profiler_fn_type;
tree pow2_profiler_fn_type;
tree one_value_profiler_fn_type;
+ tree one_float_value_profiler_fn_type;
tree gcov_type_ptr;
tree ic_profiler_fn_type;
tree ic_topn_profiler_fn_type;
@@ -199,8 +378,17 @@ tree_init_edge_profiler (void)
= build_fn_decl ("__gcov_one_value_profiler",
one_value_profiler_fn_type);
+ /* void (*) (gcov_type *, gcov_float_t) */
+ one_float_value_profiler_fn_type
+ = build_function_type_list (void_type_node,
+ gcov_type_ptr, gcov_type_node,
+ NULL_TREE);
+ tree_one_float_value_profiler_fn
+ = build_fn_decl ("__gcov_one_float_value_profiler",
+ one_float_value_profiler_fn_type);
+
tree_init_ic_make_global_vars ();
-
+
/* void (*) (gcov_type *, gcov_type, void *, void *) */
ic_profiler_fn_type
= build_function_type_list (void_type_node,
@@ -261,6 +449,7 @@ add_abnormal_goto_call_edges (gimple_stmt_iterator gsi)
static void
tree_gen_edge_profiler (int edgeno, edge e)
{
+ void** slot;
tree ref, one;
gimple stmt1, stmt2, stmt3;
@@ -274,6 +463,15 @@ tree_gen_edge_profiler (int edgeno, edge e)
stmt2 = gimple_build_assign_with_ops (PLUS_EXPR, gcov_type_tmp_var,
gcov_type_tmp_var, one);
stmt3 = gimple_build_assign (unshare_expr (ref), gcov_type_tmp_var);
+
+ if (flag_profile_generate_sampling)
+ {
+ slot = htab_find_slot_with_hash (instrumentation_to_be_sampled, stmt1,
+ htab_hash_pointer (stmt1), INSERT);
+ gcc_assert (!*slot);
+ *slot = stmt1;
+ }
+
gsi_insert_on_edge (e, stmt1);
gsi_insert_on_edge (e, stmt2);
gsi_insert_on_edge (e, stmt3);
@@ -350,7 +548,7 @@ tree_gen_one_value_profiler (histogram_value value, unsigned tag, unsigned base)
tree ref_ptr = tree_coverage_counter_addr (tag, base);
gimple call;
tree val;
-
+
ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
true, NULL_TREE, true, GSI_SAME_STMT);
val = prepare_instrumented_value (&gsi, value);
@@ -359,6 +557,33 @@ tree_gen_one_value_profiler (histogram_value value, unsigned tag, unsigned base)
add_abnormal_goto_call_edges (gsi);
}
+/* Output instructions as GIMPLE trees for code to find the most common value.
+ VALUE is the expression whose value is profiled. TAG is the tag of the
+ section for counters, BASE is offset of the counter position. */
+
+static void
+tree_gen_one_float_value_profiler (histogram_value value, unsigned tag,
+ unsigned base)
+{
+ gimple stmt = value->hvalue.stmt;
+ gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
+ tree ref_ptr = tree_coverage_counter_addr (tag, base);
+ gimple call;
+ tree val;
+
+ ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
+ true, NULL_TREE, true, GSI_SAME_STMT);
+
+ val = force_gimple_operand_gsi (&gsi, fold_convert (get_gcov_float_t (),
+ value->hvalue.value),
+ true, NULL_TREE, true, GSI_SAME_STMT);
+
+ call = gimple_build_call (tree_one_float_value_profiler_fn, 2, ref_ptr,
+ val);
+ gsi_insert_before (&gsi, call, GSI_NEW_STMT);
+ add_abnormal_goto_call_edges (gsi);
+}
+
/* Output instructions as GIMPLE trees for code to find the most
common called function in indirect call.
@@ -450,7 +675,7 @@ tree_gen_ic_func_profiler (void)
gsi = gsi_start_bb (bb);
/* Set __gcov_indirect_call_callee to 0,
so that calls from other modules won't get misattributed
- to the last caller of the current callee. */
+ to the last caller of the current callee. */
void0 = build_int_cst (build_pointer_type (void_type_node), 0);
stmt2 = gimple_build_assign (ic_void_ptr_var, void0);
gsi_insert_after (&gsi, stmt2, GSI_NEW_STMT);
@@ -524,7 +749,7 @@ tree_gen_dc_profiler (unsigned base, gimple call_stmt)
gimple stmt1, stmt2, stmt3;
gimple_stmt_iterator gsi = gsi_for_stmt (call_stmt);
tree tmp1, tmp2, tmp3, callee = gimple_call_fn (call_stmt);
-
+
/* Insert code:
__gcov_direct_call_counters = get_relevant_counter_ptr ();
__gcov_callee = (void *) callee;
@@ -650,6 +875,509 @@ tree_gen_ior_profiler (histogram_value value, unsigned tag, unsigned base)
add_abnormal_goto_call_edges (gsi);
}
+/* String operation substitution record. For each operation, e.g., memcpy,
+ we keep up to four declarations, e.g., libopt__memcpy__{0,1,2,3}.
+ They correspond to memcpy versions in which memory access is nontemporal
+ in neither, first, second or both arguments (dst, src) respectively. */
+
+struct stringop_subst
+{
+ const char* original_name; /* E.g., "memcpy". */
+ int num_args; /* Number of args, 3 for memcpy. */
+ int num_ptr_args; /* Number of pointer args, 2 for memcpy. */
+ tree instr_fun; /* E.g., declaration of instrument_memcpy. */
+ tree nt_ops[4]; /* E.g., libopt__memcpy__{0,1,2,3}. */
+};
+typedef struct stringop_subst* stringop_subst_t;
+
+/* Substitution database. XXX: switch to hash table. */
+
+static struct stringop_subst stringop_decl[] =
+{
+ {"memcpy", 3, 2, NULL, {NULL, NULL, NULL, NULL}},
+ {"memset", 3, 1, NULL, {NULL, NULL, NULL, NULL}},
+ {"memmove", 3, 2, NULL, {NULL, NULL, NULL, NULL}},
+ {"memcmp", 3, 2, NULL, {NULL, NULL, NULL, NULL}},
+ {"bcmp", 3, 2, NULL, {NULL, NULL, NULL, NULL}},
+ {"strlen", 1, 1, NULL, {NULL, NULL, NULL, NULL}},
+ {"strcpy", 2, 2, NULL, {NULL, NULL, NULL, NULL}},
+ {"strncpy", 3, 2, NULL, {NULL, NULL, NULL, NULL}},
+ {"strcat", 2, 2, NULL, {NULL, NULL, NULL, NULL}},
+ {"strncat", 3, 2, NULL, {NULL, NULL, NULL, NULL}},
+ {"strdup", 1, 1, NULL, {NULL, NULL, NULL, NULL}},
+ {"strndup", 2, 1, NULL, {NULL, NULL, NULL, NULL}},
+ {"strcmp", 2, 2, NULL, {NULL, NULL, NULL, NULL}},
+ {"strncmp", 3, 2, NULL, {NULL, NULL, NULL, NULL}},
+ {"strcasecmp", 2, 2, NULL, {NULL, NULL, NULL, NULL}},
+ {"strncasecmp", 3, 2, NULL, {NULL, NULL, NULL, NULL}},
+ {NULL, 0, 0, NULL, {NULL, NULL, NULL, NULL}}
+};
+
+/* Get the corresponding element in STRINGOP_DECL for NAME. */
+
+static stringop_subst_t
+get_stringop_subst (const char* name)
+{
+ stringop_subst_t it;
+ for (it = stringop_decl; it->original_name; it++)
+ if (strcmp (name, it->original_name) == 0)
+ return it;
+ return 0;
+}
+
+/* Return the matching substitution if call site STMT is worth replacing. */
+
+static stringop_subst_t
+reusedist_is_interesting_call (gimple stmt)
+{
+ tree fndecl, name;
+
+ if (gimple_code (stmt) != GIMPLE_CALL)
+ return 0;
+
+ fndecl = gimple_call_fndecl (stmt);
+
+ if (fndecl == NULL_TREE)
+ return 0;
+
+ name = DECL_NAME (fndecl);
+
+ if (name == NULL_TREE)
+ return 0;
+
+ return get_stringop_subst (IDENTIFIER_POINTER (name));
+}
+
+/* Make up an instrumentation function name for string operation OP. */
+
+static void
+reusedist_instr_func_name (const char* op, char result[], int size)
+{
+ int written;
+
+ written = snprintf (result, size, "reusedist_instr_%s", op);
+
+ gcc_assert (written < size);
+}
+
+/* Create a declaration for an instr. function if not already done.
+ Use TEMPLATE_STMT to figure out argument types. */
+
+static tree
+reusedist_get_instr_decl (gimple template_stmt, stringop_subst_t subst)
+{
+ if (!subst->instr_fun)
+ {
+ tree args;
+ char name[64];
+
+ if (!ptr_void)
+ ptr_void = build_pointer_type (void_type_node);
+
+ reusedist_instr_func_name (subst->original_name, name, 64);
+
+ switch (subst->num_args)
+ {
+ case 1:
+ args = build_function_type_list (
+ void_type_node, ptr_void,
+ TREE_TYPE (gimple_call_arg (template_stmt, 0)),
+ NULL_TREE);
+ break;
+ case 2:
+ args = build_function_type_list (
+ void_type_node, ptr_void,
+ TREE_TYPE (gimple_call_arg (template_stmt, 0)),
+ TREE_TYPE (gimple_call_arg (template_stmt, 1)),
+ NULL_TREE);
+ break;
+ case 3:
+ args = build_function_type_list (
+ void_type_node, ptr_void,
+ TREE_TYPE (gimple_call_arg (template_stmt, 0)),
+ TREE_TYPE (gimple_call_arg (template_stmt, 1)),
+ TREE_TYPE (gimple_call_arg (template_stmt, 2)),
+ NULL_TREE);
+ break;
+ default:
+ gcc_assert (false);
+ }
+ subst->instr_fun = build_fn_decl (name, args);
+ }
+
+ return subst->instr_fun;
+}
+
+/* Return call to instrumentation function for string op call site STMT.
+ Given a call to memcpy (dst, src, len), it will return a call to
+ reusedist_instrument_memcpy (counters, dst, src, len). */
+
+static gimple
+reusedist_make_instr_call (gimple stmt, stringop_subst_t subst, tree counters)
+{
+ tree profiler_fn;
+
+ if (!subst)
+ return 0;
+
+ profiler_fn = reusedist_get_instr_decl (stmt, subst);
+
+ switch (subst->num_args)
+ {
+ case 1:
+ return gimple_build_call (profiler_fn, 1 + subst->num_args, counters,
+ gimple_call_arg (stmt, 0));
+ case 2:
+ return gimple_build_call (profiler_fn, 1 + subst->num_args, counters,
+ gimple_call_arg (stmt, 0),
+ gimple_call_arg (stmt, 1));
+ case 3:
+ return gimple_build_call (profiler_fn, 1 + subst->num_args, counters,
+ gimple_call_arg (stmt, 0),
+ gimple_call_arg (stmt, 1),
+ gimple_call_arg (stmt, 2));
+ default:
+ gcc_assert (false);
+ }
+}
+
+/* Reuse distance information for a single memory block at a single site.
+ For some operations, such as memcpy, there will be two such descriptors,
+ one of the source and one for the destination.
+ We're keeping the average reuse distance
+ (e.g., distance from a MEMCPY call until the memory written is first used).
+ We're also keeping the average operation size (e.g., memcpy size).
+ These averages are measured over all dynamic invocations of the same
+ static site. We're also storing the dynamic operation count.
+
+ We're also keeping a measure named dist_x_size, which is the sum of
+ products (distance * size) across all dynamic instances. This is meant
+ to account for some information loss through aggregation. For instance,
+ consider two scenarios.
+ A: 50% of operations have large reuse distance but are very short.
+ 50% of operations have short reuse distance but are very long.
+ B: 50% of operations have large reuse distance and are large.
+ 50% of operations have short reuse distance and are short.
+ Without the dist_x_size measure, these scenarios can't be told apart
+ from the other three measures. With the dist_x_size measure, scenario B
+ will look like a better candidate. */
+
+struct reusedist_t {
+ gcov_type mean_dist; /* Average reuse distance. */
+ gcov_type mean_size; /* Average size of memory referenced. */
+ gcov_type count; /* Operation count. */
+ gcov_type dist_x_size; /* Sum of (distance * size >> 12) across all ops. */
+};
+
+typedef struct reusedist_t reusedist_t;
+
+/* Number of gcov counters for one reuse distance measurement. */
+
+const int RD_NUM_COUNTERS = sizeof(reusedist_t) / sizeof(gcov_type);
+
+/* Initialize RD from gcov COUNTERS. */
+
+static void
+reusedist_from_counters (const gcov_type* counters,
+ reusedist_t* rd)
+{
+ memcpy (rd, counters, RD_NUM_COUNTERS * sizeof (gcov_type));
+}
+
+/* Instrument current function to collect reuse distance for string ops.
+ The heavy lifting is done by an external library. The interface
+ to this library is functions like this:
+
+ void reusedist_instr_memcpy(gcov_type *counters,
+ void *dst, void *src, size_t len);
+
+ This function will measure the reuse distance for the given operations
+ DST with offset LEN, and store values in COUNTERS for one or two pointer
+ arguments. E.g., for memcpy 2 * RD_NUM_COUNTERS counters will be set,
+ first RD_NUM_COUNTERS for DST and last RD_NUM_COUNTERS for SRC.
+ For strlen, only RD_NUM_COUNTERS counters will be allocated thus the
+ runtime is expected to set only RD_NUM_COUNTERS counters.
+ The counters will record:
+ - mean reuse distance
+ - mean operation size
+ - call count
+ - sum(reuse distance * operation size) across all calls
+ To avoid overflow, each product is first scaled down by a factor of 2^12.
+
+ All reuse distance measurements for dynamic executions of the same static
+ string operation will be aggregated into a single set of counters.
+ The reuse distance library uses the passed COUNTERS pointer as index
+ in its internal tables. */
+
+static void
+tree_gen_reusedist (void)
+{
+ basic_block bb;
+ gimple_stmt_iterator gsi;
+
+ if (DECL_STATIC_CONSTRUCTOR (current_function_decl))
+ return;
+
+ tree_init_edge_profiler ();
+
+ FOR_EACH_BB (bb)
+ for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+ {
+ gimple stmt = gsi_stmt (gsi);
+ stringop_subst_t subst = reusedist_is_interesting_call (stmt);
+
+ if (subst
+ && coverage_counter_alloc (
+ GCOV_COUNTER_REUSE_DIST,
+ subst->num_ptr_args * RD_NUM_COUNTERS))
+ {
+ location_t locus;
+ tree counters = tree_coverage_counter_addr (
+ GCOV_COUNTER_REUSE_DIST, 0);
+
+ counters = force_gimple_operand_gsi (
+ &gsi, counters, true, NULL_TREE, true, GSI_SAME_STMT);
+
+ gsi_insert_after (
+ &gsi,
+ reusedist_make_instr_call (stmt, subst, counters),
+ GSI_NEW_STMT);
+
+ locus = (stmt != NULL)
+ ? gimple_location (stmt)
+ : DECL_SOURCE_LOCATION (current_function_decl);
+ inform (locus,
+ "inserted reuse distance instrumentation for %qs, using "
+ "%d gcov counters", subst->original_name,
+ subst->num_ptr_args * RD_NUM_COUNTERS);
+ }
+ }
+}
+
+/* Make up a nontemporal substitution name, e.g., "libopt__memcpy__3". */
+
+static void
+nt_op_name (const char* name, int suffix, char result[], int size)
+{
+ int written;
+
+ written = snprintf (result, size, "libopt__%s__%d", name, suffix);
+
+ gcc_assert (written < size);
+}
+
+/* Get size threshold for reusedist substitution decisions. */
+
+static gcov_type
+reusedist_get_size_threshold (const char* name)
+{
+ if (!strcmp (name, "memcpy"))
+ return (gcov_type)PARAM_VALUE (PARAM_REUSEDIST_MEMCPY_SIZE_THRESH);
+
+ if (!strcmp (name, "memset"))
+ return (gcov_type)PARAM_VALUE (PARAM_REUSEDIST_MEMSET_SIZE_THRESH);
+
+ /* Use memcpy threshold as default for unspecified operations. */
+ return (gcov_type)PARAM_VALUE (PARAM_REUSEDIST_MEMCPY_SIZE_THRESH);
+}
+
+/* Get distance threshold for reusedist substitution decisions. */
+
+static gcov_type
+reusedist_get_distance_large_threshold (void)
+{
+ return (gcov_type)PARAM_VALUE (PARAM_REUSEDIST_MEAN_DIST_LARGE_THRESH);
+}
+
+/* Get distance threshold for reusedist substitution decisions. */
+
+static gcov_type
+reusedist_get_distance_small_threshold (void)
+{
+ return (gcov_type)PARAM_VALUE (PARAM_REUSEDIST_MEAN_DIST_SMALL_THRESH);
+}
+
+/* Get call count threshold for reusedist substitution decisions. */
+
+static gcov_type
+reusedist_get_count_threshold (void)
+{
+ return (gcov_type)PARAM_VALUE (PARAM_REUSEDIST_CALL_COUNT_THRESH);
+}
+
+/* Return whether switching to nontemporal string operation is worth it.
+ NAME is the function name, such as "memcpy".
+ COUNTERS is a pointer to gcov counters for this operation site.
+ Return 1 if worth it, -1 if not worth it and 0 if not sure. */
+
+static int
+reusedist_nt_is_worth_it (const char* name, const gcov_type* counters)
+{
+ reusedist_t rd;
+
+ reusedist_from_counters (counters, &rd);
+
+ /* XXX: Need to add check for dist_x_size. */
+
+ if (rd.mean_size < reusedist_get_size_threshold (name)
+ || rd.count < reusedist_get_count_threshold ())
+ /* If the size of the operation is small, don't substitute. */
+ return 0;
+
+ if (rd.mean_dist >= reusedist_get_distance_large_threshold ())
+ /* Enforce non-temporal. */
+ return 1;
+ else if (rd.mean_dist <= reusedist_get_distance_small_threshold ())
+ /* Enforce temporal. */
+ return -1;
+ else
+ /* Not conclusive. */
+ return 0;
+}
+
+/* Create a declaration for a nontemporal version if not already done.
+ INDEX is the index of the version in list [first, second, both]. */
+
+static tree
+reusedist_get_nt_decl (tree template_decl, stringop_subst_t subst, int index)
+{
+ if (!subst->nt_ops[index])
+ {
+ char nt_name[256];
+ nt_op_name (subst->original_name, index, nt_name, 256);
+ subst->nt_ops[index] = build_fn_decl (nt_name,
+ TREE_TYPE (template_decl));
+ }
+
+ return subst->nt_ops[index];
+}
+
+/* Issue notes with reuse distance values in COUNTERS for given ARG. */
+
+static void
+maybe_issue_profile_use_note (location_t locus, gcov_type* counters, int arg)
+{
+ reusedist_t rd;
+
+ reusedist_from_counters (counters, &rd);
+
+ if (rd.count)
+ inform (locus, "reuse distance counters for arg %d: %lld %lld %lld %lld",
+ arg, (long long int)rd.mean_dist, (long long int)rd.mean_size,
+ (long long int)rd.count, (long long int)rd.dist_x_size);
+}
+
+/* Substitute with nontemporal version when profitable. */
+
+static void
+reusedist_maybe_replace_with_nt_version (gimple stmt,
+ gcov_type* counters,
+ stringop_subst_t subst)
+{
+ int first, second, suffix;
+ tree subst_decl;
+ const char* name = subst->original_name;
+ location_t locus;
+
+ locus = (stmt != NULL)
+ ? gimple_location (stmt)
+ : DECL_SOURCE_LOCATION (current_function_decl);
+
+ gcc_assert (1 == subst->num_ptr_args || 2 == subst->num_ptr_args);
+
+ maybe_issue_profile_use_note (locus, counters, 1);
+ first = reusedist_nt_is_worth_it (name, counters);
+
+ if (2 == subst->num_ptr_args)
+ {
+ maybe_issue_profile_use_note (locus, counters + RD_NUM_COUNTERS, 2);
+ second = reusedist_nt_is_worth_it (name, counters + RD_NUM_COUNTERS);
+ }
+ else
+ second = 0;
+
+ if (first > 0)
+ /* Nontemporal in first arg. */
+ {
+ /* The operation on the first arg should be nontemporal. */
+ if (second > 0)
+ suffix = 3;
+ else
+ suffix = 1;
+ }
+ else if (first < 0)
+ /* Temporal in first arg. */
+ {
+ if (second > 0)
+ suffix = 2;
+ else if (second < 0)
+ suffix = 0;
+ else
+ suffix = -1;
+ }
+ else
+ /* Don't know about the first arg. */
+ {
+ if (second > 0)
+ suffix = 2;
+ else
+ suffix = -1;
+ }
+
+ if (suffix == -1)
+ return;
+
+ subst_decl = reusedist_get_nt_decl (gimple_call_fndecl (stmt), subst,
+ suffix);
+ gimple_call_set_fndecl (stmt, subst_decl);
+ inform (locus, "replaced %qs with non-temporal %qs",
+ subst->original_name,
+ IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (subst_decl)));
+}
+
+/* Replace string operations with equivalent nontemporal, when profitable. */
+
+static void
+optimize_reusedist (void)
+{
+ basic_block bb;
+ gimple_stmt_iterator gsi;
+ unsigned n_counters;
+ unsigned counter_index = 0;
+ gcov_type *counters = get_coverage_counts_no_warn (
+ DECL_STRUCT_FUNCTION (current_function_decl),
+ GCOV_COUNTER_REUSE_DIST, &n_counters);
+
+ if (!n_counters || DECL_STATIC_CONSTRUCTOR (current_function_decl))
+ return;
+
+ gcc_assert (!(n_counters % RD_NUM_COUNTERS));
+
+ FOR_EACH_BB (bb)
+ for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+ {
+ gimple stmt = gsi_stmt (gsi);
+ stringop_subst_t subst = reusedist_is_interesting_call (stmt);
+
+ if (subst)
+ {
+ if (counter_index < n_counters)
+ reusedist_maybe_replace_with_nt_version (
+ stmt, &counters[counter_index], subst);
+ counter_index += subst->num_ptr_args * RD_NUM_COUNTERS;
+ }
+ }
+
+ if (counter_index != n_counters)
+ {
+ warning (0, "coverage mismatch for reuse distance counters "
+ "in function %qs", IDENTIFIER_POINTER
+ (DECL_ASSEMBLER_NAME (current_function_decl)));
+ inform (input_location, "number of counters is %u instead of %u",
+ n_counters, counter_index);
+ }
+}
+
/* Return 1 if tree-based profiling is in effect, else 0.
If it is, set up hooks for tree-based profiling.
Gate for pass_tree_profile. */
@@ -657,7 +1385,8 @@ tree_gen_ior_profiler (histogram_value value, unsigned tag, unsigned base)
static bool
do_tree_profiling (void)
{
- if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities)
+ if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities
+ || flag_profile_reusedist || flag_optimize_locality)
{
tree_register_profile_hooks ();
gimple_register_value_prof_hooks ();
@@ -736,7 +1465,7 @@ direct_call_profiling (void)
build_pointer_type (gcov_type_node));
DECL_ARTIFICIAL (dc_gcov_type_ptr_var) = 1;
DECL_EXTERNAL (dc_gcov_type_ptr_var) = 1;
- if (targetm.have_tls)
+ if (targetm.have_tls && !is_kernel_build)
{
DECL_TLS_MODEL (dc_gcov_type_ptr_var) =
decl_default_tls_model (dc_gcov_type_ptr_var);
@@ -746,7 +1475,7 @@ direct_call_profiling (void)
ptr_void);
DECL_ARTIFICIAL (dc_void_ptr_var) = 1;
DECL_EXTERNAL (dc_void_ptr_var) = 1;
- if (targetm.have_tls)
+ if (targetm.have_tls && !is_kernel_build)
{
DECL_TLS_MODEL (dc_void_ptr_var) =
decl_default_tls_model (dc_void_ptr_var);
@@ -766,6 +1495,7 @@ direct_call_profiling (void)
/* Check if this is a direct call, and not a builtin call. */
if (gimple_code (stmt) != GIMPLE_CALL
|| gimple_call_fndecl (stmt) == NULL_TREE
+ || DECL_BUILT_IN (gimple_call_fndecl (stmt))
|| DECL_IS_BUILTIN (gimple_call_fndecl (stmt)))
continue;
@@ -832,11 +1562,14 @@ struct profile_hooks tree_profile_hooks =
tree_gen_interval_profiler, /* gen_interval_profiler */
tree_gen_pow2_profiler, /* gen_pow2_profiler */
tree_gen_one_value_profiler, /* gen_one_value_profiler */
+ tree_gen_one_float_value_profiler, /* gen_one_float_value_profiler */
tree_gen_const_delta_profiler, /* gen_const_delta_profiler */
tree_gen_ic_profiler, /* gen_ic_profiler */
tree_gen_dc_profiler, /* gen_dc_profiler */
tree_gen_average_profiler, /* gen_average_profiler */
- tree_gen_ior_profiler /* gen_ior_profiler */
+ tree_gen_ior_profiler, /* gen_ior_profiler */
+ tree_gen_reusedist,
+ optimize_reusedist
};
#include "gt-tree-profile.h"
diff --git a/gcc-4.4.3/gcc/tree-sample-profile.c b/gcc-4.4.3/gcc/tree-sample-profile.c
index b60405785..1c4b410d3 100644
--- a/gcc-4.4.3/gcc/tree-sample-profile.c
+++ b/gcc-4.4.3/gcc/tree-sample-profile.c
@@ -82,6 +82,8 @@ struct sample_freq_detail *sample_buf;
<stack[0].filename>:<stack[0].line_num>. */
static htab_t sp_inline_htab;
+static htab_t sp_indirect_htab;
+
static htab_t sp_funcname_htab;
/* Buffer to hold elements inserted into sp_inline_htab. */
struct sample_inline_freq *inline_sample_buf;
@@ -166,6 +168,36 @@ dump_cfg_profile (const char *pname)
fclose (prof_compare_file);
}
+/* extract the path info of NAME, and return the file name. */
+static const char *realname (const char *name) {
+ const char *c;
+ for (c = name; *c; c++) {
+ if (*c == '/') name = c+1;
+ }
+ return name;
+}
+
+static hashval_t
+sp_indirect_hash (const void *fb_info)
+{
+ const struct sample_indirect_call *si =
+ (const struct sample_indirect_call *) fb_info;
+ hashval_t h = 0x9e3779b9;
+
+ return iterative_hash (si->func_name, strlen (si->func_name), h);
+}
+
+static int
+sp_indirect_eq (const void *p, const void *q)
+{
+ const struct sample_indirect_call *a =
+ (const struct sample_indirect_call *) p;
+
+ const struct sample_indirect_call *b =
+ (const struct sample_indirect_call *) q;
+
+ return !strcmp(a->func_name, b->func_name);
+}
/* Functions used for hash table to store samples.
key = string base_filename:line_num. */
@@ -173,15 +205,14 @@ dump_cfg_profile (const char *pname)
/* Create a hash string with FILENAME, LINE_NUM, DISCRIMINATOR, and
FUNCNAME. */
static hashval_t
-create_hash_string (const char *filename, int line_num, int discriminator,
- const char *funcname)
+create_hash_string (const char *filename, int line_num, int discriminator)
{
/* An arbitrary initial value borrowed from hashtab.c. */
hashval_t h = 0x9e3779b9;
+ filename = realname (filename);
h = iterative_hash (filename, strlen (filename), h);
h = iterative_hash (&line_num, sizeof (line_num), h);
h = iterative_hash (&discriminator, sizeof(discriminator), h);
- h = iterative_hash (funcname, strlen (funcname), h);
return h;
}
@@ -195,8 +226,8 @@ sp_info_hash (const void *fb_info)
gcc_assert (sp->line_num >= 0);
- return create_hash_string (sp->filename, sp->line_num, sp->discriminator,
- sp->func_name);
+ return create_hash_string (realname (sp->filename), sp->line_num,
+ sp->discriminator);
}
@@ -213,8 +244,7 @@ sp_info_eq (const void *p, const void *q)
return (a->line_num == b->line_num)
&& (a->discriminator == b->discriminator)
- && (!strcmp (a->filename, b->filename))
- && (!strcmp (a->func_name, b->func_name));
+ && (!strcmp (realname (a->filename), realname (b->filename)));
}
/* Compute hash value for INLINE_INFO. */
@@ -230,19 +260,18 @@ sp_inline_info_hash (const void *inline_info)
while (i < depth)
{
- h = iterative_hash (i_info->inline_stack[i].loc.file,
- strlen (i_info->inline_stack[i].loc.file), h);
+ h = iterative_hash (realname (i_info->inline_stack[i].loc.file),
+ strlen (realname (i_info->inline_stack[i].loc.file)),
+ h);
h = iterative_hash (&(i_info->inline_stack[i].loc.line),
sizeof (i_info->inline_stack[i].loc.line), h);
- h = iterative_hash (&(i_info->inline_stack[i].discriminator),
- sizeof (i_info->inline_stack[i].discriminator), h);
i++;
}
- h = iterative_hash (i_info->filename, strlen (i_info->filename), h);
+ h = iterative_hash (realname (i_info->filename),
+ strlen (realname (i_info->filename)), h);
h = iterative_hash (&(i_info->line_num), sizeof (i_info->line_num), h);
h = iterative_hash (&(i_info->discriminator),
sizeof (i_info->discriminator), h);
- h = iterative_hash (i_info->func_name, strlen (i_info->func_name), h);
return h;
}
@@ -273,15 +302,13 @@ sp_inline_info_eq (const void *p, const void *q)
while (i < a->depth)
{
if ((a->inline_stack[i].loc.line != b->inline_stack[i].loc.line)
- || (a->inline_stack[i].discriminator !=
- b->inline_stack[i].discriminator)
- || strcmp (a->inline_stack[i].loc.file, b->inline_stack[i].loc.file))
+ || strcmp (realname (a->inline_stack[i].loc.file),
+ realname (b->inline_stack[i].loc.file)))
return 0;
i++;
}
- return !strcmp (a->filename, b->filename)
- && !strcmp (a->func_name, b->func_name);
+ return !strcmp (realname (a->filename), realname (b->filename));
}
/* Usage model: All elements in the hash table are deleted only at time of hash
@@ -417,6 +444,54 @@ sp_get_inline_stack (gimple stmt, struct expanded_inline_location *stack)
return i;
}
+/* Build a hashtab element to state that FUNC_NAME has an indirect
+ call edge of weight COUNT to the TARGET function. */
+
+static void
+sp_add_indirect_call (const char *func_name, const char *target,
+ gcov_type count)
+{
+ struct sample_indirect_call ic;
+ struct sample_indirect_call *entry;
+ struct sample_indirect_call **slot;
+ unsigned i;
+ ic.func_name = func_name;
+
+ slot = (struct sample_indirect_call **)
+ htab_find_slot (sp_indirect_htab, (void *) &ic, INSERT);
+
+ if (!*slot) {
+ *slot = (struct sample_indirect_call *)
+ xmalloc(sizeof(struct sample_indirect_call));
+ (*slot)->func_name = func_name;
+ (*slot)->num_values = 0;
+ }
+ entry = *slot;
+ if (entry->num_values == MAX_IND_FUNCS)
+ return;
+ for (i = 0; i < entry->num_values; i++) {
+ if (!strcmp(target, entry->targets[i])) {
+ entry->count[i] += count;
+ return;
+ }
+ }
+ entry->targets[entry->num_values] = 0;
+ entry->targets[entry->num_values++] = target;
+}
+
+/* Read in the FUNC_NAME, return the hashtab that contains the
+ indirect calls from this function. */
+
+struct sample_indirect_call *
+sp_get_indirect_calls (const char *func_name)
+{
+ struct sample_indirect_call ic;
+ ic.func_name = func_name;
+
+ return (struct sample_indirect_call *)
+ htab_find (sp_indirect_htab, (void *) &ic);
+}
+
/* Read file header from input file INFILE into PROG_UNIT. Return 0 if
successful, -1 otherwise. */
static int
@@ -747,10 +822,18 @@ read_inline_function (FILE *infile, struct profile *prog_unit,
for (k = 0; k < sample.num_value; k++) {
inline_sample_buf[j].values[k].type = hist_buf[k].type;
if (hist_buf[k].type == CALL_HIST)
- inline_sample_buf[j].values[k].value.func_name =
- &(prog_unit->str_table[hist_buf[k].value]);
+ {
+ inline_sample_buf[j].values[k].value.func_name =
+ &(prog_unit->str_table[hist_buf[k].value]);
+ sp_add_indirect_call (
+ &(prog_unit->str_table[func_hdr->func_name_index]),
+ &(prog_unit->str_table[hist_buf[k].value]),
+ hist_buf[k].count);
+ }
else
- inline_sample_buf[j].values[k].value.value = hist_buf[k].value;
+ {
+ inline_sample_buf[j].values[k].value.value = hist_buf[k].value;
+ }
inline_sample_buf[j].values[k].count = hist_buf[k].count;
}
}
@@ -893,7 +976,7 @@ sp_read_modules (FILE *infile, struct profile *prog_unit)
{
char *file_name = &(prog_unit->str_table[hdr[i].module_name_index]);
/* Traverse the modules to find the primarial module. */
- if (!strcmp (file_name, curr_file_name))
+ if (!strcmp (realname (file_name), realname (curr_file_name)))
{
unsigned int j;
int curr_module = 1, idx = 0;
@@ -996,7 +1079,8 @@ sp_reader (const char *in_filename, struct profile *prog_unit)
sample_buf[0].func_name =
&(prog_unit->str_table[func_hdr.func_name_index]);
- sample_buf[0].filename = "";
+ sample_buf[0].filename =
+ &(prog_unit->str_table[func_hdr.func_name_index]);
sample_buf[0].line_num = 0;
sample_buf[0].discriminator = 0;
sample_buf[0].freq = func_hdr.entry_count;
@@ -1056,10 +1140,18 @@ sp_reader (const char *in_filename, struct profile *prog_unit)
for (k = 0; k < sample.num_value; k++) {
sample_buf[j].values[k].type = hist_buf[k].type;
if (hist_buf[k].type == CALL_HIST)
- sample_buf[j].values[k].value.func_name =
- &(prog_unit->str_table[hist_buf[k].value]);
+ {
+ sample_buf[j].values[k].value.func_name =
+ &(prog_unit->str_table[hist_buf[k].value]);
+ sp_add_indirect_call (
+ &(prog_unit->str_table[func_hdr.func_name_index]),
+ &(prog_unit->str_table[hist_buf[k].value]),
+ hist_buf[k].count);
+ }
else
- sample_buf[j].values[k].value.value = hist_buf[k].value;
+ {
+ sample_buf[j].values[k].value.value = hist_buf[k].value;
+ }
sample_buf[j].values[k].count = hist_buf[k].count;
}
}
@@ -1106,18 +1198,18 @@ compare (const void *a, const void *b) {
const struct sample_hist *y = (const struct sample_hist *) b;
if (x->type != y->type)
{
- return x->type - y->type;
+ return y->type - x->type;
}
else if (x->count != y->count)
{
- return x->count - y->count;
+ return y->count - x->count;
}
else
{
if (x->type == CALL_HIST)
return strcmp (x->value.func_name, y->value.func_name);
else
- return x->value.value - y->value.value;
+ return y->value.value - x->value.value;
}
}
@@ -1140,20 +1232,20 @@ sp_annotate_bb (basic_block bb)
if (flag_sample_profile_use_entry && bb == ENTRY_BLOCK_PTR)
{
struct sample_freq_detail ir_loc;
- struct sample_freq_detail *htab_entry;
- hashval_t hash_val;
- ir_loc.filename = "";
+ struct sample_freq_detail **slot;
+ struct sample_freq_detail *htab_entry = NULL;
+ ir_loc.filename
+ = sp_get_real_funcname (current_function_assembler_name ());
ir_loc.func_name
= sp_get_real_funcname (current_function_assembler_name ());
ir_loc.line_num = 0;
ir_loc.discriminator = 0;
- hash_val = create_hash_string (ir_loc.filename, ir_loc.line_num,
- ir_loc.discriminator,
- ir_loc.func_name);
-
- htab_entry = (struct sample_freq_detail *)
- htab_find_with_hash (sp_htab, (void *) &ir_loc, hash_val);
+ slot = (struct sample_freq_detail **)
+ htab_find_slot (sp_htab, &ir_loc, INSERT);
+ if (*slot) {
+ htab_entry = *slot;
+ }
if (htab_entry) {
bb->count = htab_entry->freq;
@@ -1244,8 +1336,8 @@ sp_annotate_bb (basic_block bb)
ir_loc.line_num = lineno;
ir_loc.discriminator = discriminator;
- hash_val = create_hash_string (ir_loc.filename, lineno, discriminator,
- ir_loc.func_name);
+ hash_val = create_hash_string (ir_loc.filename, lineno,
+ discriminator);
htab_entry = (struct sample_freq_detail *)
htab_find_with_hash (sp_htab, (void *) &ir_loc, hash_val);
@@ -1426,6 +1518,7 @@ sp_annotate_cfg (void)
basic_block bb;
int num_bb_annotated = 0;
gcov_type func_max_count = 0;
+ cgraph_need_artificial_indirect_call_edges = 0;
if (dump_file)
{
@@ -1520,6 +1613,12 @@ init_sample_profile (void)
0,
xcalloc,
free);
+ sp_indirect_htab = htab_create_alloc ((size_t) SP_FUNCNAME_HTAB_INIT_SIZE,
+ sp_indirect_hash,
+ sp_indirect_eq,
+ 0,
+ xcalloc,
+ free);
sp_num_samples = sp_reader (sample_data_name, &prog_unit);
sp_profile_info =
@@ -1551,6 +1650,8 @@ end_sample_profile (void)
if (sp_inline_htab)
htab_delete (sp_inline_htab);
sp_inline_htab = NULL;
+ if (sp_indirect_htab)
+ htab_delete (sp_indirect_htab);
free (inline_sample_buf);
if (sp_profile_info)
free (sp_profile_info);
@@ -1561,6 +1662,9 @@ static unsigned int
execute_sample_profile (void)
{
/* Annotate CFG with sample profile. */
+ flow_call_edges_add (NULL);
+ compact_blocks ();
+ remove_fake_edges ();
sp_annotate_cfg ();
cfun->after_tree_profile = 1;
return 0;
diff --git a/gcc-4.4.3/gcc/tree-sample-profile.h b/gcc-4.4.3/gcc/tree-sample-profile.h
index 98b2ecb3e..2e68879c0 100644
--- a/gcc-4.4.3/gcc/tree-sample-profile.h
+++ b/gcc-4.4.3/gcc/tree-sample-profile.h
@@ -242,6 +242,15 @@ struct sample_inline_freq
float freq;
};
+#define MAX_IND_FUNCS 1024
+struct sample_indirect_call
+{
+ const char *func_name;
+ unsigned num_values;
+ const char *targets[MAX_IND_FUNCS];
+ unsigned long long count[MAX_IND_FUNCS];
+};
+
/* Store profile per feedback data file. */
struct profile
{
@@ -260,4 +269,5 @@ extern void sp_add_funcname_mapping (const char *, const char *);
extern const char *sp_get_real_funcname (const char *name);
extern void sp_set_sample_profile (gcov_type max_count);
extern void gimple_sample_vpt (gimple, struct sample_hist *, int);
+extern struct sample_indirect_call *sp_get_indirect_calls (const char *);
#endif
diff --git a/gcc-4.4.3/gcc/tree-ssa-alias.c b/gcc-4.4.3/gcc/tree-ssa-alias.c
index 6d79bff8f..f1ae5c74c 100644
--- a/gcc-4.4.3/gcc/tree-ssa-alias.c
+++ b/gcc-4.4.3/gcc/tree-ssa-alias.c
@@ -191,6 +191,7 @@ struct alias_info
/* Pointers that have been used in an indirect load/store operation. */
struct pointer_set_t *dereferenced_ptrs;
+
};
@@ -2119,7 +2120,6 @@ delete_alias_info (struct alias_info *ai)
delete_points_to_sets ();
}
-
/* Used for hashing to identify pointer infos with identical
pt_vars bitmaps. */
@@ -2456,6 +2456,26 @@ create_alias_map_for (tree var, struct alias_info *ai)
ai->addressable_vars[ai->num_addressable_vars++] = alias_map;
}
+/* For indirect reference REF with integer address, create
+ a .GLOBAL_VAR for it if needed. */
+
+static void
+create_global_var_for_literal_addr (tree ref)
+{
+ if (gimple_global_var (cfun) != NULL)
+ return;
+
+ if (handled_component_p (ref))
+ ref = get_base_address (ref);
+
+ if (!ref)
+ return;
+
+ if (INDIRECT_REF_P (ref)
+ && TREE_CODE (TREE_OPERAND (ref, 0)) == INTEGER_CST
+ && !integer_zerop (TREE_OPERAND (ref, 0)))
+ create_global_var ();
+}
/* Update related alias information kept in AI. This is used when
building name tags, alias sets and deciding grouping heuristics.
@@ -2504,7 +2524,17 @@ update_alias_info_1 (gimple stmt, struct alias_info *ai)
&& TREE_CODE (var) != RESULT_DECL
&& is_gimple_reg_type (TREE_TYPE (var)))
bitmap_set_bit (gimple_addressable_vars (cfun), DECL_UID (var));
+
}
+
+ if (lhs)
+ create_global_var_for_literal_addr (lhs);
+ if (gimple_code (stmt) == GIMPLE_ASSIGN)
+ {
+ tree rhs = gimple_assign_rhs1 (stmt);
+
+ create_global_var_for_literal_addr (rhs);
+ }
}
/* Process each operand use. For pointers, determine whether they
diff --git a/gcc-4.4.3/gcc/tree-ssa-dce.c b/gcc-4.4.3/gcc/tree-ssa-dce.c
index 39126cd7d..e199495f8 100644
--- a/gcc-4.4.3/gcc/tree-ssa-dce.c
+++ b/gcc-4.4.3/gcc/tree-ssa-dce.c
@@ -716,6 +716,37 @@ remove_dead_phis (basic_block bb)
return something_changed;
}
+/* Fix up references to VOP SSANAMEs defined by STMT
+ which is to be removed. */
+
+static void
+fixup_vdef_refs (gimple stmt)
+{
+ struct voptype_d *vdefs;
+ use_operand_p use_op;
+ imm_use_iterator iter;
+
+ vdefs = gimple_vdef_ops (stmt);
+ while (vdefs)
+ {
+ int n, j;
+ tree prev_nm;
+ VEC(use_operand_p, heap) *fixup_opnds = NULL;
+
+ n = VDEF_NUM (vdefs);
+ gcc_assert (n == 1);
+ prev_nm = VDEF_OP (vdefs, 0);
+ FOR_EACH_IMM_USE_FAST (use_op, iter, VDEF_RESULT (vdefs))
+ VEC_safe_push (use_operand_p, heap, fixup_opnds, use_op);
+
+ for (j = 0;
+ VEC_iterate (use_operand_p, fixup_opnds, j, use_op);
+ ++j)
+ set_ssa_use_from_ptr (use_op, prev_nm);
+
+ vdefs = vdefs->next;
+ }
+}
/* Remove dead statement pointed to by iterator I. Receives the basic block BB
containing I so that we don't have to look it up. */
@@ -810,9 +841,6 @@ remove_dead_stmt (gimple_stmt_iterator *i, basic_block bb)
{
gimple_stmt_iterator gsi;
gimple next_stmt;
- struct voptype_d *vdefs;
- use_operand_p use_op;
- imm_use_iterator iter;
gsi = gsi_for_stmt (stmt);
gsi_next (&gsi);
@@ -829,26 +857,7 @@ remove_dead_stmt (gimple_stmt_iterator *i, basic_block bb)
}
/* Now fixup SSA. */
- vdefs = gimple_vdef_ops (stmt);
- while (vdefs)
- {
- int n, j;
- tree prev_nm;
- VEC(use_operand_p, heap) *fixup_opnds = NULL;
-
- n = VDEF_NUM (vdefs);
- gcc_assert (n == 1);
- prev_nm = VDEF_OP (vdefs, 0);
- FOR_EACH_IMM_USE_FAST (use_op, iter, VDEF_RESULT (vdefs))
- VEC_safe_push (use_operand_p, heap, fixup_opnds, use_op);
-
- for (j = 0;
- VEC_iterate (use_operand_p, fixup_opnds, j, use_op);
- ++j)
- set_ssa_use_from_ptr (use_op, prev_nm);
-
- vdefs = vdefs->next;
- }
+ fixup_vdef_refs (stmt);
}
gsi_remove (i, true);
release_defs (stmt);
diff --git a/gcc-4.4.3/gcc/tree-ssa-loop-im.c b/gcc-4.4.3/gcc/tree-ssa-loop-im.c
index 9183d3375..d6e0218ab 100644
--- a/gcc-4.4.3/gcc/tree-ssa-loop-im.c
+++ b/gcc-4.4.3/gcc/tree-ssa-loop-im.c
@@ -1794,6 +1794,10 @@ gen_lsm_tmp_name (tree ref)
lsm_tmp_name_add ("S");
break;
+ case INTEGER_CST:
+ lsm_tmp_name_add ("C");
+ break;
+
case RESULT_DECL:
lsm_tmp_name_add ("R");
break;
diff --git a/gcc-4.4.3/gcc/tree-ssa-loop-ivopts.c b/gcc-4.4.3/gcc/tree-ssa-loop-ivopts.c
index 144dace8f..53ecdcf0f 100644
--- a/gcc-4.4.3/gcc/tree-ssa-loop-ivopts.c
+++ b/gcc-4.4.3/gcc/tree-ssa-loop-ivopts.c
@@ -93,6 +93,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-affine.h"
#include "target.h"
#include "tree-inline.h"
+#include "dbgcnt.h"
/* The infinite cost. */
#define INFTY 10000000
@@ -150,7 +151,7 @@ enum use_type
/* Cost of a computation. */
typedef struct
{
- unsigned cost; /* The runtime cost. */
+ int cost; /* The runtime cost. */
unsigned complexity; /* The estimate of the complexity of the code for
the computation (in no concrete units --
complexity field should be larger for more
@@ -206,6 +207,8 @@ enum iv_position
{
IP_NORMAL, /* At the end, just before the exit condition. */
IP_END, /* At the end of the latch block. */
+ IP_BEFORE_USE, /* Immediately before a specific use. */
+ IP_AFTER_USE, /* Immediately after a specific use. */
IP_ORIGINAL /* The original biv. */
};
@@ -225,6 +228,9 @@ struct iv_cand
to replace the final value of an iv by direct
computation of the value. */
unsigned cost; /* Cost of the candidate. */
+ unsigned cost_step; /* Cost of the candidate's increment operation. */
+ struct iv_use *ainc_use; /* For IP_{BEFORE,AFTER}_USE candidates, the place
+ where it is incremented. */
bitmap depends_on; /* The list of invariants that are used in step of the
biv. */
};
@@ -570,6 +576,14 @@ dump_cand (FILE *file, struct iv_cand *cand)
fprintf (file, " incremented before exit test\n");
break;
+ case IP_BEFORE_USE:
+ fprintf (file, " incremented before use %d\n", cand->ainc_use->id);
+ break;
+
+ case IP_AFTER_USE:
+ fprintf (file, " incremented after use %d\n", cand->ainc_use->id);
+ break;
+
case IP_END:
fprintf (file, " incremented at end\n");
break;
@@ -622,14 +636,14 @@ stmt_after_ip_normal_pos (struct loop *loop, gimple stmt)
}
/* Returns true if STMT if after the place where the original induction
- variable CAND is incremented. */
+ variable CAND is incremented. If TRUE_IF_EQUAL is set, we return true
+ if the positions are identical. */
static bool
-stmt_after_ip_original_pos (struct iv_cand *cand, gimple stmt)
+stmt_after_inc_pos (struct iv_cand *cand, gimple stmt, bool true_if_equal)
{
basic_block cand_bb = gimple_bb (cand->incremented_at);
basic_block stmt_bb = gimple_bb (stmt);
- gimple_stmt_iterator bsi;
if (!dominated_by_p (CDI_DOMINATORS, stmt_bb, cand_bb))
return false;
@@ -637,15 +651,10 @@ stmt_after_ip_original_pos (struct iv_cand *cand, gimple stmt)
if (stmt_bb != cand_bb)
return true;
- /* Scan the block from the end, since the original ivs are usually
- incremented at the end of the loop body. */
- for (bsi = gsi_last_bb (stmt_bb); ; gsi_prev (&bsi))
- {
- if (gsi_stmt (bsi) == cand->incremented_at)
- return false;
- if (gsi_stmt (bsi) == stmt)
- return true;
- }
+ if (true_if_equal
+ && gimple_uid (stmt) == gimple_uid (cand->incremented_at))
+ return true;
+ return gimple_uid (stmt) > gimple_uid (cand->incremented_at);
}
/* Returns true if STMT if after the place where the induction variable
@@ -663,7 +672,11 @@ stmt_after_increment (struct loop *loop, struct iv_cand *cand, gimple stmt)
return stmt_after_ip_normal_pos (loop, stmt);
case IP_ORIGINAL:
- return stmt_after_ip_original_pos (cand, stmt);
+ case IP_AFTER_USE:
+ return stmt_after_inc_pos (cand, stmt, false);
+
+ case IP_BEFORE_USE:
+ return stmt_after_inc_pos (cand, stmt, true);
default:
gcc_unreachable ();
@@ -754,9 +767,10 @@ contains_abnormal_ssa_name_p (tree expr)
EXIT of DATA->current_loop, or NULL if something goes wrong. */
static tree
-niter_for_exit (struct ivopts_data *data, edge exit)
+niter_for_exit (struct ivopts_data *data, edge exit,
+ struct tree_niter_desc **desc_p)
{
- struct tree_niter_desc desc;
+ struct tree_niter_desc* desc = NULL;
tree niter;
void **slot;
@@ -775,18 +789,24 @@ niter_for_exit (struct ivopts_data *data, edge exit)
being zero). Also, we cannot safely work with ssa names that
appear in phi nodes on abnormal edges, so that we do not create
overlapping life ranges for them (PR 27283). */
+ desc = XNEW (struct tree_niter_desc);
if (number_of_iterations_exit (data->current_loop,
- exit, &desc, true)
- && integer_zerop (desc.may_be_zero)
- && !contains_abnormal_ssa_name_p (desc.niter))
- niter = desc.niter;
+ exit, desc, true)
+ && integer_zerop (desc->may_be_zero)
+ && !contains_abnormal_ssa_name_p (desc->niter))
+ niter = desc->niter;
else
niter = NULL_TREE;
- *pointer_map_insert (data->niters, exit) = niter;
+ desc->niter = niter;
+ slot = pointer_map_insert (data->niters, exit);
+ *slot = desc;
}
else
- niter = (tree) *slot;
+ niter = ((struct tree_niter_desc *) *slot)->niter;
+
+ if (desc_p)
+ *desc_p = (struct tree_niter_desc *) *slot;
return niter;
}
@@ -803,7 +823,7 @@ niter_for_single_dom_exit (struct ivopts_data *data)
if (!exit)
return NULL;
- return niter_for_exit (data, exit);
+ return niter_for_exit (data, exit, NULL);
}
/* Initializes data structures used by the iv optimization pass, stored
@@ -2185,7 +2205,9 @@ add_candidate_1 (struct ivopts_data *data,
if (cand->pos != pos)
continue;
- if (cand->incremented_at != incremented_at)
+ if (cand->incremented_at != incremented_at
+ || ((pos == IP_AFTER_USE || pos == IP_BEFORE_USE)
+ && cand->ainc_use != use))
continue;
if (!cand->iv)
@@ -2233,6 +2255,11 @@ add_candidate_1 (struct ivopts_data *data,
walk_tree (&step, find_depends, &cand->depends_on, NULL);
}
+ if (pos == IP_AFTER_USE || pos == IP_BEFORE_USE)
+ cand->ainc_use = use;
+ else
+ cand->ainc_use = NULL;
+
if (dump_file && (dump_flags & TDF_DETAILS))
dump_cand (dump_file, cand);
}
@@ -2276,6 +2303,56 @@ allow_ip_end_pos_p (struct loop *loop)
return false;
}
+/* If possible, adds autoincrement candidates BASE + STEP * i based on use USE.
+ Important field is set to IMPORTANT. */
+
+static void
+add_autoinc_candidates (struct ivopts_data *data, tree base, tree step,
+ bool important, struct iv_use *use)
+{
+ basic_block use_bb = gimple_bb (use->stmt);
+ enum machine_mode mem_mode;
+ unsigned HOST_WIDE_INT cstepi;
+
+ /* If we insert the increment in any position other than the standard
+ ones, we must ensure that it is incremented once per iteration.
+ It must not be in an inner nested loop, or one side of an if
+ statement. */
+ if (use_bb->loop_father != data->current_loop
+ || !dominated_by_p (CDI_DOMINATORS, data->current_loop->latch, use_bb)
+ || stmt_could_throw_p (use->stmt)
+ || !cst_and_fits_in_hwi (step))
+ return;
+
+ cstepi = int_cst_value (step);
+
+ mem_mode = TYPE_MODE (TREE_TYPE (*use->op_p));
+ if ((HAVE_PRE_INCREMENT && GET_MODE_SIZE (mem_mode) == cstepi)
+ || (HAVE_PRE_DECREMENT && GET_MODE_SIZE (mem_mode) == -cstepi))
+ {
+ enum tree_code code = MINUS_EXPR;
+ tree new_base;
+ tree new_step = step;
+
+ if (POINTER_TYPE_P (TREE_TYPE (base)))
+ {
+ new_step = fold_build1 (NEGATE_EXPR, TREE_TYPE (step), step);
+ code = POINTER_PLUS_EXPR;
+ }
+ else
+ new_step = fold_convert (TREE_TYPE (base), new_step);
+ new_base = fold_build2 (code, TREE_TYPE (base), base, new_step);
+ add_candidate_1 (data, new_base, step, important, IP_BEFORE_USE, use,
+ use->stmt);
+ }
+ if ((HAVE_POST_INCREMENT && GET_MODE_SIZE (mem_mode) == cstepi)
+ || (HAVE_POST_DECREMENT && GET_MODE_SIZE (mem_mode) == -cstepi))
+ {
+ add_candidate_1 (data, base, step, important, IP_AFTER_USE, use,
+ use->stmt);
+ }
+}
+
/* Adds a candidate BASE + STEP * i. Important field is set to IMPORTANT and
position to POS. If USE is not NULL, the candidate is set as related to
it. The candidate computation is scheduled on all available positions. */
@@ -2289,6 +2366,9 @@ add_candidate (struct ivopts_data *data,
if (ip_end_pos (data->current_loop)
&& allow_ip_end_pos_p (data->current_loop))
add_candidate_1 (data, base, step, important, IP_END, use, NULL);
+
+ if (use != NULL && use->type == USE_ADDRESS)
+ add_autoinc_candidates (data, base, step, important, use);
}
/* Add a standard "0 + 1 * iteration" iv candidate for a
@@ -2462,24 +2542,6 @@ record_important_candidates (struct ivopts_data *data)
}
}
-/* Finds the candidates for the induction variables. */
-
-static void
-find_iv_candidates (struct ivopts_data *data)
-{
- /* Add commonly used ivs. */
- add_standard_iv_candidates (data);
-
- /* Add old induction variables. */
- add_old_ivs_candidates (data);
-
- /* Add induction variables derived from uses. */
- add_derived_ivs_candidates (data);
-
- /* Record the important candidates. */
- record_important_candidates (data);
-}
-
/* Allocates the data structure mapping the (use, candidate) pairs to costs.
If consider_all_candidates is true, we use a two-dimensional array, otherwise
we allocate a simple list to every use. */
@@ -2571,7 +2633,7 @@ infinite_cost_p (comp_cost cost)
/* Sets cost of (USE, CANDIDATE) pair to COST and record that it depends
on invariants DEPENDS_ON and that the value used in expressing it
- is VALUE.*/
+ is VALUE. */
static void
set_use_iv_cost (struct ivopts_data *data,
@@ -3095,21 +3157,30 @@ multiplier_allowed_in_address_p (HOST_WIDE_INT ratio, enum machine_mode mode)
variable is omitted. Compute the cost for a memory reference that accesses
a memory location of mode MEM_MODE.
+ MAY_AUTOINC is set to true if the autoincrement (increasing index by
+ size of MEM_MODE / RATIO) is available. To make this determination, we
+ look at the size of the increment to be made, which is given in CSTEP.
+ CSTEP may be zero if the step is unknown.
+ STMT_AFTER_INC is true iff the statement we're looking at is after the
+ increment of the original biv.
+
TODO -- there must be some better way. This all is quite crude. */
static comp_cost
get_address_cost (bool symbol_present, bool var_present,
unsigned HOST_WIDE_INT offset, HOST_WIDE_INT ratio,
- enum machine_mode mem_mode,
- bool speed)
+ HOST_WIDE_INT cstep, enum machine_mode mem_mode, bool speed,
+ bool stmt_after_inc, bool *may_autoinc)
{
static bool initialized[MAX_MACHINE_MODE];
static HOST_WIDE_INT rat[MAX_MACHINE_MODE], off[MAX_MACHINE_MODE];
static HOST_WIDE_INT min_offset[MAX_MACHINE_MODE], max_offset[MAX_MACHINE_MODE];
static unsigned costs[MAX_MACHINE_MODE][2][2][2][2];
+ static bool has_preinc[MAX_MACHINE_MODE], has_postinc[MAX_MACHINE_MODE];
+ static bool has_predec[MAX_MACHINE_MODE], has_postdec[MAX_MACHINE_MODE];
unsigned cost, acost, complexity;
- bool offset_p, ratio_p;
- HOST_WIDE_INT s_offset;
+ bool offset_p, ratio_p, autoinc;
+ HOST_WIDE_INT s_offset, autoinc_offset, msize;
unsigned HOST_WIDE_INT mask;
unsigned bits;
@@ -3168,6 +3239,26 @@ get_address_cost (bool symbol_present, bool var_present,
reg0 = gen_raw_REG (Pmode, LAST_VIRTUAL_REGISTER + 1);
reg1 = gen_raw_REG (Pmode, LAST_VIRTUAL_REGISTER + 2);
+ if (HAVE_PRE_DECREMENT)
+ {
+ addr = gen_rtx_PRE_DEC (Pmode, reg0);
+ has_predec[mem_mode] = memory_address_p (mem_mode, addr);
+ }
+ if (HAVE_POST_DECREMENT)
+ {
+ addr = gen_rtx_POST_DEC (Pmode, reg0);
+ has_postdec[mem_mode] = memory_address_p (mem_mode, addr);
+ }
+ if (HAVE_PRE_INCREMENT)
+ {
+ addr = gen_rtx_PRE_INC (Pmode, reg0);
+ has_preinc[mem_mode] = memory_address_p (mem_mode, addr);
+ }
+ if (HAVE_POST_INCREMENT)
+ {
+ addr = gen_rtx_POST_INC (Pmode, reg0);
+ has_postinc[mem_mode] = memory_address_p (mem_mode, addr);
+ }
for (i = 0; i < 16; i++)
{
sym_p = i & 1;
@@ -3206,7 +3297,7 @@ get_address_cost (bool symbol_present, bool var_present,
if (base)
addr = gen_rtx_fmt_ee (PLUS, Pmode, addr, base);
-
+
start_sequence ();
/* To avoid splitting addressing modes, pretend that no cse will
follow. */
@@ -3251,7 +3342,7 @@ get_address_cost (bool symbol_present, bool var_present,
if (acost < costs[mem_mode][1][var_p][off_p][rat_p])
costs[mem_mode][1][var_p][off_p][rat_p] = acost;
}
-
+
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "Address costs:\n");
@@ -3276,6 +3367,9 @@ get_address_cost (bool symbol_present, bool var_present,
acost = costs[mem_mode][sym_p][var_p][off_p][rat_p];
fprintf (dump_file, "index costs %d\n", acost);
}
+ if (has_predec[mem_mode] || has_postdec[mem_mode]
+ || has_preinc[mem_mode] || has_postinc[mem_mode])
+ fprintf (dump_file, " May include autoinc/dec\n");
fprintf (dump_file, "\n");
}
}
@@ -3287,6 +3381,23 @@ get_address_cost (bool symbol_present, bool var_present,
offset |= ~mask;
s_offset = offset;
+ autoinc = false;
+ msize = GET_MODE_SIZE (mem_mode);
+ autoinc_offset = offset;
+ if (stmt_after_inc)
+ autoinc_offset += ratio * cstep;
+ if (symbol_present || var_present || ratio != 1)
+ autoinc = false;
+ else if ((has_postinc[mem_mode] && autoinc_offset == 0
+ && msize == cstep)
+ || (has_postdec[mem_mode] && autoinc_offset == 0
+ && msize == -cstep)
+ || (has_preinc[mem_mode] && autoinc_offset == msize
+ && msize == cstep)
+ || (has_predec[mem_mode] && autoinc_offset == -msize
+ && msize == -cstep))
+ autoinc = true;
+
cost = 0;
offset_p = (s_offset != 0
&& min_offset[mem_mode] <= s_offset
@@ -3300,6 +3411,8 @@ get_address_cost (bool symbol_present, bool var_present,
if (s_offset && !offset_p && !symbol_present)
cost += add_cost (Pmode, speed);
+ if (may_autoinc)
+ *may_autoinc = autoinc;
acost = costs[mem_mode][symbol_present][var_present][offset_p][ratio_p];
complexity = (symbol_present != 0) + (var_present != 0) + offset_p + ratio_p;
return new_cost (cost + acost, complexity);
@@ -3438,7 +3551,7 @@ force_expr_to_var_cost (tree expr, bool speed)
computations often are either loop invariant or at least can
be shared between several iv uses, so letting this grow without
limits would not give reasonable results. */
- if (cost.cost > target_spill_cost [speed])
+ if (cost.cost > (int) target_spill_cost [speed])
cost.cost = target_spill_cost [speed];
return cost;
@@ -3687,19 +3800,22 @@ create_loop_invariant_temp (tree ubase, tree cbase, HOST_WIDE_INT ratio)
from induction variable CAND. If ADDRESS_P is true, we just need
to create an address from it, otherwise we want to get it into
register. A set of invariants we depend on is stored in
- DEPENDS_ON. AT is the statement at that the value is computed. */
+ DEPENDS_ON. AT is the statement at that the value is computed.
+ If CAN_AUTOINC is nonnull, use it to record whether autoinc
+ addressing is likely. */
static comp_cost
get_computation_cost_at (struct ivopts_data *data,
struct iv_use *use, struct iv_cand *cand,
- bool address_p, bitmap *depends_on, gimple at)
+ bool address_p, bitmap *depends_on, gimple at,
+ bool *can_autoinc)
{
tree ubase = use->iv->base, ustep = use->iv->step;
tree cbase, cstep;
tree utype = TREE_TYPE (ubase), ctype;
unsigned HOST_WIDE_INT cstepi, offset = 0;
HOST_WIDE_INT ratio, aratio;
- bool var_present, symbol_present;
+ bool var_present, symbol_present, stmt_is_after_inc;
comp_cost cost;
unsigned n_sums;
double_int rat;
@@ -3805,7 +3921,8 @@ get_computation_cost_at (struct ivopts_data *data,
/* If we are after the increment, the value of the candidate is higher by
one iteration. */
- if (stmt_after_increment (data->current_loop, cand, at))
+ stmt_is_after_inc = stmt_after_increment (data->current_loop, cand, at);
+ if (stmt_is_after_inc)
offset -= ratio * cstepi;
/* Now the computation is in shape symbol + var1 + const + ratio * var2.
@@ -3813,8 +3930,10 @@ get_computation_cost_at (struct ivopts_data *data,
find the cost of addressing this. */
if (address_p)
return add_costs (cost, get_address_cost (symbol_present, var_present,
- offset, ratio,
- TYPE_MODE (TREE_TYPE (*use->op_p)), speed));
+ offset, ratio, cstepi,
+ TYPE_MODE (TREE_TYPE (*use->op_p)),
+ speed, stmt_is_after_inc,
+ can_autoinc));
/* Otherwise estimate the costs for computing the expression. */
aratio = ratio > 0 ? ratio : -ratio;
@@ -3844,6 +3963,9 @@ get_computation_cost_at (struct ivopts_data *data,
return cost;
fallback:
+ if (can_autoinc)
+ *can_autoinc = false;
+
{
/* Just get the expression, expand it and measure the cost. */
tree comp = get_computation_at (data->current_loop, use, cand, at);
@@ -3862,15 +3984,17 @@ fallback:
from induction variable CAND. If ADDRESS_P is true, we just need
to create an address from it, otherwise we want to get it into
register. A set of invariants we depend on is stored in
- DEPENDS_ON. */
+ DEPENDS_ON. If CAN_AUTOINC is nonnull, use it to record whether
+ autoinc addressing is likely. */
static comp_cost
get_computation_cost (struct ivopts_data *data,
struct iv_use *use, struct iv_cand *cand,
- bool address_p, bitmap *depends_on)
+ bool address_p, bitmap *depends_on, bool *can_autoinc)
{
return get_computation_cost_at (data,
- use, cand, address_p, depends_on, use->stmt);
+ use, cand, address_p, depends_on, use->stmt,
+ can_autoinc);
}
/* Determines cost of basing replacement of USE on CAND in a generic
@@ -3894,7 +4018,7 @@ determine_use_iv_cost_generic (struct ivopts_data *data,
return true;
}
- cost = get_computation_cost (data, use, cand, false, &depends_on);
+ cost = get_computation_cost (data, use, cand, false, &depends_on, NULL);
if (use->use_pos == IU_OUTSIDE_LOOP_ONLY && !infinite_cost_p (cost))
cost.cost /= avg_loop_niter (data->current_loop);
@@ -3911,8 +4035,20 @@ determine_use_iv_cost_address (struct ivopts_data *data,
struct iv_use *use, struct iv_cand *cand)
{
bitmap depends_on;
- comp_cost cost = get_computation_cost (data, use, cand, true, &depends_on);
+ bool can_autoinc;
+ comp_cost cost = get_computation_cost (data, use, cand, true, &depends_on,
+ &can_autoinc);
+ if (cand->ainc_use == use)
+ {
+ if (can_autoinc)
+ cost.cost -= cand->cost_step;
+ /* If we generated the candidate solely for exploiting autoincrement
+ opportunities, and it turns out it can't be used, set the cost to
+ infinity to make sure we ignore it. */
+ else if (cand->pos == IP_AFTER_USE || cand->pos == IP_BEFORE_USE)
+ cost = infinite_cost;
+ }
set_use_iv_cost (data, use, cand, cost, depends_on, NULL_TREE);
return !infinite_cost_p (cost);
@@ -3995,6 +4131,7 @@ may_eliminate_iv (struct ivopts_data *data,
tree nit, period;
struct loop *loop = data->current_loop;
aff_tree bnd;
+ struct tree_niter_desc *desc = NULL;
if (TREE_CODE (cand->iv->step) != INTEGER_CST)
return false;
@@ -4013,7 +4150,7 @@ may_eliminate_iv (struct ivopts_data *data,
if (flow_bb_inside_loop_p (loop, exit->dest))
return false;
- nit = niter_for_exit (data, exit);
+ nit = niter_for_exit (data, exit, &desc);
if (!nit)
return false;
@@ -4025,8 +4162,17 @@ may_eliminate_iv (struct ivopts_data *data,
/* If the number of iterations is constant, compare against it directly. */
if (TREE_CODE (nit) == INTEGER_CST)
{
- if (!tree_int_cst_lt (nit, period))
- return false;
+ /* See cand_value_at. */
+ if (stmt_after_increment (loop, cand, use->stmt))
+ {
+ if (!tree_int_cst_lt (nit, period))
+ return false;
+ }
+ else
+ {
+ if (tree_int_cst_lt (period, nit))
+ return false;
+ }
}
/* If not, and if this is the only possible exit of the loop, see whether
@@ -4035,11 +4181,25 @@ may_eliminate_iv (struct ivopts_data *data,
else
{
double_int period_value, max_niter;
- if (!estimated_loop_iterations (loop, true, &max_niter))
- return false;
+
+ max_niter = desc->max;
+ if (stmt_after_increment (loop, cand, use->stmt))
+ max_niter = double_int_add (max_niter, double_int_one);
period_value = tree_to_double_int (period);
if (double_int_ucmp (max_niter, period_value) > 0)
- return false;
+ {
+ /* See if we can take advantage of inferred loop bound information. */
+ if (loop_only_exit_p (loop, exit))
+ {
+ if (!estimated_loop_iterations (loop, true, &max_niter))
+ return false;
+ /* The loop bound is already adjusted by adding 1. */
+ if (double_int_ucmp (max_niter, period_value) > 0)
+ return false;
+ }
+ else
+ return false;
+ }
}
cand_value_at (loop, cand, use->stmt, nit, &bnd);
@@ -4088,7 +4248,7 @@ determine_use_iv_cost_condition (struct ivopts_data *data,
gcc_assert (ok);
express_cost = get_computation_cost (data, use, cand, false,
- &depends_on_express);
+ &depends_on_express, NULL);
fd_ivopts_data = data;
walk_tree (&cmp_iv->base, find_depends, &depends_on_express, NULL);
@@ -4140,6 +4300,78 @@ determine_use_iv_cost (struct ivopts_data *data,
}
}
+/* Return true if get_computation_cost indicates that autoincrement is
+ a possibility for the pair of USE and CAND, false otherwise. */
+
+static bool
+autoinc_possible_for_pair (struct ivopts_data *data, struct iv_use *use,
+ struct iv_cand *cand)
+{
+ bitmap depends_on;
+ bool can_autoinc;
+ comp_cost cost;
+
+ if (use->type != USE_ADDRESS)
+ return false;
+
+ cost = get_computation_cost (data, use, cand, true, &depends_on,
+ &can_autoinc);
+
+ BITMAP_FREE (depends_on);
+
+ return !infinite_cost_p (cost) && can_autoinc;
+}
+
+/* Examine IP_ORIGINAL candidates to see if they are incremented next to a
+ use that allows autoincrement, and set their AINC_USE if possible. */
+
+static void
+set_autoinc_for_original_candidates (struct ivopts_data *data)
+{
+ unsigned i, j;
+
+ for (i = 0; i < n_iv_cands (data); i++)
+ {
+ struct iv_cand *cand = iv_cand (data, i);
+ struct iv_use *closest = NULL;
+ if (cand->pos != IP_ORIGINAL)
+ continue;
+ for (j = 0; j < n_iv_uses (data); j++)
+ {
+ struct iv_use *use = iv_use (data, j);
+ unsigned uid = gimple_uid (use->stmt);
+ if (gimple_bb (use->stmt) != gimple_bb (cand->incremented_at)
+ || uid > gimple_uid (cand->incremented_at))
+ continue;
+ if (closest == NULL || uid > gimple_uid (closest->stmt))
+ closest = use;
+ }
+ if (closest == NULL || !autoinc_possible_for_pair (data, closest, cand))
+ continue;
+ cand->ainc_use = closest;
+ }
+}
+
+/* Finds the candidates for the induction variables. */
+
+static void
+find_iv_candidates (struct ivopts_data *data)
+{
+ /* Add commonly used ivs. */
+ add_standard_iv_candidates (data);
+
+ /* Add old induction variables. */
+ add_old_ivs_candidates (data);
+
+ /* Add induction variables derived from uses. */
+ add_derived_ivs_candidates (data);
+
+ set_autoinc_for_original_candidates (data);
+
+ /* Record the important candidates. */
+ record_important_candidates (data);
+}
+
/* Determines costs of basing the use of the iv on an iv candidate. */
static void
@@ -4255,6 +4487,7 @@ determine_iv_cost (struct ivopts_data *data, struct iv_cand *cand)
cost++;
cand->cost = cost;
+ cand->cost_step = cost_step;
}
/* Determines costs of computation of the candidates. */
@@ -4279,7 +4512,7 @@ determine_iv_costs (struct ivopts_data *data)
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, " %d\t%d\n", i, cand->cost);
}
-
+
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "\n");
}
@@ -5482,6 +5715,13 @@ create_new_iv (struct ivopts_data *data, struct iv_cand *cand)
after = true;
break;
+ case IP_AFTER_USE:
+ after = true;
+ /* fall through */
+ case IP_BEFORE_USE:
+ incr_pos = gsi_for_stmt (cand->incremented_at);
+ break;
+
case IP_ORIGINAL:
/* Mark that the iv is preserved. */
name_info (data, cand->var_before)->preserve_biv = true;
@@ -5629,6 +5869,9 @@ cause_overlapping_lr (struct ivopts_data *data,
if (!CONSTANT_CLASS_P (gimple_assign_rhs2 (increment)))
return NULL;
+ if (gimple_assign_rhs1 (increment) != selected_iv_nm)
+ return NULL;
+
return increment;
}
@@ -6423,6 +6666,19 @@ remove_unused_ivs (struct ivopts_data *data)
}
}
+/* Frees memory occupied by struct tree_niter_desc in *VALUE. Callback
+ for pointer_map_traverse. */
+
+static bool
+free_tree_niter_desc (const void *key ATTRIBUTE_UNUSED, void **value,
+ void *data ATTRIBUTE_UNUSED)
+{
+ struct tree_niter_desc *const niter = (struct tree_niter_desc *) *value;
+
+ free (niter);
+ return true;
+}
+
/* Frees data allocated by the optimization of a single loop. */
static void
@@ -6435,6 +6691,7 @@ free_loop_data (struct ivopts_data *data)
if (data->niters)
{
+ pointer_map_traverse (data->niters, free_tree_niter_desc, NULL);
pointer_map_destroy (data->niters);
data->niters = NULL;
}
@@ -6531,7 +6788,10 @@ tree_ssa_iv_optimize_loop (struct ivopts_data *data, struct loop *loop)
bool changed = false;
struct iv_ca *iv_ca;
edge exit;
+ basic_block *body;
+ if (!dbg_cnt (ivopts))
+ return false;
gcc_assert (!data->niters);
data->current_loop = loop;
data->speed = optimize_loop_for_speed_p (loop);
@@ -6552,6 +6812,10 @@ tree_ssa_iv_optimize_loop (struct ivopts_data *data, struct loop *loop)
fprintf (dump_file, "\n");
}
+ body = get_loop_body (loop);
+ renumber_gimple_stmt_uids_in_blocks (body, loop->num_nodes);
+ free (body);
+
/* For each ssa name determines whether it behaves as an induction variable
in some loop. */
if (!find_induction_variables (data))
@@ -6566,8 +6830,8 @@ tree_ssa_iv_optimize_loop (struct ivopts_data *data, struct loop *loop)
find_iv_candidates (data);
/* Calculates the costs (item 3, part 1). */
- determine_use_iv_costs (data);
determine_iv_costs (data);
+ determine_use_iv_costs (data);
determine_set_costs (data);
/* Find the optimal set of induction variables (item 3, part 2). */
diff --git a/gcc-4.4.3/gcc/tree-ssa-lrs.c b/gcc-4.4.3/gcc/tree-ssa-lrs.c
index e871d2534..4bdbf5883 100644
--- a/gcc-4.4.3/gcc/tree-ssa-lrs.c
+++ b/gcc-4.4.3/gcc/tree-ssa-lrs.c
@@ -2350,7 +2350,7 @@ compute_rd_gen_kill_set (basic_block bb, int bb_ridx,
static void
initialize_data_flow_rd (lrs_region_p region)
{
- int i, n, nb, bit_first = 0, bit_last = -1, entry_rid;
+ int i, n, nb, bit_first = 0, bit_last = -1, entry_rid = 0;
tree vvar;
region->vname_bit_pos_map = pointer_map_create ();
@@ -4150,7 +4150,7 @@ update_data_flow (gimple_stmt_iterator moved_stmt_gsi,
= get_across_stmt_use_ref_set (prev_stmt, region);
else
{
- int bidx;
+ int bidx = 0;
basic_block bb = gimple_bb (moved_stmt);
get_bb_index_in_region (bb, region, &bidx);
live_across_prev
@@ -4542,7 +4542,7 @@ get_reaching_vdefs (gimple target_loc, bool is_after,
}
else
{
- int rid;
+ int rid = 0;
basic_block bb = gimple_bb (target_loc);
get_bb_index_in_region (bb, region, &rid);
reaching_defs = get_bb_rd_out_set (rid, region);
@@ -4700,7 +4700,7 @@ check_down_motion_profitability (gimple target_loc,
else
{
basic_block bb;
- int rid;
+ int rid = 0;
bb = gimple_bb (target_loc);
get_bb_index_in_region (bb, region, &rid);
live_ur_set = get_bb_use_ref_in_set (rid, region);
diff --git a/gcc-4.4.3/gcc/tree-ssa-operands.c b/gcc-4.4.3/gcc/tree-ssa-operands.c
index a762f5f9b..0a8e1b7c0 100644
--- a/gcc-4.4.3/gcc/tree-ssa-operands.c
+++ b/gcc-4.4.3/gcc/tree-ssa-operands.c
@@ -1545,10 +1545,21 @@ get_addr_dereference_operands (gimple stmt, tree *addr, int flags,
}
else if (TREE_CODE (ptr) == INTEGER_CST)
{
+ tree literal_addr_tag;
+
/* If a constant is used as a pointer, we can't generate a real
operand for it but we mark the statement volatile to prevent
optimizations from messing things up. */
gimple_set_has_volatile_ops (stmt, true);
+ literal_addr_tag = gimple_global_var (cfun);
+ if (!integer_zerop (ptr)
+ && literal_addr_tag && !(flags & opf_no_vops))
+ {
+ if (flags & opf_def)
+ append_vdef (literal_addr_tag);
+ else
+ append_vuse (literal_addr_tag);
+ }
return;
}
else
@@ -1647,7 +1658,8 @@ add_call_clobber_ops (gimple stmt, tree callee ATTRIBUTE_UNUSED)
{
tree var = gimple_global_var (cfun);
add_virtual_operand (var, stmt, opf_def, NULL, 0, -1, true);
- return;
+ if (bitmap_empty_p (gimple_call_clobbered_vars (cfun)))
+ return;
}
/* Get info for local and module level statics. There is a bit
diff --git a/gcc-4.4.3/gcc/tree-ssa-pre.c b/gcc-4.4.3/gcc/tree-ssa-pre.c
index 342730776..2a8b4b425 100644
--- a/gcc-4.4.3/gcc/tree-ssa-pre.c
+++ b/gcc-4.4.3/gcc/tree-ssa-pre.c
@@ -3967,6 +3967,7 @@ eliminate (void)
print_gimple_stmt (dump_file, stmt, 0, 0);
}
+ fixup_vdef_ssa_val_refs (stmt);
/* Propagate all may-uses to the uses of their defs. */
FOR_EACH_SSA_VDEF_OPERAND (def, usevec, stmt, oi)
{
diff --git a/gcc-4.4.3/gcc/tree-ssa-sccvn.c b/gcc-4.4.3/gcc/tree-ssa-sccvn.c
index aa70b94d5..c1f71da54 100644
--- a/gcc-4.4.3/gcc/tree-ssa-sccvn.c
+++ b/gcc-4.4.3/gcc/tree-ssa-sccvn.c
@@ -1625,6 +1625,36 @@ set_ssa_val_to (tree from, tree to)
return false;
}
+/* Fix up references to VOP SSANAMEs defined by STMT
+ which is to be removed. This function does not
+ fix up references in VUSE/VDEFs which need to be
+ handled seperately. */
+
+void
+fixup_vdef_ssa_val_refs (gimple stmt)
+{
+ struct voptype_d *vdefs;
+ tree var;
+ int i;
+
+ vdefs = gimple_vdef_ops (stmt);
+ while (vdefs)
+ {
+ tree def_nm;
+ tree prev_nm;
+
+ def_nm = VDEF_RESULT (vdefs);
+ prev_nm = VDEF_OP (vdefs, 0);
+
+ for (i = 0; VEC_iterate (tree, SSANAMES (cfun), i, var); i++)
+ {
+ if (var && SSA_VAL (var) == def_nm)
+ set_ssa_val_to (var, prev_nm);
+ }
+ vdefs = vdefs->next;
+ }
+}
+
/* Set all definitions in STMT to value number to themselves.
Return true if a value number changed. */
diff --git a/gcc-4.4.3/gcc/tree-ssa-uninit.c b/gcc-4.4.3/gcc/tree-ssa-uninit.c
index 41437b962..6edd89e87 100644
--- a/gcc-4.4.3/gcc/tree-ssa-uninit.c
+++ b/gcc-4.4.3/gcc/tree-ssa-uninit.c
@@ -215,7 +215,7 @@ find_control_equiv_block (basic_block bb)
}
#define MAX_NUM_CHAINS 8
-#define MAX_CHAIN_LEN 5
+#define MAX_CHAIN_LEN 8
/* Computes the control dependence chains (paths of edges)
for DEP_BB up to the dominating basic block BB (the head node of a
@@ -728,6 +728,160 @@ is_use_properly_guarded (gimple use_stmt,
sbitmap uninit_opnds,
struct pointer_set_t *visited_phis);
+/* A helper function for prune_uninit_phi_opnds_in_unrealizable_paths.
+ Returns true if FLAG_ARG is defined by another phi node, and
+ the I th operand of PHI is also defined by another phi in the same
+ basic block of FLAG_ARG def's bb; returns false otherwise. If it
+ returns true, the defining statements for the flag and phi arg
+ are stored in *FLAG_ARG_DEF and *PHI_ARG_DEF. */
+
+static bool
+is_phi_arg_defined_by_phi (tree flag_arg, gimple phi, unsigned i,
+ gimple *flag_arg_def, gimple *phi_arg_def)
+{
+ tree phi_arg;
+
+ if (TREE_CODE (flag_arg) != SSA_NAME)
+ return false;
+
+ *flag_arg_def = SSA_NAME_DEF_STMT (flag_arg);
+ if (gimple_code (*flag_arg_def) != GIMPLE_PHI)
+ return false;
+
+ phi_arg = gimple_phi_arg_def (phi, i);
+ if (TREE_CODE (phi_arg) != SSA_NAME)
+ return false;
+
+ *phi_arg_def = SSA_NAME_DEF_STMT (phi_arg);
+ if (gimple_code (*phi_arg_def) != GIMPLE_PHI)
+ return false;
+
+ if (gimple_bb (*phi_arg_def) != gimple_bb (*flag_arg_def))
+ return false;
+
+ return true;
+}
+
+/* Returns true if all uninitialized opnds are pruned. Returns false
+ otherwise. PHI is the phi node with uninitialized operands,
+ UNINIT_OPNDS is the bitmap of the uninitialize operand positions,
+ FLAG_DEF is the statement defining the flag guarding the use of the
+ PHI output, BOUNDARY_CST is the const value used in the predicate
+ associated with the flag, CMP_CODE is the comparison code used in
+ the predicate, VISITED_PHIS is the pointer set of phis visited, and
+ VISITED_FLAG_PHIS is the pointer to the pointer set of flag definitions
+ that are also phis.
+
+ Example scenario:
+
+ BB1:
+ flag_1 = phi <0, 1> // (1)
+ var_1 = phi <undef, some_val>
+
+
+ BB2:
+ flag_2 = phi <0, flag_1, flag_1> // (2)
+ var_2 = phi <undef, var_1, var_1>
+ if (flag_2 == 1)
+ goto BB3;
+
+ BB3:
+ use of var_2 // (3)
+
+ Because some flag arg in (1) is not constant, if we do not look into the
+ flag phis recursively, it is conservatively treated as unknown and var_1
+ is thought to be flowed into use at (3). Since var_1 is potentially uninitialized
+ a false warning will be emitted. Checking recursively into (1), the compiler can
+ find out that only some_val (which is defined) can flow into (3) which is OK. */
+
+static bool
+prune_uninit_phi_opnds_in_unrealizable_paths (
+ gimple phi, sbitmap uninit_opnds,
+ gimple flag_def, tree boundary_cst,
+ enum tree_code cmp_code,
+ struct pointer_set_t *visited_phis,
+ struct pointer_set_t **visited_flag_phis)
+{
+ sbitmap_iterator sbi;
+ unsigned i;
+
+ EXECUTE_IF_SET_IN_SBITMAP (uninit_opnds, 0, i, sbi)
+ {
+ tree flag_arg;
+
+ flag_arg = gimple_phi_arg_def (flag_def, i);
+
+ if (!is_gimple_constant (flag_arg))
+ {
+ gimple flag_arg_def, phi_arg_def;
+ sbitmap uninit_opnds_arg_phi;
+
+ if (!is_phi_arg_defined_by_phi (flag_arg,
+ phi, i,
+ &flag_arg_def,
+ &phi_arg_def))
+ return false;
+
+ if (!*visited_flag_phis)
+ *visited_flag_phis = pointer_set_create ();
+
+ if (pointer_set_insert (*visited_flag_phis, flag_arg_def))
+ return false;
+
+ /* Now recursively prune the uninitialized phi args. */
+ uninit_opnds_arg_phi = compute_uninit_opnds_pos (phi_arg_def);
+ if (!prune_uninit_phi_opnds_in_unrealizable_paths (
+ phi_arg_def, uninit_opnds_arg_phi,
+ flag_arg_def, boundary_cst, cmp_code,
+ visited_phis, visited_flag_phis))
+ {
+ sbitmap_free (uninit_opnds_arg_phi);
+ return false;
+ }
+ sbitmap_free (uninit_opnds_arg_phi);
+ pointer_set_delete (*visited_flag_phis, flag_arg_def);
+ continue;
+ }
+
+ /* Now check if the constant is in the guarded range. */
+ if (is_value_included_in (flag_arg, boundary_cst, cmp_code))
+ {
+ tree opnd;
+ gimple opnd_def;
+
+ /* Now that we know that this undefined edge is not
+ pruned. If the operand is defined by another phi,
+ we can further prune the incoming edges of that
+ phi by checking the predicates of this operands. */
+
+ opnd = gimple_phi_arg_def (phi, i);
+ opnd_def = SSA_NAME_DEF_STMT (opnd);
+ if (gimple_code (opnd_def) == GIMPLE_PHI)
+ {
+ edge opnd_edge;
+ sbitmap uninit_opnds2
+ = compute_uninit_opnds_pos (opnd_def);
+ gcc_assert (!sbitmap_empty_p (uninit_opnds2));
+ opnd_edge = gimple_phi_arg_edge (phi, i);
+ if (!is_use_properly_guarded (phi,
+ opnd_edge->src,
+ opnd_def,
+ uninit_opnds2,
+ visited_phis))
+ {
+ sbitmap_free (uninit_opnds2);
+ return false;
+ }
+ sbitmap_free (uninit_opnds2);
+ }
+ else
+ return false;
+ }
+ }
+
+ return true;
+}
+
/* A helper function that determines if the predicate set
of the use is not overlapping with that of the uninit paths.
The most common senario of guarded use is in Example 1:
@@ -816,7 +970,8 @@ use_pred_not_overlap_with_undef_path_pred (
bool swap_cond = false;
bool invert = false;
VEC(use_pred_info_t, heap) *the_pred_chain;
- sbitmap_iterator sbi;
+ struct pointer_set_t *visited_flag_phis = NULL;
+ bool all_pruned = false;
gcc_assert (num_preds > 0);
/* Find within the common prefix of multiple predicate chains
@@ -879,51 +1034,17 @@ use_pred_not_overlap_with_undef_path_pred (
if (cmp_code == ERROR_MARK)
return false;
- EXECUTE_IF_SET_IN_SBITMAP (uninit_opnds, 0, i, sbi)
- {
- tree flag_arg;
-
- flag_arg = gimple_phi_arg_def (flag_def, i);
- if (!is_gimple_constant (flag_arg))
- return false;
-
- /* Now check if the constant is in the guarded range. */
- if (is_value_included_in (flag_arg, boundary_cst, cmp_code))
- {
- tree opnd;
- gimple opnd_def;
-
- /* Now that we know that this undefined edge is not
- pruned. If the operand is defined by another phi,
- we can further prune the incoming edges of that
- phi by checking the predicates of this operands. */
-
- opnd = gimple_phi_arg_def (phi, i);
- opnd_def = SSA_NAME_DEF_STMT (opnd);
- if (gimple_code (opnd_def) == GIMPLE_PHI)
- {
- edge opnd_edge;
- sbitmap uninit_opnds2
- = compute_uninit_opnds_pos (opnd_def);
- gcc_assert (!sbitmap_empty_p (uninit_opnds2));
- opnd_edge = gimple_phi_arg_edge (phi, i);
- if (!is_use_properly_guarded (phi,
- opnd_edge->src,
- opnd_def,
- uninit_opnds2,
- visited_phis))
- {
- sbitmap_free (uninit_opnds2);
- return false;
- }
- sbitmap_free (uninit_opnds2);
- }
- else
- return false;
- }
- }
-
- return true;
+ all_pruned = prune_uninit_phi_opnds_in_unrealizable_paths (phi,
+ uninit_opnds,
+ flag_def,
+ boundary_cst,
+ cmp_code,
+ visited_phis,
+ &visited_flag_phis);
+
+ if (visited_flag_phis)
+ pointer_set_destroy (visited_flag_phis);
+ return all_pruned;
}
/* Returns true if TC is AND or OR */
@@ -1639,7 +1760,7 @@ warn_uninitialized_phi (gimple phi, VEC(gimple, heap) **worklist,
}
uninit_op = gimple_phi_arg_def (phi, sbitmap_first_set_bit (uninit_opnds));
- warn_uninit (uninit_op,
+ warn_uninit (OPT_Wmaybe_uninitialized, uninit_op,
"%qD may be used uninitialized in this function",
uninit_use_stmt);
@@ -1701,7 +1822,7 @@ execute_late_warn_uninitialized (void)
cur_phi = VEC_pop (gimple, worklist);
warn_uninitialized_phi (cur_phi, &worklist, added_to_worklist);
}
-
+
VEC_free (gimple, heap, worklist);
pointer_set_destroy (added_to_worklist);
pointer_set_destroy (possibly_undefined_names);
diff --git a/gcc-4.4.3/gcc/tree-ssa.c b/gcc-4.4.3/gcc/tree-ssa.c
index 11e079d6a..c00dd27f8 100644
--- a/gcc-4.4.3/gcc/tree-ssa.c
+++ b/gcc-4.4.3/gcc/tree-ssa.c
@@ -1419,10 +1419,11 @@ walk_use_def_chains (tree var, walk_use_def_chains_fn fn, void *data,
changed conditionally uninitialized to unconditionally uninitialized. */
/* Emit a warning for T, an SSA_NAME, being uninitialized. The exact
- warning text is in MSGID and LOCUS may contain a location or be null. */
+ warning text is in MSGID and LOCUS may contain a location or be null.
+ WC is the warning code. */
void
-warn_uninit (tree t, const char *gmsgid, void *data)
+warn_uninit (enum opt_code wc, tree t, const char *gmsgid, void *data)
{
tree var = SSA_NAME_VAR (t);
gimple context = (gimple) data;
@@ -1446,7 +1447,7 @@ warn_uninit (tree t, const char *gmsgid, void *data)
: DECL_SOURCE_LOCATION (var);
xloc = expand_location (location);
floc = expand_location (DECL_SOURCE_LOCATION (cfun->decl));
- if (warning_at (location, OPT_Wuninitialized, gmsgid, var))
+ if (warning_at (location, wc, gmsgid, var))
{
TREE_NO_WARNING (var) = 1;
@@ -1526,10 +1527,12 @@ warn_uninitialized_var (tree *tp, int *walk_subtrees, void *data_)
/* We only do data flow with SSA_NAMEs, so that's all we
can warn about. */
if (data->always_executed)
- warn_uninit (t, "%qD is used uninitialized in this function",
+ warn_uninit (OPT_Wuninitialized,
+ t, "%qD is used uninitialized in this function",
data->stmt);
else if (data->warn_possibly_uninitialized)
- warn_uninit (t, "%qD may be used uninitialized in this function",
+ warn_uninit (OPT_Wuninitialized,
+ t, "%qD may be used uninitialized in this function",
data->stmt);
*walk_subtrees = 0;
break;
diff --git a/gcc-4.4.3/gcc/tree-stack-overlay.c b/gcc-4.4.3/gcc/tree-stack-overlay.c
new file mode 100644
index 000000000..a382a1c1d
--- /dev/null
+++ b/gcc-4.4.3/gcc/tree-stack-overlay.c
@@ -0,0 +1,1004 @@
+/* A pass for coalescing stack variables.
+
+ Copyright (C) 2010
+ 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 "ggc.h"
+#include "tm.h"
+#include "tree.h"
+#include "tm_p.h"
+#include "basic-block.h"
+#include "function.h"
+#include "expr.h"
+#include "langhooks.h"
+#include "tree-flow.h"
+#include "timevar.h"
+#include "tree-dump.h"
+#include "tree-pass.h"
+#include "except.h"
+#include "flags.h"
+#include "diagnostic.h"
+#include "toplev.h"
+#include "debug.h"
+#include "params.h"
+#include "target.h"
+#include "tree-stack-overlay.h"
+#include "vec.h"
+
+
+/* Based on the stack layout phase in cfgexpand. Creates new union
+ types with variables that can share stack slots as fields. During
+ RTL generation, all fields of the union arer assigned to the same
+ stack slot. */
+
+#define EOC (-1)
+
+/* This structure holds data relevant to one variable that will be
+ placed in a stack slot. */
+struct stack_var
+{
+ /* The Variable. */
+ tree decl;
+
+
+ /* Initially, the size of the variable. Later, the size of the partition,
+ if this variable becomes it's partition's representative. */
+ HOST_WIDE_INT size;
+
+ /* The partition representative. */
+ int representative;
+
+ /* The next stack variable in the partition, or EOC. */
+ int next;
+
+ /* The numbers of conflicting stack variables. */
+ bitmap conflicts;
+
+ /* A new union type containing all variables in the partition. NULL if the
+ partition is singleton. */
+ tree union_decl;
+
+ /* The field corresponding to this declaration in the created union */
+ tree field_decl;
+};
+
+/* This struct maps a VAR_DECL to a vector of DECLs. */
+struct overlay_decl_mapping GTY(())
+{
+ tree decl;
+ VEC(tree,gc) *value;
+};
+
+
+/* We have an array of such objects while deciding allocation. */
+static struct stack_var *stack_vars;
+static int stack_vars_alloc;
+static int stack_vars_num;
+
+/* Map between var_decl to field_decl inside a union type. */
+static htab_t decl_field_map = NULL;
+
+/* Store newly synthesized union variables in union_vars. */
+static tree union_vars = NULL_TREE;
+
+/* An array of indices such that stack_vars[stack_vars_sorted[i]].size
+ is non-decreasing. */
+static int *stack_vars_sorted;
+
+/* Make the decls associated with luid's X and Y conflict. */
+
+static void
+add_stack_var_conflict (size_t x, size_t y)
+{
+ struct stack_var *a = &stack_vars[x];
+ struct stack_var *b = &stack_vars[y];
+ if (!a->conflicts)
+ a->conflicts = BITMAP_ALLOC (NULL);
+ if (!b->conflicts)
+ b->conflicts = BITMAP_ALLOC (NULL);
+ bitmap_set_bit (a->conflicts, y);
+ bitmap_set_bit (b->conflicts, x);
+}
+
+/* Check whether the decls associated with luid's X and Y conflict. */
+
+static bool
+stack_var_conflict_p (size_t x, size_t y)
+{
+ struct stack_var *a = &stack_vars[x];
+ struct stack_var *b = &stack_vars[y];
+ if (!a->conflicts || !b->conflicts)
+ return false;
+ return bitmap_bit_p (a->conflicts, y);
+}
+
+/* Returns true if TYPE is or contains a union type. */
+
+static bool
+aggregate_contains_union_type (tree type)
+{
+ tree field;
+
+ if (TREE_CODE (type) == UNION_TYPE
+ || TREE_CODE (type) == QUAL_UNION_TYPE)
+ return true;
+ if (TREE_CODE (type) == ARRAY_TYPE)
+ return aggregate_contains_union_type (TREE_TYPE (type));
+ if (TREE_CODE (type) != RECORD_TYPE)
+ return false;
+
+ for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+ if (TREE_CODE (field) == FIELD_DECL)
+ if (aggregate_contains_union_type (TREE_TYPE (field)))
+ return true;
+
+ return false;
+}
+
+/* A subroutine of execute_stack_overlay. If two variables X and Y have
+ alias sets that do not conflict, then do add a conflict for these
+ variable in the interference graph. We also need to make sure to add
+ conflicts for union containing structures. Else RTL alias analysis
+ comes along and due to type based aliasing rules decides that for two
+ overlapping union temporaries { short s; int i; } accesses to the same
+ mem through different types may not alias and happily reorders stores
+ across life-time boundaries of the temporaries (See PR25654).
+ We also have to mind MEM_IN_STRUCT_P and MEM_SCALAR_P. */
+
+static void
+add_alias_set_conflicts (void)
+{
+ size_t i, j, n = stack_vars_num;
+
+ for (i = 0; i < n; ++i)
+ {
+ tree type_i = TREE_TYPE (stack_vars[i].decl);
+ bool aggr_i = AGGREGATE_TYPE_P (type_i);
+ bool contains_union;
+
+ contains_union = aggregate_contains_union_type (type_i);
+ for (j = 0; j < i; ++j)
+ {
+ tree type_j = TREE_TYPE (stack_vars[j].decl);
+ bool aggr_j = AGGREGATE_TYPE_P (type_j);
+ if (aggr_i != aggr_j
+ /* Either the objects conflict by means of type based
+ aliasing rules, or we need to add a conflict. */
+ || !objects_must_conflict_p (type_i, type_j)
+ /* In case the types do not conflict ensure that access
+ to elements will conflict. In case of unions we have
+ to be careful as type based aliasing rules may say
+ access to the same memory does not conflict. So play
+ safe and add a conflict in this case. */
+ || (contains_union && flag_strict_aliasing))
+ add_stack_var_conflict (i, j);
+ }
+ }
+}
+
+/* Examine TYPE and determine a bit mask of the following features. */
+
+#define SPCT_HAS_LARGE_CHAR_ARRAY 1
+#define SPCT_HAS_SMALL_CHAR_ARRAY 2
+#define SPCT_HAS_ARRAY 4
+#define SPCT_HAS_AGGREGATE 8
+
+static unsigned int
+stack_protect_classify_type (tree type)
+{
+ unsigned int ret = 0;
+ tree t;
+
+ switch (TREE_CODE (type))
+ {
+ case ARRAY_TYPE:
+ t = TYPE_MAIN_VARIANT (TREE_TYPE (type));
+ if (t == char_type_node
+ || t == signed_char_type_node
+ || t == unsigned_char_type_node)
+ {
+ unsigned HOST_WIDE_INT max = PARAM_VALUE (PARAM_SSP_BUFFER_SIZE);
+ unsigned HOST_WIDE_INT len;
+
+ if (!TYPE_SIZE_UNIT (type)
+ || !host_integerp (TYPE_SIZE_UNIT (type), 1))
+ len = max;
+ else
+ len = tree_low_cst (TYPE_SIZE_UNIT (type), 1);
+
+ if (len < max)
+ ret = SPCT_HAS_SMALL_CHAR_ARRAY | SPCT_HAS_ARRAY;
+ else
+ ret = SPCT_HAS_LARGE_CHAR_ARRAY | SPCT_HAS_ARRAY;
+ }
+ else
+ ret = SPCT_HAS_ARRAY;
+ break;
+
+ case UNION_TYPE:
+ case QUAL_UNION_TYPE:
+ case RECORD_TYPE:
+ ret = SPCT_HAS_AGGREGATE;
+ for (t = TYPE_FIELDS (type); t ; t = TREE_CHAIN (t))
+ if (TREE_CODE (t) == FIELD_DECL)
+ ret |= stack_protect_classify_type (TREE_TYPE (t));
+ break;
+
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+/* Return nonzero if DECL should be segregated into the "vulnerable" upper
+ part of the local stack frame. Remember if we ever return nonzero for
+ any variable in this function. The return value is the phase number in
+ which the variable should be allocated. */
+
+static int
+stack_protect_decl_phase (tree decl)
+{
+ unsigned int bits = stack_protect_classify_type (TREE_TYPE (decl));
+ int ret = 0;
+
+ if (flag_stack_protect == 2)
+ {
+ if ((bits & (SPCT_HAS_SMALL_CHAR_ARRAY | SPCT_HAS_LARGE_CHAR_ARRAY))
+ && !(bits & SPCT_HAS_AGGREGATE))
+ ret = 1;
+ else if (bits & SPCT_HAS_ARRAY)
+ ret = 2;
+ }
+ else
+ ret = (bits & SPCT_HAS_LARGE_CHAR_ARRAY) != 0;
+
+ return ret;
+}
+
+/* Ensure that variables in different stack protection phases conflict
+ so that they are not merged and share the same stack slot. */
+
+static void
+add_stack_protection_conflicts (void)
+{
+ size_t i, j, n = stack_vars_num;
+ unsigned char *phase;
+
+ phase = XNEWVEC (unsigned char, n);
+ for (i = 0; i < n; ++i)
+ phase[i] = stack_protect_decl_phase (stack_vars[i].decl);
+
+ for (i = 0; i < n; ++i)
+ {
+ unsigned char ph_i = phase[i];
+ for (j = 0; j < i; ++j)
+ if (ph_i != phase[j])
+ add_stack_var_conflict (i, j);
+ }
+
+ XDELETEVEC (phase);
+}
+
+/* A subroutine of partition_stack_vars. A comparison function for qsort,
+ sorting an array of indices by the size of the object in descending
+ order. */
+
+static int
+stack_var_size_cmp (const void *a, const void *b)
+{
+ HOST_WIDE_INT sa = stack_vars[*(const int *)a].size;
+ HOST_WIDE_INT sb = stack_vars[*(const int *)b].size;
+ unsigned int uida = DECL_UID (stack_vars[*(const int *)a].decl);
+ unsigned int uidb = DECL_UID (stack_vars[*(const int *)b].decl);
+
+ if (sa > sb)
+ return -1;
+ if (sa < sb)
+ return 1;
+ /* For stack variables of the same size use the uid of the decl
+ to make the sort stable. */
+ if (uida < uidb)
+ return -1;
+ if (uida > uidb)
+ return 1;
+ return 0;
+}
+
+/* A subroutine of partition_stack_vars. B is the index of a stack var
+ that is not merged with any other variable. A is the index of a stack
+ var which is in a partition of one or more stack vars with A as the
+ representative. Add B to the partition containing A, set B's representative
+ to be A and extend A's conflict list with that of B's. */
+
+static void
+union_stack_vars (int a, int b)
+{
+ struct stack_var *vb = &stack_vars[b];
+ bitmap_iterator bi;
+ unsigned u;
+
+
+ /* Add B to A's partition. */
+ stack_vars[b].next = stack_vars[a].next;
+ stack_vars[b].representative = a;
+ stack_vars[a].next = b;
+
+ /* Update the interference graph and merge the conflicts. */
+ if (vb->conflicts)
+ {
+ EXECUTE_IF_SET_IN_BITMAP (vb->conflicts, 0, u, bi)
+ add_stack_var_conflict (a, u);
+ BITMAP_FREE (vb->conflicts);
+ }
+}
+
+/* A subroutine of execute_stack_overlay. Binpack the variables into
+ partitions constrained by the interference graph. The overall
+ algorithm used is as follows:
+
+ Sort the objects by descending order of size.
+ For each object A {
+ S = size(A)
+ O = 0
+ loop {
+ Look for the largest non-conflicting object B with size <= S.
+ UNION (A, B)
+ }
+ }
+*/
+
+static void
+partition_stack_vars (void)
+{
+ int si, sj, n = stack_vars_num;
+
+ stack_vars_sorted = XNEWVEC (int, stack_vars_num);
+ for (si = 0; si < n; ++si)
+ stack_vars_sorted[si] = si;
+
+ if (n == 1)
+ return;
+
+ /* Sorting in descending order prevents cases cases like this:
+ sizeof(a) = 100, sizeof(b) = 100, sizeof(c) = 1, c conflicts with a.
+ If variables are considered in ascending order, c and b would be
+ merged resulting in 200 bytes stack frame size. Sorting in descending
+ order results in a and b being merged, resulting in 101 bytes stack
+ size. */
+ qsort (stack_vars_sorted, n, sizeof (int), stack_var_size_cmp);
+
+ for (si = 0; si < n; ++si)
+ {
+ int i = stack_vars_sorted[si];
+ /* Ignore objects that aren't partition representatives. If we
+ see a var that is not a partition representative, it must
+ have been merged earlier. */
+ if (stack_vars[i].representative != i)
+ continue;
+
+ for (sj = si + 1; sj < n; sj++)
+ {
+ int j = stack_vars_sorted[sj];
+
+ /* Ignore objects that aren't partition representatives. */
+ if (stack_vars[j].representative != j)
+ continue;
+
+ /* Ignore conflicting objects. */
+ if (stack_var_conflict_p (i, j))
+ continue;
+
+ /* UNION the two objects. */
+ union_stack_vars (i, j);
+ }
+ }
+}
+
+/* A debugging aid for execute_stack_overlay. Dump the generated partitions. */
+
+static void
+dump_stack_var_partition (void)
+{
+ int si, i, j, n = stack_vars_num;
+ int part = 0;
+
+ for (si = 0; si < n; ++si)
+ {
+ i = stack_vars_sorted[si];
+
+ /* Skip variables that aren't partition representatives, for now. */
+ if (stack_vars[i].representative != i)
+ continue;
+
+ fprintf (dump_file, "Partition %d: size " HOST_WIDE_INT_PRINT_DEC
+ " variables : ", part++, stack_vars[i].size);
+
+ for (j = i; j != EOC; j = stack_vars[j].next)
+ {
+ fputc (' ', dump_file);
+ print_generic_expr (dump_file, stack_vars[j].decl, dump_flags);
+ }
+ fputc ('\n', dump_file);
+ }
+ fprintf (dump_file, "Number of partitions = %d\n", part);
+}
+
+/* A subroutine of add_stack_vars_in_block. Identify variables that will be
+ stack-allocated and add them to stack_vars array. */
+
+static void
+add_stack_var (tree var)
+{
+ if (TREE_CODE (var) != VAR_DECL
+ || DECL_EXTERNAL (var)
+ || DECL_HAS_VALUE_EXPR_P (var)
+ || TREE_STATIC (var)
+ || DECL_RTL_SET_P (var)
+ || DECL_HARD_REGISTER (var)
+ || use_register_for_decl (var)
+ || (flag_float_store && FLOAT_TYPE_P (TREE_TYPE (var)))
+ /* If a volatile shares a slot with a non-volatile, the
+ union has to be marked volatile to prevent unsafe
+ optimizations, preventing optimizations on the original
+ non-volatile. */
+ || (TYPE_VOLATILE (TREE_TYPE (var))))
+ return;
+
+ /* Without optimization, *most* variables are allocated from the
+ stack, which makes the quadratic problem large exactly when we
+ want compilation to proceed as quickly as possible. On the
+ other hand, we don't want the function's stack frame size to
+ get completely out of hand. So we avoid adding scalars and
+ "small" aggregates to the list at all. */
+ if (optimize == 0 && tree_low_cst (DECL_SIZE_UNIT (var), 1) < 32)
+ return;
+
+ if (stack_vars_num >= stack_vars_alloc)
+ {
+ if (stack_vars_alloc)
+ stack_vars_alloc = stack_vars_alloc * 3 / 2;
+ else
+ stack_vars_alloc = 32;
+ stack_vars
+ = XRESIZEVEC (struct stack_var, stack_vars, stack_vars_alloc);
+ }
+ stack_vars[stack_vars_num].decl = var;
+ stack_vars[stack_vars_num].size = tree_low_cst (DECL_SIZE_UNIT (var), 1);
+
+ /* All variables are initially in their own partition. */
+ stack_vars[stack_vars_num].representative = stack_vars_num;
+ stack_vars[stack_vars_num].next = EOC;
+
+ /* All variables initially conflict with no other. */
+ stack_vars[stack_vars_num].conflicts = NULL;
+
+ stack_vars[stack_vars_num].union_decl = NULL;
+ stack_vars[stack_vars_num].field_decl = NULL;
+
+ stack_vars_num++;
+}
+
+
+/* A subroutine of execute_stack_overlay. Walk down through the BLOCK tree
+ identifying stack variables that can possibly be coalesced.
+
+ TOPLEVEL is true if this is the outermost BLOCK. */
+
+static void
+add_stack_vars_in_block (tree block, bool toplevel)
+{
+ size_t i, j, old_sv_num, this_sv_num, new_sv_num;
+ tree t;
+
+ old_sv_num = toplevel ? 0 : stack_vars_num;
+
+ /* Collect all stack vars at this level if this is not the outermost block.
+ Since vartiables in the outermost block always conflict with everything
+ there is no need to add them to stack_vars. */
+ if (!toplevel)
+ for (t = BLOCK_VARS (block); t ; t = TREE_CHAIN (t))
+ if (TREE_USED (t))
+ add_stack_var (t);
+
+ this_sv_num = stack_vars_num;
+
+ /* Recursively call the method in all SUBBLOCKS. */
+ for (t = BLOCK_SUBBLOCKS (block); t ; t = BLOCK_CHAIN (t))
+ add_stack_vars_in_block (t, false);
+
+ /* Since we do not track exact variable lifetimes (which is not even
+ possible for variables whose address escapes), we mirror the block
+ tree in the interference graph. Here we cause all variables at this
+ level, and all sublevels, to conflict. Do make certain that a
+ variable conflicts with itself. */
+ if (old_sv_num < this_sv_num)
+ {
+ new_sv_num = stack_vars_num;
+
+ for (i = old_sv_num; i < new_sv_num; ++i)
+ for (j = i < this_sv_num ? i+1 : this_sv_num; j-- > old_sv_num ;)
+ add_stack_var_conflict (i, j);
+ }
+}
+
+/* A subroutine of init_stack_overlay. Walk down through the BLOCK tree
+ and clear TREE_USED on all local variables. */
+
+static void
+clear_tree_used (tree block)
+{
+ tree t;
+
+ for (t = BLOCK_VARS (block); t ; t = TREE_CHAIN (t))
+ /* if (!TREE_STATIC (t) && !DECL_EXTERNAL (t)) */
+ TREE_USED (t) = 0;
+
+ for (t = BLOCK_SUBBLOCKS (block); t ; t = BLOCK_CHAIN (t))
+ clear_tree_used (t);
+}
+
+/* Create a name "union."+i and returns a tree corresponding to that */
+static inline tree
+get_union_name (int i)
+{
+ char * new_name = NULL;
+ ASM_FORMAT_PRIVATE_NAME(new_name, "union", i);
+ return get_identifier (new_name);
+}
+
+/* Given an index into stack_vars, create field declarations corresponbding to
+ each variable in the partition and link them together into a single tree. */
+static tree
+create_fields (int index, size_t *align)
+{
+ tree new_types = NULL_TREE;
+ tree last = NULL_TREE;
+ *align = 0;
+
+ while (index != EOC)
+ {
+ tree decl = stack_vars[index].decl;
+ tree name = DECL_NAME (decl);
+ tree type = TREE_TYPE(decl);
+ tree new_decl = build_decl (FIELD_DECL, name, type);
+ if (*align < DECL_ALIGN (decl))
+ *align = DECL_ALIGN (decl);
+ stack_vars[index].field_decl = new_decl;
+ if (!new_types)
+ new_types = new_decl;
+ else
+ TREE_CHAIN (last) = new_decl;
+ last = new_decl;
+ index = stack_vars[index].next;
+ }
+ TREE_CHAIN (last) = NULL_TREE;
+ return new_types;
+}
+/* This functions builds an union for the partition
+ with representative stack_vars[i]. */
+
+static tree
+build_union_type (int i)
+{
+ tree attributes = NULL_TREE; /* Attributes??? */
+ tree ref = 0;
+ tree x;
+ size_t align;
+ tree fields = create_fields (i, &align);
+ tree name = get_union_name (i);
+
+ ref = make_node (UNION_TYPE);
+ TYPE_SIZE (ref) = 0;
+ decl_attributes (&ref, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE);
+ TYPE_PACKED (ref) = 0; /* Packing ??? */
+ for (x = fields; x; x = TREE_CHAIN (x))
+ {
+ DECL_CONTEXT (x) = ref;
+ DECL_PACKED (x) |= TYPE_PACKED (ref);
+ }
+ TYPE_FIELDS (ref) = fields;
+ DECL_CONTEXT (TYPE_FIELDS (ref)) = ref;
+ TYPE_NAME (ref) = name;
+ layout_type (ref);
+ TYPE_ALIGN (ref) = align;
+ if (dump_file) {
+ tree tmp;
+ fprintf (dump_file, "Created new type: \n ");
+ print_generic_expr (dump_file, ref, dump_flags);
+ fprintf (dump_file, " {\n");
+ tmp = fields;
+ while (tmp)
+ {
+ tree field_type = TREE_TYPE (tmp);
+ fprintf (dump_file, " ");
+ print_generic_expr (dump_file, field_type, dump_flags);
+ fprintf (dump_file, " ");
+ print_generic_expr (dump_file, tmp, dump_flags);
+ fprintf (dump_file, ";\n");
+ tmp = TREE_CHAIN (tmp);
+ }
+ fprintf (dump_file, "};\n\n");
+ }
+ return ref;
+}
+
+/* Set attributes for a newly created VAR_DECL */
+static inline void
+set_decl_attributes (tree new_decl)
+{
+
+ TREE_PUBLIC (new_decl) = 0;
+ TREE_THIS_VOLATILE (new_decl) = 0;
+ TREE_ADDRESSABLE (new_decl) = 1;
+ DECL_TLS_MODEL (new_decl) = TLS_MODEL_NONE;
+ /* Unset DECL_IGNORED_P to prevent this variable from being removed from
+ BLOCK_VARS by remove_unused_locals */
+ DECL_IGNORED_P (new_decl) = 0;
+}
+
+/* This function generates and returns new variable name based on
+ ORIG_DECL name, combined with index I.
+ The form of the new name is <orig_name>.<I> . */
+
+static tree
+gen_var_name (unsigned HOST_WIDE_INT i)
+{
+ const char *old_name = "union";
+ char *prefix;
+ char *new_name;
+ prefix = XALLOCAVEC (char, strlen (old_name) + 1);
+ strcpy (prefix, old_name);
+ ASM_FORMAT_PRIVATE_NAME (new_name, prefix, i);
+ return get_identifier (new_name);
+}
+/* Create a new local variable of the given type */
+static tree
+create_new_var (tree type, size_t i)
+{
+ tree new_decl = NULL;
+ tree new_name = gen_var_name (i);
+ const char *name = IDENTIFIER_POINTER (new_name);
+ new_decl = create_tmp_var (type, name); /* New var name??? */
+ set_decl_attributes (new_decl);
+ add_referenced_var (new_decl);
+ get_var_ann (new_decl);
+ TREE_CHAIN (new_decl) = union_vars;
+ /* Do not emit any spurious uninitialized variable warning for
+ the synthesized variable. */
+ TREE_NO_WARNING (new_decl) = 1;
+ union_vars = new_decl;
+ return new_decl;
+}
+
+/* Build union VAR_DECLs for each partition in stack_vars */
+static void
+build_union_decls (void)
+{
+ int i;
+ tree outer_block = DECL_INITIAL (current_function_decl);
+ for (i = 0; i < stack_vars_num; i++)
+ {
+ if (stack_vars[i].next != EOC && stack_vars[i].representative == i)
+ {
+ tree new_type = build_union_type (i);
+ tree new_decl;
+ new_decl = create_new_var (new_type, i);
+ stack_vars[i].union_decl = new_decl;
+ }
+ }
+ BLOCK_VARS (outer_block) = chainon (BLOCK_VARS (outer_block), union_vars);
+
+}
+
+/* Hash function for overlay_decl_mapping */
+static hashval_t
+overlay_decl_mapping_hash (const void *x)
+{
+ return htab_hash_pointer (((const struct overlay_decl_mapping *)x)->decl);
+}
+
+/* Equality function for overlay_decl_mapping */
+static int
+overlay_decl_mapping_eq (const void *x, const void *y)
+{
+ return ((const struct overlay_decl_mapping *)x)->decl == (const_tree)y;
+}
+
+/* This function is a callback for traversal over decl_field_map
+ hashtable. SLOT is a pointer to struct overlay_decl_mapping. This
+ function frees memory allocated for overlay_decl_mapping and pointed
+ by *SLOT. */
+
+static int
+free_decl_field_map_entry (void **slot, void *data ATTRIBUTE_UNUSED)
+{
+ struct overlay_decl_mapping *entry = (struct overlay_decl_mapping *)*slot;
+ VEC_free (tree, gc, entry->value);
+ ggc_free (entry);
+ *slot = NULL;
+ return 1;
+}
+
+/* Free decl_field_map hashtable. */
+
+static void
+free_htab (htab_t table)
+{
+ if (table)
+ htab_traverse (table, free_decl_field_map_entry, NULL);
+ htab_delete (table);
+}
+
+static void
+add_to_decl_map (htab_t decl_map, tree union_decl, tree original_decl)
+{
+ void **slot =
+ htab_find_slot_with_hash (decl_map, union_decl,
+ htab_hash_pointer(union_decl), INSERT);
+ struct overlay_decl_mapping *map_entry =
+ (struct overlay_decl_mapping *)(*slot);
+ if (map_entry == NULL)
+ {
+ map_entry = GGC_CNEW (struct overlay_decl_mapping);
+ map_entry->decl = union_decl;
+ *slot = map_entry;
+ }
+ VEC_safe_push (tree, gc, map_entry->value, original_decl);
+}
+
+/* Given the DECL of a synthesized variable, return a vector of original
+ VAR_DECLs. */
+VEC(tree,gc) *
+get_original_stack_vars (tree union_decl)
+{
+ struct overlay_decl_mapping *entry;
+ if (cfun->union_decl_list_map == NULL)
+ return NULL;
+ entry = (struct overlay_decl_mapping *)htab_find_with_hash
+ (cfun->union_decl_list_map, union_decl, htab_hash_pointer(union_decl));
+ if (entry == NULL)
+ return NULL;
+ return entry->value;
+}
+
+/* Traverse the stack_vars array and build the decl_field_map table for
+ non-singleton partitions */
+static void
+build_decl_map (void)
+{
+ int i;
+ tree new_field_decl;
+
+ decl_field_map = htab_create (stack_vars_num, overlay_decl_mapping_hash,
+ overlay_decl_mapping_eq, NULL);
+ cfun->union_decl_list_map =
+ htab_create_ggc (stack_vars_num,overlay_decl_mapping_hash,
+ overlay_decl_mapping_eq, NULL);
+ for (i = 0; i < stack_vars_num; i++)
+ {
+ tree field = stack_vars[i].field_decl;
+ if (field != NULL)
+ {
+ tree field_type = TREE_TYPE (field);
+ tree base = stack_vars[i].union_decl;
+ if (base == NULL)
+ base = stack_vars[stack_vars[i].representative].union_decl;
+ new_field_decl =
+ build3 (COMPONENT_REF, field_type, base, field, NULL_TREE);
+ /* We need to retain the original variables to generate correct debug
+ information. But since it does not have any uses it will be removed
+ from REFERENCED_VARs which causes problems in alias analysis.
+ Prevent the removal of the variable from the REFERENCED_VARs by
+ setting TREE_ADDRESSABLE to 1. */
+ TREE_ADDRESSABLE (stack_vars[i].decl) = 0;
+ add_to_decl_map (decl_field_map, stack_vars[i].decl, new_field_decl);
+ add_to_decl_map (cfun->union_decl_list_map, base, stack_vars[i].decl);
+ }
+ }
+}
+/* Callback function used to replace trees matching original stack variables
+ with new union field declarations */
+static tree
+replace_vars_gimple_op (tree *tp, int *walk_subtrees, void *data)
+{
+ tree t = *tp;
+ struct overlay_decl_mapping *tree_pair =
+ (struct overlay_decl_mapping *)htab_find_with_hash
+ (decl_field_map, t, htab_hash_pointer(t));
+ data = data;
+ if (tree_pair != NULL)
+ {
+ *tp = VEC_index (tree, tree_pair->value, 0);
+ *walk_subtrees = 0;
+ if (data)
+ {
+ struct walk_stmt_info *wsi = (struct walk_stmt_info *)data;
+ wsi->changed = true;
+ }
+ }
+ return NULL;
+
+}
+
+/* Returns true if DECL is replaced by a synthesized VAR_DECL. */
+static bool
+replaced_var_decl (tree decl)
+{
+ struct overlay_decl_mapping *tree_pair =
+ (struct overlay_decl_mapping *)htab_find_with_hash
+ (decl_field_map, decl, htab_hash_pointer(decl));
+ return (tree_pair != NULL);
+}
+
+/* Replace all stack variables in a basic block */
+static void
+replace_vars_bb (basic_block bb)
+{
+ gimple_stmt_iterator gsi;
+ struct walk_stmt_info wsi;
+ for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+ {
+ gimple stmt;
+ stmt = gsi_stmt (gsi);
+ wsi.pset = NULL;
+ wsi.changed = false;
+ if (gimple_code (stmt) != GIMPLE_LABEL)
+ walk_gimple_op (stmt, replace_vars_gimple_op, &wsi);
+ if (wsi.changed)
+ update_stmt (stmt);
+ }
+ /* Traverse all PHI nodes in BB marking used operands. */
+ for (gsi = gsi_start_phis (bb); !gsi_end_p(gsi); gsi_next (&gsi))
+ {
+ use_operand_p arg_p;
+ gimple phi;
+ ssa_op_iter i;
+ phi = gsi_stmt (gsi);
+ FOR_EACH_PHI_ARG (arg_p, phi, i, SSA_OP_USE)
+ {
+ tree arg = USE_FROM_PTR (arg_p);
+ wsi.changed = false;
+ walk_tree (&arg, replace_vars_gimple_op, &wsi, NULL);
+ if (wsi.changed)
+ SET_USE (arg_p, arg);
+ }
+ }
+}
+
+/* Replace all stack variables in this function*/
+static void
+replace_vars (void)
+{
+ basic_block bb;
+ FOR_EACH_BB_FN (bb, cfun)
+ replace_vars_bb (bb);
+}
+
+/* Prepare for stack overlay. */
+static void
+init_stack_overlay (void)
+{
+ tree t;
+ /* Clear TREE_USED on all variables associated with a block scope. */
+ clear_tree_used (DECL_INITIAL (current_function_decl));
+
+ /* Set TREE_USED on all variables in the local_decls. */
+ for (t = cfun->local_decls; t; t = TREE_CHAIN (t))
+ TREE_USED (TREE_VALUE (t)) = 1;
+}
+
+/* Free up stack variable graph data. */
+static void
+fini_stack_overlay (void)
+{
+ size_t i, n = stack_vars_num;
+ tree *cell;
+ /* Remove replaced decls from local_decls. */
+ for (cell = &cfun->local_decls; *cell; )
+ {
+ tree var = TREE_VALUE (*cell);
+ if (replaced_var_decl (var))
+ {
+ *cell = TREE_CHAIN(*cell);
+ continue;
+ }
+ cell = &TREE_CHAIN (*cell);
+ }
+
+ for (i = 0; i < n; i++)
+ BITMAP_FREE (stack_vars[i].conflicts);
+ XDELETEVEC (stack_vars);
+ XDELETEVEC (stack_vars_sorted);
+ stack_vars = NULL;
+ stack_vars_sorted = NULL;
+ union_vars = NULL_TREE;
+ stack_vars_alloc = stack_vars_num = 0;
+ free_htab (decl_field_map);
+ decl_field_map = NULL;
+}
+
+static unsigned int
+execute_stack_overlay (void)
+{
+ tree outer_block = DECL_INITIAL (current_function_decl);
+
+
+ init_stack_overlay ();
+
+ /* At this point, all variables within the block tree with TREE_USED
+ set are actually used by the optimized function. Lay them out. */
+ add_stack_vars_in_block (outer_block, true);
+
+ if (stack_vars_num > 0)
+ {
+ /* Due to the way alias sets work, no variables with non-conflicting
+ alias sets may be assigned the same address. Add conflicts to
+ reflect this. */
+ add_alias_set_conflicts ();
+
+ /* If stack protection is enabled, we don't share space between
+ vulnerable data and non-vulnerable data. */
+ if (flag_stack_protect)
+ add_stack_protection_conflicts ();
+
+ /* Now that we have collected all stack variables, and have computed a
+ minimal interference graph, attempt to save some stack space. */
+ partition_stack_vars ();
+ if (dump_file)
+ dump_stack_var_partition ();
+ build_union_decls ();
+ build_decl_map ();
+ replace_vars ();
+ fini_stack_overlay ();
+ }
+
+
+ return 0;
+}
+
+static bool
+gate_stack_overlay (void)
+{
+ return flag_early_stack_alloc != 0;
+}
+
+struct gimple_opt_pass pass_stack_overlay=
+{
+ {
+ GIMPLE_PASS,
+ "stack-overlay", /* name */
+ gate_stack_overlay, /* gate */
+ execute_stack_overlay, /* execute */
+ NULL, /* sub */
+ NULL, /* next */
+ 0, /* static_pass_number */
+ 0, /* tv_id */
+ PROP_cfg, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ TODO_dump_func, /* todo_flags_finish */
+ }
+};
+
+#include "gt-tree-stack-overlay.h"
diff --git a/gcc-4.4.3/gcc/tree-stack-overlay.h b/gcc-4.4.3/gcc/tree-stack-overlay.h
new file mode 100644
index 000000000..f80e9899e
--- /dev/null
+++ b/gcc-4.4.3/gcc/tree-stack-overlay.h
@@ -0,0 +1,27 @@
+/* A pass for coalescing stack variables.
+ Copyright (C) 2010
+ Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+
+#ifndef TREE_STACK_OVERLAY_H
+#define TREE_STACK_OVERLAY_H
+
+VEC(tree,gc) *get_original_stack_vars (tree);
+
+#endif /* TREE_STACK_OVERLAY_H */
diff --git a/gcc-4.4.3/gcc/tree-threadsafe-analyze.c b/gcc-4.4.3/gcc/tree-threadsafe-analyze.c
index eb49db529..b7dfae5e0 100644
--- a/gcc-4.4.3/gcc/tree-threadsafe-analyze.c
+++ b/gcc-4.4.3/gcc/tree-threadsafe-analyze.c
@@ -45,6 +45,11 @@ along with GCC; see the file COPYING3. If not see
__attribute__ ((locks_excluded(__VA_ARGS__)))
__attribute__ ((lock_returned(x)))
__attribute__ ((no_thread_safety_analysis))
+ __attribute__ ((ignore_reads_begin))
+ __attribute__ ((ignore_reads_end))
+ __attribute__ ((ignore_writes_begin))
+ __attribute__ ((ignore_writes_end))
+ __attribute__ ((unprotected_read))
If multi-threaded code is annotated with these attributes, this analysis
pass can detect the following potential thread safety issues:
@@ -97,6 +102,13 @@ struct bb_threadsafe_info
/* Indicating whether the BB has been visited in the analysis. */
bool visited;
+ /* Flags indicating whether we should ignore reads or writes in the
+ analysis. The flags are set and unset during the analysis when seeing
+ function calls annotated with ignore_{reads|writes}_{begin|end}
+ attributes. */
+ bool reads_ignored;
+ bool writes_ignored;
+
/* Number of predecessors visited. Used for topological traversal of BBs. */
unsigned int n_preds_visited;
@@ -712,7 +724,12 @@ build_fully_qualified_lock (tree lock_field, tree base)
When matching two expressions, we currently only do it symbolically.
That is, if two different pointers, say p and q, point to the same
- location, they will not map to the same canonical expr. */
+ location, they will not map to the same canonical expr.
+
+ This function can also be called to get a canonical form of an expression
+ which may not be a lock. For example, when trying to canonicalize the base
+ object expression. And in that case, IS_TEMP_EXPR is set to true so that
+ the expression will not be inserted into the LOCK_EXPR_TAB. */
tree
get_canonical_lock_expr (tree lock, tree base_obj, bool is_temp_expr)
@@ -797,7 +814,8 @@ get_canonical_lock_expr (tree lock, tree base_obj, bool is_temp_expr)
We would like to ignore the "operator->" (or "operator.")
and simply return mu. We also treat the "get" method of
- a smart pointer the same as operator->. */
+ a smart pointer the same as operator->. And we only do it
+ when LOCK is indeed a lock expr, not some temp expr. */
else if (fdecl
&& ((DECL_NAME (fdecl)
== maybe_get_identifier ("operator->"))
@@ -805,6 +823,7 @@ get_canonical_lock_expr (tree lock, tree base_obj, bool is_temp_expr)
== maybe_get_identifier ("operator."))
|| (DECL_NAME (fdecl)
== maybe_get_identifier ("get")))
+ && !is_temp_expr
&& POINTER_TYPE_P (TREE_TYPE (lock))
&& lookup_attribute ("lockable", TYPE_ATTRIBUTES (
TREE_TYPE (TREE_TYPE (lock)))))
@@ -1579,6 +1598,15 @@ add_lock_to_lockset (gimple call, tree lockable,
acquires multiple locks, this function is called multiple times (see
process_function_attrs() below).
+ Besides the call itself (CALL), we also pass in the function decl (FDECL).
+ While the function decl of a call can be easily extracted by calling
+ gimple_call_fndecl in most cases, it becomes a bit tricky when the function
+ is virtual as gimple_call_fndecl will simply return NULL. We will need to
+ get the function decl through the reference object in this case.
+ Since we have already done all the things necessary to get the function
+ decl earlier (see handle_call_gs()), instead of doing the whole dance again
+ here, we might as well pass in the function decl that we extracted earlier.
+
The lock to be acquired is either the base object (i.e. BASE_OBJ)
when the primitive is a member function of a lockable class (e.g. "mu" in
mu->Lock()), or specified by an attribute parameter and passed in as ARG.
@@ -1586,13 +1614,12 @@ add_lock_to_lockset (gimple call, tree lockable,
argument that corresponds to the lock to be acquired. */
static void
-handle_lock_primitive_attrs (gimple call, tree arg, tree base_obj,
+handle_lock_primitive_attrs (gimple call, tree fdecl, tree arg, tree base_obj,
bool is_exclusive_lock, bool is_trylock,
struct pointer_set_t *live_excl_locks,
struct pointer_set_t *live_shared_locks,
const location_t *locus)
{
- tree fdecl = gimple_call_fndecl (call);
char lname[LOCK_NAME_LEN];
void **entry;
tree lockable;
@@ -1726,11 +1753,11 @@ remove_lock_from_lockset (tree lockable, struct pointer_set_t *live_excl_locks,
functions annotated with the "unlock" attribute). Besides taking the
lock out of the live lock set, it also checks whether the user code
is trying to release a lock that's not currently held. For the
- explanations on parameters ARG and BASE_OBJ, please see the comments for
- handle_lock_primitive_attrs above. */
+ explanations on parameters FDECL, ARG, and BASE_OBJ, please see the
+ comments for handle_lock_primitive_attrs above. */
static void
-handle_unlock_primitive_attr (gimple call, tree arg, tree base_obj,
+handle_unlock_primitive_attr (gimple call, tree fdecl, tree arg, tree base_obj,
struct bb_threadsafe_info *bbinfo,
const location_t *locus)
{
@@ -1774,7 +1801,6 @@ handle_unlock_primitive_attr (gimple call, tree arg, tree base_obj,
scoped_lock);
if (entry)
{
- tree fdecl = gimple_call_fndecl (call);
gcc_assert (fdecl);
lockable = (tree) *entry;
/* Since this is a scoped lock, if the unlock routine is
@@ -1822,6 +1848,147 @@ handle_unlock_primitive_attr (gimple call, tree arg, tree base_obj,
locus, dump_expr_tree (lockable, lname));
}
+/* A helper function for handling function "locks_excluded" attribute.
+ Check if LOCK is in the current live lock sets and emit warnings if so.
+
+ LOCK: the lock being examined.
+ FDECL: function decl of the call.
+ BASE_OBJ: base object if FDECL is a method (member function).
+ LIVE_EXCL_LOCKS: current live exclusive lock set.
+ LIVE_SHARED LOCKS: current live shared lock set.
+ LOCUS: location info of the call. */
+
+static void
+check_func_lock_excluded (tree lock, tree fdecl, tree base_obj,
+ const struct pointer_set_t *live_excl_locks,
+ const struct pointer_set_t *live_shared_locks,
+ const location_t *locus)
+{
+ tree lock_contained;
+
+ /* LOCK could be NULL if the front-end/parser cannot recognize it.
+ Simply ignore it and return. */
+ if (!lock)
+ return;
+
+ /* When the base obj tree is not an ADDR_EXPR, which means it is a
+ pointer (i.e. base->foo() or foo(base)), we will need to create
+ a new base that is INDIRECT_REF so that we would be able to form
+ a correct full expression for a lock later. On the other hand,
+ if the base obj is an ADDR_EXPR (i.e. base.foo() or foo(&base)),
+ we need to remove the address-taken operation. */
+ if (base_obj)
+ {
+ tree canon_base = get_canonical_lock_expr (base_obj, NULL_TREE,
+ true /* is_temp_expr */);
+ if (TREE_CODE (canon_base) != ADDR_EXPR)
+ {
+ gcc_assert (POINTER_TYPE_P (TREE_TYPE (canon_base)));
+ base_obj = build1 (INDIRECT_REF,
+ TREE_TYPE (TREE_TYPE (canon_base)),
+ canon_base);
+ }
+ else
+ base_obj = TREE_OPERAND (canon_base, 0);
+ }
+
+ if (!DECL_P (lock))
+ lock = get_canonical_lock_expr (lock, NULL_TREE, false /* is_temp_expr */);
+
+ /* Check if the excluded lock is in the live lock sets when the
+ function is called. If so, issue a warning. */
+ if ((lock_contained = lock_set_contains (live_excl_locks, lock,
+ base_obj, true))
+ || (lock_contained = lock_set_contains (live_shared_locks, lock,
+ base_obj, true)))
+ {
+ char lname[LOCK_NAME_LEN];
+ void **entry = pointer_map_contains (lock_locus_map, lock_contained);
+ if (entry)
+ warning (OPT_Wthread_safety,
+ G_("%HCannot call function %qE with lock %s held"
+ " (previously acquired at line %d)"),
+ locus, DECL_NAME (fdecl),
+ dump_expr_tree (lock_contained, lname),
+ LOCATION_LINE (*((location_t *) *entry)));
+ else
+ warning (OPT_Wthread_safety,
+ G_("%HCannot call function %qE with lock %s held"
+ " (at function entry)"),
+ locus, DECL_NAME (fdecl),
+ dump_expr_tree (lock_contained, lname));
+ }
+}
+
+/* Function lock requirement type. */
+
+enum FUNC_LOCK_REQ_TYPE {
+ FLR_EXCL_LOCK_REQUIRED,
+ FLR_SHARED_LOCK_REQUIRED,
+ FLR_LOCK_EXCLUDED
+};
+
+/* Handle function lock requirement attributes ("exclusive_locks_required",
+ "shared_locks_required", and "locks_excluded").
+
+ CALL: function/method call that's currently being examined.
+ FDECL: function/method decl of the call.
+ BASE_OBJ: base object if FDECL is a method (member function).
+ ATTR: attribute of type FUNC_LOCK_REQ_TYPE.
+ REQ_TYPE: function lock requirement type.
+ LIVE_EXCL_LOCKS: current live exclusive lock set.
+ LIVE_SHARED LOCKS: current live shared lock set.
+ LOCUS: location info of the call. */
+
+static void
+handle_function_lock_requirement (gimple call, tree fdecl, tree base_obj,
+ tree attr, enum FUNC_LOCK_REQ_TYPE req_type,
+ const struct pointer_set_t *live_excl_locks,
+ const struct pointer_set_t *live_shared_locks,
+ const location_t *locus)
+{
+ tree arg;
+ tree lock;
+
+ for (arg = TREE_VALUE (attr); arg; arg = TREE_CHAIN (arg))
+ {
+ tree tmp_base_obj = base_obj;
+ lock = TREE_VALUE (arg);
+ gcc_assert (lock);
+ /* If lock is the error_mark_node, just set it to NULL_TREE so that
+ we will reduce the level of checking later. (i.e. Only check whether
+ there is any live lock at this point in check_lock_required and
+ ignore the lock in check_func_lock_excluded.) */
+ if (lock == error_mark_node)
+ lock = NULL_TREE;
+ else if (TREE_CODE (lock) == INTEGER_CST)
+ {
+ lock = get_actual_argument_from_position (call, lock);
+ /* If the lock is a function argument, we don't want to
+ prepend the base object to the lock name. Set the
+ TMP_BASE_OBJ to NULL. */
+ tmp_base_obj = NULL_TREE;
+ }
+
+ if (req_type == FLR_EXCL_LOCK_REQUIRED)
+ check_lock_required (lock, fdecl, tmp_base_obj,
+ false /* is_indirect_ref */,
+ live_excl_locks, live_shared_locks,
+ locus, TSA_WRITE);
+ else if (req_type == FLR_SHARED_LOCK_REQUIRED)
+ check_lock_required (lock, fdecl, tmp_base_obj,
+ false /* is_indirect_ref */,
+ live_excl_locks, live_shared_locks,
+ locus, TSA_READ);
+ else
+ {
+ gcc_assert (req_type == FLR_LOCK_EXCLUDED);
+ check_func_lock_excluded (lock, fdecl, tmp_base_obj,
+ live_excl_locks, live_shared_locks, locus);
+ }
+ }
+}
+
/* The main routine that handles the thread safety attributes for
functions. CALL is the call expression being analyzed. FDECL is its
corresponding function decl tree. LIVE_EXCL_LOCKS and LIVE_SHARED_LOCKS
@@ -1836,13 +2003,27 @@ process_function_attrs (gimple call, tree fdecl,
struct pointer_set_t *live_excl_locks = current_bb_info->live_excl_locks;
struct pointer_set_t *live_shared_locks = current_bb_info->live_shared_locks;
tree attr = NULL_TREE;
- char lname[LOCK_NAME_LEN];
tree base_obj = NULL_TREE;
bool is_exclusive_lock;
bool is_trylock;
gcc_assert (is_gimple_call (call));
+ /* First check if the function call is annotated with any escape-hatch
+ related attributes and set/reset the corresponding flags if so. */
+ if (lookup_attribute("ignore_reads_begin", DECL_ATTRIBUTES (fdecl))
+ != NULL_TREE)
+ current_bb_info->reads_ignored = true;
+ if (lookup_attribute("ignore_reads_end", DECL_ATTRIBUTES (fdecl))
+ != NULL_TREE)
+ current_bb_info->reads_ignored = false;
+ if (lookup_attribute("ignore_writes_begin", DECL_ATTRIBUTES (fdecl))
+ != NULL_TREE)
+ current_bb_info->writes_ignored = true;
+ if (lookup_attribute("ignore_writes_end", DECL_ATTRIBUTES (fdecl))
+ != NULL_TREE)
+ current_bb_info->writes_ignored = false;
+
/* If the function is a class member, the first argument of the function
(i.e. "this" pointer) would be the base object. */
if (TREE_CODE (TREE_TYPE (fdecl)) == METHOD_TYPE)
@@ -1900,16 +2081,16 @@ process_function_attrs (gimple call, tree fdecl,
in its arguments, we iterate through the argument list and
handle each of the locks individually. */
for (; arg; arg = TREE_CHAIN (arg))
- handle_lock_primitive_attrs (call, TREE_VALUE (arg), base_obj,
- is_exclusive_lock, is_trylock,
- live_excl_locks,
+ handle_lock_primitive_attrs (call, fdecl, TREE_VALUE (arg),
+ base_obj, is_exclusive_lock,
+ is_trylock, live_excl_locks,
live_shared_locks, locus);
}
else
{
/* If the attribute does not have any argument left, the lock to
be acquired is the base obj (e.g. "mu" in mu->TryLock()). */
- handle_lock_primitive_attrs (call, NULL_TREE, base_obj,
+ handle_lock_primitive_attrs (call, fdecl, NULL_TREE, base_obj,
is_exclusive_lock, is_trylock,
live_excl_locks, live_shared_locks,
locus);
@@ -1931,7 +2112,7 @@ process_function_attrs (gimple call, tree fdecl,
/* If the attribute does not have any argument, the lock to be
acquired is the base obj (e.g. "mu" in mu->Lock()). */
gcc_assert (!is_trylock);
- handle_lock_primitive_attrs (call, NULL_TREE, base_obj,
+ handle_lock_primitive_attrs (call, fdecl, NULL_TREE, base_obj,
is_exclusive_lock, is_trylock,
live_excl_locks, live_shared_locks,
locus);
@@ -1961,131 +2142,41 @@ process_function_attrs (gimple call, tree fdecl,
warn_thread_mismatched_lock_acq_rel = 0;
continue;
}
- handle_unlock_primitive_attr (call, TREE_VALUE (arg), base_obj,
- current_bb_info, locus);
+ handle_unlock_primitive_attr (call, fdecl, TREE_VALUE (arg),
+ base_obj, current_bb_info, locus);
}
}
else
/* If the attribute does not have any argument, the lock to be
released is the base obj (e.g. "mu" in mu->Unlock()). */
- handle_unlock_primitive_attr (call, NULL_TREE, base_obj,
+ handle_unlock_primitive_attr (call, fdecl, NULL_TREE, base_obj,
current_bb_info, locus);
}
if (warn_thread_unguarded_func)
{
- tree arg;
- tree lock;
-
/* Handle the attributes specifying the lock requirements of
functions. */
- if ((attr = lookup_attribute("exclusive_locks_required",
- DECL_ATTRIBUTES (fdecl))) != NULL_TREE)
- {
- for (arg = TREE_VALUE (attr); arg; arg = TREE_CHAIN (arg))
- {
- lock = TREE_VALUE (arg);
- gcc_assert (lock);
- /* If lock is the error_mark_node, just set it to NULL_TREE
- so that check_lock_required will reduce the level of checking
- (i.e. only checks whether there is any live lock at this
- point. */
- if (lock == error_mark_node)
- lock = NULL_TREE;
- else if (TREE_CODE (lock) == INTEGER_CST)
- lock = get_actual_argument_from_position (call, lock);
- check_lock_required (lock, fdecl, base_obj,
- false /* is_indirect_ref */,
- live_excl_locks, live_shared_locks,
- locus, TSA_WRITE);
- }
- }
+ if ((attr = lookup_attribute ("exclusive_locks_required",
+ DECL_ATTRIBUTES (fdecl))) != NULL_TREE)
+ handle_function_lock_requirement (call, fdecl, base_obj, attr,
+ FLR_EXCL_LOCK_REQUIRED,
+ live_excl_locks, live_shared_locks,
+ locus);
- if ((attr = lookup_attribute("shared_locks_required",
- DECL_ATTRIBUTES (fdecl))) != NULL_TREE)
- {
- for (arg = TREE_VALUE (attr); arg; arg = TREE_CHAIN (arg))
- {
- lock = TREE_VALUE (arg);
- gcc_assert (lock);
- /* If lock is the error_mark_node, just set it to NULL_TREE
- so that check_lock_required will reduce the level of checking
- (i.e. only checks whether there is any live lock at this
- point. */
- if (lock == error_mark_node)
- lock = NULL_TREE;
- else if (TREE_CODE (lock) == INTEGER_CST)
- lock = get_actual_argument_from_position (call, lock);
- check_lock_required (lock, fdecl, base_obj,
- false /* is_indirect_ref */,
- live_excl_locks, live_shared_locks,
- locus, TSA_READ);
- }
- }
+ if ((attr = lookup_attribute ("shared_locks_required",
+ DECL_ATTRIBUTES (fdecl))) != NULL_TREE)
+ handle_function_lock_requirement (call, fdecl, base_obj, attr,
+ FLR_SHARED_LOCK_REQUIRED,
+ live_excl_locks, live_shared_locks,
+ locus);
- if ((attr = lookup_attribute("locks_excluded", DECL_ATTRIBUTES (fdecl)))
+ if ((attr = lookup_attribute ("locks_excluded", DECL_ATTRIBUTES (fdecl)))
!= NULL_TREE)
- {
- /* When the base obj tree is not an ADDR_EXPR, which means it is a
- pointer (i.e. base->foo() or foo(base)), we will need to create
- a new base that is INDIRECT_REF so that we would be able to form
- a correct full expression for a lock later. On the other hand,
- if the base obj is an ADDR_EXPR (i.e. base.foo() or foo(&base)),
- we need to remove the address-taken operation. */
- if (base_obj)
- {
- tree canon_base = get_canonical_lock_expr (base_obj, NULL_TREE,
- true /* is_temp_expr */);
- if (TREE_CODE (canon_base) != ADDR_EXPR)
- {
- gcc_assert (POINTER_TYPE_P (TREE_TYPE (canon_base)));
- base_obj = build1 (INDIRECT_REF,
- TREE_TYPE (TREE_TYPE (canon_base)),
- canon_base);
- }
- else
- base_obj = TREE_OPERAND (canon_base, 0);
- }
-
- for (arg = TREE_VALUE (attr); arg; arg = TREE_CHAIN (arg))
- {
- tree lock_contained;
- lock = TREE_VALUE (arg);
- gcc_assert (lock);
- /* If lock is the error_mark_node, just ignore it. */
- if (lock == error_mark_node)
- continue;
- if (TREE_CODE (lock) == INTEGER_CST)
- lock = get_actual_argument_from_position (call, lock);
- lock = get_canonical_lock_expr (lock, NULL_TREE,
- false /* is_temp_expr */);
- gcc_assert (lock);
- /* Check if the excluded lock is in the live lock sets when the
- function is called. If so, issue a warning. */
- if ((lock_contained = lock_set_contains (live_excl_locks,
- lock, base_obj, true))
- || (lock_contained = lock_set_contains (live_shared_locks,
- lock, base_obj,
- true)))
- {
- void **entry = pointer_map_contains (lock_locus_map,
- lock_contained);
- if (entry)
- warning (OPT_Wthread_safety,
- G_("%HCannot call function %qE with lock %s held"
- " (previously acquired at line %d)"),
- locus, DECL_NAME (fdecl),
- dump_expr_tree (lock_contained, lname),
- LOCATION_LINE (*((location_t *) *entry)));
- else
- warning (OPT_Wthread_safety,
- G_("%HCannot call function %qE with lock %s held"
- " (at function entry)"),
- locus, DECL_NAME (fdecl),
- dump_expr_tree (lock_contained, lname));
- }
- }
- }
+ handle_function_lock_requirement (call, fdecl, base_obj, attr,
+ FLR_LOCK_EXCLUDED,
+ live_excl_locks, live_shared_locks,
+ locus);
}
}
@@ -2203,6 +2294,7 @@ handle_call_gs (gimple call, struct bb_threadsafe_info *current_bb_info)
tree fdecl = gimple_call_fndecl (call);
int num_args = gimple_call_num_args (call);
int arg_index = 0;
+ tree arg_type = NULL_TREE;
tree arg;
tree lhs;
location_t locus;
@@ -2226,80 +2318,148 @@ handle_call_gs (gimple call, struct bb_threadsafe_info *current_bb_info)
/* The callee fndecl could be NULL, e.g., when the function is passed in
as an argument. */
- if (fdecl && TREE_CODE (TREE_TYPE (fdecl)) == METHOD_TYPE)
- {
- /* If an object, x, is guarded by a lock, whether or not calling
- x.foo() requires an exclusive lock depends on if foo() is const.
- TODO: Note that to determine if a class member function is const, we
- would've liked to use DECL_CONST_MEMFUNC_P instead of the following
- long sequence of macro calls. However, we got an undefined reference
- to `cp_type_quals' at link time when using DECL_CONST_MEMFUNC_P. */
- bool is_const_memfun = TYPE_READONLY
- (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (fdecl)))));
- enum access_mode rw_mode = is_const_memfun ? TSA_READ : TSA_WRITE;
-
- /* A method should have at least one argument, i.e."this" pointer */
- gcc_assert (num_args);
- arg = gimple_call_arg (call, 0);
-
- /* If the base object (i.e. "this" object) is a SSA name of a temp
- variable, as shown in the following example (assuming the source
- code is 'base.method_call()'):
-
- D.5041_2 = &this_1(D)->base;
- result.0_3 = method_call (D.5041_2);
-
- we will need to get the rhs of the SSA def of the temp variable
- in order for the analysis to work correctly. */
- if (TREE_CODE (arg) == SSA_NAME)
+ if (fdecl)
+ {
+ arg_type = TYPE_ARG_TYPES (TREE_TYPE (fdecl));
+ if (TREE_CODE (TREE_TYPE (fdecl)) == METHOD_TYPE)
{
- tree vdecl = SSA_NAME_VAR (arg);
- if (DECL_ARTIFICIAL (vdecl)
- && !gimple_nop_p (SSA_NAME_DEF_STMT (arg)))
+ /* If an object, x, is guarded by a lock, whether or not
+ calling x.foo() requires an exclusive lock depends on
+ if foo() is const. */
+ enum access_mode rw_mode =
+ lang_hooks.decl_is_const_member_func (fdecl) ? TSA_READ
+ : TSA_WRITE;
+
+ /* A method should have at least one argument, i.e."this" pointer */
+ gcc_assert (num_args);
+ arg = gimple_call_arg (call, 0);
+
+ /* If the base object (i.e. "this" object) is a SSA name of a temp
+ variable, as shown in the following example (assuming the source
+ code is 'base.method_call()'):
+
+ D.5041_2 = &this_1(D)->base;
+ result.0_3 = method_call (D.5041_2);
+
+ we will need to get the rhs of the SSA def of the temp variable
+ in order for the analysis to work correctly. */
+ if (TREE_CODE (arg) == SSA_NAME)
{
- gimple def_stmt = SSA_NAME_DEF_STMT (arg);
- if (is_gimple_assign (def_stmt)
- && (get_gimple_rhs_class (gimple_assign_rhs_code (def_stmt))
- == GIMPLE_SINGLE_RHS))
- arg = gimple_assign_rhs1 (def_stmt);
+ tree vdecl = SSA_NAME_VAR (arg);
+ if (DECL_ARTIFICIAL (vdecl)
+ && !gimple_nop_p (SSA_NAME_DEF_STMT (arg)))
+ {
+ gimple def_stmt = SSA_NAME_DEF_STMT (arg);
+ if (is_gimple_assign (def_stmt)
+ && (get_gimple_rhs_class (gimple_assign_rhs_code (
+ def_stmt)) == GIMPLE_SINGLE_RHS))
+ arg = gimple_assign_rhs1 (def_stmt);
+ }
}
- }
- /* Analyze the base object ("this"). */
- if (TREE_CODE (arg) == ADDR_EXPR)
- {
- /* Handle the case of x.foo() or foo(&x) */
- analyze_expr (TREE_OPERAND (arg, 0), NULL_TREE,
- false /* is_indirect_ref */,
- current_bb_info->live_excl_locks,
- current_bb_info->live_shared_locks, &locus, rw_mode);
- }
- else
- {
- /* Handle the case of x->foo() or foo(x) */
- gcc_assert (POINTER_TYPE_P (TREE_TYPE (arg)));
- handle_indirect_ref(arg, current_bb_info->live_excl_locks,
- current_bb_info->live_shared_locks,
- &locus, rw_mode);
- }
+ /* Analyze the base object ("this") if we are not instructed to
+ ignore it. */
+ if (!(current_bb_info->reads_ignored && rw_mode == TSA_READ)
+ && !(current_bb_info->writes_ignored && rw_mode == TSA_WRITE))
+ {
+ if (TREE_CODE (arg) == ADDR_EXPR)
+ {
+ /* Handle smart/scoped pointers. They are not actual
+ pointers but they can be annotated with
+ "point_to_guarded_by" attribute and have overloaded "->"
+ and "*" operators, so we treat them as normal pointers. */
+ if ((DECL_NAME (fdecl) == maybe_get_identifier ("operator->"))
+ || (DECL_NAME (fdecl)
+ == maybe_get_identifier ("operator*")))
+ handle_indirect_ref(TREE_OPERAND (arg, 0),
+ current_bb_info->live_excl_locks,
+ current_bb_info->live_shared_locks,
+ &locus, rw_mode);
+ else
+ /* Handle the case of x.foo() or foo(&x) */
+ analyze_expr (TREE_OPERAND (arg, 0), NULL_TREE,
+ false /* is_indirect_ref */,
+ current_bb_info->live_excl_locks,
+ current_bb_info->live_shared_locks, &locus,
+ rw_mode);
+ }
+ else
+ {
+ /* Handle the case of x->foo() or foo(x) */
+ gcc_assert (POINTER_TYPE_P (TREE_TYPE (arg)));
+ handle_indirect_ref(arg, current_bb_info->live_excl_locks,
+ current_bb_info->live_shared_locks,
+ &locus, rw_mode);
+ }
+ }
- /* Advance to the next argument */
- ++arg_index;
+ /* Advance to the next argument */
+ ++arg_index;
+ arg_type = TREE_CHAIN (arg_type);
+ }
}
- /* Analyze the call's arguments */
- for ( ; arg_index < num_args; ++arg_index)
+ /* Analyze the call's arguments if we are not instructed to ignore the
+ reads. */
+ if (!current_bb_info->reads_ignored
+ && (!fdecl
+ || !lookup_attribute("unprotected_read", DECL_ATTRIBUTES (fdecl))))
{
- arg = gimple_call_arg (call, arg_index);
- if (!CONSTANT_CLASS_P (arg))
- analyze_expr (arg, NULL_TREE, false /* is_indirect_ref */,
- current_bb_info->live_excl_locks,
- current_bb_info->live_shared_locks, &locus, TSA_READ);
+ for ( ; arg_index < num_args; ++arg_index)
+ {
+ arg = gimple_call_arg (call, arg_index);
+ if (!CONSTANT_CLASS_P (arg))
+ {
+ /* In analyze_expr routine, an address-taken expr (e.g. &x) will
+ be skipped because the variable itself is not actually
+ accessed. However, if an argument which is an address-taken
+ expr, say &x, is passed into a function for a reference
+ parameter, we want to treat it as a use of x because this is
+ what users expect and most likely x will be used in the
+ callee body anyway. */
+ if (arg_type
+ && TREE_CODE (TREE_VALUE (arg_type)) == REFERENCE_TYPE)
+ {
+ tree canon_arg = arg;
+ /* The argument could be an SSA_NAME. Try to get the rhs of
+ its SSA_DEF. */
+ if (TREE_CODE (arg) == SSA_NAME)
+ {
+ tree vdecl = SSA_NAME_VAR (arg);
+ if (DECL_ARTIFICIAL (vdecl)
+ && !gimple_nop_p (SSA_NAME_DEF_STMT (arg)))
+ {
+ gimple def_stmt = SSA_NAME_DEF_STMT (arg);
+ if (is_gimple_assign (def_stmt)
+ && (get_gimple_rhs_class (
+ gimple_assign_rhs_code (def_stmt))
+ == GIMPLE_SINGLE_RHS))
+ canon_arg = gimple_assign_rhs1 (def_stmt);
+ }
+ }
+ /* For an argument which is an ADDR_EXPR, say &x, that
+ corresponds to a reference parameter, remove the
+ address-taken operator and only pass 'x' to
+ analyze_expr. */
+ if (TREE_CODE (canon_arg) == ADDR_EXPR)
+ arg = TREE_OPERAND (canon_arg, 0);
+ }
+
+ analyze_expr (arg, NULL_TREE, false /* is_indirect_ref */,
+ current_bb_info->live_excl_locks,
+ current_bb_info->live_shared_locks, &locus,
+ TSA_READ);
+ }
+
+ if (arg_type)
+ arg_type = TREE_CHAIN (arg_type);
+ }
}
- /* Analyze the call's lhs if existing. */
+ /* Analyze the call's lhs if it exists and we are not instructed to ignore
+ the writes. */
lhs = gimple_call_lhs (call);
- if (lhs != NULL_TREE)
+ if (lhs != NULL_TREE && !current_bb_info->writes_ignored)
analyze_expr (lhs, NULL_TREE, false /* is_indirect_ref */,
current_bb_info->live_excl_locks,
current_bb_info->live_shared_locks, &locus, TSA_WRITE);
@@ -2879,7 +3039,11 @@ analyze_op_r (tree *tp, int *walk_subtrees, void *data)
enum access_mode mode = wi->is_lhs ? TSA_WRITE : TSA_READ;
location_t locus;
- if (!CONSTANT_CLASS_P (*tp))
+ /* Analyze the statement operand if we are not instructed to ignore the
+ reads or writes and if it is not a constant. */
+ if (!(current_bb_info->reads_ignored && mode == TSA_READ)
+ && !(current_bb_info->writes_ignored && mode == TSA_WRITE)
+ && !CONSTANT_CLASS_P (*tp))
{
if (!gimple_has_location (stmt))
locus = input_location;
@@ -3052,9 +3216,14 @@ execute_threadsafe_analyze (void)
continue;
/* If this is the first predecessor of bb's, simply copy the
- predecessor's live-out sets to bb's live (working) sets. */
+ predecessor's live-out sets and reads/writes_ignored flags
+ to bb's live (working) sets and corresponding flags. */
if (current_bb_info->live_excl_locks == NULL)
{
+ current_bb_info->reads_ignored =
+ threadsafe_info[pred_bb->index].reads_ignored;
+ current_bb_info->writes_ignored =
+ threadsafe_info[pred_bb->index].writes_ignored;
current_bb_info->live_excl_locks = pointer_set_copy (
threadsafe_info[pred_bb->index].liveout_exclusive_locks);
current_bb_info->live_shared_locks = pointer_set_copy (
@@ -3116,6 +3285,15 @@ execute_threadsafe_analyze (void)
}
}
+ /* Logical-and'ing the current BB's reads/writes_ignored flags with
+ predecessor's flags. These flags will be true at the beginning
+ of a BB only when they are true at the end of all the
+ precedecessors. */
+ current_bb_info->reads_ignored &=
+ threadsafe_info[pred_bb->index].reads_ignored;
+ current_bb_info->writes_ignored &=
+ threadsafe_info[pred_bb->index].writes_ignored;
+
/* Intersect the current (working) live set with the predecessor's
live-out set. Locks that are not in the intersection (i.e.
complement set) should be reported as improperly released. */
diff --git a/gcc-4.4.3/gcc/tree-vrp.c b/gcc-4.4.3/gcc/tree-vrp.c
index e14949f8a..f03412f24 100644
--- a/gcc-4.4.3/gcc/tree-vrp.c
+++ b/gcc-4.4.3/gcc/tree-vrp.c
@@ -5682,7 +5682,7 @@ vrp_evaluate_conditional (enum tree_code code, tree op0, tree op1, gimple stmt)
{
bool sop;
tree ret;
- bool only_ranges;
+ bool only_ranges = false;
/* Some passes and foldings leak constants with overflow flag set
into the IL. Avoid doing wrong things with these and bail out. */
diff --git a/gcc-4.4.3/gcc/unwind-dw2-fde-glibc.c b/gcc-4.4.3/gcc/unwind-dw2-fde-glibc.c
index d246ae124..11f53dd31 100644
--- a/gcc-4.4.3/gcc/unwind-dw2-fde-glibc.c
+++ b/gcc-4.4.3/gcc/unwind-dw2-fde-glibc.c
@@ -33,7 +33,7 @@
#include "tconfig.h"
#include "tsystem.h"
#ifndef inhibit_libc
-#include <link.h>
+#include <elf.h> /* Get DT_CONFIG. */
#endif
#include "coretypes.h"
#include "tm.h"
@@ -49,6 +49,8 @@
&& (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) \
|| (__GLIBC__ == 2 && __GLIBC_MINOR__ == 2 && defined(DT_CONFIG)))
+#include <link.h>
+
#ifndef __RELOC_POINTER
# define __RELOC_POINTER(ptr, base) ((ptr) + (base))
#endif
diff --git a/gcc-4.4.3/gcc/value-prof.c b/gcc-4.4.3/gcc/value-prof.c
index efbdea91a..6b1402d56 100644
--- a/gcc-4.4.3/gcc/value-prof.c
+++ b/gcc-4.4.3/gcc/value-prof.c
@@ -50,6 +50,9 @@ along with GCC; see the file COPYING3. If not see
#include "params.h"
#include "tree-sample-profile.h"
+/* TODO(martint): Switch from math.h to mpfr.h. */
+#include <math.h>
+
static struct value_prof_hooks *value_prof_hooks;
/* In this file value profile based optimizations are placed. Currently the
@@ -86,6 +89,7 @@ static tree gimple_divmod_fixed_value (gimple, tree, int, gcov_type, gcov_type);
static tree gimple_mod_pow2 (gimple, int, gcov_type, gcov_type);
static tree gimple_mod_subtract (gimple, int, int, int, gcov_type, gcov_type,
gcov_type);
+static bool gimple_float_math_call_transform (gimple_stmt_iterator *);
static bool gimple_divmod_fixed_value_transform (gimple_stmt_iterator *);
static bool gimple_mod_pow2_value_transform (gimple_stmt_iterator *);
static bool gimple_mod_subtract_transform (gimple_stmt_iterator *);
@@ -256,6 +260,20 @@ dump_histogram_value (FILE *dump_file, histogram_value hist)
}
fprintf (dump_file, ".\n");
break;
+ case HIST_TYPE_SINGLE_FLOAT_VALUE:
+ fprintf (dump_file, "Single float value ");
+ if (hist->hvalue.counters)
+ {
+ fprintf (dump_file, "value:%f"
+ " match:"HOST_WIDEST_INT_PRINT_DEC
+ " wrong:"HOST_WIDEST_INT_PRINT_DEC,
+ gcov_type_to_float (hist->hvalue.counters[0]),
+ (HOST_WIDEST_INT) hist->hvalue.counters[1],
+ (HOST_WIDEST_INT) hist->hvalue.counters[2]);
+ }
+ fprintf (dump_file, ".\n");
+ break;
+
case HIST_TYPE_AVERAGE:
fprintf (dump_file, "Average value ");
@@ -562,6 +580,65 @@ check_ic_counter (gimple stmt, gcov_type *count1, gcov_type *count2,
return false;
}
+/* Process the math functions given by --ffvpt-functions=. */
+struct ffvpt_options_s
+ffvtp_process_options (const char *arg)
+{
+ const char *start = arg;
+
+ struct ffvpt_options_s ffvpt_options;
+ ffvpt_options.exp_set = 0;
+ ffvpt_options.log_set = 0;
+ ffvpt_options.pow_set = 0;
+ ffvpt_options.sqrt_set = 0;
+
+ while (*start)
+ {
+ if (strncmp ("all", start, 3) == 0
+ && (start[4] == '\0' || start[3] == ','))
+ {
+ ffvpt_options.exp_set = 1;
+ ffvpt_options.log_set = 1;
+ ffvpt_options.pow_set = 1;
+ ffvpt_options.sqrt_set = 1;
+ break;
+ }
+
+ if (strncmp ("exp", start, 3) == 0
+ && (start[3] == '\0' || start[3] == ','))
+ ffvpt_options.exp_set = 1;
+ else if (strncmp ("log", start, 3) == 0
+ && (start[3] == '\0' || start[3] == ','))
+ ffvpt_options.log_set = 1;
+ else if (strncmp ("pow", start, 3) == 0
+ && (start[3] == '\0' || start[3] == ','))
+ ffvpt_options.pow_set = 1;
+ else if (strncmp ("sqrt", start, 4) == 0
+ && (start[4] == '\0' || start[4] == ','))
+ ffvpt_options.sqrt_set = 1;
+ else
+ warning (0, "Unsupported function in the beginning of: %qs", start);
+ start = strchr (start,',');
+ if (start != NULL)
+ ++start;
+ else
+ break;
+ }
+ return ffvpt_options;
+}
+
+/* Return if flags allow for ffvpt optimizations. */
+static bool
+do_float_value_profile_transformations (void)
+{
+ return flag_float_value_profile_transformations
+ && (ffvpt_options.exp_set
+ || ffvpt_options.log_set
+ || ffvpt_options.pow_set
+ || ffvpt_options.sqrt_set);
+}
+
+
/* GIMPLE based transformations. */
@@ -604,12 +681,14 @@ gimple_value_profile_transformations (void)
current statement remain valid (although possibly
modified) upon return. */
if (flag_value_profile_transformations
- && (gimple_mod_subtract_transform (&gsi)
- || gimple_divmod_fixed_value_transform (&gsi)
- || gimple_mod_pow2_value_transform (&gsi)
- || gimple_stringops_transform (&gsi)
- || gimple_ic_transform (stmt)))
- {
+ && ((gimple_mod_subtract_transform (&gsi)
+ || gimple_divmod_fixed_value_transform (&gsi)
+ || gimple_mod_pow2_value_transform (&gsi)
+ || gimple_stringops_transform (&gsi)
+ || gimple_ic_transform (stmt))
+ || (do_float_value_profile_transformations ()
+ && gimple_float_math_call_transform (&gsi))))
+ {
stmt = gsi_stmt (gsi);
changed = true;
/* Original statement may no longer be in the same block. */
@@ -711,7 +790,7 @@ gimple_divmod_fixed_value (gimple stmt, tree value, int prob, gcov_type count,
e13->count = all - count;
remove_edge (e23);
-
+
e24 = make_edge (bb2, bb4, EDGE_FALLTHRU);
e24->probability = REG_BR_PROB_BASE;
e24->count = count;
@@ -723,6 +802,209 @@ gimple_divmod_fixed_value (gimple stmt, tree value, int prob, gcov_type count,
}
+/* Replace a math function call with a series of statements that check
+ for a specific input value and if found, use a precalculated value.
+e.g.:
+ a = fn(b)
+-->
+ if (b == k_1): // bb1
+ a = k2 // bb2
+ else
+ a = fn(b) // bb3
+ // bb4
+*/
+static tree
+gimple_ffvpt_update_math_calls (gimple stmt, tree value, int prob,
+ gcov_type count, gcov_type all,
+ tree new_value_expr)
+{
+
+ gimple stmt1, stmt2, stmt3;
+ tree tmp_b, tmp_a, tmp_k1;
+ gimple bb1end, bb2end, bb3end;
+ basic_block bb, bb2, bb3, bb4;
+ tree optype; /* , calltree; */
+ edge e12, e13, e23, e24, e34;
+ gimple_stmt_iterator gsi;
+
+ gcc_assert (is_gimple_call (stmt));
+
+ optype = TREE_TYPE (gimple_assign_lhs (stmt)); /* double variable */
+
+ bb = gimple_bb (stmt);
+ gsi = gsi_for_stmt (stmt);
+
+ tmp_k1 = create_tmp_var (optype, "PROF");
+ tmp_b = create_tmp_var (optype, "PROF");
+ stmt1 = gimple_build_assign (tmp_k1, fold_convert (optype, value));
+ /* Get the value from the call. */
+ stmt2 = gimple_build_assign (tmp_b, gimple_call_arg (stmt, 0));
+ stmt3 = gimple_build_cond (NE_EXPR, tmp_b, tmp_k1, NULL_TREE, NULL_TREE);
+ gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
+ gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT);
+ gsi_insert_before (&gsi, stmt3, GSI_SAME_STMT);
+ bb1end = stmt3;
+ /* a = k_2 */
+ tmp_a = gimple_get_lhs (stmt);
+ stmt1 = gimple_build_assign (tmp_a, new_value_expr);
+ gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
+ bb2end = stmt1;
+ bb3end = stmt;
+ /* Fix CFG. */
+ /* Edge e23 connects bb2 to bb3, etc. */
+ e12 = split_block (bb, bb1end);
+ bb2 = e12->dest;
+ bb2->count = count;
+ e23 = split_block (bb2, bb2end);
+ bb3 = e23->dest;
+ bb3->count = all - count;
+ e34 = split_block (bb3, bb3end);
+ bb4 = e34->dest;
+ bb4->count = all;
+
+ e12->flags &= ~EDGE_FALLTHRU;
+ e12->flags |= EDGE_FALSE_VALUE;
+ e12->probability = prob;
+ e12->count = count;
+ e13 = make_edge (bb, bb3, EDGE_TRUE_VALUE);
+ e13->probability = REG_BR_PROB_BASE - prob;
+ e13->count = all - count;
+
+ remove_edge (e23);
+
+ e24 = make_edge (bb2, bb4, EDGE_FALLTHRU);
+ e24->probability = REG_BR_PROB_BASE;
+ e24->count = count;
+ e34->probability = REG_BR_PROB_BASE;
+ e34->count = all - count;
+
+ return value;
+}
+
+/* Return a REAL_VALUE from gcov_type representing a double. */
+static REAL_VALUE_TYPE
+gen_real_from_gcov_type (gcov_type g)
+{
+ int len = 8;
+ unsigned char ptr[8];
+ REAL_VALUE_TYPE r;
+ int i;
+ for (i = 0; i < 8; ++i)
+ {
+ ptr[i] = g & 0xff;
+ g = g >> 8;
+ }
+ if (!real_from_native (double_type_node, ptr, len, &r))
+ warning (0, "Error converting value to real.");
+
+ return r;
+}
+
+static tree
+gimple_float_pow_call (gimple stmt, double arg2, int prob, gcov_type count,
+ gcov_type all)
+{
+ tree tree_arg2;
+ REAL_VALUE_TYPE r;
+
+ r = gen_real_from_gcov_type (gcov_float_to_type (arg2));
+
+ tree_arg2 = build_real (get_gcov_float_t (), r);
+
+ if (arg2 == 0.0 || arg2 == 1.0 || arg2 == 2.0) {
+ /* convert:
+ a = pow(x,y)
+ to:
+ if (y == 0.0 | 1.0 | 2.0): // bb1
+ a = 1.0 | x | x*x // bb2
+ else
+ a = pow(x,y) // bb3
+ // bb4
+ */
+ gimple stmt1, stmt2, stmt3;
+ tree tmp_b, tmp_a, tmp_k1;
+ gimple bb1end, bb2end, bb3end;
+ basic_block bb, bb2, bb3, bb4;
+ tree optype;
+ edge e12, e13, e23, e24, e34;
+ gimple_stmt_iterator gsi;
+
+
+ gcc_assert (is_gimple_call (stmt));
+
+ optype = TREE_TYPE (gimple_assign_lhs (stmt)); /*double variable */
+ bb = gimple_bb (stmt);
+ gsi = gsi_for_stmt (stmt);
+
+ tmp_k1 = create_tmp_var (optype, "PROF");
+ tmp_b = create_tmp_var (optype, "PROF");
+ stmt1 = gimple_build_assign (tmp_k1, fold_convert (optype, tree_arg2));
+ /*get the value from the call */
+ stmt2 = gimple_build_assign (tmp_b, gimple_call_arg (stmt, 1));
+ stmt3 = gimple_build_cond (NE_EXPR, tmp_b, tmp_k1, NULL_TREE, NULL_TREE);
+ gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
+ gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT);
+ gsi_insert_before (&gsi, stmt3, GSI_SAME_STMT);
+ bb1end = stmt3;
+
+ /* a = 1.0 */
+ tmp_a = gimple_get_lhs (stmt);
+ if (arg2 == 0.0) {
+ tree tree_one;
+ r = gen_real_from_gcov_type (gcov_float_to_type (1.0));
+ tree_one = build_real (get_gcov_float_t (), r);
+ stmt1 = gimple_build_assign (tmp_a, tree_one);
+ } else if (arg2 == 1.0) {
+ /* pow (x, 1.0) => x */
+ tree tree_x = gimple_call_arg (stmt, 0);
+ stmt1 = gimple_build_assign (tmp_a, tree_x);
+ } else if (arg2 == 2.0) {
+ /* pow (x, 2.0) => x*x */
+ tree tree_x = gimple_call_arg (stmt, 0);
+ stmt1 = gimple_build_assign_with_ops (MULT_EXPR, tmp_a, tree_x, tree_x);
+ } else {
+ gcc_unreachable ();
+ }
+
+ gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
+ bb2end = stmt1;
+ bb3end = stmt;
+
+ /* Fix CFG. */
+ /* Edge e23 connects bb2 to bb3, etc. */
+ e12 = split_block (bb, bb1end);
+ bb2 = e12->dest;
+ bb2->count = count;
+ e23 = split_block (bb2, bb2end);
+ bb3 = e23->dest;
+ bb3->count = all - count;
+ e34 = split_block (bb3, bb3end);
+ bb4 = e34->dest;
+ bb4->count = all;
+
+ e12->flags &= ~EDGE_FALLTHRU;
+ e12->flags |= EDGE_FALSE_VALUE;
+ e12->probability = prob;
+ e12->count = count;
+
+ e13 = make_edge (bb, bb3, EDGE_TRUE_VALUE);
+ e13->probability = REG_BR_PROB_BASE - prob;
+ e13->count = all - count;
+
+ remove_edge (e23);
+
+ e24 = make_edge (bb2, bb4, EDGE_FALLTHRU);
+ e24->probability = REG_BR_PROB_BASE;
+ e24->count = count;
+
+ e34->probability = REG_BR_PROB_BASE;
+ e34->count = all - count;
+ }
+
+ return tree_arg2;
+}
+
+
/* Do transform 1) on INSN if applicable. */
static bool
@@ -795,6 +1077,270 @@ gimple_divmod_fixed_value_transform (gimple_stmt_iterator *si)
return true;
}
+enum ffvpt_math_functions
+{
+ FFVPT_EXP_FUN,
+ FFVPT_LOG_FUN,
+ FFVPT_POW_FUN,
+ FFVPT_SQRT_FUN,
+ FFVPT_AMD_EXP_FUN,
+ FFVPT_AMD_LOG_FUN,
+ FFVPT_AMD_POW_FUN,
+ FFVPT_AMD_SQRT_FUN,
+ FFVPT_UNSUPPORTED_FUN
+};
+
+/* Return info if call is a math function that can be optimized by ffvpt. */
+static enum ffvpt_math_functions
+get_ffvpt_math_function (gimple call, tree fndecl)
+{
+ tree id;
+ int id_len;
+ if (fndecl && DECL_NAME (fndecl) && TREE_PUBLIC (fndecl))
+ {
+ id = DECL_ASSEMBLER_NAME (fndecl);
+ id_len = IDENTIFIER_LENGTH (id);
+ if (id_len == 7 || id_len == 8 || id_len == 9)
+ {
+ const char *name = IDENTIFIER_POINTER (id);
+ /* Validate name and type of functions. */
+ if (name[0] == 'a')
+ {
+ if (! strcmp (name, "amd_exp") || ! strcmp (name, "acml_exp"))
+ {
+ if (validate_gimple_arglist (call, REAL_TYPE, VOID_TYPE))
+ return FFVPT_AMD_EXP_FUN;
+ }
+ else if (! strcmp (name, "amd_pow") || ! strcmp (name, "acml_pow"))
+ {
+ if (validate_gimple_arglist (call, REAL_TYPE, REAL_TYPE,
+ VOID_TYPE))
+ return FFVPT_AMD_POW_FUN;
+ }
+ else if (! strcmp (name, "amd_log") || ! strcmp (name, "acml_log"))
+ {
+ if (validate_gimple_arglist (call, REAL_TYPE, VOID_TYPE))
+ return FFVPT_AMD_LOG_FUN;
+ }
+ else if (! strcmp (name, "amd_sqrt")
+ || ! strcmp (name, "acml_sqrt"))
+ {
+ if (validate_gimple_arglist (call, REAL_TYPE, VOID_TYPE))
+ return FFVPT_AMD_SQRT_FUN;
+ }
+ }
+ }
+ }
+
+ if (!DECL_BUILT_IN (fndecl)
+ || (DECL_BUILT_IN_CLASS (fndecl) != BUILT_IN_NORMAL))
+ return FFVPT_UNSUPPORTED_FUN;
+
+ switch (DECL_FUNCTION_CODE (fndecl))
+ {
+ CASE_FLT_FN (BUILT_IN_EXP):
+ return FFVPT_EXP_FUN;
+ CASE_FLT_FN (BUILT_IN_LOG):
+ return FFVPT_LOG_FUN;
+ CASE_FLT_FN (BUILT_IN_SQRT):
+ return FFVPT_SQRT_FUN;
+ CASE_FLT_FN (BUILT_IN_POW):
+ return FFVPT_POW_FUN;
+ }
+ return FFVPT_UNSUPPORTED_FUN;
+}
+
+
+static bool
+gimple_float_math_call_transform (gimple_stmt_iterator *si)
+{
+ histogram_value histogram;
+ gcov_type val, count, all;
+ gcov_float_t val_f;
+ tree value;
+ tree result;
+
+ gcov_type prob;
+ gimple stmt;
+ tree fndecl;
+ tree arg1;
+
+ double cal_result;
+
+ int bln_precalculate = 0;
+
+ REAL_VALUE_TYPE r;
+
+ enum ffvpt_math_functions math_fun;
+
+ stmt = gsi_stmt (*si);
+ if (gimple_code (stmt) != GIMPLE_CALL)
+ return false;
+
+ fndecl = gimple_call_fndecl (stmt);
+ if (fndecl == NULL)
+ return false;
+
+ math_fun = get_ffvpt_math_function (stmt, fndecl);
+ switch (math_fun)
+ {
+ case FFVPT_UNSUPPORTED_FUN:
+ /* Not a (supported) math function */
+ break;
+ case FFVPT_EXP_FUN:
+ case FFVPT_AMD_EXP_FUN:
+ if (!ffvpt_options.exp_set)
+ return false;
+ arg1 = gimple_call_arg (stmt, 0);
+ break;
+ case FFVPT_LOG_FUN:
+ case FFVPT_AMD_LOG_FUN:
+ if (!ffvpt_options.log_set)
+ return false;
+ arg1 = gimple_call_arg (stmt, 0);
+ break;
+ case FFVPT_POW_FUN:
+ case FFVPT_AMD_POW_FUN:
+ /* Profile the second argument */
+ if (!ffvpt_options.pow_set)
+ return false;
+ arg1 = gimple_call_arg (stmt, 1);
+ break;
+ case FFVPT_SQRT_FUN:
+ case FFVPT_AMD_SQRT_FUN:
+ if (!ffvpt_options.sqrt_set)
+ return false;
+ arg1 = gimple_call_arg (stmt, 0);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ histogram = gimple_histogram_value_of_type (cfun, stmt,
+ HIST_TYPE_SINGLE_FLOAT_VALUE);
+ if (!histogram)
+ return false;
+
+ value = histogram->hvalue.value;
+ val = histogram->hvalue.counters[0];
+ val_f = gcov_type_to_float (val);
+
+ count = histogram->hvalue.counters[1];
+ all = histogram->hvalue.counters[2];
+ gimple_remove_histogram_value (cfun, stmt, histogram);
+
+ /* We require that count is at least half of all; this means
+ that for the transformation to fire the value must be constant
+ at least 50% of time (and 75% gives the guarantee of usage). */
+ if (all == 0 || 2 * count < all) {
+ if (dump_file)
+ {
+ fprintf (dump_file, "Not enough count: %ld all: %ld\n", count, all);
+ }
+ return false;
+ }
+
+ if (check_counter (stmt, "value", &count, &all, gimple_bb (stmt)->count)) {
+ if (dump_file)
+ {
+ fprintf (dump_file, "check counter failed\n");
+ }
+ return false;
+ }
+
+ /* Compute probability of taking the optimal path. */
+ prob = (count * REG_BR_PROB_BASE + all / 2) / all;
+
+ switch (math_fun)
+ {
+ case FFVPT_EXP_FUN:
+ case FFVPT_AMD_EXP_FUN:
+ cal_result = exp (val_f);
+ bln_precalculate = 1;
+ break;
+ case FFVPT_LOG_FUN:
+ case FFVPT_AMD_LOG_FUN:
+ cal_result = log (val_f);
+ bln_precalculate = 1;
+ break;
+ case FFVPT_SQRT_FUN:
+ case FFVPT_AMD_SQRT_FUN:
+ cal_result = sqrt (val_f);
+ bln_precalculate = 1;
+ break;
+ case FFVPT_POW_FUN:
+ case FFVPT_AMD_POW_FUN:
+ bln_precalculate = 0;
+ break;
+ default:
+ /* Unsupported math function found. */
+ gcc_unreachable ();
+ }
+ if (bln_precalculate)
+ {
+ tree tree_val;
+ tree cal_tree;
+ r = gen_real_from_gcov_type (val);
+ tree_val = build_real (get_gcov_float_t (), r);
+ r = gen_real_from_gcov_type (gcov_float_to_type (cal_result));
+ cal_tree = build_real (get_gcov_float_t (), r);
+
+ result = gimple_ffvpt_update_math_calls (stmt, tree_val, prob, count, all,
+ cal_tree);
+ }
+ else if (bln_precalculate == 0)
+ {
+ /* Calls pow with second argument almost always a constant...*/
+ /* tree tree_arg_1; */
+ if (val_f == 0.0)
+ {
+ /* Replace with 1.00! */
+ result = gimple_float_pow_call (stmt, val_f, prob, count, all);
+ }
+ else if (val_f == 1.0)
+ {
+ /* Replace with first argument */
+ result = gimple_float_pow_call (stmt, val_f, prob, count, all);
+ }
+ else if (val_f == 2.0)
+ {
+ /* Replace with first argument times itself */
+ result = gimple_float_pow_call (stmt, val_f, prob, count, all);
+ }
+ else
+ {
+ /* TODO(martint): Consider optimizing other constants as well.
+ For example 0.5 -> sqrt() */
+ return false;
+ }
+
+ }
+ if (dump_file)
+ {
+ if (bln_precalculate) {
+ fprintf (dump_file,
+ "Math call (%s) to constant value: %f in %s (use %f) "
+ "(count:%ld, all:%ld)\n",
+ lang_hooks.decl_printable_name (fndecl, 1),
+ val_f,
+ current_function_name (),
+ cal_result,
+ count,
+ all);
+ } else {
+ fprintf (dump_file,
+ "Math call (%s) with constant argument (%f) optimized in %s: "
+ "(count:%ld, all:%ld)\n",
+ lang_hooks.decl_printable_name (fndecl, 1),
+ val_f,
+ current_function_name (),
+ count,
+ all);
+ }
+ }
+ return true;
+}
+
/* Generate code for transformation 2 (with parent gimple assign STMT and
probability of taking the optimal path PROB, which is equivalent to COUNT/ALL
within roundoff error). This generates the result into a temp and returns
@@ -1173,6 +1719,18 @@ find_func_by_pid (int pid)
}
+/* Remove a cgraph node from the map of pids */
+
+void
+cgraph_remove_pid (struct cgraph_node *n)
+{
+ if (pid_map == NULL || n->pid < 0)
+ return;
+
+ pid_map [n->pid] = NULL;
+}
+
+
/* Initialize map of gids (gid -> cgraph node) */
static htab_t gid_map = NULL;
@@ -1283,50 +1841,79 @@ find_func_by_global_id (unsigned HOST_WIDE_INT gid)
in the profile.
TODO: need to transform this lookup method to hash table. */
-static struct cgraph_node *
-find_func_by_name (char *name)
+struct cgraph_node *
+find_func_by_name (const char *name)
{
- struct cgraph_node *n;
- struct cgraph_node *ret = NULL;
- int match = 0;
+ struct cgraph_node *node = NULL;
+ int len = strlen (name);
+
+ for (node = cgraph_nodes; node; node = node->next) {
+ const char *fname = IDENTIFIER_POINTER (decl_assembler_name (node->decl));
+ if (!node->global.inlined_to
+ && node->analyzed
+ && node->master_clone == node
+ && !strncmp(fname, name, len)
+ && (!strncmp(fname + len, "_cmo_", 5) || fname[len] == 0
+ || fname[len] == '.'))
+ break;
+ }
+ return node;
+}
- for (n = cgraph_nodes; n; n = n->next)
- {
- const char *fname = IDENTIFIER_POINTER (decl_assembler_name (n->decl));
- if (!strcmp(fname, name)) {
- match ++;
- ret = n;
- }
- }
- if (match == 1)
- return ret;
- else
- return NULL;
+/* Counts the number of arguments in the function_decl FN_DECL.
+
+ Returns the number of arguments. */
+static unsigned
+function_decl_num_args (tree fn_decl)
+{
+ tree arg;
+ unsigned count = 0;
+ for (arg = DECL_ARGUMENTS (fn_decl); arg; arg = TREE_CHAIN (arg))
+ count++;
+ return count;
}
/* Perform sanity check on the indirect call target. Due to race conditions,
false function target may be attributed to an indirect call site. If the
call expression type mismatches with the target function's type, expand_call
may ICE. Here we only do very minimal sanity check just to make compiler happy.
- Returns true if TARGET is considered ok for call CALL_EXPR. */
+ Returns true if TARGET is considered ok for call CALL_STMT. */
static bool
-check_ic_target (tree call_expr, struct cgraph_node *target)
+check_ic_target (gimple call_stmt, struct cgraph_node *target)
{
tree tgt_decl;
/* Return types. */
tree icall_type, tgt_type;
+ tree call_expr;
tgt_decl = target->decl;
tgt_type = TREE_TYPE (TREE_TYPE (tgt_decl));
+ call_expr = gimple_call_fn (call_stmt);
icall_type = TREE_TYPE (call_expr);
if (POINTER_TYPE_P (icall_type))
icall_type = TREE_TYPE (icall_type);
icall_type = TREE_TYPE (icall_type);
- return (TREE_CODE (icall_type) == TREE_CODE (tgt_type)
- && TYPE_MODE (icall_type) == TYPE_MODE (tgt_type));
+ if (TREE_CODE (icall_type) != TREE_CODE (tgt_type)
+ || TYPE_MODE (icall_type) != TYPE_MODE (tgt_type))
+ return false;
+
+ /* Verify that CALL_STMT has the same number of arguments as TGT_TYPE. */
+ if (gimple_call_num_args (call_stmt) != function_decl_num_args (tgt_decl))
+ return false;
+
+ /* Record types should have matching sizes. */
+ if (TREE_CODE (icall_type) == RECORD_TYPE
+ && TYPE_SIZE (icall_type) != NULL_TREE
+ && TYPE_SIZE (tgt_type) != NULL_TREE
+ && TREE_CODE (TYPE_SIZE (icall_type)) == INTEGER_CST
+ && (TREE_CODE (TYPE_SIZE (tgt_type)) != INTEGER_CST ||
+ !tree_int_cst_equal (TYPE_SIZE (icall_type), TYPE_SIZE (tgt_type))))
+ return false;
+
+ return true;
}
/* Do transformation
@@ -1460,7 +2047,7 @@ gimple_ic_transform_single_targ (gimple stmt, histogram_value histogram)
if (direct_call == NULL)
return false;
- if (!check_ic_target (gimple_call_fn (stmt), direct_call))
+ if (!check_ic_target (stmt, direct_call))
return false;
modify = gimple_ic (stmt, stmt, direct_call, prob, count, all);
@@ -1567,7 +2154,7 @@ gimple_ic_transform_mult_targ (gimple stmt, histogram_value histogram)
locus = (stmt != NULL) ? gimple_location (stmt)
: DECL_SOURCE_LOCATION (current_function_decl);
if (direct_call1 == NULL
- || !check_ic_target (gimple_call_fn (stmt), direct_call1))
+ || !check_ic_target (stmt, direct_call1))
{
if (flag_ripa_verbose)
{
@@ -1635,7 +2222,7 @@ gimple_ic_transform_mult_targ (gimple stmt, histogram_value histogram)
" hist->all "HOST_WIDEST_INT_PRINT_DEC"\n", count1, all);
}
- if (direct_call2 && check_ic_target (gimple_call_fn (stmt), direct_call2)
+ if (direct_call2 && check_ic_target (stmt, direct_call2)
/* Don't indirect-call promote if the target is in auxiliary module and
DECL_ARTIFICIAL and not TREE_PUBLIC, because we don't static-promote
DECL_ARTIFICIALs yet. */
@@ -1731,6 +2318,14 @@ interesting_stringop_to_profile_p (tree fndecl, gimple call, int *size_arg)
{
enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
+ /* XXX: Disable stringop collection with reuse distance instrumentation
+ or optimization. Otherwise we end up with hard to correct profile
+ mismatches for functions where reuse distance-based transformation are
+ made. We see a number of "memcpy" at instrumentation time and a different
+ number of "memcpy" at profile use time. */
+ if (flag_profile_reusedist || flag_optimize_locality)
+ return false;
+
if (fcode != BUILT_IN_MEMCPY && fcode != BUILT_IN_MEMPCPY
&& fcode != BUILT_IN_MEMSET && fcode != BUILT_IN_BZERO)
return false;
@@ -1990,6 +2585,50 @@ stringop_block_profile (gimple stmt, unsigned int *expected_align,
}
}
+
+
+/* Find log,exp,pow,squrt calls and profile arguments. */
+static void
+gimple_math_call_to_profile (gimple stmt, histogram_values *values)
+{
+ /* histogram_value hist; */
+ tree fndecl;
+ tree arg1;
+ enum ffvpt_math_functions math_fun;
+
+ if (gimple_code (stmt) != GIMPLE_CALL)
+ return;
+
+ /* Hopefully the math function */
+ fndecl = gimple_call_fndecl (stmt);
+ if (fndecl == NULL)
+ return;
+
+ /* Look for amd_exp, amd_log, amd_pow*/
+ math_fun = get_ffvpt_math_function (stmt, fndecl);
+ if (math_fun != FFVPT_UNSUPPORTED_FUN)
+ {
+ if (math_fun == FFVPT_POW_FUN || math_fun == FFVPT_AMD_POW_FUN)
+ arg1 = gimple_call_arg (stmt, 1);
+ else
+ arg1 = gimple_call_arg (stmt, 0);
+ if (dump_file)
+ {
+ fprintf (dump_file, "Add profiling for call to %s in %s\n",
+ lang_hooks.decl_printable_name (fndecl, 1),
+ current_function_name ());
+ }
+ VEC_reserve (histogram_value, heap, *values, 3);
+ VEC_quick_push (histogram_value, *values,
+ gimple_alloc_histogram_value (cfun,
+ HIST_TYPE_SINGLE_FLOAT_VALUE,
+ stmt, arg1));
+ }
+ return;
+}
+
+
+
struct value_prof_hooks {
/* Find list of values for which we want to measure histograms. */
void (*find_values_to_profile) (histogram_values *);
@@ -2298,6 +2937,8 @@ gimple_values_to_profile (gimple stmt, histogram_values *values)
gimple_divmod_values_to_profile (stmt, values);
gimple_stringops_values_to_profile (stmt, values);
gimple_indirect_call_to_profile (stmt, values);
+ if (flag_float_value_profile_transformations)
+ gimple_math_call_to_profile (stmt, values);
}
}
@@ -2313,7 +2954,7 @@ gimple_find_values_to_profile (histogram_values *values)
FOR_EACH_BB (bb)
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
gimple_values_to_profile (gsi_stmt (gsi), values);
-
+
for (i = 0; VEC_iterate (histogram_value, *values, i, hist); i++)
{
switch (hist->type)
@@ -2330,6 +2971,10 @@ gimple_find_values_to_profile (histogram_values *values)
hist->n_counters = 3;
break;
+ case HIST_TYPE_SINGLE_FLOAT_VALUE:
+ hist->n_counters = 3;
+ break;
+
case HIST_TYPE_CONST_DELTA:
hist->n_counters = 4;
break;
diff --git a/gcc-4.4.3/gcc/value-prof.h b/gcc-4.4.3/gcc/value-prof.h
index ad4bf90d0..31700d064 100644
--- a/gcc-4.4.3/gcc/value-prof.h
+++ b/gcc-4.4.3/gcc/value-prof.h
@@ -28,9 +28,11 @@ enum hist_type
HIST_TYPE_POW2, /* Histogram of power of 2 values. */
HIST_TYPE_SINGLE_VALUE, /* Tries to identify the value that is (almost)
always constant. */
+ HIST_TYPE_SINGLE_FLOAT_VALUE, /* Tries to identify the value that is (almost)
+ always constant. */
HIST_TYPE_CONST_DELTA, /* Tries to identify the (almost) always constant
difference between two evaluations of a value. */
- HIST_TYPE_INDIR_CALL, /* Tries to identify the function that is (almost)
+ HIST_TYPE_INDIR_CALL, /* Tries to identify the function that is (almost)
called in indirect call */
HIST_TYPE_AVERAGE, /* Compute average value (sum of all values). */
HIST_TYPE_IOR, /* Used to compute expected alignment. */
@@ -97,6 +99,9 @@ struct profile_hooks {
/* Insert code to find the most common value. */
void (*gen_one_value_profiler) (histogram_value, unsigned, unsigned);
+ /* Insert code to find the most common value. */
+ void (*gen_one_float_value_profiler) (histogram_value, unsigned, unsigned);
+
/* Insert code to find the most common value of a difference between two
evaluations of an expression. */
void (*gen_const_delta_profiler) (histogram_value, unsigned, unsigned);
@@ -112,6 +117,12 @@ struct profile_hooks {
/* Insert code to ior value of an expression. */
void (*gen_ior_profiler) (histogram_value, unsigned, unsigned);
+
+ /* Reuse distance profiler. */
+ void (*reusedist_profiler) (void);
+
+ /* Reuse distance optimizer. */
+ void (*optimize_reusedist) (void);
};
histogram_value gimple_histogram_value (struct function *, gimple);
@@ -128,6 +139,9 @@ void verify_histograms (void);
void free_histograms (void);
void stringop_block_profile (gimple, unsigned int *, HOST_WIDE_INT *);
+struct ffvpt_options_s
+ffvtp_process_options (const char *arg);
+
/* In profile.c. */
extern void init_branch_prob (void);
extern void branch_prob (void);
diff --git a/gcc-4.4.3/gcc/varasm.c b/gcc-4.4.3/gcc/varasm.c
index 670c887ee..3874e10d3 100644
--- a/gcc-4.4.3/gcc/varasm.c
+++ b/gcc-4.4.3/gcc/varasm.c
@@ -5702,7 +5702,11 @@ decl_default_tls_model (const_tree decl)
bool is_local;
is_local = targetm.binds_local_p (decl);
- if (!flag_shlib)
+ #ifdef ENABLE_ESP
+ if (!flag_pic)
+ #else
+ if (!flag_shlib)
+ #endif
{
if (is_local)
kind = TLS_MODEL_LOCAL_EXEC;
diff --git a/gcc-4.4.3/libgcc/Makefile.in b/gcc-4.4.3/libgcc/Makefile.in
index a7b3d829d..02ca0a28b 100644
--- a/gcc-4.4.3/libgcc/Makefile.in
+++ b/gcc-4.4.3/libgcc/Makefile.in
@@ -280,6 +280,12 @@ vis_hide =
gen-hide-list = echo > \$@
endif
+# We add crtbeginTS.o to the EXTRA_PARTS list if enable_crtbeginTS = yes
+enable_libgcc_crtbeginTS = $(enable_crtbeginTS)
+ifeq ($(enable_libgcc_crtbeginTS),yes)
+EXTRA_PARTS += crtbeginTS.o
+endif
+
ifneq ($(EXTRA_PARTS),)
extra-parts = libgcc-extra-parts
INSTALL_PARTS = $(EXTRA_PARTS)
@@ -729,10 +735,13 @@ $(libgcov-objects): %$(objext): $(gcc_srcdir)/libgcov.c
dyn-ipa.o: %$(objext): $(gcc_srcdir)/libgcov.c
$(gcc_compile) -c $(gcc_srcdir)/dyn-ipa.c
+pmu-profile.o: %$(objext): $(gcc_srcdir)/libgcov.c
+ $(gcc_compile) -c $(gcc_srcdir)/pmu-profile.c
+
# Static libraries.
libgcc.a: $(libgcc-objects)
-libgcov.a: $(libgcov-objects) dyn-ipa$(objext)
+libgcov.a: $(libgcov-objects) dyn-ipa$(objext) pmu-profile$(objext)
libunwind.a: $(libunwind-objects)
libgcc_eh.a: $(libgcc-eh-objects)
@@ -834,6 +843,13 @@ crtendS$(objext): $(gcc_srcdir)/crtstuff.c
crtbeginT.o: $(gcc_srcdir)/crtstuff.c
$(crt_compile) $(CRTSTUFF_T_CFLAGS) \
-c $(gcc_srcdir)/crtstuff.c -DCRT_BEGIN -DCRTSTUFFT_O
+
+# This is a version of crtbegin for -static -fPIE links.
+ifeq ($(enable_libgcc_crtbeginTS),yes)
+crtbeginTS.o: $(gcc_srcdir)/crtstuff.c
+ $(crt_compile) $(CRTSTUFF_T_CFLAGS_S) \
+ -c $(gcc_srcdir)/crtstuff.c -DCRT_BEGIN -DCRTSTUFFT_O -DCRTSTUFFS_O
+endif
endif
# Build extra startfiles in the libgcc directory.
diff --git a/gcc-4.4.3/libiberty/getpagesize.c b/gcc-4.4.3/libiberty/getpagesize.c
index 4d44f30f1..aa0757bb9 100644
--- a/gcc-4.4.3/libiberty/getpagesize.c
+++ b/gcc-4.4.3/libiberty/getpagesize.c
@@ -67,6 +67,7 @@ getpagesize (void)
return (GNU_OUR_PAGESIZE);
}
#endif
+
#else /* VMS */
#if 0 /* older distributions of gcc-vms are missing <syidef.h> */
diff --git a/gcc-4.4.3/libmudflap/Makefile.in b/gcc-4.4.3/libmudflap/Makefile.in
index d3d4be353..7985ad6e7 100644
--- a/gcc-4.4.3/libmudflap/Makefile.in
+++ b/gcc-4.4.3/libmudflap/Makefile.in
@@ -253,9 +253,17 @@ ACLOCAL_AMFLAGS = -I .. -I ../config
MAINT_CHARSET = latin1
SUBDIRS = testsuite
+# Some stuff don't compile with SSP and FORTIFY_SOURCE
+enable_esp = @enable_esp@
+ifeq ($(enable_esp),yes)
+ NO_ESP_CFLAGS = -fno-stack-protector -U_FORTIFY_SOURCE
+else
+ NO_ESP_CFLAGS =
+endif
+
# May be used by various substitution variables.
gcc_version := $(shell cat $(top_srcdir)/../gcc/BASE-VER)
-AM_CFLAGS = -Wall $(SECTION_FLAGS)
+AM_CFLAGS = -Wall $(SECTION_FLAGS) $(NO_ESP_CFLAGS)
@LIBMUDFLAPTH_FALSE@libmudflapth =
@LIBMUDFLAPTH_TRUE@libmudflapth = libmudflapth.la
toolexeclib_LTLIBRARIES = libmudflap.la $(libmudflapth)
diff --git a/gcc-4.4.3/libmudflap/configure b/gcc-4.4.3/libmudflap/configure
index 14abb1f03..0baab2358 100755
--- a/gcc-4.4.3/libmudflap/configure
+++ b/gcc-4.4.3/libmudflap/configure
@@ -458,7 +458,7 @@ ac_includes_default="\
# include <unistd.h>
#endif"
-ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os target_noncanonical INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT multi_basedir CC ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE CFLAGS CPP CPPFLAGS CXX CXXFLAGS LDFLAGS ac_ct_CXX CXXDEPMODE am__fastdepCXX_TRUE am__fastdepCXX_FALSE EGREP LIBTOOL SED FGREP GREP LD DUMPBIN ac_ct_DUMPBIN NM LN_S OBJDUMP ac_ct_OBJDUMP AR ac_ct_AR RANLIB ac_ct_RANLIB lt_ECHO DSYMUTIL ac_ct_DSYMUTIL NMEDIT ac_ct_NMEDIT LIPO ac_ct_LIPO OTOOL ac_ct_OTOOL OTOOL64 ac_ct_OTOOL64 CXXCPP enable_shared enable_static MF_HAVE_STDINT_H MF_HAVE_UINTPTR_T LIBMUDFLAPTH_TRUE LIBMUDFLAPTH_FALSE build_libmudflapth toolexecdir toolexeclibdir ac_ct_NM SECTION_FLAGS LIBOBJS LTLIBOBJS'
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os target_noncanonical INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar enable_esp MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT multi_basedir CC ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE CFLAGS CPP CPPFLAGS CXX CXXFLAGS LDFLAGS ac_ct_CXX CXXDEPMODE am__fastdepCXX_TRUE am__fastdepCXX_FALSE EGREP LIBTOOL SED FGREP GREP LD DUMPBIN ac_ct_DUMPBIN NM LN_S OBJDUMP ac_ct_OBJDUMP AR ac_ct_AR RANLIB ac_ct_RANLIB lt_ECHO DSYMUTIL ac_ct_DSYMUTIL NMEDIT ac_ct_NMEDIT LIPO ac_ct_LIPO OTOOL ac_ct_OTOOL OTOOL64 ac_ct_OTOOL64 CXXCPP enable_shared enable_static MF_HAVE_STDINT_H MF_HAVE_UINTPTR_T LIBMUDFLAPTH_TRUE LIBMUDFLAPTH_FALSE build_libmudflapth toolexecdir toolexeclibdir ac_ct_NM SECTION_FLAGS LIBOBJS LTLIBOBJS'
ac_subst_files=''
ac_pwd=`pwd`
@@ -2053,6 +2053,8 @@ am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'
+
+
echo "$as_me:$LINENO: checking for --enable-version-specific-runtime-libs" >&5
echo $ECHO_N "checking for --enable-version-specific-runtime-libs... $ECHO_C" >&6
# Check whether --enable-version-specific-runtime-libs or --disable-version-specific-runtime-libs was given.
@@ -6250,13 +6252,13 @@ if test "${lt_cv_nm_interface+set}" = set; then
else
lt_cv_nm_interface="BSD nm"
echo "int some_variable = 0;" > conftest.$ac_ext
- (eval echo "\"\$as_me:6253: $ac_compile\"" >&5)
+ (eval echo "\"\$as_me:6255: $ac_compile\"" >&5)
(eval "$ac_compile" 2>conftest.err)
cat conftest.err >&5
- (eval echo "\"\$as_me:6256: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
+ (eval echo "\"\$as_me:6258: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
(eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
cat conftest.err >&5
- (eval echo "\"\$as_me:6259: output\"" >&5)
+ (eval echo "\"\$as_me:6261: output\"" >&5)
cat conftest.out >&5
if $GREP 'External.*some_variable' conftest.out > /dev/null; then
lt_cv_nm_interface="MS dumpbin"
@@ -7413,7 +7415,7 @@ ia64-*-hpux*)
;;
*-*-irix6*)
# Find out which ABI we are using.
- echo '#line 7416 "configure"' > conftest.$ac_ext
+ echo '#line 7418 "configure"' > conftest.$ac_ext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
@@ -9435,11 +9437,11 @@ else
-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:9438: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:9440: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:9442: \$? = $ac_status" >&5
+ echo "$as_me:9444: \$? = $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.
@@ -9774,11 +9776,11 @@ else
-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:9777: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:9779: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:9781: \$? = $ac_status" >&5
+ echo "$as_me:9783: \$? = $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.
@@ -9879,11 +9881,11 @@ else
-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:9882: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:9884: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:9886: \$? = $ac_status" >&5
+ echo "$as_me:9888: \$? = $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
@@ -9934,11 +9936,11 @@ else
-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:9937: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:9939: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:9941: \$? = $ac_status" >&5
+ echo "$as_me:9943: \$? = $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
@@ -12746,7 +12748,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 12749 "configure"
+#line 12751 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -12842,7 +12844,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 12845 "configure"
+#line 12847 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -14858,11 +14860,11 @@ else
-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:14861: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:14863: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:14865: \$? = $ac_status" >&5
+ echo "$as_me:14867: \$? = $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.
@@ -14957,11 +14959,11 @@ else
-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:14960: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:14962: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:14964: \$? = $ac_status" >&5
+ echo "$as_me:14966: \$? = $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
@@ -15009,11 +15011,11 @@ else
-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:15012: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:15014: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:15016: \$? = $ac_status" >&5
+ echo "$as_me:15018: \$? = $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
@@ -17778,6 +17780,9 @@ ac_configure_args="${multilib_arg} ${ac_configure_args}"
multi_basedir="$multi_basedir"
CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
CC="$CC"
+CXX="$CXX"
+GFORTRAN="$GFORTRAN"
+GCJ="$GCJ"
AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"
@@ -18267,6 +18272,7 @@ s,@am__leading_dot@,$am__leading_dot,;t t
s,@AMTAR@,$AMTAR,;t t
s,@am__tar@,$am__tar,;t t
s,@am__untar@,$am__untar,;t t
+s,@enable_esp@,$enable_esp,;t t
s,@MAINTAINER_MODE_TRUE@,$MAINTAINER_MODE_TRUE,;t t
s,@MAINTAINER_MODE_FALSE@,$MAINTAINER_MODE_FALSE,;t t
s,@MAINT@,$MAINT,;t t
diff --git a/gcc-4.4.3/libmudflap/configure.ac b/gcc-4.4.3/libmudflap/configure.ac
index 359573a7e..510e7eaef 100644
--- a/gcc-4.4.3/libmudflap/configure.ac
+++ b/gcc-4.4.3/libmudflap/configure.ac
@@ -9,6 +9,8 @@ ACX_NONCANONICAL_TARGET
AM_INIT_AUTOMAKE
+AC_SUBST([enable_esp])
+
AC_MSG_CHECKING([for --enable-version-specific-runtime-libs])
AC_ARG_ENABLE(version-specific-runtime-libs,
[ --enable-version-specific-runtime-libs Specify that runtime libraries should be installed in a compiler-specific directory ],
diff --git a/gcc-4.4.3/libstdc++-v3/include/backward/hashtable.h b/gcc-4.4.3/libstdc++-v3/include/backward/hashtable.h
index ca04c76fd..4d74eaf95 100644
--- a/gcc-4.4.3/libstdc++-v3/include/backward/hashtable.h
+++ b/gcc-4.4.3/libstdc++-v3/include/backward/hashtable.h
@@ -124,7 +124,8 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
_Hashtable_iterator(_Node* __n, _Hashtable* __tab)
: _M_cur(__n), _M_ht(__tab) { }
- _Hashtable_iterator() { }
+ _Hashtable_iterator()
+ : _M_cur(0), _M_ht(0) { }
reference
operator*() const
diff --git a/gcc-4.4.3/libstdc++-v3/include/bits/stl_algo.h b/gcc-4.4.3/libstdc++-v3/include/bits/stl_algo.h
index f54b1cd77..d4b04d1da 100644
--- a/gcc-4.4.3/libstdc++-v3/include/bits/stl_algo.h
+++ b/gcc-4.4.3/libstdc++-v3/include/bits/stl_algo.h
@@ -74,13 +74,12 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
#if __google_stl_debug_compare
template<typename _Compare>
struct _CheckedCompare {
- // Mutable because some clients use non-const operator().
- mutable _Compare _M_compare;
+ _Compare _M_compare;
_CheckedCompare(const _Compare & __comp): _M_compare(__comp) { }
template <typename _Tp>
- bool operator()(const _Tp& __x, const _Tp& __y) const {
+ bool operator()(const _Tp& __x, const _Tp& __y) {
if (_M_compare(__x, __x))
__throw_runtime_error("strict weak ordering: (__x LT __x) != false");
if (_M_compare(__y, __y))
@@ -96,7 +95,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
// indexterm/internal/numericterms.cc
// fails without this.
template <typename _Tp1, typename _Tp2>
- bool operator()(const _Tp1& __x, const _Tp2& __y) const {
+ bool operator()(const _Tp1& __x, const _Tp2& __y) {
return _M_compare(__x, __y);
}
};
diff --git a/gcc-4.4.3/libstdc++-v3/include/bits/stl_tree.h b/gcc-4.4.3/libstdc++-v3/include/bits/stl_tree.h
index 4f0ad2d8d..e2cc1518d 100644
--- a/gcc-4.4.3/libstdc++-v3/include/bits/stl_tree.h
+++ b/gcc-4.4.3/libstdc++-v3/include/bits/stl_tree.h
@@ -456,22 +456,34 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
#if __google_stl_debug_rbtree
template<typename _KeyCompare>
struct _CheckedCompare {
- // Mutable because some clients use non-const operator().
- mutable _KeyCompare _M_key_compare;
+ _KeyCompare _M_key_compare;
_CheckedCompare(): _M_key_compare() { }
_CheckedCompare(const _KeyCompare & __comp): _M_key_compare(__comp) { }
- bool operator()(const _Key& __x, const _Key& __y) const {
- if (_M_key_compare(__x, __x))
+ // Template arg required to avoid duplicating code in the two op()
+ // operators below. User-provided _M_key_compare may not be const,
+ // but needs to be callable from our const op().
+ // See http://b/1731200 for details.
+ template <typename _KeyCompareT>
+ static bool _M_compare_with(_KeyCompareT& __comp, const _Key& __x, const _Key& __y) {
+ if (__comp(__x, __x))
__throw_runtime_error("strict weak ordering: (__x LT __x) != false");
- if (_M_key_compare(__y, __y))
+ if (__comp(__y, __y))
__throw_runtime_error("strict weak ordering: (__y LT __y) != false");
- bool lt = _M_key_compare(__x, __y);
- if (lt && _M_key_compare(__y, __x))
+ bool lt = __comp(__x, __y);
+ if (lt && __comp(__y, __x))
__throw_runtime_error("strict weak ordering: ((__x LT __y) && (__y LT __x)) != false");
return lt;
}
+ bool operator()(const _Key& __x, const _Key& __y) const {
+ return _M_compare_with(_M_key_compare, __x, __y);
+ }
+
+ bool operator()(const _Key& __x, const _Key& __y) {
+ return _M_compare_with(_M_key_compare, __x, __y);
+ }
+
operator _KeyCompare() const { return _M_key_compare; }
};
diff --git a/gcc-4.4.3/libstdc++-v3/include/ext/sso_string_base.h b/gcc-4.4.3/libstdc++-v3/include/ext/sso_string_base.h
index ee704f51d..c32960902 100644
--- a/gcc-4.4.3/libstdc++-v3/include/ext/sso_string_base.h
+++ b/gcc-4.4.3/libstdc++-v3/include/ext/sso_string_base.h
@@ -84,7 +84,7 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
{
if (!_M_is_local())
_M_destroy(_M_allocated_capacity);
-#if __google_stl_debug_string
+#if __google_stl_debug_string_dangling
else {
// Wipe local storage for destructed string with 0xCD.
// This mimics what DebugAllocation does to free()d memory.
@@ -170,15 +170,29 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
_M_leak() { }
void
- _M_set_length(size_type __n)
+ _M_set_length_no_wipe(size_type __n)
{
_M_length(__n);
traits_type::assign(_M_data()[__n], _CharT());
}
+ void
+ _M_set_length(size_type __n)
+ {
+#if __google_stl_debug_string_dangling
+ if (__n + 1 < _M_length())
+ {
+ // Wipe the storage with 0xCD.
+ // Also wipes the old NUL terminator.
+ __builtin_memset(_M_data() + __n + 1, 0xcd, _M_length() - __n);
+ }
+#endif
+ _M_set_length_no_wipe(__n);
+ }
+
__sso_string_base()
: _M_dataplus(_M_local_data)
- { _M_set_length(0); }
+ { _M_set_length_no_wipe(0); }
__sso_string_base(const _Alloc& __a);
@@ -235,6 +249,9 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
__sso_string_base<_CharT, _Traits, _Alloc>::
_M_swap(__sso_string_base& __rcs)
{
+ if (this == &__rcs)
+ return;
+
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 431. Swapping containers with unequal allocators.
std::__alloc_swap<_CharT_alloc_type>::_S_do_it(_M_get_allocator(),
@@ -334,7 +351,7 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
__sso_string_base<_CharT, _Traits, _Alloc>::
__sso_string_base(const _Alloc& __a)
: _M_dataplus(__a, _M_local_data)
- { _M_set_length(0); }
+ { _M_set_length_no_wipe(0); }
template<typename _CharT, typename _Traits, typename _Alloc>
__sso_string_base<_CharT, _Traits, _Alloc>::
@@ -409,7 +426,7 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
// Allocate more space.
__capacity = __len + 1;
_CharT* __another = _M_create(__capacity, __len);
- _S_copy(__another, _M_data(), __len);
+ this->_S_copy(__another, _M_data(), __len);
_M_dispose();
_M_data(__another);
_M_capacity(__capacity);
@@ -424,7 +441,7 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
__throw_exception_again;
}
- _M_set_length(__len);
+ _M_set_length_no_wipe(__len);
}
template<typename _CharT, typename _Traits, typename _Alloc>
@@ -449,14 +466,14 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
// Check for out_of_range and length_error exceptions.
__try
- { _S_copy_chars(_M_data(), __beg, __end); }
+ { this->_S_copy_chars(_M_data(), __beg, __end); }
__catch(...)
{
_M_dispose();
__throw_exception_again;
}
- _M_set_length(__dnew);
+ _M_set_length_no_wipe(__dnew);
}
template<typename _CharT, typename _Traits, typename _Alloc>
@@ -471,9 +488,9 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
}
if (__n)
- _S_assign(_M_data(), __n, __c);
+ this->_S_assign(_M_data(), __n, __c);
- _M_set_length(__n);
+ _M_set_length_no_wipe(__n);
}
template<typename _CharT, typename _Traits, typename _Alloc>
@@ -496,7 +513,7 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
}
if (__rsize)
- _S_copy(_M_data(), __rcs._M_data(), __rsize);
+ this->_S_copy(_M_data(), __rcs._M_data(), __rsize);
_M_set_length(__rsize);
}
@@ -518,14 +535,14 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
|| __res > size_type(_S_local_capacity))
{
_CharT* __tmp = _M_create(__res, __capacity);
- _S_copy(__tmp, _M_data(), _M_length() + 1);
+ this->_S_copy(__tmp, _M_data(), _M_length() + 1);
_M_dispose();
_M_data(__tmp);
_M_capacity(__res);
}
else if (!_M_is_local())
{
- _S_copy(_M_local_data, _M_data(), _M_length() + 1);
+ this->_S_copy(_M_local_data, _M_data(), _M_length() + 1);
_M_destroy(__capacity);
_M_data(_M_local_data);
}
@@ -544,11 +561,11 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
_CharT* __r = _M_create(__new_capacity, _M_capacity());
if (__pos)
- _S_copy(__r, _M_data(), __pos);
+ this->_S_copy(__r, _M_data(), __pos);
if (__s && __len2)
- _S_copy(__r + __pos, __s, __len2);
+ this->_S_copy(__r + __pos, __s, __len2);
if (__how_much)
- _S_copy(__r + __pos + __len2,
+ this->_S_copy(__r + __pos + __len2,
_M_data() + __pos + __len1, __how_much);
_M_dispose();
@@ -564,7 +581,7 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
const size_type __how_much = _M_length() - __pos - __n;
if (__how_much && __n)
- _S_move(_M_data() + __pos, _M_data() + __pos + __n,
+ this->_S_move(_M_data() + __pos, _M_data() + __pos + __n,
__how_much);
_M_set_length(_M_length() - __n);
diff --git a/gcc-4.4.3/libstdc++-v3/include/ext/vstring.h b/gcc-4.4.3/libstdc++-v3/include/ext/vstring.h
index c7bf2d2bf..6377ca57d 100644
--- a/gcc-4.4.3/libstdc++-v3/include/ext/vstring.h
+++ b/gcc-4.4.3/libstdc++-v3/include/ext/vstring.h
@@ -1340,7 +1340,7 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
&& __i2 <= _M_iend());
__glibcxx_requires_valid_range(__k1, __k2);
typedef typename std::__is_integer<_InputIterator>::__type _Integral;
- return _M_replace_dispatch(__i1, __i2, __k1, __k2, _Integral());
+ return this->_M_replace_dispatch(__i1, __i2, __k1, __k2, _Integral());
}
// Specializations for the common case of pointer and iterator:
@@ -1899,7 +1899,7 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
int __r = traits_type::compare(this->_M_data(), __str.data(), __len);
if (!__r)
- __r = _S_compare(__size, __osize);
+ __r = this->_S_compare(__size, __osize);
return __r;
}
diff --git a/gcc-4.4.3/libstdc++-v3/include/ext/vstring.tcc b/gcc-4.4.3/libstdc++-v3/include/ext/vstring.tcc
index 99193896b..2c3a8e276 100644
--- a/gcc-4.4.3/libstdc++-v3/include/ext/vstring.tcc
+++ b/gcc-4.4.3/libstdc++-v3/include/ext/vstring.tcc
@@ -464,7 +464,7 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
int __r = traits_type::compare(this->_M_data() + __pos,
__str.data(), __len);
if (!__r)
- __r = _S_compare(__n, __osize);
+ __r = this->_S_compare(__n, __osize);
return __r;
}
@@ -483,7 +483,7 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
int __r = traits_type::compare(this->_M_data() + __pos1,
__str.data() + __pos2, __len);
if (!__r)
- __r = _S_compare(__n1, __n2);
+ __r = this->_S_compare(__n1, __n2);
return __r;
}
@@ -499,7 +499,7 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
const size_type __len = std::min(__size, __osize);
int __r = traits_type::compare(this->_M_data(), __s, __len);
if (!__r)
- __r = _S_compare(__size, __osize);
+ __r = this->_S_compare(__size, __osize);
return __r;
}
@@ -516,7 +516,7 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
const size_type __len = std::min(__n1, __osize);
int __r = traits_type::compare(this->_M_data() + __pos, __s, __len);
if (!__r)
- __r = _S_compare(__n1, __osize);
+ __r = this->_S_compare(__n1, __osize);
return __r;
}
@@ -533,7 +533,7 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
const size_type __len = std::min(__n1, __n2);
int __r = traits_type::compare(this->_M_data() + __pos, __s, __len);
if (!__r)
- __r = _S_compare(__n1, __n2);
+ __r = this->_S_compare(__n1, __n2);
return __r;
}