summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>2011-11-16 06:49:51 +0000
committerlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>2011-11-16 06:49:51 +0000
commit1cd66bce1663eb648638d311b493de0dcc4146c3 (patch)
tree3868095e11c305bc6d667e4019e6be3848ca2726
parent435fe8432a466f1d298e9ef5153fb89034f5f6a2 (diff)
parent124f4875c51251f493b8388916f90a3ae5f22fbb (diff)
downloadgcc-1cd66bce1663eb648638d311b493de0dcc4146c3.tar.gz
Merge from trunk. arrayarg.f90 regressing
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/reload-v2a@181401 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--ChangeLog20
-rw-r--r--MAINTAINERS7
-rw-r--r--Makefile.def1
-rw-r--r--Makefile.in8
-rw-r--r--Makefile.tpl7
-rwxr-xr-xconfigure420
-rw-r--r--configure.ac3
-rw-r--r--gcc/ChangeLog439
-rw-r--r--gcc/DATESTAMP2
-rw-r--r--gcc/ada/ChangeLog36
-rw-r--r--gcc/ada/Make-generated.in31
-rw-r--r--gcc/ada/fe.h16
-rw-r--r--gcc/ada/gcc-interface/Make-lang.in4
-rw-r--r--gcc/ada/gcc-interface/Makefile.in37
-rw-r--r--gcc/ada/gcc-interface/gigi.h6
-rw-r--r--gcc/ada/gcc-interface/trans.c154
-rw-r--r--gcc/ada/gcc-interface/utils2.c107
-rw-r--r--gcc/builtins.c107
-rw-r--r--gcc/cgraph.h2
-rw-r--r--gcc/cgraphunit.c6
-rw-r--r--gcc/combine.c10
-rw-r--r--gcc/config.in7
-rw-r--r--gcc/config/alpha/elf.h9
-rw-r--r--gcc/config/elfos.h113
-rw-r--r--gcc/config/i386/constraints.md7
-rw-r--r--gcc/config/i386/i386-opts.h3
-rw-r--r--gcc/config/i386/i386-protos.h1
-rw-r--r--gcc/config/i386/i386.c1142
-rw-r--r--gcc/config/i386/i386.h8
-rw-r--r--gcc/config/i386/i386.md6
-rw-r--r--gcc/config/i386/i386.opt3
-rw-r--r--gcc/config/i386/predicates.md5
-rw-r--r--gcc/config/i386/sse.md20
-rw-r--r--gcc/config/pa/pa-linux.h3
-rw-r--r--gcc/config/pa/pa.c3
-rw-r--r--gcc/config/pa/pa.h5
-rw-r--r--gcc/config/rs6000/rs6000.c1
-rw-r--r--gcc/config/rs6000/rs6000.md4
-rw-r--r--gcc/config/sh/linux.h4
-rw-r--r--gcc/config/sh/sh.c8
-rw-r--r--gcc/config/sh/sh.h18
-rw-r--r--gcc/config/sparc/linux.h9
-rw-r--r--gcc/config/sparc/linux64.h9
-rw-r--r--gcc/config/sparc/sparc.c440
-rw-r--r--gcc/config/sparc/sparc.md54
-rwxr-xr-xgcc/configure2
-rw-r--r--gcc/configure.ac2
-rw-r--r--gcc/cp/ChangeLog50
-rw-r--r--gcc/cp/call.c39
-rw-r--r--gcc/cp/cp-gimplify.c3
-rw-r--r--gcc/cp/cp-tree.h23
-rw-r--r--gcc/cp/decl2.c10
-rw-r--r--gcc/cp/init.c2
-rw-r--r--gcc/cp/method.c1
-rw-r--r--gcc/cp/parser.c2
-rw-r--r--gcc/cp/pt.c56
-rw-r--r--gcc/cp/typeck.c41
-rw-r--r--gcc/cprop.c142
-rw-r--r--gcc/defaults.h11
-rw-r--r--gcc/doc/extend.texi21
-rw-r--r--gcc/doc/gcov.texi51
-rw-r--r--gcc/doc/install.texi2
-rw-r--r--gcc/doc/invoke.texi2
-rw-r--r--gcc/dwarf2asm.c21
-rw-r--r--gcc/dwarf2out.c27
-rw-r--r--gcc/final.c120
-rw-r--r--gcc/fold-const.c164
-rw-r--r--gcc/fortran/ChangeLog17
-rw-r--r--gcc/fortran/symbol.c82
-rw-r--r--gcc/fortran/trans-decl.c8
-rw-r--r--gcc/function.c2
-rw-r--r--gcc/function.h4
-rw-r--r--gcc/gcov.c688
-rw-r--r--gcc/gimple-pretty-print.c7
-rw-r--r--gcc/gimple.c42
-rw-r--r--gcc/gimplify.c38
-rw-r--r--gcc/ipa.c2
-rw-r--r--gcc/objc/ChangeLog5
-rw-r--r--gcc/objc/objc-next-runtime-abi-01.c5
-rw-r--r--gcc/omp-low.c145
-rw-r--r--gcc/optabs.c31
-rw-r--r--gcc/optabs.h3
-rw-r--r--gcc/opts-common.c2
-rw-r--r--gcc/output.h9
-rw-r--r--gcc/sync-builtins.def6
-rw-r--r--gcc/system.h4
-rw-r--r--gcc/testsuite/ChangeLog164
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/defaulted33.C32
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/noexcept16.C130
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/static_assert5.C21
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic119.C13
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/anon8.C6
-rw-r--r--gcc/testsuite/g++.dg/opt/stack2.C33
-rw-r--r--gcc/testsuite/g++.dg/parse/template21.C2
-rw-r--r--gcc/testsuite/g++.dg/template/conv12.C25
-rw-r--r--gcc/testsuite/g++.dg/template/linkage1.C18
-rw-r--r--gcc/testsuite/g++.dg/template/nontype13.C2
-rw-r--r--gcc/testsuite/g++.dg/warn/ref-temp1.C11
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/linkage4.C2
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr51077.c15
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr51023.c18
-rw-r--r--gcc/testsuite/gcc.dg/atomic-flag.c32
-rw-r--r--gcc/testsuite/gcc.dg/atomic-invalid.c7
-rw-r--r--gcc/testsuite/gcc.dg/atomic-noinline-aux.c15
-rw-r--r--gcc/testsuite/gcc.dg/atomic-noinline.c7
-rw-r--r--gcc/testsuite/gcc.dg/debug/dwarf2/asm-line1.c20
-rw-r--r--gcc/testsuite/gcc.dg/split-5.c171
-rw-r--r--gcc/testsuite/gcc.dg/tm/memopt-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr51042.c22
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr51070.c34
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr51071.c33
-rw-r--r--gcc/testsuite/gcc.dg/torture/vshuf-16.inc4
-rw-r--r--gcc/testsuite/gcc.dg/torture/vshuf-32.inc4
-rw-r--r--gcc/testsuite/gcc.dg/torture/vshuf-4.inc4
-rw-r--r--gcc/testsuite/gcc.dg/torture/vshuf-8.inc4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/phi-opt-6.c13
-rw-r--r--gcc/testsuite/gcc.dg/vect/fast-math-vect-call-1.c22
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr51000.c19
-rw-r--r--gcc/testsuite/gcc.misc-tests/gcov-14.c2
-rw-r--r--gcc/testsuite/gcc.misc-tests/gcov-15.c30
-rw-r--r--gcc/testsuite/gcc.target/i386/sw-1.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/20080410-1.c5
-rw-r--r--gcc/testsuite/gcc.target/sh/pr21255-2-ml.c10
-rw-r--r--gcc/testsuite/gfortran.dg/vect/pr51058-2.f9020
-rw-r--r--gcc/testsuite/gfortran.dg/vect/pr51058.f9019
-rw-r--r--gcc/testsuite/gnat.dg/atomic6_1.adb39
-rw-r--r--gcc/testsuite/gnat.dg/atomic6_2.adb45
-rw-r--r--gcc/testsuite/gnat.dg/atomic6_3.adb58
-rw-r--r--gcc/testsuite/gnat.dg/atomic6_4.adb45
-rw-r--r--gcc/testsuite/gnat.dg/atomic6_5.adb38
-rw-r--r--gcc/testsuite/gnat.dg/atomic6_6.adb39
-rw-r--r--gcc/testsuite/gnat.dg/atomic6_7.adb40
-rw-r--r--gcc/testsuite/gnat.dg/atomic6_8.adb37
-rw-r--r--gcc/testsuite/gnat.dg/atomic6_pkg.ads34
-rw-r--r--gcc/testsuite/gnat.dg/loop_optimization9.adb124
-rw-r--r--gcc/testsuite/gnat.dg/loop_optimization9.ads18
-rw-r--r--gcc/testsuite/lib/gcc-simulate-thread.exp5
-rw-r--r--gcc/testsuite/lib/target-supports.exp8
-rw-r--r--gcc/tree-emutls.c4
-rw-r--r--gcc/tree-loop-distribution.c103
-rw-r--r--gcc/tree-object-size.c2
-rw-r--r--gcc/tree-ssa-phiopt.c61
-rw-r--r--gcc/tree-ssa-pre.c113
-rw-r--r--gcc/tree-ssa-propagate.c10
-rw-r--r--gcc/tree-stdarg.c9
-rw-r--r--gcc/tree-vect-generic.c2
-rw-r--r--gcc/tree-vect-loop.c21
-rw-r--r--gcc/tree-vect-patterns.c4
-rw-r--r--gcc/tree-vect-slp.c150
-rw-r--r--gcc/tree-vect-stmts.c30
-rw-r--r--gcc/varasm.c126
-rw-r--r--gcc/varpool.c14
-rw-r--r--gcc/vec.h5
-rw-r--r--libada/ChangeLog5
-rw-r--r--libada/Makefile.in11
-rw-r--r--libffi/ChangeLog5
-rw-r--r--libffi/aclocal.m41
-rwxr-xr-xlibffi/configure17
-rw-r--r--libffi/configure.ac12
-rw-r--r--libgcc/ChangeLog41
-rw-r--r--libgcc/config.host2
-rw-r--r--libgcc/config/i386/morestack.S78
-rw-r--r--libgcc/config/pa/t-stublib17
-rw-r--r--libgcc/config/pa/t-stublib6413
-rw-r--r--libgcc/config/rs6000/linux-unwind.h2
-rw-r--r--libgcc/config/spu/t-elf2
-rw-r--r--libgcc/generic-morestack.c252
-rw-r--r--libgcc/libgcc-std.ver.in8
-rw-r--r--libgfortran/ChangeLog69
-rw-r--r--libgfortran/config.h.in48
-rwxr-xr-xlibgfortran/configure600
-rw-r--r--libgfortran/configure.ac37
-rw-r--r--libgfortran/intrinsics/clock.c26
-rw-r--r--libgfortran/intrinsics/cpu_time.c4
-rw-r--r--libgfortran/intrinsics/ctime.c20
-rw-r--r--libgfortran/intrinsics/date_and_time.c28
-rw-r--r--libgfortran/intrinsics/execute_command_line.c6
-rw-r--r--libgfortran/intrinsics/exit.c8
-rw-r--r--libgfortran/intrinsics/extends_type_of.c7
-rw-r--r--libgfortran/intrinsics/gerror.c6
-rw-r--r--libgfortran/intrinsics/kill.c8
-rw-r--r--libgfortran/intrinsics/malloc.c8
-rw-r--r--libgfortran/intrinsics/move_alloc.c8
-rw-r--r--libgfortran/intrinsics/perror.c6
-rw-r--r--libgfortran/intrinsics/random.c8
-rw-r--r--libgfortran/intrinsics/signal.c26
-rw-r--r--libgfortran/intrinsics/stat.c7
-rw-r--r--libgfortran/intrinsics/system.c7
-rw-r--r--libgfortran/intrinsics/system_clock.c2
-rw-r--r--libgfortran/intrinsics/time.c20
-rw-r--r--libgfortran/intrinsics/time_1.h54
-rw-r--r--libgfortran/intrinsics/umask.c7
-rw-r--r--libgfortran/io/format.c4
-rw-r--r--libgfortran/io/intrinsics.c5
-rw-r--r--libgfortran/io/io.h9
-rw-r--r--libgfortran/io/transfer.c9
-rw-r--r--libgfortran/io/write.c10
-rw-r--r--libgfortran/io/write_float.def2
-rw-r--r--libgfortran/runtime/backtrace.c1
-rw-r--r--libgfortran/runtime/compile_options.c24
-rw-r--r--libgfortran/runtime/error.c7
-rw-r--r--libgfortran/runtime/main.c2
-rw-r--r--libgo/Makefile.am1
-rw-r--r--libgo/Makefile.in32
-rw-r--r--libgo/runtime/go-defer.c24
-rw-r--r--libgo/runtime/go-deferred-recover.c5
-rw-r--r--libgo/runtime/go-go.c14
-rw-r--r--libgo/runtime/go-main.c4
-rw-r--r--libgo/runtime/go-panic-defer.c13
-rw-r--r--libgo/runtime/go-panic.c16
-rw-r--r--libgo/runtime/go-panic.h30
-rw-r--r--libgo/runtime/go-recover.c13
-rw-r--r--libgo/runtime/go-unwind.c39
-rw-r--r--libgo/runtime/mgc0.c3
-rw-r--r--libgo/runtime/proc.c6
-rw-r--r--libgo/runtime/runtime.h35
-rw-r--r--libitm/ChangeLog55
-rw-r--r--libitm/Makefile.am4
-rw-r--r--libitm/Makefile.in31
-rw-r--r--libitm/acinclude.m414
-rw-r--r--libitm/alloc_cpp.cc8
-rw-r--r--libitm/barrier.tpl170
-rw-r--r--libitm/config.h.in3
-rw-r--r--libitm/config/alpha/cacheline.h86
-rw-r--r--libitm/config/alpha/sjlj.S4
-rw-r--r--libitm/config/alpha/unaligned.h118
-rw-r--r--libitm/config/generic/cacheline.cc49
-rw-r--r--libitm/config/generic/cacheline.h49
-rw-r--r--libitm/config/generic/cachepage.h77
-rw-r--r--libitm/config/generic/tls.cc47
-rw-r--r--libitm/config/generic/unaligned.h228
-rw-r--r--libitm/config/posix/cachepage.cc183
-rw-r--r--libitm/config/x86/cacheline.cc73
-rw-r--r--libitm/config/x86/cacheline.h121
-rw-r--r--libitm/config/x86/sjlj.S19
-rw-r--r--libitm/config/x86/unaligned.h237
-rw-r--r--libitm/config/x86/x86_avx.cc112
-rw-r--r--libitm/config/x86/x86_sse.cc79
-rw-r--r--libitm/configure55
-rw-r--r--libitm/configure.ac2
-rw-r--r--libitm/libitm_i.h1
-rw-r--r--libitm/memcpy.cc365
-rw-r--r--libitm/memset.cc78
-rw-r--r--libitm/method-wbetl.cc628
-rw-r--r--libitm/testsuite/Makefile.in4
-rw-r--r--libitm/testsuite/libitm.c++/static_ctor.C1
-rw-r--r--libitm/testsuite/libitm.c/notx.c3
-rw-r--r--libitm/testsuite/libitm.c/reentrant.c1
-rw-r--r--libitm/testsuite/libitm.c/simple-2.c2
-rw-r--r--libitm/testsuite/libitm.c/txrelease.c2
-rw-r--r--libstdc++-v3/ChangeLog51
-rw-r--r--libstdc++-v3/doc/xml/manual/using.xml6
-rw-r--r--libstdc++-v3/include/bits/allocator.h3
-rw-r--r--libstdc++-v3/include/bits/atomic_base.h64
-rw-r--r--libstdc++-v3/include/c_global/cmath84
-rw-r--r--libstdc++-v3/include/ext/type_traits.h56
-rw-r--r--libstdc++-v3/include/tr1/cmath55
-rw-r--r--libstdc++-v3/testsuite/23_containers/vector/capacity/shrink_to_fit2.cc61
-rw-r--r--libstdc++-v3/testsuite/25_algorithms/max/1.cc8
-rw-r--r--libstdc++-v3/testsuite/25_algorithms/min/1.cc8
-rw-r--r--libstdc++-v3/testsuite/25_algorithms/minmax/1.cc8
-rw-r--r--libstdc++-v3/testsuite/26_numerics/cmath/51083.cc62
-rw-r--r--libstdc++-v3/testsuite/26_numerics/complex/51083.cc54
-rw-r--r--libstdc++-v3/testsuite/tr1/8_c_compatibility/cmath/51083.cc62
-rw-r--r--libstdc++-v3/testsuite/tr1/8_c_compatibility/complex/51083.cc54
265 files changed, 7243 insertions, 5470 deletions
diff --git a/ChangeLog b/ChangeLog
index bb781a889cf..e18fea2234f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,23 @@
+2011-11-12 Andrey Belevantsev <abel@ispras.ru>
+
+ * MAINTAINERS (Reviewers): Keep the list sorted.
+
+2011-11-11 Andrey Belevantsev <abel@ispras.ru>
+
+ * MAINTAINERS (Selective Scheduling): Add myself as a reviewer.
+
+2011-11-09 Roland McGrath <mcgrathr@google.com>
+
+ * configure.ac: Add tool checks for READELF and READELF_FOR_TARGET.
+ * configure: Rebuild.
+ * Makefile.def (flags_to_pass): Add READELF_FOR_TARGET.
+ * Makefile.tpl (READELF, READELF_FOR_TARGET): New variables.
+ (HOST_EXPORTS): Add READELF, READELF_FOR_TARGET.
+ (BASE_FLAGS_TO_PASS): Add READELF_FOR_TARGET.
+ (BASE_TARGET_EXPORTS, EXTRA_HOST_FLAGS, EXTRA_TARGET_FLAGS):
+ Add READELF.
+ * Makefile.in: Rebuild.
+
2011-11-09 Jason Merrill <jason@redhat.com>
* Makefile.def (language=c++): Remove check-c++0x.
diff --git a/MAINTAINERS b/MAINTAINERS
index c78388267dd..511c08ac104 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -281,14 +281,15 @@ Graphite Tobias Grosser grosser@fim.uni-passau.de
Graphite Sebastian Pop sebastian.pop@amd.com
libcpp Tom Tromey tromey@redhat.com
loop optimizer Zdenek Dvorak ook@ucw.cz
+LTO Diego Novillo dnovillo@google.com
+LTO Richard Guenther rguenther@suse.de
+LTO plugin Cary Coutant ccoutant@google.com
Plugin Diego Novillo dnovillo@google.com
Plugin Le-Chun Wu lcwu@google.com
register allocation Peter Bergner bergner@vnet.ibm.com
register allocation Kenneth Zadeck zadeck@naturalbridge.com
register allocation Seongbae Park seongbae.park@gmail.com
-LTO Diego Novillo dnovillo@google.com
-LTO Richard Guenther rguenther@suse.de
-LTO plugin Cary Coutant ccoutant@google.com
+selective scheduling Andrey Belevantsev abel@ispras.ru
Note that while reviewers can approve changes to parts of the compiler
that they maintain, they still need approval for their own patches
diff --git a/Makefile.def b/Makefile.def
index b4236bac086..5de12bf6915 100644
--- a/Makefile.def
+++ b/Makefile.def
@@ -260,6 +260,7 @@ flags_to_pass = { flag= LIBCXXFLAGS_FOR_TARGET ; };
flags_to_pass = { flag= NM_FOR_TARGET ; };
flags_to_pass = { flag= OBJDUMP_FOR_TARGET ; };
flags_to_pass = { flag= RANLIB_FOR_TARGET ; };
+flags_to_pass = { flag= READELF_FOR_TARGET ; };
flags_to_pass = { flag= STRIP_FOR_TARGET ; };
flags_to_pass = { flag= WINDRES_FOR_TARGET ; };
flags_to_pass = { flag= WINDMC_FOR_TARGET ; };
diff --git a/Makefile.in b/Makefile.in
index c377f577332..88797b4bf06 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -206,6 +206,7 @@ HOST_EXPORTS = \
WINDMC="$(WINDMC)"; export WINDMC; \
OBJCOPY="$(OBJCOPY)"; export OBJCOPY; \
OBJDUMP="$(OBJDUMP)"; export OBJDUMP; \
+ READELF="$(READELF)"; export READELF; \
AR_FOR_TARGET="$(AR_FOR_TARGET)"; export AR_FOR_TARGET; \
AS_FOR_TARGET="$(AS_FOR_TARGET)"; export AS_FOR_TARGET; \
GCC_FOR_TARGET="$(GCC_FOR_TARGET)"; export GCC_FOR_TARGET; \
@@ -213,6 +214,7 @@ HOST_EXPORTS = \
NM_FOR_TARGET="$(NM_FOR_TARGET)"; export NM_FOR_TARGET; \
OBJDUMP_FOR_TARGET="$(OBJDUMP_FOR_TARGET)"; export OBJDUMP_FOR_TARGET; \
RANLIB_FOR_TARGET="$(RANLIB_FOR_TARGET)"; export RANLIB_FOR_TARGET; \
+ READELF_FOR_TARGET="$(READELF_FOR_TARGET)"; export READELF_FOR_TARGET; \
TOPLEVEL_CONFIGURE_ARGUMENTS="$(TOPLEVEL_CONFIGURE_ARGUMENTS)"; export TOPLEVEL_CONFIGURE_ARGUMENTS; \
HOST_LIBS="$(STAGE1_LIBS)"; export HOST_LIBS; \
GMPLIBS="$(HOST_GMPLIBS)"; export GMPLIBS; \
@@ -285,6 +287,7 @@ BASE_TARGET_EXPORTS = \
NM="$(COMPILER_NM_FOR_TARGET)"; export NM; \
OBJDUMP="$(OBJDUMP_FOR_TARGET)"; export OBJDUMP; \
RANLIB="$(RANLIB_FOR_TARGET)"; export RANLIB; \
+ READELF="$(READELF_FOR_TARGET)"; export READELF; \
STRIP="$(STRIP_FOR_TARGET)"; export STRIP; \
WINDRES="$(WINDRES_FOR_TARGET)"; export WINDRES; \
WINDMC="$(WINDMC_FOR_TARGET)"; export WINDMC; \
@@ -397,6 +400,7 @@ LIPO = @LIPO@
NM = @NM@
OBJDUMP = @OBJDUMP@
RANLIB = @RANLIB@
+READELF = @READELF@
STRIP = @STRIP@
WINDRES = @WINDRES@
WINDMC = @WINDMC@
@@ -555,6 +559,7 @@ LIPO_FOR_TARGET=@LIPO_FOR_TARGET@
NM_FOR_TARGET=@NM_FOR_TARGET@
OBJDUMP_FOR_TARGET=@OBJDUMP_FOR_TARGET@
RANLIB_FOR_TARGET=@RANLIB_FOR_TARGET@
+READELF_FOR_TARGET=@READELF_FOR_TARGET@
STRIP_FOR_TARGET=@STRIP_FOR_TARGET@
WINDRES_FOR_TARGET=@WINDRES_FOR_TARGET@
WINDMC_FOR_TARGET=@WINDMC_FOR_TARGET@
@@ -771,6 +776,7 @@ BASE_FLAGS_TO_PASS = \
"NM_FOR_TARGET=$(NM_FOR_TARGET)" \
"OBJDUMP_FOR_TARGET=$(OBJDUMP_FOR_TARGET)" \
"RANLIB_FOR_TARGET=$(RANLIB_FOR_TARGET)" \
+ "READELF_FOR_TARGET=$(READELF_FOR_TARGET)" \
"STRIP_FOR_TARGET=$(STRIP_FOR_TARGET)" \
"WINDRES_FOR_TARGET=$(WINDRES_FOR_TARGET)" \
"WINDMC_FOR_TARGET=$(WINDMC_FOR_TARGET)" \
@@ -819,6 +825,7 @@ EXTRA_HOST_FLAGS = \
'NM=$(NM)' \
'OBJDUMP=$(OBJDUMP)' \
'RANLIB=$(RANLIB)' \
+ 'READELF=$(READELF)' \
'STRIP=$(STRIP)' \
'WINDRES=$(WINDRES)' \
'WINDMC=$(WINDMC)'
@@ -859,6 +866,7 @@ EXTRA_TARGET_FLAGS = \
'NM=$(COMPILER_NM_FOR_TARGET)' \
'OBJDUMP=$$(OBJDUMP_FOR_TARGET)' \
'RANLIB=$$(RANLIB_FOR_TARGET)' \
+ 'READELF=$$(READELF_FOR_TARGET)' \
'WINDRES=$$(WINDRES_FOR_TARGET)' \
'WINDMC=$$(WINDMC_FOR_TARGET)' \
'XGCC_FLAGS_FOR_TARGET=$(XGCC_FLAGS_FOR_TARGET)' \
diff --git a/Makefile.tpl b/Makefile.tpl
index 2944d60d642..ae263e6d36f 100644
--- a/Makefile.tpl
+++ b/Makefile.tpl
@@ -209,6 +209,7 @@ HOST_EXPORTS = \
WINDMC="$(WINDMC)"; export WINDMC; \
OBJCOPY="$(OBJCOPY)"; export OBJCOPY; \
OBJDUMP="$(OBJDUMP)"; export OBJDUMP; \
+ READELF="$(READELF)"; export READELF; \
AR_FOR_TARGET="$(AR_FOR_TARGET)"; export AR_FOR_TARGET; \
AS_FOR_TARGET="$(AS_FOR_TARGET)"; export AS_FOR_TARGET; \
GCC_FOR_TARGET="$(GCC_FOR_TARGET)"; export GCC_FOR_TARGET; \
@@ -216,6 +217,7 @@ HOST_EXPORTS = \
NM_FOR_TARGET="$(NM_FOR_TARGET)"; export NM_FOR_TARGET; \
OBJDUMP_FOR_TARGET="$(OBJDUMP_FOR_TARGET)"; export OBJDUMP_FOR_TARGET; \
RANLIB_FOR_TARGET="$(RANLIB_FOR_TARGET)"; export RANLIB_FOR_TARGET; \
+ READELF_FOR_TARGET="$(READELF_FOR_TARGET)"; export READELF_FOR_TARGET; \
TOPLEVEL_CONFIGURE_ARGUMENTS="$(TOPLEVEL_CONFIGURE_ARGUMENTS)"; export TOPLEVEL_CONFIGURE_ARGUMENTS; \
HOST_LIBS="$(STAGE1_LIBS)"; export HOST_LIBS; \
GMPLIBS="$(HOST_GMPLIBS)"; export GMPLIBS; \
@@ -288,6 +290,7 @@ BASE_TARGET_EXPORTS = \
NM="$(COMPILER_NM_FOR_TARGET)"; export NM; \
OBJDUMP="$(OBJDUMP_FOR_TARGET)"; export OBJDUMP; \
RANLIB="$(RANLIB_FOR_TARGET)"; export RANLIB; \
+ READELF="$(READELF_FOR_TARGET)"; export READELF; \
STRIP="$(STRIP_FOR_TARGET)"; export STRIP; \
WINDRES="$(WINDRES_FOR_TARGET)"; export WINDRES; \
WINDMC="$(WINDMC_FOR_TARGET)"; export WINDMC; \
@@ -400,6 +403,7 @@ LIPO = @LIPO@
NM = @NM@
OBJDUMP = @OBJDUMP@
RANLIB = @RANLIB@
+READELF = @READELF@
STRIP = @STRIP@
WINDRES = @WINDRES@
WINDMC = @WINDMC@
@@ -493,6 +497,7 @@ LIPO_FOR_TARGET=@LIPO_FOR_TARGET@
NM_FOR_TARGET=@NM_FOR_TARGET@
OBJDUMP_FOR_TARGET=@OBJDUMP_FOR_TARGET@
RANLIB_FOR_TARGET=@RANLIB_FOR_TARGET@
+READELF_FOR_TARGET=@READELF_FOR_TARGET@
STRIP_FOR_TARGET=@STRIP_FOR_TARGET@
WINDRES_FOR_TARGET=@WINDRES_FOR_TARGET@
WINDMC_FOR_TARGET=@WINDMC_FOR_TARGET@
@@ -612,6 +617,7 @@ EXTRA_HOST_FLAGS = \
'NM=$(NM)' \
'OBJDUMP=$(OBJDUMP)' \
'RANLIB=$(RANLIB)' \
+ 'READELF=$(READELF)' \
'STRIP=$(STRIP)' \
'WINDRES=$(WINDRES)' \
'WINDMC=$(WINDMC)'
@@ -652,6 +658,7 @@ EXTRA_TARGET_FLAGS = \
'NM=$(COMPILER_NM_FOR_TARGET)' \
'OBJDUMP=$$(OBJDUMP_FOR_TARGET)' \
'RANLIB=$$(RANLIB_FOR_TARGET)' \
+ 'READELF=$$(READELF_FOR_TARGET)' \
'WINDRES=$$(WINDRES_FOR_TARGET)' \
'WINDMC=$$(WINDMC_FOR_TARGET)' \
'XGCC_FLAGS_FOR_TARGET=$(XGCC_FLAGS_FOR_TARGET)' \
diff --git a/configure b/configure
index 8a37411f686..f5c76be1968 100755
--- a/configure
+++ b/configure
@@ -571,6 +571,7 @@ RAW_CXX_FOR_TARGET
WINDMC_FOR_TARGET
WINDRES_FOR_TARGET
STRIP_FOR_TARGET
+READELF_FOR_TARGET
RANLIB_FOR_TARGET
OBJDUMP_FOR_TARGET
NM_FOR_TARGET
@@ -585,6 +586,7 @@ GCJ_FOR_TARGET
GCC_FOR_TARGET
CXX_FOR_TARGET
CC_FOR_TARGET
+READELF
OBJDUMP
OBJCOPY
WINDMC
@@ -815,6 +817,7 @@ WINDRES
WINDMC
OBJCOPY
OBJDUMP
+READELF
CC_FOR_TARGET
CXX_FOR_TARGET
GCC_FOR_TARGET
@@ -829,6 +832,7 @@ LIPO_FOR_TARGET
NM_FOR_TARGET
OBJDUMP_FOR_TARGET
RANLIB_FOR_TARGET
+READELF_FOR_TARGET
STRIP_FOR_TARGET
WINDRES_FOR_TARGET
WINDMC_FOR_TARGET'
@@ -1577,6 +1581,7 @@ Some influential environment variables:
WINDMC WINDMC for the host
OBJCOPY OBJCOPY for the host
OBJDUMP OBJDUMP for the host
+ READELF READELF for the host
CC_FOR_TARGET
CC for the target
CXX_FOR_TARGET
@@ -1605,6 +1610,8 @@ Some influential environment variables:
OBJDUMP for the target
RANLIB_FOR_TARGET
RANLIB for the target
+ READELF_FOR_TARGET
+ READELF for the target
STRIP_FOR_TARGET
STRIP for the target
WINDRES_FOR_TARGET
@@ -9608,6 +9615,147 @@ fi
+if test -n "$READELF"; then
+ ac_cv_prog_READELF=$READELF
+elif test -n "$ac_cv_prog_READELF"; then
+ READELF=$ac_cv_prog_READELF
+fi
+
+if test -n "$ac_cv_prog_READELF"; then
+ for ncn_progname in readelf; do
+ # Extract the first word of "${ncn_progname}", so it can be a program name with args.
+set dummy ${ncn_progname}; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_READELF+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$READELF"; then
+ ac_cv_prog_READELF="$READELF" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_READELF="${ncn_progname}"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+READELF=$ac_cv_prog_READELF
+if test -n "$READELF"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $READELF" >&5
+$as_echo "$READELF" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ done
+fi
+
+for ncn_progname in readelf; do
+ if test -n "$ncn_tool_prefix"; then
+ # Extract the first word of "${ncn_tool_prefix}${ncn_progname}", so it can be a program name with args.
+set dummy ${ncn_tool_prefix}${ncn_progname}; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_READELF+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$READELF"; then
+ ac_cv_prog_READELF="$READELF" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_READELF="${ncn_tool_prefix}${ncn_progname}"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+READELF=$ac_cv_prog_READELF
+if test -n "$READELF"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $READELF" >&5
+$as_echo "$READELF" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ fi
+ if test -z "$ac_cv_prog_READELF" && test $build = $host ; then
+ # Extract the first word of "${ncn_progname}", so it can be a program name with args.
+set dummy ${ncn_progname}; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_READELF+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$READELF"; then
+ ac_cv_prog_READELF="$READELF" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_READELF="${ncn_progname}"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+READELF=$ac_cv_prog_READELF
+if test -n "$READELF"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $READELF" >&5
+$as_echo "$READELF" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ fi
+ test -n "$ac_cv_prog_READELF" && break
+done
+
+if test -z "$ac_cv_prog_READELF" ; then
+ set dummy readelf
+ if test $build = $host ; then
+ READELF="$2"
+ else
+ READELF="${ncn_tool_prefix}$2"
+ fi
+fi
+
+
+
@@ -12447,6 +12595,236 @@ fi
+if test -z "$ac_cv_path_READELF_FOR_TARGET" ; then
+ if test -n "$with_build_time_tools"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for readelf in $with_build_time_tools" >&5
+$as_echo_n "checking for readelf in $with_build_time_tools... " >&6; }
+ if test -x $with_build_time_tools/readelf; then
+ READELF_FOR_TARGET=`cd $with_build_time_tools && pwd`/readelf
+ ac_cv_path_READELF_FOR_TARGET=$READELF_FOR_TARGET
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_READELF_FOR_TARGET" >&5
+$as_echo "$ac_cv_path_READELF_FOR_TARGET" >&6; }
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ fi
+ elif test $build != $host && test $have_gcc_for_target = yes; then
+ READELF_FOR_TARGET=`$GCC_FOR_TARGET --print-prog-name=readelf`
+ test $READELF_FOR_TARGET = readelf && READELF_FOR_TARGET=
+ test -n "$READELF_FOR_TARGET" && ac_cv_path_READELF_FOR_TARGET=$READELF_FOR_TARGET
+ fi
+fi
+if test -z "$ac_cv_path_READELF_FOR_TARGET" && test -n "$gcc_cv_tool_dirs"; then
+ # Extract the first word of "readelf", so it can be a program name with args.
+set dummy readelf; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_path_READELF_FOR_TARGET+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $READELF_FOR_TARGET in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_READELF_FOR_TARGET="$READELF_FOR_TARGET" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $gcc_cv_tool_dirs
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_path_READELF_FOR_TARGET="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+READELF_FOR_TARGET=$ac_cv_path_READELF_FOR_TARGET
+if test -n "$READELF_FOR_TARGET"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $READELF_FOR_TARGET" >&5
+$as_echo "$READELF_FOR_TARGET" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_path_READELF_FOR_TARGET" ; then
+
+
+if test -n "$READELF_FOR_TARGET"; then
+ ac_cv_prog_READELF_FOR_TARGET=$READELF_FOR_TARGET
+elif test -n "$ac_cv_prog_READELF_FOR_TARGET"; then
+ READELF_FOR_TARGET=$ac_cv_prog_READELF_FOR_TARGET
+fi
+
+if test -n "$ac_cv_prog_READELF_FOR_TARGET"; then
+ for ncn_progname in readelf; do
+ # Extract the first word of "${ncn_progname}", so it can be a program name with args.
+set dummy ${ncn_progname}; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_READELF_FOR_TARGET+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$READELF_FOR_TARGET"; then
+ ac_cv_prog_READELF_FOR_TARGET="$READELF_FOR_TARGET" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_READELF_FOR_TARGET="${ncn_progname}"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+READELF_FOR_TARGET=$ac_cv_prog_READELF_FOR_TARGET
+if test -n "$READELF_FOR_TARGET"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $READELF_FOR_TARGET" >&5
+$as_echo "$READELF_FOR_TARGET" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ done
+fi
+
+if test -z "$ac_cv_prog_READELF_FOR_TARGET" && test -n "$with_build_time_tools"; then
+ for ncn_progname in readelf; do
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ncn_progname} in $with_build_time_tools" >&5
+$as_echo_n "checking for ${ncn_progname} in $with_build_time_tools... " >&6; }
+ if test -x $with_build_time_tools/${ncn_progname}; then
+ ac_cv_prog_READELF_FOR_TARGET=$with_build_time_tools/${ncn_progname}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ break
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ fi
+ done
+fi
+
+if test -z "$ac_cv_prog_READELF_FOR_TARGET"; then
+ for ncn_progname in readelf; do
+ if test -n "$ncn_target_tool_prefix"; then
+ # Extract the first word of "${ncn_target_tool_prefix}${ncn_progname}", so it can be a program name with args.
+set dummy ${ncn_target_tool_prefix}${ncn_progname}; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_READELF_FOR_TARGET+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$READELF_FOR_TARGET"; then
+ ac_cv_prog_READELF_FOR_TARGET="$READELF_FOR_TARGET" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_READELF_FOR_TARGET="${ncn_target_tool_prefix}${ncn_progname}"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+READELF_FOR_TARGET=$ac_cv_prog_READELF_FOR_TARGET
+if test -n "$READELF_FOR_TARGET"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $READELF_FOR_TARGET" >&5
+$as_echo "$READELF_FOR_TARGET" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ fi
+ if test -z "$ac_cv_prog_READELF_FOR_TARGET" && test $build = $target ; then
+ # Extract the first word of "${ncn_progname}", so it can be a program name with args.
+set dummy ${ncn_progname}; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_READELF_FOR_TARGET+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$READELF_FOR_TARGET"; then
+ ac_cv_prog_READELF_FOR_TARGET="$READELF_FOR_TARGET" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_READELF_FOR_TARGET="${ncn_progname}"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+READELF_FOR_TARGET=$ac_cv_prog_READELF_FOR_TARGET
+if test -n "$READELF_FOR_TARGET"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $READELF_FOR_TARGET" >&5
+$as_echo "$READELF_FOR_TARGET" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ fi
+ test -n "$ac_cv_prog_READELF_FOR_TARGET" && break
+ done
+fi
+
+if test -z "$ac_cv_prog_READELF_FOR_TARGET" ; then
+ set dummy readelf
+ if test $build = $target ; then
+ READELF_FOR_TARGET="$2"
+ else
+ READELF_FOR_TARGET="${ncn_target_tool_prefix}$2"
+ fi
+else
+ READELF_FOR_TARGET="$ac_cv_prog_READELF_FOR_TARGET"
+fi
+
+else
+ READELF_FOR_TARGET=$ac_cv_path_READELF_FOR_TARGET
+fi
+
+
+
+
if test -z "$ac_cv_path_STRIP_FOR_TARGET" ; then
if test -n "$with_build_time_tools"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for strip in $with_build_time_tools" >&5
@@ -13771,6 +14149,48 @@ $as_echo "pre-installed" >&6; }
fi
fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking where to find the target readelf" >&5
+$as_echo_n "checking where to find the target readelf... " >&6; }
+if test "x${build}" != "x${host}" ; then
+ if expr "x$READELF_FOR_TARGET" : "x/" > /dev/null; then
+ # We already found the complete path
+ ac_dir=`dirname $READELF_FOR_TARGET`
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: pre-installed in $ac_dir" >&5
+$as_echo "pre-installed in $ac_dir" >&6; }
+ else
+ # Canadian cross, just use what we found
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: pre-installed" >&5
+$as_echo "pre-installed" >&6; }
+ fi
+else
+ ok=yes
+ case " ${configdirs} " in
+ *" binutils "*) ;;
+ *) ok=no ;;
+ esac
+
+ if test $ok = yes; then
+ # An in-tree tool is available and we can use it
+ READELF_FOR_TARGET='$$r/$(HOST_SUBDIR)/binutils/readelf'
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: just compiled" >&5
+$as_echo "just compiled" >&6; }
+ elif expr "x$READELF_FOR_TARGET" : "x/" > /dev/null; then
+ # We already found the complete path
+ ac_dir=`dirname $READELF_FOR_TARGET`
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: pre-installed in $ac_dir" >&5
+$as_echo "pre-installed in $ac_dir" >&6; }
+ elif test "x$target" = "x$host"; then
+ # We can use an host tool
+ READELF_FOR_TARGET='$(READELF)'
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: host tool" >&5
+$as_echo "host tool" >&6; }
+ else
+ # We need a cross tool
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: pre-installed" >&5
+$as_echo "pre-installed" >&6; }
+ fi
+fi
+
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking where to find the target strip" >&5
$as_echo_n "checking where to find the target strip... " >&6; }
if test "x${build}" != "x${host}" ; then
diff --git a/configure.ac b/configure.ac
index efabad4a224..a5034b26217 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3059,6 +3059,7 @@ NCN_STRICT_CHECK_TOOLS(WINDRES, windres)
NCN_STRICT_CHECK_TOOLS(WINDMC, windmc)
NCN_STRICT_CHECK_TOOLS(OBJCOPY, objcopy)
NCN_STRICT_CHECK_TOOLS(OBJDUMP, objdump)
+NCN_STRICT_CHECK_TOOLS(READELF, readelf)
AC_SUBST(CC)
AC_SUBST(CXX)
AC_SUBST(CFLAGS)
@@ -3092,6 +3093,7 @@ ACX_CHECK_INSTALLED_TARGET_TOOL(LIPO_FOR_TARGET, lipo)
ACX_CHECK_INSTALLED_TARGET_TOOL(NM_FOR_TARGET, nm)
ACX_CHECK_INSTALLED_TARGET_TOOL(OBJDUMP_FOR_TARGET, objdump)
ACX_CHECK_INSTALLED_TARGET_TOOL(RANLIB_FOR_TARGET, ranlib)
+ACX_CHECK_INSTALLED_TARGET_TOOL(READELF_FOR_TARGET, readelf)
ACX_CHECK_INSTALLED_TARGET_TOOL(STRIP_FOR_TARGET, strip)
ACX_CHECK_INSTALLED_TARGET_TOOL(WINDRES_FOR_TARGET, windres)
ACX_CHECK_INSTALLED_TARGET_TOOL(WINDMC_FOR_TARGET, windmc)
@@ -3121,6 +3123,7 @@ GCC_TARGET_TOOL(lipo, LIPO_FOR_TARGET, LIPO)
GCC_TARGET_TOOL(nm, NM_FOR_TARGET, NM, [binutils/nm-new])
GCC_TARGET_TOOL(objdump, OBJDUMP_FOR_TARGET, OBJDUMP, [binutils/objdump])
GCC_TARGET_TOOL(ranlib, RANLIB_FOR_TARGET, RANLIB, [binutils/ranlib])
+GCC_TARGET_TOOL(readelf, READELF_FOR_TARGET, READELF, [binutils/readelf])
GCC_TARGET_TOOL(strip, STRIP_FOR_TARGET, STRIP, [binutils/strip-new])
GCC_TARGET_TOOL(windres, WINDRES_FOR_TARGET, WINDRES, [binutils/windres])
GCC_TARGET_TOOL(windmc, WINDMC_FOR_TARGET, WINDMC, [binutils/windmc])
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index ce1bac49427..9a713cfbf1c 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,423 @@
+2011-11-14 Zolotukhin Michael <michael.v.zolotukhin@gmail.com>
+ Jan Hubicka <jh@suse.cz>
+
+ * config/i386/i386.h (processor_costs): Add second dimension to
+ stringop_algs array.
+ * config/i386/i386.c (cost models): Initialize second dimension of
+ stringop_algs arrays.
+ (core_cost): New costs based on generic64 costs with updated stringop
+ values.
+ (promote_duplicated_reg): Add support for vector modes, add
+ declaration.
+ (promote_duplicated_reg_to_size): Likewise.
+ (processor_target): Set core costs for core variants.
+ (expand_set_or_movmem_via_loop_with_iter): New function.
+ (expand_set_or_movmem_via_loop): Enable reuse of the same iters in
+ different loops, produced by this function.
+ (emit_strset): New function.
+ (expand_movmem_epilogue): Add epilogue generation for bigger sizes,
+ use SSE-moves where possible.
+ (expand_setmem_epilogue): Likewise.
+ (expand_movmem_prologue): Likewise for prologue.
+ (expand_setmem_prologue): Likewise.
+ (expand_constant_movmem_prologue): Likewise.
+ (expand_constant_setmem_prologue): Likewise.
+ (decide_alg): Add new argument align_unknown. Fix algorithm of
+ strategy selection if TARGET_INLINE_ALL_STRINGOPS is set; Skip sse_loop
+ (decide_alignment): Update desired alignment according to chosen move
+ mode.
+ (ix86_expand_movmem): Change unrolled_loop strategy to use SSE-moves.
+ (ix86_expand_setmem): Likewise.
+ (ix86_slow_unaligned_access): Implementation of new hook
+ slow_unaligned_access.
+ * config/i386/i386.md (strset): Enable half-SSE moves.
+ * config/i386/sse.md (vec_dupv4si): Add expand for vec_dupv4si.
+ (vec_dupv2di): Add expand for vec_dupv2di.
+
+2011-11-14 Dimitrios Apostolou <jimis@gmx.net>
+
+ PR bootstrap/51094
+ PR middle-end/51116
+ * config/elfos.h (TARGET_ASM_INTERNAL_LABEL): Remove.
+ * varasm.c (default_elf_internal_label): Remove.
+
+2011-11-14 Kai Tietz <ktietz@redhat.com>
+
+ * gcov.c (generate_results): Add missing semicolon and
+ correct indent.
+
+2011-11-14 Ira Rosen <ira.rosen@linaro.org>
+
+ PR bootstrap/51112
+ * tree-vect-stmts.c (vectorizable_condition): Initialize comp_vectype.
+
+2011-11-14 Mingjie Xing <mingjie.xing@gmail.com>
+
+ * doc/invoke.texi (Wunused-result): Change @pxref{Variable Attributes}
+ to @pxref{Function Attributes}.
+
+2011-11-13 Oleg Endo <oleg.endo@t-online.de>
+
+ PR target/50694
+ * config/sh/sh.h (IS_LITTLE_ENDIAN_OPTION, UNSUPPORTED_SH2A):
+ New macros.
+ (DRIVER_SELF_SPECS): Use new macros to filter out
+ unsupported options taking the default configuration into
+ account.
+
+2011-11-13 Jonathan Wakely <jwakely.gcc@gmail.com>
+
+ * doc/install.texi (Specific): Fix anchor for
+ x86_64-*-solaris2.1[0-9]*.
+
+2011-11-13 Nathan Sidwell <nathan@acm.org>
+
+ * gcov.c (source_prefix, source_length): New globals.
+ (flag_relative_only): Likewise.
+ (print_usage, options, process_args): Update.
+ (generate_results): Use coverage.name, check
+ flag_relative_only. Adjust messages.
+ (find_source): Check source_prefix.
+ (output_lines): Use coverage.name, adjust messages.
+ * doc/gcov.texi (Invoking Gcov): Document new options.
+
+2011-11-12 Jason Merrill <jason@redhat.com>
+
+ PR c++/51060
+ * gimplify.c (gimplify_target_expr): Add a clobber to the cleanup.
+ (gimplify_modify_expr): Don't try to simplify it.
+
+2011-11-12 Dimitrios Apostolou <jimis@gmx.net>
+
+ PR bootstrap/51094
+ * config/elfos.h (STRING_ASM_OP): Define.
+ * varasm.c (default_elf_asm_output_limited_string): Use it.
+
+ PR bootstrap/51094
+ * gcc/configure.ac: Check for stpcpy declaration.
+ * system.h: Declare it if not.
+ * config.in, configure: Regenerate.
+
+2011-11-12 Richard Henderson <rth@redhat.com>
+
+ * config/rs6000/rs6000.md (fix_trunc<SFDF>si2_stfiwx): Use
+ nonimmediate_operand for the destination.
+ (fixuns_trunc<SFDF>si2_stfiwx): Likewise.
+
+ * builtins.c (expand_builtin_compare_and_swap): If target is const0,
+ don't pass the target to expand_atomic_compare_and_swap.
+ (expand_builtin_atomic_compare_exchange): Likewise.
+
+ * config/sh/linux.h (TARGET_INIT_LIBFUNCS): New.
+ * config/sh/sh.c (sh_init_sync_libfuncs): New.
+
+ * config/pa/pa-linux.h (TARGET_SYNC_LIBCALL): New.
+ * config/pa/pa.h (TARGET_SYNC_LIBCALL): New default.
+ * config/pa/pa.c (pa_init_libfuncs): Use init_sync_libfuncs.
+
+2011-11-12 Iain Sandoe <iains@gcc.gnu.org>
+
+ PR target/45233
+ * config/rs6000/rs6000.c (rs6000_legitimize_reload_address):
+ Only expand a symbol ref. into an access when the entity is defined
+ in the TU.
+
+2011-11-12 Jan Hubicka <jh@suse.cz>
+
+ PR bootstrap/50822
+ * cgraphunit.c (output_weakrefs): Output really only weakrefs.
+
+2011-11-12 Nathan Sidwell <nathan@acm.org>
+
+ * gcov.c (struct name_map): New.
+ (names, n_names, a_names): New global vars.
+ (print_usage): Adjust usage.
+ (generate_results): Canonicalize main file name.
+ (release_structures): Adjust.
+ (name_search, name_sort): New callbacks.
+ (find_source): Look for and create a canonical name.
+ (canonicalize_name): New.
+ (make_gcov_file_name): Reimplement and fix mangling.
+ (mangle_name): New.
+ * doc/gcov.texi: Update documentation about path preservation.
+
+2011-11-11 David S. Miller <davem@davemloft.net>
+
+ * config/sparc/linux.h (ASM_GENERATE_INTERNAL_LABEL): Delete.
+ * config/sparc/linux64.h (ASM_GENERATE_INTERNAL_LABEL): Delete.
+
+2011-11-11 Jakub Jelinek <jakub@redhat.com>
+
+ * config/i386/i386-protos.h (ix86_maybe_emit_epilogue_vzeroupper):
+ New prototype.
+ * config/i386/i386.c (ix86_maybe_emit_epilogue_vzeroupper): New
+ function.
+ (ix86_expand_epilogue): Use it.
+ * config/i386/i386.md (return, simple_return): Call it in the
+ expanders.
+
+ PR tree-optimization/51091
+ * tree-stdarg.c (execute_optimize_stdarg): Ignore TREE_CLOBBER_P
+ rhs also in the va_list_simple_ptr case.
+
+ PR tree-optimization/51058
+ * tree-vect-slp.c (vect_remove_slp_scalar_calls): New function.
+ (vect_schedule_slp): Call it.
+ * tree-vect-stmts.c (vectorizable_call): If slp_node != NULL,
+ don't replace scalar calls with setting of their lhs to zero here.
+
+ PR tree-optimization/51074
+ * fold-const.c (vec_cst_ctor_to_array, fold_vec_perm): New functions.
+ (fold_binary_loc): Handle VEC_EXTRACT_EVEN_EXPR,
+ VEC_EXTRACT_ODD_EXPR, VEC_INTERLEAVE_HIGH_EXPR and
+ VEC_INTERLEAVE_LOW_EXPR with VECTOR_CST or CONSTRUCTOR operands.
+ (fold_ternary_loc): Handle VEC_PERM_EXPR with VECTOR_CST or
+ CONSTRUCTOR operands.
+ * tree-ssa-propagate.c (valid_gimple_rhs_p): Handle ternary
+ expressions.
+ * tree-vect-generic.c (lower_vec_perm): Mask sel_int elements
+ to 0 .. 2 * elements - 1.
+
+2011-11-11 Richard Henderson <rth@redhat.com>
+
+ * gimple-pretty-print.c (dump_gimple_omp_atomic_load): Dump needed.
+ (dump_gimple_omp_atomic_store): Likewise.
+ * optabs.c (can_atomic_exchange_p): New.
+ * optabs.h (can_atomic_exchange_p): Declare.
+ * omp-low.c (expand_omp_atomic_load): Implement.
+ (expand_omp_atomic_store): Likewise.
+ (expand_omp_atomic): Update for new arguments to load/store.
+
+2011-11-11 Eric Botcazou <ebotcazou@adacore.com>
+
+ * cprop.c: Adjust outdated comments throughout.
+ (hash_scan_set): Rename PAT parameter into SET.
+ (cprop_pavloc): Rename into...
+ (cprop_avloc): ...this.
+ (cprop_absaltered): Rename into...
+ (cprop_kill): ...this.
+ (alloc_cprop_mem): Adjust for above renaming.
+ (free_cprop_mem): Likewise.
+ (compute_cprop_data): Likewise.
+ (compute_local_properties): Rename TRANSP parameter into KILL and
+ adjust throughout. Rework comments.
+ (try_replace_reg): Fix long line.
+ (cprop_jump): Likewise.
+ (constprop_register): Fix prototype and take INSN last.
+ (cprop_insn): Adjust calls to above function. Fix long lines.
+ (bypass_block): Likewise.
+ (one_cprop_pass): Likewise.
+
+2011-11-11 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/alpha/elf.h (ELF_ASCII_ESCAPES): Rename from ESCAPES.
+ (ELF_STRING_LIMIT): Rename from STRING_LIMIT.
+
+2011-11-11 Jason Merrill <jason@redhat.com>
+
+ * varasm.c (default_elf_asm_output_limited_string): #ifdef
+ ELF_ASCII_ESCAPES.
+ (default_elf_asm_output_ascii): Likewise.
+
+2011-11-11 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/50762
+ * config/i386/constraints.md (j): New address constraint.
+ * config/i386/predicates.md (lea_address_operand): Redefine as
+ special predicate.
+ * config/i386/i386.md (*lea_3_zext): Use "j" constraint for operand 1.
+ (*lea_4_zext): Ditto.
+
+2011-11-11 David S. Miller <davem@davemloft.net>
+
+ Revert
+ 2011-11-05 David S. Miller <davem@davemloft.net>
+
+ * config/sparc/sparc.md (UNSPEC_SHORT_LOAD): New unspec.
+ (zero-extend_v8qi_vis, zero_extend_v4hi_vis): New expanders.
+ (*zero_extend_v8qi_<P:mode>_insn,
+ *zero_extend_v4hi_<P:mode>_insn): New insns.
+ * config/sparc/sparc.c (vector_init_move_words,
+ vector_init_prepare_elts, sparc_expand_vector_init_vis2,
+ sparc_expand_vector_init_vis1): New functions.
+ (vector_init_bshuffle): Rewrite to handle more cases and make use
+ of locs[] array prepared by vector_init_prepare_elts.
+ (vector_init_fpmerge, vector_init_faligndata): Delete.
+ (sparc_expand_vector_init): Rewrite using new infrastructure.
+
+2011-11-11 Jakub Jelinek <jakub@redhat.com>
+
+ * opts-common.c (generate_canonical_option): Free opt_text
+ it it has been allocated here and not stored anywhere.
+
+ * tree-vect-slp.c (vect_free_slp_tree): Also free SLP_TREE_CHILDREN
+ vector.
+ (vect_create_new_slp_node): Don't allocate node before checking stmt
+ type.
+ (vect_free_oprnd_info): Remove FREE_DEF_STMTS argument, always
+ free def_stmts vectors and additionally free oprnd_info.
+ (vect_build_slp_tree): Adjust callers. Call it even if
+ stop_recursion. If vect_create_new_slp_node or
+ vect_build_slp_tree fails, properly handle freeing memory.
+ If it succeeded, clear def_stmts in oprnd_info.
+
+2011-11-11 Dimitrios Apostolou <jimis@gmx.net>
+
+ * defaults.h (ASM_OUTPUT_LABEL, ASM_OUTPUT_INTERNAL_LABEL): Expand on
+ multiple lines for readability.
+ * output.h (fprint_whex, fprint_w, fprint_ul, sprint_ul): Declare.
+ (ASM_OUTPUT_LABELREF): Call fputs instead of asm_fprintf.
+ * dwarf2asm.c (dw2_assemble_integer, dw2_asm_output_data,
+ dw2_asm_data_uleb128, dw2_asm_delta_uleb128,
+ dw2_asm_delta_sleb128): Convert fprintf calls to the new functions.
+ * dwarf2out.c (dwarf2out_source_line): Call fprint_ul instead of
+ fprintf.
+ * final.c (fprint_whex, fprint_w, fprint_ul, sprint_ul): New functions
+ serving as fast replacements for fprintf integer to string conversions.
+ (sprint_ul_rev): Internal helper for the above.
+ (output_addr_const) <CONST_INT>: Don't use fprintf.
+ * varasm.c: Fix some whitespace inconsistencies.
+ (default_elf_asm_output_limited_string): New.
+ (default_elf_asm_output_ascii): Likewise.
+ (default_elf_internal_label): Likewise.
+ * config/elfos.h (ASM_GENERATE_INTERNAL_LABEL): Use sprint_ul and
+ stpcpy instead of sprintf.
+ (TARGET_ASM_INTERNAL_LABEL): Define as default_elf_internal_label.
+ (ELF_ASCII_ESCAPES, ELF_STRING_LIMIT): Rename from old ESCAPES and
+ STRING_LIMIT macros.
+ (ASM_OUTPUT_LIMITED_STRING, ASM_OUTPUT_ASCII): Call functions that
+ provide the same functionality.
+ * config/i386/i386.c (print_reg): Call fprint_ul instead of fprintf.
+
+2011-11-10 Andrew MacLeod <amacleod@redhat.com>
+
+ * doc/extend.texi: Document __atomic_test_and_set and __atomic_clear.
+
+2011-11-10 Andrew MacLeod <amacleod@redhat.com>
+
+ PR middle-end/51038
+ * builtins.c (expand_builtin_atomic_clear): New. Expand atomic_clear.
+ (expand_builtin_atomic_test_and_set): New. Expand atomic test_and_set.
+ (expand_builtin): Add cases for test_and_set and clear.
+ * sync-builtins.def (BUILT_IN_ATOMIC_TEST_AND_SET): New.
+ (BUILT_IN_ATOMIC_CLEAR): New.
+
+2011-11-10 Roberto Agostino Vitillo <ravitillo@lbl.gov>
+
+ PR debug/50983
+ * dwarf2out.c (set_cur_line_info_table): Restore the last is_stmt
+ value in the current line table.
+
+2011-11-10 Nathan Sidwell <nathan@acm.org>
+
+ * gcov.c (struct function_info): Make src an index, not a pointer.
+ (struct source_info): Remove index and next source fields.
+ (fn_end): New static var.
+ (sources_index): Remove.
+ (sources): Now a pointer to an array, not a list.
+ (n_sources, a_sources): New.
+ (process_file): Adjust for changes to read_graph_file. Insert
+ functions into source lists and check line numbers here.
+ (generate_results): Only allocate lines for sources with
+ contents. Adjust for source array.
+ (release_structures): Likewise.
+ (find_source): Return source index, adjust for source array.
+ (read_graph_file): Return function list. Don't insert into source
+ lists here.
+ (read_count_file): Take list of functions.
+ (solve_flow_graph): Reverse the arc lists here.
+ (add_line_counts): Adjust for source array.
+
+2011-11-10 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/51077
+ * tree-object-size.c (addr_object_size): Check TREE_CODE of
+ MEM_REF's operand rather than code of the MEM_REF itself.
+
+2011-11-10 Andrew MacLeod <amacleod@redhat.com>
+
+ PR rtl-optimization/51040
+ * optabs.c (expand_atomic_fetch_op): Patchup code for NAND should
+ be AND followed by NOT.
+ * builtins.c (expand_builtin_atomic_fetch_op): Patchup code for NAND
+ should be AND followed by NOT.
+
+2011-11-10 Jakub Jelinek <jakub@redhat.com>
+
+ * vec.h (VEC_BASE): If base is at offset 0 in the structure,
+ use &(P)->base even if P is NULL.
+
+ PR rtl-optimization/51023
+ * combine.c (simplify_comparison) <case SIGN_EXTEND>: Don't use
+ val_signbit_known_clear_p for signed comparison narrowing
+ optimization. Don't check for non-VOIDmode, use
+ HWI_COMPUTABLE_MODE_P macro.
+ <case ZERO_EXTEND>: Don't check for non-VOIDmode.
+ Optimize even when const_op is equal to GET_MODE_MASK (mode),
+ don't optimize if const_op is negative.
+
+2011-11-10 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/51042
+ * tree-ssa-pre.c (phi_translate_1): Avoid recursing on
+ self-referential expressions. Refactor code to avoid duplication.
+
+2011-11-10 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/51070
+ * tree-loop-distribution.c (generate_builtin): Do not replace
+ the loop with a builtin if the partition contains statements which
+ results are used outside of the loop.
+ (pass_loop_distribution): Verify and collect.
+
+2011-11-10 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/51030
+ * tree-ssa-phiopt.c (jump_function_from_stmt): New function.
+ (value_replacement): Use it to handle trivial non-empty
+ intermediate blocks.
+
+2011-11-10 Richard Guenther <rguenther@suse.de>
+
+ PR middle-end/51071
+ * gimple.c (gimple_has_side_effects): Remove checking code
+ that doesn't belong here.
+
+2011-11-10 Ira Rosen <ira.rosen@linaro.org>
+
+ PR tree-optimization/51058
+ * tree-vect-slp.c (vect_get_constant_vectors): Handle CALL_EXPR.
+
+2011-11-10 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/51000
+ * tree-vect-patterns.c (vect_recog_bool_pattern): If adding
+ a pattern stmt for a bool store, adjust DR_STMT too.
+ Don't handle bool conversions to single bit precision lhs.
+ * tree-vect-stmts.c (vect_remove_stores): If next is a pattern
+ stmt, remove its related stmt and free its stmt_vinfo.
+ (free_stmt_vec_info): Free also pattern stmt's vinfo and
+ pattern def stmt's vinfo.
+ * tree-vect-loop.c (destroy_loop_vec_info): Don't try to
+ free pattern stmt's vinfo here.
+ (vect_transform_loop): When calling vect_remove_stores,
+ do gsi_next first and don't call gsi_remove. If not strided
+ store, free stmt vinfo for gsi_stmt (si) rather than stmt.
+
+2011-11-09 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/50911
+ * config/i386/i386.c (expand_vec_perm_interleave2): If d->vmode is
+ V4SImode, !TARGET_SSE2 and punpck[lh]* is needed, change dremap.vmode
+ to V4SFmode.
+
+ * function.h (requires_stack_frame_p): New prototype.
+ * function.c (requires_stack_frame_p): No longer static.
+ * config/i386/i386.c (ix86_finalize_stack_realign_flags): If
+ stack_realign_fp was just a conservative guess for a function
+ which doesn't use sp/fp/argp at all, clear frame_pointer_needed
+ and stack realignment.
+
2011-11-09 Paolo Carlini <paolo.carlini@oracle.com>
PR preprocessor/51061
@@ -176,8 +596,7 @@
* tree-sra.c (build_accesses_from_assign): Ignore clobbers.
* tree-ssa-dce.c (mark_stmt_if_obviously_necessary): Clobbers of
SSA names aren't necessary.
- (propagate_necessity): Accept and ignore constructors on the rhs,
- tidy.
+ (propagate_necessity): Accept and ignore constructors on the rhs, tidy.
* gimple.c (walk_gimple_op): Accept constructors like mem_rhs.
* tree-ssa-structalias.c (find_func_aliases): Clobbers don't store
any known value.
@@ -239,8 +658,7 @@
* trans-mem.c: New file.
* trans-mem.h: New file.
- * opts.c (finish_options): Error out when using -flto and
- -fgnu-tm.
+ * opts.c (finish_options): Error out when using -flto and -fgnu-tm.
* config/i386/i386.c: Define TARGET_VECTORIZE* transactional variants.
(ix86_handle_tm_regparm_attribute, struct bdesc_tm,
@@ -582,8 +1000,7 @@
2011-11-07 H.J. Lu <hongjiu.lu@intel.com>
* dwarf2cfi.c (dwarf2out_frame_debug_expr): Check
- HARD_FRAME_POINTER_REGNUM instead of hard_frame_pointer_rtx
- in Rule 18.
+ HARD_FRAME_POINTER_REGNUM instead of hard_frame_pointer_rtx in Rule 18.
2011-11-07 Jakub Jelinek <jakub@redhat.com>
@@ -616,8 +1033,7 @@
* tree-data-ref.h (initialize_data_dependence_relation,
compute_self_dependence): New prototypes.
* tree-vect-data-refs.c (vect_check_gather): New function.
- (vect_analyze_data_refs): Detect possible gather load data
- refs.
+ (vect_analyze_data_refs): Detect possible gather load data refs.
* tree-vectorizer.h (struct _stmt_vec_info): Add gather_p field.
(STMT_VINFO_GATHER_P): Define.
(vect_check_gather): New prototype.
@@ -630,7 +1046,7 @@
(avx2_gathersi<mode>, *avx2_gathersi<mode>): Use <VEC_GATHER_IDXSI>
instead of <VEC_GATHER_MODE>.
(avx2_gatherdi<mode>): Use <VEC_GATHER_IDXDI> instead of
- <<AVXMODE48P_DI> and <VEC_GATHER_SRCDI> instead of VEC_GATHER_MODE
+ <AVXMODE48P_DI> and <VEC_GATHER_SRCDI> instead of VEC_GATHER_MODE
on src and mask operands.
(*avx2_gatherdi<mode>): Likewise. Use VEC_GATHER_MODE iterator
instead of AVXMODE48P_DI.
@@ -646,7 +1062,7 @@
2011-11-07 Uros Bizjak <ubizjak@gmail.com>
- * config/i386/f16cintrin: Remove extra _X86INTRIN_H_INCLUDED check.
+ * config/i386/f16cintrin.h: Remove extra _X86INTRIN_H_INCLUDED check.
2011-11-07 Tristan Gingold <gingold@adacore.com>
@@ -919,8 +1335,7 @@
2011-11-6 Richard Guenther <rguenther@suse.de>
- * ipa-prop.c (ipa_modify_call_arguments): Re-compute
- inlinable flag.
+ * ipa-prop.c (ipa_modify_call_arguments): Re-compute inlinable flag.
2011-11-06 Ira Rosen <ira.rosen@linaro.org>
diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
index 353490df82a..89ee407b8f1 100644
--- a/gcc/DATESTAMP
+++ b/gcc/DATESTAMP
@@ -1 +1 @@
-20111109
+20111114
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index 51b2719a387..f8d6489ac83 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,3 +1,39 @@
+2011-11-12 Iain Sandoe <iains@gcc.gnu.org>
+
+ * gcc-interface/Makefile.in (stamp-gnatlib-$(RTSDIR)): Don't link
+ s-oscons.ads.
+ (OSCONS_CPP, OSCONS_EXTRACT): New.
+ (./bldtools/oscons/xoscons): New Target.
+ ($(RTSDIR)/s-oscons.ads): New Target.
+ (gnatlib): Depend on $(RTSDIR)/s-oscons.ads.
+ * gcc-interface/Make-lang.in (ada/s-oscons.ads) Remove as dependency.
+ * Make-generated.in: Remove machinery to generate xoscons and
+ ada/s-oscons.ads.
+
+2011-11-10 Eric Botcazou <ebotcazou@adacore.com>
+
+ * fe.h (Serious_Errors_Detected): New macro.
+ * gcc-interface/gigi.h (build_atomic_load): Declare.
+ (build_atomic_store): Likewise.
+ * gcc-interface/trans.c (atomic_sync_required_p): New predicate.
+ (call_to_gnu): Add ATOMIC_SYNC parameter. Use local variable.
+ Build an atomic load for an In or In Out parameter if needed.
+ Build an atomic store for the assignment of an Out parameter if needed.
+ Build an atomic store to the target if ATOMIC_SYNC is true.
+ (present_in_lhs_or_actual_p): New predicate.
+ (gnat_to_gnu) <N_Identifier>: Build an atomic load if needed.
+ <N_Explicit_Dereference>: Likewise.
+ <N_Indexed_Component>: Likewise.
+ <N_Selected_Component>: Likewise.
+ <N_Assignment_Statement>: Adjust call to call_to_gnu.
+ Build an atomic store to the LHS if needed.
+ <N_Function_Call>: Adjust call to call_to_gnu.
+ * gcc-interface/utils2.c: Include toplev.h.
+ (resolve_atomic_size): New static function.
+ (build_atomic_load): New function.
+ (build_atomic_store): Likewise.
+ * gcc-interface/Make-lang.in (ada/utils2.o): Add toplev.h.
+
2011-11-07 Olivier Hainque <hainque@adacore.com>
* sigtramp-ppcvxw.c: Add general comments.
diff --git a/gcc/ada/Make-generated.in b/gcc/ada/Make-generated.in
index 74536191483..ac52e491eeb 100644
--- a/gcc/ada/Make-generated.in
+++ b/gcc/ada/Make-generated.in
@@ -64,37 +64,6 @@ $(ADA_GEN_SUBDIR)/nmake.ads : $(ADA_GEN_SUBDIR)/sinfo.ads $(ADA_GEN_SUBDIR)/nma
$(CP) $^ $(ADA_GEN_SUBDIR)/bldtools/nmake_s
(cd $(ADA_GEN_SUBDIR)/bldtools/nmake_s; gnatmake -q xnmake ; ./xnmake -s ../../nmake.ads )
-ifeq ($(strip $(filter-out alpha64 ia64 dec hp vms% openvms% alphavms%,$(subst -, ,$(host)))),)
-OSCONS_CPP=../../../$(DECC) -E /comment=as_is -DNATIVE \
- -DTARGET='""$(target)""' s-oscons-tmplt.c
-
-OSCONS_EXTRACT=../../../$(DECC) -DNATIVE \
- -DTARGET='""$(target)""' s-oscons-tmplt.c ; \
- ld -o s-oscons-tmplt.exe s-oscons-tmplt.obj; \
- ./s-oscons-tmplt.exe > s-oscons-tmplt.s
-
-else
-# GCC_FOR_TARGET has paths relative to the gcc directory, so we need to adjust
-# for running it from $(ADA_GEN_SUBDIR)/bldtools/oscons
-OSCONS_CC=`echo "$(GCC_FOR_TARGET)" \
- | sed -e 's^\./xgcc^../../../xgcc^' -e 's^-B./^-B../../../^'`
-OSCONS_CPP=$(OSCONS_CC) $(GNATLIBCFLAGS) -E -C \
- -DTARGET=\"$(target)\" s-oscons-tmplt.c > s-oscons-tmplt.i
-OSCONS_EXTRACT=$(OSCONS_CC) -S s-oscons-tmplt.i
-endif
-
-$(ADA_GEN_SUBDIR)/s-oscons.ads : $(ADA_GEN_SUBDIR)/s-oscons-tmplt.c $(ADA_GEN_SUBDIR)/gsocket.h $(ADA_GEN_SUBDIR)/xoscons.adb $(ADA_GEN_SUBDIR)/xutil.ads $(ADA_GEN_SUBDIR)/xutil.adb
- -$(MKDIR) $(ADA_GEN_SUBDIR)/bldtools/oscons
- $(RM) $(addprefix $(ADA_GEN_SUBDIR)/bldtools/oscons/,$(notdir $^))
- $(CP) $^ $(ADA_GEN_SUBDIR)/bldtools/oscons
- (cd $(ADA_GEN_SUBDIR)/bldtools/oscons ; gnatmake -q xoscons ; \
- $(RM) s-oscons-tmplt.i s-oscons-tmplt.s ; \
- $(OSCONS_CPP) ; \
- $(OSCONS_EXTRACT) ; \
- ./xoscons ; \
- $(RM) ../../s-oscons.ads ; \
- $(CP) s-oscons.ads s-oscons.h ../../)
-
$(ADA_GEN_SUBDIR)/sdefault.adb: $(ADA_GEN_SUBDIR)/stamp-sdefault ; @true
$(ADA_GEN_SUBDIR)/stamp-sdefault : $(srcdir)/version.c Makefile
$(ECHO) "pragma Style_Checks (Off);" >tmp-sdefault.adb
diff --git a/gcc/ada/fe.h b/gcc/ada/fe.h
index 18b14611e38..fe6b22dc751 100644
--- a/gcc/ada/fe.h
+++ b/gcc/ada/fe.h
@@ -92,13 +92,15 @@ extern void Set_Identifier_Casing (Char *, const Char *);
/* err_vars: */
-#define Error_Msg_Node_2 err_vars__error_msg_node_2
-#define Error_Msg_Uint_1 err_vars__error_msg_uint_1
-#define Error_Msg_Uint_2 err_vars__error_msg_uint_2
-
-extern Entity_Id Error_Msg_Node_2;
-extern Uint Error_Msg_Uint_1;
-extern Uint Error_Msg_Uint_2;
+#define Error_Msg_Node_2 err_vars__error_msg_node_2
+#define Error_Msg_Uint_1 err_vars__error_msg_uint_1
+#define Error_Msg_Uint_2 err_vars__error_msg_uint_2
+#define Serious_Errors_Detected err_vars__serious_errors_detected
+
+extern Entity_Id Error_Msg_Node_2;
+extern Uint Error_Msg_Uint_1;
+extern Uint Error_Msg_Uint_2;
+extern Nat Serious_Errors_Detected;
/* exp_ch11: */
diff --git a/gcc/ada/gcc-interface/Make-lang.in b/gcc/ada/gcc-interface/Make-lang.in
index 221d326c6aa..4dfc45b6e79 100644
--- a/gcc/ada/gcc-interface/Make-lang.in
+++ b/gcc/ada/gcc-interface/Make-lang.in
@@ -568,7 +568,7 @@ canadian-gnattools: force
$(MAKE) -C ada $(ADA_TOOLS_FLAGS_TO_PASS) gnattools1-re
$(MAKE) -C ada $(ADA_TOOLS_FLAGS_TO_PASS) gnattools2
-gnatlib gnatlib-sjlj gnatlib-zcx gnatlib-shared: ada/s-oscons.ads force
+gnatlib gnatlib-sjlj gnatlib-zcx gnatlib-shared: force
$(MAKE) -C ada $(COMMON_FLAGS_TO_PASS) \
GNATLIBFLAGS="$(GNATLIBFLAGS)" \
GNATLIBCFLAGS="$(GNATLIBCFLAGS)" \
@@ -1297,7 +1297,7 @@ ada/utils.o : ada/gcc-interface/utils.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(COMPILER) -c $(ALL_COMPILERFLAGS) -I.. $(ALL_CPPFLAGS) $< -o $@
ada/utils2.o : ada/gcc-interface/utils2.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) $(TREE_H) $(FLAGS_H) output.h $(TREE_INLINE_H) \
+ $(TM_H) $(TREE_H) $(FLAGS_H) toplev.h output.h $(TREE_INLINE_H) \
ada/gcc-interface/ada.h ada/types.h ada/atree.h ada/elists.h ada/namet.h \
ada/nlists.h ada/snames.h ada/stringt.h ada/uintp.h ada/fe.h ada/sinfo.h \
ada/einfo.h $(ADA_TREE_H) ada/gcc-interface/gigi.h
diff --git a/gcc/ada/gcc-interface/Makefile.in b/gcc/ada/gcc-interface/Makefile.in
index d9215dfb092..d000b5df779 100644
--- a/gcc/ada/gcc-interface/Makefile.in
+++ b/gcc/ada/gcc-interface/Makefile.in
@@ -2495,21 +2495,50 @@ install-gnatlib: ../stamp-gnatlib-$(RTSDIR)
$(RTSDIR)/$(word 1,$(subst <, ,$(PAIR)));)
# Copy tsystem.h
$(CP) $(srcdir)/tsystem.h $(RTSDIR)
-# Copy generated target dependent sources
- $(RM) $(RTSDIR)/s-oscons.ads
- (cd $(RTSDIR); $(LN_S) ../s-oscons.ads s-oscons.ads)
$(RM) ../stamp-gnatlib-$(RTSDIR)
touch ../stamp-gnatlib1-$(RTSDIR)
# GNULLI End #############################################################
+ifeq ($(strip $(filter-out alpha64 ia64 dec hp vms% openvms% alphavms%,$(subst -, ,$(host)))),)
+OSCONS_CPP=../../$(DECC) -E /comment=as_is -DNATIVE \
+ -DTARGET='""$(target)""' $(fsrcpfx)ada/s-oscons-tmplt.c
+
+OSCONS_EXTRACT=../../$(DECC) -DNATIVE \
+ -DTARGET='""$(target)""' $(fsrcpfx)ada/s-oscons-tmplt.c ; \
+ ld -o s-oscons-tmplt.exe s-oscons-tmplt.obj; \
+ ./s-oscons-tmplt.exe > s-oscons-tmplt.s
+
+else
+# GCC_FOR_TARGET has paths relative to the gcc directory, so we need to adjust
+# for running it from $(RTSDIR)
+OSCONS_CC=`echo "$(GCC_FOR_TARGET)" \
+ | sed -e 's^\./xgcc^../../xgcc^' -e 's^-B./^-B../../^'`
+OSCONS_CPP=$(OSCONS_CC) $(GNATLIBCFLAGS) -E -C \
+ -DTARGET=\"$(target)\" $(fsrcpfx)ada/s-oscons-tmplt.c > s-oscons-tmplt.i
+OSCONS_EXTRACT=$(OSCONS_CC) -S s-oscons-tmplt.i
+endif
+
+./bldtools/oscons/xoscons: xoscons.adb xutil.ads xutil.adb
+ -$(MKDIR) ./bldtools/oscons
+ $(RM) $(addprefix ./bldtools/oscons/,$(notdir $^))
+ $(CP) $^ ./bldtools/oscons
+ (cd ./bldtools/oscons ; gnatmake -q xoscons)
+
+$(RTSDIR)/s-oscons.ads: ../stamp-gnatlib1-$(RTSDIR) s-oscons-tmplt.c gsocket.h ./bldtools/oscons/xoscons
+ $(RM) $(RTSDIR)/s-oscons-tmplt.i $(RTSDIR)/s-oscons-tmplt.s
+ (cd $(RTSDIR) ; \
+ $(OSCONS_CPP) ; \
+ $(OSCONS_EXTRACT) ; \
+ ../bldtools/oscons/xoscons)
+
# Don't use semicolon separated shell commands that involve list expansions.
# The semicolon triggers a call to DCL on VMS and DCL can't handle command
# line lengths in excess of 256 characters.
# Example: cd $(RTSDIR); ar rc libfoo.a $(LONG_LIST_OF_OBJS)
# is guaranteed to overflow the buffer.
-gnatlib: ../stamp-gnatlib1-$(RTSDIR) ../stamp-gnatlib2-$(RTSDIR)
+gnatlib: ../stamp-gnatlib1-$(RTSDIR) ../stamp-gnatlib2-$(RTSDIR) $(RTSDIR)/s-oscons.ads
$(MAKE) -C $(RTSDIR) \
CC="`echo \"$(GCC_FOR_TARGET)\" \
| sed -e 's,\./xgcc,../../xgcc,' -e 's,-B\./,-B../../,'`" \
diff --git a/gcc/ada/gcc-interface/gigi.h b/gcc/ada/gcc-interface/gigi.h
index 143926160ac..e22c44476db 100644
--- a/gcc/ada/gcc-interface/gigi.h
+++ b/gcc/ada/gcc-interface/gigi.h
@@ -804,6 +804,12 @@ extern unsigned int known_alignment (tree exp);
of 2. */
extern bool value_factor_p (tree value, HOST_WIDE_INT factor);
+/* Build an atomic load for the underlying atomic object in SRC. */
+extern tree build_atomic_load (tree src);
+
+/* Build an atomic store from SRC to the underlying atomic object in DEST. */
+extern tree build_atomic_store (tree dest, tree src);
+
/* Make a binary operation of kind OP_CODE. RESULT_TYPE is the type
desired for the result. Usually the operation is to be performed
in that type. For MODIFY_EXPR and ARRAY_REF, RESULT_TYPE may be 0
diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c
index 1f43f4dcc94..8a74e6ccb45 100644
--- a/gcc/ada/gcc-interface/trans.c
+++ b/gcc/ada/gcc-interface/trans.c
@@ -3300,6 +3300,60 @@ Subprogram_Body_to_gnu (Node_Id gnat_node)
mark_out_of_scope (Defining_Unit_Name (Specification (gnat_node)));
}
+/* Return true if GNAT_NODE requires atomic synchronization. */
+
+static bool
+atomic_sync_required_p (Node_Id gnat_node)
+{
+ const Node_Id gnat_parent = Parent (gnat_node);
+ Node_Kind kind;
+ unsigned char attr_id;
+
+ /* First, scan the node to find the Atomic_Sync_Required flag. */
+ kind = Nkind (gnat_node);
+ if (kind == N_Type_Conversion || kind == N_Unchecked_Type_Conversion)
+ {
+ gnat_node = Expression (gnat_node);
+ kind = Nkind (gnat_node);
+ }
+
+ switch (kind)
+ {
+ case N_Expanded_Name:
+ case N_Explicit_Dereference:
+ case N_Identifier:
+ case N_Indexed_Component:
+ case N_Selected_Component:
+ if (!Atomic_Sync_Required (gnat_node))
+ return false;
+ break;
+
+ default:
+ return false;
+ }
+
+ /* Then, scan the parent to find out cases where the flag is irrelevant. */
+ kind = Nkind (gnat_parent);
+ switch (kind)
+ {
+ case N_Attribute_Reference:
+ attr_id = Get_Attribute_Id (Attribute_Name (gnat_parent));
+ /* Do not mess up machine code insertions. */
+ if (attr_id == Attr_Asm_Input || attr_id == Attr_Asm_Output)
+ return false;
+ break;
+
+ case N_Object_Renaming_Declaration:
+ /* Do not generate a function call as a renamed object. */
+ return false;
+
+ default:
+ break;
+ }
+
+ return true;
+}
+
/* Create a temporary variable with PREFIX and TYPE, and return it. */
static tree
@@ -3334,10 +3388,13 @@ create_init_temporary (const char *prefix, tree gnu_init, tree *gnu_init_stmt,
or an N_Procedure_Call_Statement, to a GCC tree, which is returned.
GNU_RESULT_TYPE_P is a pointer to where we should place the result type.
If GNU_TARGET is non-null, this must be a function call on the RHS of a
- N_Assignment_Statement and the result is to be placed into that object. */
+ N_Assignment_Statement and the result is to be placed into that object.
+ If, in addition, ATOMIC_SYNC is true, then the assignment to GNU_TARGET
+ requires atomic synchronization. */
static tree
-call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target)
+call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target,
+ bool atomic_sync)
{
const bool function_call = (Nkind (gnat_node) == N_Function_Call);
const bool returning_value = (function_call && !gnu_target);
@@ -3433,6 +3490,11 @@ call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target)
tree gnu_formal_type = gnat_to_gnu_type (Etype (gnat_formal));
const bool is_true_formal_parm
= gnu_formal && TREE_CODE (gnu_formal) == PARM_DECL;
+ const bool is_by_ref_formal_parm
+ = is_true_formal_parm
+ && (DECL_BY_REF_P (gnu_formal)
+ || DECL_BY_COMPONENT_PTR_P (gnu_formal)
+ || DECL_BY_DESCRIPTOR_P (gnu_formal));
/* In the Out or In Out case, we must suppress conversions that yield
an lvalue but can nevertheless cause the creation of a temporary,
because we need the real object in this case, either to pass its
@@ -3462,10 +3524,7 @@ call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target)
/* If we are passing a non-addressable parameter by reference, pass the
address of a copy. In the Out or In Out case, set up to copy back
out after the call. */
- if (is_true_formal_parm
- && (DECL_BY_REF_P (gnu_formal)
- || DECL_BY_COMPONENT_PTR_P (gnu_formal)
- || DECL_BY_DESCRIPTOR_P (gnu_formal))
+ if (is_by_ref_formal_parm
&& (gnu_name_type = gnat_to_gnu_type (Etype (gnat_name)))
&& !addressable_p (gnu_name, gnu_name_type))
{
@@ -3569,6 +3628,14 @@ call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target)
/* Start from the real object and build the actual. */
gnu_actual = gnu_name;
+ /* If this is an atomic access of an In or In Out parameter for which
+ synchronization is required, build the atomic load. */
+ if (is_true_formal_parm
+ && !is_by_ref_formal_parm
+ && Ekind (gnat_formal) != E_Out_Parameter
+ && atomic_sync_required_p (gnat_actual))
+ gnu_actual = build_atomic_load (gnu_actual);
+
/* If this was a procedure call, we may not have removed any padding.
So do it here for the part we will use as an input, if any. */
if (Ekind (gnat_formal) != E_Out_Parameter
@@ -3865,8 +3932,11 @@ call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target)
gnu_result = convert (TREE_TYPE (gnu_actual), gnu_result);
}
- gnu_result = build_binary_op (MODIFY_EXPR, NULL_TREE,
- gnu_actual, gnu_result);
+ if (atomic_sync_required_p (gnat_actual))
+ gnu_result = build_atomic_store (gnu_actual, gnu_result);
+ else
+ gnu_result = build_binary_op (MODIFY_EXPR, NULL_TREE,
+ gnu_actual, gnu_result);
set_expr_location_from_node (gnu_result, gnat_node);
append_to_statement_list (gnu_result, &gnu_stmt_list);
gnu_cico_list = TREE_CHAIN (gnu_cico_list);
@@ -3919,8 +3989,11 @@ call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target)
else
op_code = MODIFY_EXPR;
- gnu_call
- = build_binary_op (op_code, NULL_TREE, gnu_target, gnu_call);
+ if (atomic_sync)
+ gnu_call = build_atomic_store (gnu_target, gnu_call);
+ else
+ gnu_call
+ = build_binary_op (op_code, NULL_TREE, gnu_target, gnu_call);
set_expr_location_from_node (gnu_call, gnat_parent);
append_to_statement_list (gnu_call, &gnu_stmt_list);
}
@@ -4494,6 +4567,26 @@ lhs_or_actual_p (Node_Id gnat_node)
return false;
}
+/* Return true if either GNAT_NODE or a view of GNAT_NODE is on the LHS
+ of an assignment or an actual parameter of a call. */
+
+static bool
+present_in_lhs_or_actual_p (Node_Id gnat_node)
+{
+ Node_Kind kind;
+
+ if (lhs_or_actual_p (gnat_node))
+ return true;
+
+ kind = Nkind (Parent (gnat_node));
+
+ if ((kind == N_Type_Conversion || kind == N_Unchecked_Type_Conversion)
+ && lhs_or_actual_p (Parent (gnat_node)))
+ return true;
+
+ return false;
+}
+
/* Return true if GNAT_NODE, an unchecked type conversion, is a no-op as far
as gigi is concerned. This is used to avoid conversions on the LHS. */
@@ -4613,6 +4706,12 @@ gnat_to_gnu (Node_Id gnat_node)
case N_Operator_Symbol:
case N_Defining_Identifier:
gnu_result = Identifier_to_gnu (gnat_node, &gnu_result_type);
+
+ /* If this is an atomic access on the RHS for which synchronization is
+ required, build the atomic load. */
+ if (atomic_sync_required_p (gnat_node)
+ && !present_in_lhs_or_actual_p (gnat_node))
+ gnu_result = build_atomic_load (gnu_result);
break;
case N_Integer_Literal:
@@ -4897,6 +4996,12 @@ gnat_to_gnu (Node_Id gnat_node)
gnu_result = gnat_to_gnu (Prefix (gnat_node));
gnu_result_type = get_unpadded_type (Etype (gnat_node));
gnu_result = build_unary_op (INDIRECT_REF, NULL_TREE, gnu_result);
+
+ /* If this is an atomic access on the RHS for which synchronization is
+ required, build the atomic load. */
+ if (atomic_sync_required_p (gnat_node)
+ && !present_in_lhs_or_actual_p (gnat_node))
+ gnu_result = build_atomic_load (gnu_result);
break;
case N_Indexed_Component:
@@ -4963,9 +5068,15 @@ gnat_to_gnu (Node_Id gnat_node)
gnu_result = build_binary_op (ARRAY_REF, NULL_TREE,
gnu_result, gnu_expr);
}
- }
- gnu_result_type = get_unpadded_type (Etype (gnat_node));
+ gnu_result_type = get_unpadded_type (Etype (gnat_node));
+
+ /* If this is an atomic access on the RHS for which synchronization is
+ required, build the atomic load. */
+ if (atomic_sync_required_p (gnat_node)
+ && !present_in_lhs_or_actual_p (gnat_node))
+ gnu_result = build_atomic_load (gnu_result);
+ }
break;
case N_Slice:
@@ -5110,8 +5221,13 @@ gnat_to_gnu (Node_Id gnat_node)
(Parent (gnat_node)));
}
- gcc_assert (gnu_result);
gnu_result_type = get_unpadded_type (Etype (gnat_node));
+
+ /* If this is an atomic access on the RHS for which synchronization is
+ required, build the atomic load. */
+ if (atomic_sync_required_p (gnat_node)
+ && !present_in_lhs_or_actual_p (gnat_node))
+ gnu_result = build_atomic_load (gnu_result);
}
break;
@@ -5618,7 +5734,8 @@ gnat_to_gnu (Node_Id gnat_node)
N_Raise_Storage_Error);
else if (Nkind (Expression (gnat_node)) == N_Function_Call)
gnu_result
- = call_to_gnu (Expression (gnat_node), &gnu_result_type, gnu_lhs);
+ = call_to_gnu (Expression (gnat_node), &gnu_result_type, gnu_lhs,
+ atomic_sync_required_p (Name (gnat_node)));
else
{
gnu_rhs
@@ -5629,8 +5746,11 @@ gnat_to_gnu (Node_Id gnat_node)
gnu_rhs = emit_range_check (gnu_rhs, Etype (Name (gnat_node)),
gnat_node);
- gnu_result
- = build_binary_op (MODIFY_EXPR, NULL_TREE, gnu_lhs, gnu_rhs);
+ if (atomic_sync_required_p (Name (gnat_node)))
+ gnu_result = build_atomic_store (gnu_lhs, gnu_rhs);
+ else
+ gnu_result
+ = build_binary_op (MODIFY_EXPR, NULL_TREE, gnu_lhs, gnu_rhs);
/* If the type being assigned is an array type and the two sides are
not completely disjoint, play safe and use memmove. But don't do
@@ -5880,7 +6000,7 @@ gnat_to_gnu (Node_Id gnat_node)
case N_Function_Call:
case N_Procedure_Call_Statement:
- gnu_result = call_to_gnu (gnat_node, &gnu_result_type, NULL_TREE);
+ gnu_result = call_to_gnu (gnat_node, &gnu_result_type, NULL_TREE, false);
break;
/************************/
diff --git a/gcc/ada/gcc-interface/utils2.c b/gcc/ada/gcc-interface/utils2.c
index 4075a27014c..c303e2f20a3 100644
--- a/gcc/ada/gcc-interface/utils2.c
+++ b/gcc/ada/gcc-interface/utils2.c
@@ -29,6 +29,7 @@
#include "tm.h"
#include "tree.h"
#include "flags.h"
+#include "toplev.h"
#include "ggc.h"
#include "output.h"
#include "tree-inline.h"
@@ -590,6 +591,112 @@ nonbinary_modular_operation (enum tree_code op_code, tree type, tree lhs,
return convert (type, result);
}
+/* This page contains routines that implement the Ada semantics with regard
+ to atomic objects. They are fully piggybacked on the middle-end support
+ for atomic loads and stores.
+
+ *** Memory barriers and volatile objects ***
+
+ We implement the weakened form of the C.6(16) clause that was introduced
+ in Ada 2012 (AI05-117). Earlier forms of this clause wouldn't have been
+ implementable without significant performance hits on modern platforms.
+
+ We also take advantage of the requirements imposed on shared variables by
+ 9.10 (conditions for sequential actions) to have non-erroneous execution
+ and consider that C.6(16) and C.6(17) only prescribe an uniform order of
+ volatile updates with regard to sequential actions, i.e. with regard to
+ reads or updates of atomic objects.
+
+ As such, an update of an atomic object by a task requires that all earlier
+ accesses to volatile objects have completed. Similarly, later accesses to
+ volatile objects cannot be reordered before the update of the atomic object.
+ So, memory barriers both before and after the atomic update are needed.
+
+ For a read of an atomic object, to avoid seeing writes of volatile objects
+ by a task earlier than by the other tasks, a memory barrier is needed before
+ the atomic read. Finally, to avoid reordering later reads or updates of
+ volatile objects to before the atomic read, a barrier is needed after the
+ atomic read.
+
+ So, memory barriers are needed before and after atomic reads and updates.
+ And, in order to simplify the implementation, we use full memory barriers
+ in all cases, i.e. we enforce sequential consistency for atomic accesses. */
+
+/* Return the size of TYPE, which must be a positive power of 2. */
+
+static unsigned int
+resolve_atomic_size (tree type)
+{
+ unsigned HOST_WIDE_INT size = tree_low_cst (TYPE_SIZE_UNIT (type), 1);
+
+ if (size == 1 || size == 2 || size == 4 || size == 8 || size == 16)
+ return size;
+
+ /* We shouldn't reach here without having already detected that the size
+ isn't compatible with an atomic access. */
+ gcc_assert (Serious_Errors_Detected);
+
+ return 0;
+}
+
+/* Build an atomic load for the underlying atomic object in SRC. */
+
+tree
+build_atomic_load (tree src)
+{
+ tree ptr_type
+ = build_pointer_type
+ (build_qualified_type (void_type_node, TYPE_QUAL_VOLATILE));
+ tree mem_model = build_int_cst (integer_type_node, MEMMODEL_SEQ_CST);
+ tree orig_src = src;
+ tree type = TREE_TYPE (src);
+ tree t, val;
+ unsigned int size;
+ int fncode;
+
+ src = remove_conversions (src, false);
+ size = resolve_atomic_size (TREE_TYPE (src));
+ if (size == 0)
+ return orig_src;
+
+ fncode = (int) BUILT_IN_ATOMIC_LOAD_N + exact_log2 (size) + 1;
+ t = builtin_decl_implicit ((enum built_in_function) fncode);
+
+ src = build_unary_op (ADDR_EXPR, ptr_type, src);
+ val = build_call_expr (t, 2, src, mem_model);
+
+ return unchecked_convert (type, val, true);
+}
+
+/* Build an atomic store from SRC to the underlying atomic object in DEST. */
+
+tree
+build_atomic_store (tree dest, tree src)
+{
+ tree ptr_type
+ = build_pointer_type
+ (build_qualified_type (void_type_node, TYPE_QUAL_VOLATILE));
+ tree mem_model = build_int_cst (integer_type_node, MEMMODEL_SEQ_CST);
+ tree orig_dest = dest;
+ tree t, int_type;
+ unsigned int size;
+ int fncode;
+
+ dest = remove_conversions (dest, false);
+ size = resolve_atomic_size (TREE_TYPE (dest));
+ if (size == 0)
+ return build_binary_op (MODIFY_EXPR, NULL_TREE, orig_dest, src);
+
+ fncode = (int) BUILT_IN_ATOMIC_STORE_N + exact_log2 (size) + 1;
+ t = builtin_decl_implicit ((enum built_in_function) fncode);
+ int_type = gnat_type_for_size (BITS_PER_UNIT * size, 1);
+
+ dest = build_unary_op (ADDR_EXPR, ptr_type, dest);
+ src = unchecked_convert (int_type, src, true);
+
+ return build_call_expr (t, 3, dest, src, mem_model);
+}
+
/* Make a binary operation of kind OP_CODE. RESULT_TYPE is the type
desired for the result. Usually the operation is to be performed
in that type. For INIT_EXPR and MODIFY_EXPR, RESULT_TYPE must be
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 516292783bc..9dc68cc341f 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -5144,7 +5144,6 @@ expand_builtin_sync_operation (enum machine_mode mode, tree exp,
case BUILT_IN_SYNC_FETCH_AND_NAND_4:
case BUILT_IN_SYNC_FETCH_AND_NAND_8:
case BUILT_IN_SYNC_FETCH_AND_NAND_16:
-
if (warned_f_a_n)
break;
@@ -5158,7 +5157,6 @@ expand_builtin_sync_operation (enum machine_mode mode, tree exp,
case BUILT_IN_SYNC_NAND_AND_FETCH_4:
case BUILT_IN_SYNC_NAND_AND_FETCH_8:
case BUILT_IN_SYNC_NAND_AND_FETCH_16:
-
if (warned_n_a_f)
break;
@@ -5190,16 +5188,24 @@ expand_builtin_compare_and_swap (enum machine_mode mode, tree exp,
bool is_bool, rtx target)
{
rtx old_val, new_val, mem;
+ rtx *pbool, *poval;
/* Expand the operands. */
mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
old_val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
new_val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 2), mode);
- if (!expand_atomic_compare_and_swap ((is_bool ? &target : NULL),
- (is_bool ? NULL : &target),
- mem, old_val, new_val, false,
- MEMMODEL_SEQ_CST, MEMMODEL_SEQ_CST))
+ pbool = poval = NULL;
+ if (target != const0_rtx)
+ {
+ if (is_bool)
+ pbool = &target;
+ else
+ poval = &target;
+ }
+ if (!expand_atomic_compare_and_swap (pbool, poval, mem, old_val, new_val,
+ false, MEMMODEL_SEQ_CST,
+ MEMMODEL_SEQ_CST))
return NULL_RTX;
return target;
@@ -5338,8 +5344,9 @@ expand_builtin_atomic_compare_exchange (enum machine_mode mode, tree exp,
oldval = copy_to_reg (gen_rtx_MEM (mode, expect));
- if (!expand_atomic_compare_and_swap (&target, &oldval, mem, oldval,
- desired, is_weak, success, failure))
+ if (!expand_atomic_compare_and_swap ((target == const0_rtx ? NULL : &target),
+ &oldval, mem, oldval, desired,
+ is_weak, success, failure))
return NULL_RTX;
emit_move_insn (gen_rtx_MEM (mode, expect), oldval);
@@ -5460,11 +5467,85 @@ expand_builtin_atomic_fetch_op (enum machine_mode mode, tree exp, rtx target,
/* Then issue the arithmetic correction to return the right result. */
if (!ignore)
- ret = expand_simple_binop (mode, code, ret, val, NULL_RTX, true,
- OPTAB_LIB_WIDEN);
+ {
+ if (code == NOT)
+ {
+ ret = expand_simple_binop (mode, AND, ret, val, NULL_RTX, true,
+ OPTAB_LIB_WIDEN);
+ ret = expand_simple_unop (mode, NOT, ret, target, true);
+ }
+ else
+ ret = expand_simple_binop (mode, code, ret, val, target, true,
+ OPTAB_LIB_WIDEN);
+ }
return ret;
}
+
+/* Expand an atomic clear operation.
+ void _atomic_clear (BOOL *obj, enum memmodel)
+ EXP is the call expression. */
+
+static rtx
+expand_builtin_atomic_clear (tree exp)
+{
+ enum machine_mode mode;
+ rtx mem, ret;
+ enum memmodel model;
+
+ mode = mode_for_size (BOOL_TYPE_SIZE, MODE_INT, 0);
+ mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
+ model = get_memmodel (CALL_EXPR_ARG (exp, 1));
+
+ if (model == MEMMODEL_ACQUIRE || model == MEMMODEL_ACQ_REL)
+ {
+ error ("invalid memory model for %<__atomic_store%>");
+ return const0_rtx;
+ }
+
+ /* Try issuing an __atomic_store, and allow fallback to __sync_lock_release.
+ Failing that, a store is issued by __atomic_store. The only way this can
+ fail is if the bool type is larger than a word size. Unlikely, but
+ handle it anyway for completeness. Assume a single threaded model since
+ there is no atomic support in this case, and no barriers are required. */
+ ret = expand_atomic_store (mem, const0_rtx, model, true);
+ if (!ret)
+ emit_move_insn (mem, const0_rtx);
+ return const0_rtx;
+}
+
+/* Expand an atomic test_and_set operation.
+ bool _atomic_test_and_set (BOOL *obj, enum memmodel)
+ EXP is the call expression. */
+
+static rtx
+expand_builtin_atomic_test_and_set (tree exp)
+{
+ rtx mem, ret;
+ enum memmodel model;
+ enum machine_mode mode;
+
+ mode = mode_for_size (BOOL_TYPE_SIZE, MODE_INT, 0);
+ mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
+ model = get_memmodel (CALL_EXPR_ARG (exp, 1));
+
+ /* Try issuing an exchange. If it is lock free, or if there is a limited
+ functionality __sync_lock_test_and_set, this will utilize it. */
+ ret = expand_atomic_exchange (NULL_RTX, mem, const1_rtx, model, true);
+ if (ret)
+ return ret;
+
+ /* Otherwise, there is no lock free support for test and set. Simply
+ perform a load and a store. Since this presumes a non-atomic architecture,
+ also assume single threadedness and don't issue barriers either. */
+
+ ret = gen_reg_rtx (mode);
+ emit_move_insn (ret, mem);
+ emit_move_insn (mem, const1_rtx);
+ return ret;
+}
+
+
/* Return true if (optional) argument ARG1 of size ARG0 is always lock free on
this architecture. If ARG1 is NULL, use typical alignment for size ARG0. */
@@ -6693,6 +6774,12 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
if (target)
return target;
break;
+
+ case BUILT_IN_ATOMIC_TEST_AND_SET:
+ return expand_builtin_atomic_test_and_set (exp);
+
+ case BUILT_IN_ATOMIC_CLEAR:
+ return expand_builtin_atomic_clear (exp);
case BUILT_IN_ATOMIC_ALWAYS_LOCK_FREE:
return expand_builtin_atomic_always_lock_free (exp);
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index 9e98ce9e2ef..834d3d4a443 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -641,6 +641,7 @@ void debug_varpool_node_set (varpool_node_set);
void free_varpool_node_set (varpool_node_set);
void ipa_discover_readonly_nonaddressable_vars (void);
bool cgraph_comdat_can_be_unshared_p (struct cgraph_node *);
+bool varpool_externally_visible_p (struct varpool_node *, bool);
/* In predict.c */
bool cgraph_maybe_hot_edge_p (struct cgraph_edge *e);
@@ -681,6 +682,7 @@ bool const_value_known_p (tree);
bool varpool_for_node_and_aliases (struct varpool_node *,
bool (*) (struct varpool_node *, void *),
void *, bool);
+void varpool_add_new_variable (tree);
/* Walk all reachable static variables. */
#define FOR_EACH_STATIC_VARIABLE(node) \
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index e401b8f2f2b..40bcf8fc9ef 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -2101,13 +2101,15 @@ output_weakrefs (void)
struct varpool_node *vnode;
for (node = cgraph_nodes; node; node = node->next)
if (node->alias && DECL_EXTERNAL (node->decl)
- && !TREE_ASM_WRITTEN (node->decl))
+ && !TREE_ASM_WRITTEN (node->decl)
+ && lookup_attribute ("weakref", DECL_ATTRIBUTES (node->decl)))
assemble_alias (node->decl,
node->thunk.alias ? DECL_ASSEMBLER_NAME (node->thunk.alias)
: get_alias_symbol (node->decl));
for (vnode = varpool_nodes; vnode; vnode = vnode->next)
if (vnode->alias && DECL_EXTERNAL (vnode->decl)
- && !TREE_ASM_WRITTEN (vnode->decl))
+ && !TREE_ASM_WRITTEN (vnode->decl)
+ && lookup_attribute ("weakref", DECL_ATTRIBUTES (vnode->decl)))
assemble_alias (vnode->decl,
vnode->alias_of ? DECL_ASSEMBLER_NAME (vnode->alias_of)
: get_alias_symbol (vnode->decl));
diff --git a/gcc/combine.c b/gcc/combine.c
index ad9aa389871..1714c749e16 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -11397,9 +11397,10 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
later on, and then we wouldn't know whether to sign- or
zero-extend. */
mode = GET_MODE (XEXP (op0, 0));
- if (mode != VOIDmode && GET_MODE_CLASS (mode) == MODE_INT
+ if (GET_MODE_CLASS (mode) == MODE_INT
&& ! unsigned_comparison_p
- && val_signbit_known_clear_p (mode, const_op)
+ && HWI_COMPUTABLE_MODE_P (mode)
+ && trunc_int_for_mode (const_op, mode) == const_op
&& have_insn_for (COMPARE, mode))
{
op0 = XEXP (op0, 0);
@@ -11477,10 +11478,11 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
case ZERO_EXTEND:
mode = GET_MODE (XEXP (op0, 0));
- if (mode != VOIDmode && GET_MODE_CLASS (mode) == MODE_INT
+ if (GET_MODE_CLASS (mode) == MODE_INT
&& (unsigned_comparison_p || equality_comparison_p)
&& HWI_COMPUTABLE_MODE_P (mode)
- && ((unsigned HOST_WIDE_INT) const_op < GET_MODE_MASK (mode))
+ && (unsigned HOST_WIDE_INT) const_op <= GET_MODE_MASK (mode)
+ && const_op >= 0
&& have_insn_for (COMPARE, mode))
{
op0 = XEXP (op0, 0);
diff --git a/gcc/config.in b/gcc/config.in
index 3950e289b7c..18dde6f1855 100644
--- a/gcc/config.in
+++ b/gcc/config.in
@@ -815,6 +815,13 @@
#endif
+/* Define to 1 if we found a declaration for 'stpcpy', otherwise define to 0.
+ */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_STPCPY
+#endif
+
+
/* Define to 1 if we found a declaration for 'strsignal', otherwise define to
0. */
#ifndef USED_FOR_TARGET
diff --git a/gcc/config/alpha/elf.h b/gcc/config/alpha/elf.h
index 8fa17451f86..3b5ec08e989 100644
--- a/gcc/config/alpha/elf.h
+++ b/gcc/config/alpha/elf.h
@@ -344,8 +344,8 @@ do { \
the i386) don't know about that. Also, we don't use \v
since some versions of gas, such as 2.2 did not accept it. */
-#undef ESCAPES
-#define ESCAPES \
+#undef ELF_ASCII_ESCAPES
+#define ELF_ASCII_ESCAPES \
"\1\1\1\1\1\1\1\1btn\1fr\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\
\0\0\"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\\\0\0\0\
@@ -366,8 +366,9 @@ do { \
If your target assembler doesn't support the .string directive, you
should define this to zero. */
-#undef STRING_LIMIT
-#define STRING_LIMIT ((unsigned) 256)
+#undef ELF_STRING_LIMIT
+#define ELF_STRING_LIMIT ((unsigned) 256)
+
#undef STRING_ASM_OP
#define STRING_ASM_OP "\t.string\t"
diff --git a/gcc/config/elfos.h b/gcc/config/elfos.h
index e483216ef7f..dc68c810f26 100644
--- a/gcc/config/elfos.h
+++ b/gcc/config/elfos.h
@@ -117,7 +117,11 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#define ASM_GENERATE_INTERNAL_LABEL(LABEL, PREFIX, NUM) \
do \
{ \
- sprintf (LABEL, "*.%s%u", PREFIX, (unsigned) (NUM)); \
+ char *__p; \
+ (LABEL)[0] = '*'; \
+ (LABEL)[1] = '.'; \
+ __p = stpcpy (&(LABEL)[2], PREFIX); \
+ sprint_ul (__p, (unsigned long) (NUM)); \
} \
while (0)
@@ -371,7 +375,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
the i386) don't know about that. Also, we don't use \v
since some versions of gas, such as 2.2 did not accept it. */
-#define ESCAPES \
+#define ELF_ASCII_ESCAPES \
"\1\1\1\1\1\1\1\1btn\1fr\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\
\0\0\"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\\\0\0\0\
@@ -393,7 +397,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
should define this to zero.
*/
-#define STRING_LIMIT ((unsigned) 256)
+#define ELF_STRING_LIMIT ((unsigned) 256)
#define STRING_ASM_OP "\t.string\t"
@@ -405,36 +409,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
comma separated lists of numbers). */
#define ASM_OUTPUT_LIMITED_STRING(FILE, STR) \
- do \
- { \
- register const unsigned char *_limited_str = \
- (const unsigned char *) (STR); \
- register unsigned ch; \
- \
- fprintf ((FILE), "%s\"", STRING_ASM_OP); \
- \
- for (; (ch = *_limited_str); _limited_str++) \
- { \
- register int escape; \
- \
- switch (escape = ESCAPES[ch]) \
- { \
- case 0: \
- putc (ch, (FILE)); \
- break; \
- case 1: \
- fprintf ((FILE), "\\%03o", ch); \
- break; \
- default: \
- putc ('\\', (FILE)); \
- putc (escape, (FILE)); \
- break; \
- } \
- } \
- \
- fprintf ((FILE), "\"\n"); \
- } \
- while (0)
+ default_elf_asm_output_limited_string ((FILE), (STR))
/* The routine used to output sequences of byte values. We use a special
version of this for most svr4 targets because doing so makes the
@@ -444,76 +419,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
STRING_LIMIT) we output those using ASM_OUTPUT_LIMITED_STRING. */
#undef ASM_OUTPUT_ASCII
-#define ASM_OUTPUT_ASCII(FILE, STR, LENGTH) \
- do \
- { \
- const unsigned char *_ascii_bytes = \
- (const unsigned char *) (STR); \
- const unsigned char *limit = _ascii_bytes + (LENGTH); \
- const unsigned char *last_null = NULL; \
- unsigned bytes_in_chunk = 0; \
- \
- for (; _ascii_bytes < limit; _ascii_bytes++) \
- { \
- const unsigned char *p; \
- \
- if (bytes_in_chunk >= 60) \
- { \
- fprintf ((FILE), "\"\n"); \
- bytes_in_chunk = 0; \
- } \
- \
- if (_ascii_bytes > last_null) \
- { \
- for (p = _ascii_bytes; p < limit && *p != '\0'; p++) \
- continue; \
- last_null = p; \
- } \
- else \
- p = last_null; \
- \
- if (p < limit && (p - _ascii_bytes) <= (long)STRING_LIMIT) \
- { \
- if (bytes_in_chunk > 0) \
- { \
- fprintf ((FILE), "\"\n"); \
- bytes_in_chunk = 0; \
- } \
- \
- ASM_OUTPUT_LIMITED_STRING ((FILE), _ascii_bytes); \
- _ascii_bytes = p; \
- } \
- else \
- { \
- register int escape; \
- register unsigned ch; \
- \
- if (bytes_in_chunk == 0) \
- fprintf ((FILE), "%s\"", ASCII_DATA_ASM_OP); \
- \
- switch (escape = ESCAPES[ch = *_ascii_bytes]) \
- { \
- case 0: \
- putc (ch, (FILE)); \
- bytes_in_chunk++; \
- break; \
- case 1: \
- fprintf ((FILE), "\\%03o", ch); \
- bytes_in_chunk += 4; \
- break; \
- default: \
- putc ('\\', (FILE)); \
- putc (escape, (FILE)); \
- bytes_in_chunk += 2; \
- break; \
- } \
- } \
- } \
- \
- if (bytes_in_chunk > 0) \
- fprintf ((FILE), "\"\n"); \
- } \
- while (0)
+#define ASM_OUTPUT_ASCII(FILE, STR, LENGTH) \
+ default_elf_asm_output_ascii ((FILE), (STR), (LENGTH));
/* Allow the use of the -frecord-gcc-switches switch via the
elf_record_gcc_switches function defined in varasm.c. */
diff --git a/gcc/config/i386/constraints.md b/gcc/config/i386/constraints.md
index bef5b30b013..941f48aa6e6 100644
--- a/gcc/config/i386/constraints.md
+++ b/gcc/config/i386/constraints.md
@@ -19,7 +19,7 @@
;;; Unused letters:
;;; B H T W
-;;; h jk v
+;;; h k v
;; Integer register constraints.
;; It is not necessary to define 'r' here.
@@ -127,6 +127,11 @@
(and (not (match_test "TARGET_X32"))
(match_operand 0 "memory_operand")))
+(define_address_constraint "j"
+ "@internal Address operand that can be zero extended in LEA instruction."
+ (and (not (match_code "const_int"))
+ (match_operand 0 "address_operand")))
+
;; Integer constant constraints.
(define_constraint "I"
"Integer constant in the range 0 @dots{} 31, for 32-bit shifts."
diff --git a/gcc/config/i386/i386-opts.h b/gcc/config/i386/i386-opts.h
index 3cc2253c3c2..07f58b99e35 100644
--- a/gcc/config/i386/i386-opts.h
+++ b/gcc/config/i386/i386-opts.h
@@ -37,7 +37,8 @@ enum stringop_alg
rep_prefix_8_byte,
loop_1_byte,
loop,
- unrolled_loop
+ unrolled_loop,
+ sse_loop
};
/* Available call abi. */
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index 6bfe13d47d6..630112f625d 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -32,6 +32,7 @@ extern void ix86_setup_frame_addresses (void);
extern HOST_WIDE_INT ix86_initial_elimination_offset (int, int);
extern void ix86_expand_prologue (void);
+extern void ix86_maybe_emit_epilogue_vzeroupper (void);
extern void ix86_expand_epilogue (int);
extern void ix86_expand_split_stack_prologue (void);
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index acf9ad8a0ea..a8e8a6a40e1 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -561,10 +561,14 @@ struct processor_costs ix86_size_cost = {/* costs for tuning for size */
COSTS_N_BYTES (2), /* cost of FABS instruction. */
COSTS_N_BYTES (2), /* cost of FCHS instruction. */
COSTS_N_BYTES (2), /* cost of FSQRT instruction. */
- {{rep_prefix_1_byte, {{-1, rep_prefix_1_byte}}},
+ {{{rep_prefix_1_byte, {{-1, rep_prefix_1_byte}}},
{rep_prefix_1_byte, {{-1, rep_prefix_1_byte}}}},
- {{rep_prefix_1_byte, {{-1, rep_prefix_1_byte}}},
+ {{rep_prefix_1_byte, {{-1, rep_prefix_1_byte}}},
+ {rep_prefix_1_byte, {{-1, rep_prefix_1_byte}}}}},
+ {{{rep_prefix_1_byte, {{-1, rep_prefix_1_byte}}},
{rep_prefix_1_byte, {{-1, rep_prefix_1_byte}}}},
+ {{rep_prefix_1_byte, {{-1, rep_prefix_1_byte}}},
+ {rep_prefix_1_byte, {{-1, rep_prefix_1_byte}}}}},
1, /* scalar_stmt_cost. */
1, /* scalar load_cost. */
1, /* scalar_store_cost. */
@@ -632,10 +636,14 @@ struct processor_costs i386_cost = { /* 386 specific costs */
COSTS_N_INSNS (22), /* cost of FABS instruction. */
COSTS_N_INSNS (24), /* cost of FCHS instruction. */
COSTS_N_INSNS (122), /* cost of FSQRT instruction. */
- {{rep_prefix_1_byte, {{-1, rep_prefix_1_byte}}},
+ {{{rep_prefix_1_byte, {{-1, rep_prefix_1_byte}}},
DUMMY_STRINGOP_ALGS},
- {{rep_prefix_1_byte, {{-1, rep_prefix_1_byte}}},
+ {{rep_prefix_1_byte, {{-1, rep_prefix_1_byte}}},
+ DUMMY_STRINGOP_ALGS}},
+ {{{rep_prefix_1_byte, {{-1, rep_prefix_1_byte}}},
DUMMY_STRINGOP_ALGS},
+ {{rep_prefix_1_byte, {{-1, rep_prefix_1_byte}}},
+ DUMMY_STRINGOP_ALGS}},
1, /* scalar_stmt_cost. */
1, /* scalar load_cost. */
1, /* scalar_store_cost. */
@@ -704,10 +712,14 @@ struct processor_costs i486_cost = { /* 486 specific costs */
COSTS_N_INSNS (3), /* cost of FABS instruction. */
COSTS_N_INSNS (3), /* cost of FCHS instruction. */
COSTS_N_INSNS (83), /* cost of FSQRT instruction. */
- {{rep_prefix_4_byte, {{-1, rep_prefix_4_byte}}},
+ {{{rep_prefix_4_byte, {{-1, rep_prefix_4_byte}}},
DUMMY_STRINGOP_ALGS},
- {{rep_prefix_4_byte, {{-1, rep_prefix_4_byte}}},
+ {{rep_prefix_4_byte, {{-1, rep_prefix_4_byte}}},
+ DUMMY_STRINGOP_ALGS}},
+ {{{rep_prefix_4_byte, {{-1, rep_prefix_4_byte}}},
DUMMY_STRINGOP_ALGS},
+ {{rep_prefix_4_byte, {{-1, rep_prefix_4_byte}}},
+ DUMMY_STRINGOP_ALGS}},
1, /* scalar_stmt_cost. */
1, /* scalar load_cost. */
1, /* scalar_store_cost. */
@@ -774,10 +786,14 @@ struct processor_costs pentium_cost = {
COSTS_N_INSNS (1), /* cost of FABS instruction. */
COSTS_N_INSNS (1), /* cost of FCHS instruction. */
COSTS_N_INSNS (70), /* cost of FSQRT instruction. */
- {{libcall, {{256, rep_prefix_4_byte}, {-1, libcall}}},
+ {{{libcall, {{256, rep_prefix_4_byte}, {-1, libcall}}},
DUMMY_STRINGOP_ALGS},
- {{libcall, {{-1, rep_prefix_4_byte}}},
+ {{libcall, {{256, rep_prefix_4_byte}, {-1, libcall}}},
+ DUMMY_STRINGOP_ALGS}},
+ {{{libcall, {{-1, rep_prefix_4_byte}}},
DUMMY_STRINGOP_ALGS},
+ {{libcall, {{-1, rep_prefix_4_byte}}},
+ DUMMY_STRINGOP_ALGS}},
1, /* scalar_stmt_cost. */
1, /* scalar load_cost. */
1, /* scalar_store_cost. */
@@ -849,12 +865,18 @@ struct processor_costs pentiumpro_cost = {
noticeable win, for bigger blocks either rep movsl or rep movsb is
way to go. Rep movsb has apparently more expensive startup time in CPU,
but after 4K the difference is down in the noise. */
- {{rep_prefix_4_byte, {{128, loop}, {1024, unrolled_loop},
+ {{{rep_prefix_4_byte, {{128, loop}, {1024, unrolled_loop},
{8192, rep_prefix_4_byte}, {-1, rep_prefix_1_byte}}},
DUMMY_STRINGOP_ALGS},
- {{rep_prefix_4_byte, {{1024, unrolled_loop},
- {8192, rep_prefix_4_byte}, {-1, libcall}}},
+ {{rep_prefix_4_byte, {{128, loop}, {1024, unrolled_loop},
+ {8192, rep_prefix_4_byte}, {-1, rep_prefix_1_byte}}},
+ DUMMY_STRINGOP_ALGS}},
+ {{{rep_prefix_4_byte, {{1024, unrolled_loop},
+ {8192, rep_prefix_4_byte}, {-1, libcall}}},
DUMMY_STRINGOP_ALGS},
+ {{rep_prefix_4_byte, {{1024, unrolled_loop},
+ {8192, rep_prefix_4_byte}, {-1, libcall}}},
+ DUMMY_STRINGOP_ALGS}},
1, /* scalar_stmt_cost. */
1, /* scalar load_cost. */
1, /* scalar_store_cost. */
@@ -922,10 +944,14 @@ struct processor_costs geode_cost = {
COSTS_N_INSNS (1), /* cost of FABS instruction. */
COSTS_N_INSNS (1), /* cost of FCHS instruction. */
COSTS_N_INSNS (54), /* cost of FSQRT instruction. */
- {{libcall, {{256, rep_prefix_4_byte}, {-1, libcall}}},
+ {{{libcall, {{256, rep_prefix_4_byte}, {-1, libcall}}},
DUMMY_STRINGOP_ALGS},
- {{libcall, {{256, rep_prefix_4_byte}, {-1, libcall}}},
+ {{libcall, {{256, rep_prefix_4_byte}, {-1, libcall}}},
+ DUMMY_STRINGOP_ALGS}},
+ {{{libcall, {{256, rep_prefix_4_byte}, {-1, libcall}}},
DUMMY_STRINGOP_ALGS},
+ {{libcall, {{256, rep_prefix_4_byte}, {-1, libcall}}},
+ DUMMY_STRINGOP_ALGS}},
1, /* scalar_stmt_cost. */
1, /* scalar load_cost. */
1, /* scalar_store_cost. */
@@ -995,10 +1021,14 @@ struct processor_costs k6_cost = {
COSTS_N_INSNS (2), /* cost of FABS instruction. */
COSTS_N_INSNS (2), /* cost of FCHS instruction. */
COSTS_N_INSNS (56), /* cost of FSQRT instruction. */
- {{libcall, {{256, rep_prefix_4_byte}, {-1, libcall}}},
+ {{{libcall, {{256, rep_prefix_4_byte}, {-1, libcall}}},
DUMMY_STRINGOP_ALGS},
- {{libcall, {{256, rep_prefix_4_byte}, {-1, libcall}}},
+ {{libcall, {{256, rep_prefix_4_byte}, {-1, libcall}}},
+ DUMMY_STRINGOP_ALGS}},
+ {{{libcall, {{256, rep_prefix_4_byte}, {-1, libcall}}},
DUMMY_STRINGOP_ALGS},
+ {{libcall, {{256, rep_prefix_4_byte}, {-1, libcall}}},
+ DUMMY_STRINGOP_ALGS}},
1, /* scalar_stmt_cost. */
1, /* scalar load_cost. */
1, /* scalar_store_cost. */
@@ -1068,10 +1098,14 @@ struct processor_costs athlon_cost = {
/* For some reason, Athlon deals better with REP prefix (relative to loops)
compared to K8. Alignment becomes important after 8 bytes for memcpy and
128 bytes for memset. */
- {{libcall, {{2048, rep_prefix_4_byte}, {-1, libcall}}},
+ {{{libcall, {{2048, rep_prefix_4_byte}, {-1, libcall}}},
DUMMY_STRINGOP_ALGS},
- {{libcall, {{2048, rep_prefix_4_byte}, {-1, libcall}}},
+ {{libcall, {{2048, rep_prefix_4_byte}, {-1, libcall}}},
+ DUMMY_STRINGOP_ALGS}},
+ {{{libcall, {{2048, rep_prefix_4_byte}, {-1, libcall}}},
DUMMY_STRINGOP_ALGS},
+ {{libcall, {{2048, rep_prefix_4_byte}, {-1, libcall}}},
+ DUMMY_STRINGOP_ALGS}},
1, /* scalar_stmt_cost. */
1, /* scalar load_cost. */
1, /* scalar_store_cost. */
@@ -1146,11 +1180,16 @@ struct processor_costs k8_cost = {
/* K8 has optimized REP instruction for medium sized blocks, but for very
small blocks it is better to use loop. For large blocks, libcall can
do nontemporary accesses and beat inline considerably. */
- {{libcall, {{6, loop}, {14, unrolled_loop}, {-1, rep_prefix_4_byte}}},
+ {{{libcall, {{6, loop}, {14, unrolled_loop}, {-1, rep_prefix_4_byte}}},
{libcall, {{16, loop}, {8192, rep_prefix_8_byte}, {-1, libcall}}}},
- {{libcall, {{8, loop}, {24, unrolled_loop},
+ {{libcall, {{6, loop}, {14, unrolled_loop}, {-1, rep_prefix_4_byte}}},
+ {libcall, {{16, loop}, {8192, rep_prefix_8_byte}, {-1, libcall}}}}},
+ {{{libcall, {{8, loop}, {24, unrolled_loop},
{2048, rep_prefix_4_byte}, {-1, libcall}}},
{libcall, {{48, unrolled_loop}, {8192, rep_prefix_8_byte}, {-1, libcall}}}},
+ {{libcall, {{8, loop}, {24, unrolled_loop},
+ {2048, rep_prefix_4_byte}, {-1, libcall}}},
+ {libcall, {{48, unrolled_loop}, {8192, rep_prefix_8_byte}, {-1, libcall}}}}},
4, /* scalar_stmt_cost. */
2, /* scalar load_cost. */
2, /* scalar_store_cost. */
@@ -1233,11 +1272,16 @@ struct processor_costs amdfam10_cost = {
/* AMDFAM10 has optimized REP instruction for medium sized blocks, but for
very small blocks it is better to use loop. For large blocks, libcall can
do nontemporary accesses and beat inline considerably. */
- {{libcall, {{6, loop}, {14, unrolled_loop}, {-1, rep_prefix_4_byte}}},
- {libcall, {{16, loop}, {8192, rep_prefix_8_byte}, {-1, libcall}}}},
- {{libcall, {{8, loop}, {24, unrolled_loop},
+ {{{libcall, {{6, loop}, {14, unrolled_loop}, {-1, rep_prefix_4_byte}}},
+ {libcall, {{16, loop}, {512, rep_prefix_8_byte}, {-1, libcall}}}},
+ {{libcall, {{6, loop}, {14, unrolled_loop}, {-1, rep_prefix_4_byte}}},
+ {libcall, {{16, loop}, {512, rep_prefix_8_byte}, {-1, libcall}}}}},
+ {{{libcall, {{8, loop}, {24, unrolled_loop},
{2048, rep_prefix_4_byte}, {-1, libcall}}},
{libcall, {{48, unrolled_loop}, {8192, rep_prefix_8_byte}, {-1, libcall}}}},
+ {{libcall, {{8, loop}, {24, unrolled_loop},
+ {2048, rep_prefix_4_byte}, {-1, libcall}}},
+ {libcall, {{48, unrolled_loop}, {8192, rep_prefix_8_byte}, {-1, libcall}}}}},
4, /* scalar_stmt_cost. */
2, /* scalar load_cost. */
2, /* scalar_store_cost. */
@@ -1320,11 +1364,16 @@ struct processor_costs bdver1_cost = {
/* BDVER1 has optimized REP instruction for medium sized blocks, but for
very small blocks it is better to use loop. For large blocks, libcall
can do nontemporary accesses and beat inline considerably. */
- {{libcall, {{6, loop}, {14, unrolled_loop}, {-1, rep_prefix_4_byte}}},
+ {{{libcall, {{6, loop}, {14, unrolled_loop}, {-1, rep_prefix_4_byte}}},
{libcall, {{16, loop}, {8192, rep_prefix_8_byte}, {-1, libcall}}}},
- {{libcall, {{8, loop}, {24, unrolled_loop},
+ {{libcall, {{6, loop}, {14, unrolled_loop}, {-1, rep_prefix_4_byte}}},
+ {libcall, {{16, loop}, {8192, rep_prefix_8_byte}, {-1, libcall}}}}},
+ {{{libcall, {{8, loop}, {24, unrolled_loop},
{2048, rep_prefix_4_byte}, {-1, libcall}}},
{libcall, {{48, unrolled_loop}, {8192, rep_prefix_8_byte}, {-1, libcall}}}},
+ {{libcall, {{8, loop}, {24, unrolled_loop},
+ {2048, rep_prefix_4_byte}, {-1, libcall}}},
+ {libcall, {{48, unrolled_loop}, {8192, rep_prefix_8_byte}, {-1, libcall}}}}},
6, /* scalar_stmt_cost. */
4, /* scalar load_cost. */
4, /* scalar_store_cost. */
@@ -1407,11 +1456,16 @@ struct processor_costs bdver2_cost = {
/* BDVER2 has optimized REP instruction for medium sized blocks, but for
very small blocks it is better to use loop. For large blocks, libcall
can do nontemporary accesses and beat inline considerably. */
- {{libcall, {{6, loop}, {14, unrolled_loop}, {-1, rep_prefix_4_byte}}},
+ {{{libcall, {{6, loop}, {14, unrolled_loop}, {-1, rep_prefix_4_byte}}},
{libcall, {{16, loop}, {8192, rep_prefix_8_byte}, {-1, libcall}}}},
- {{libcall, {{8, loop}, {24, unrolled_loop},
+ {{libcall, {{6, loop}, {14, unrolled_loop}, {-1, rep_prefix_4_byte}}},
+ {libcall, {{16, loop}, {8192, rep_prefix_8_byte}, {-1, libcall}}}}},
+ {{{libcall, {{8, loop}, {24, unrolled_loop},
{2048, rep_prefix_4_byte}, {-1, libcall}}},
{libcall, {{48, unrolled_loop}, {8192, rep_prefix_8_byte}, {-1, libcall}}}},
+ {{libcall, {{8, loop}, {24, unrolled_loop},
+ {2048, rep_prefix_4_byte}, {-1, libcall}}},
+ {libcall, {{48, unrolled_loop}, {8192, rep_prefix_8_byte}, {-1, libcall}}}}},
6, /* scalar_stmt_cost. */
4, /* scalar load_cost. */
4, /* scalar_store_cost. */
@@ -1489,11 +1543,16 @@ struct processor_costs btver1_cost = {
/* BTVER1 has optimized REP instruction for medium sized blocks, but for
very small blocks it is better to use loop. For large blocks, libcall can
do nontemporary accesses and beat inline considerably. */
- {{libcall, {{6, loop}, {14, unrolled_loop}, {-1, rep_prefix_4_byte}}},
+ {{{libcall, {{6, loop}, {14, unrolled_loop}, {-1, rep_prefix_4_byte}}},
{libcall, {{16, loop}, {8192, rep_prefix_8_byte}, {-1, libcall}}}},
- {{libcall, {{8, loop}, {24, unrolled_loop},
+ {{libcall, {{6, loop}, {14, unrolled_loop}, {-1, rep_prefix_4_byte}}},
+ {libcall, {{16, loop}, {8192, rep_prefix_8_byte}, {-1, libcall}}}}},
+ {{{libcall, {{8, loop}, {24, unrolled_loop},
{2048, rep_prefix_4_byte}, {-1, libcall}}},
{libcall, {{48, unrolled_loop}, {8192, rep_prefix_8_byte}, {-1, libcall}}}},
+ {{libcall, {{8, loop}, {24, unrolled_loop},
+ {2048, rep_prefix_4_byte}, {-1, libcall}}},
+ {libcall, {{48, unrolled_loop}, {8192, rep_prefix_8_byte}, {-1, libcall}}}}},
4, /* scalar_stmt_cost. */
2, /* scalar load_cost. */
2, /* scalar_store_cost. */
@@ -1560,11 +1619,18 @@ struct processor_costs pentium4_cost = {
COSTS_N_INSNS (2), /* cost of FABS instruction. */
COSTS_N_INSNS (2), /* cost of FCHS instruction. */
COSTS_N_INSNS (43), /* cost of FSQRT instruction. */
- {{libcall, {{12, loop_1_byte}, {-1, rep_prefix_4_byte}}},
+
+ {{{libcall, {{12, loop_1_byte}, {-1, rep_prefix_4_byte}}},
DUMMY_STRINGOP_ALGS},
- {{libcall, {{6, loop_1_byte}, {48, loop}, {20480, rep_prefix_4_byte},
+ {{libcall, {{12, loop_1_byte}, {-1, rep_prefix_4_byte}}},
+ DUMMY_STRINGOP_ALGS}},
+
+ {{{libcall, {{6, loop_1_byte}, {48, loop}, {20480, rep_prefix_4_byte},
{-1, libcall}}},
DUMMY_STRINGOP_ALGS},
+ {{libcall, {{6, loop_1_byte}, {48, loop}, {20480, rep_prefix_4_byte},
+ {-1, libcall}}},
+ DUMMY_STRINGOP_ALGS}},
1, /* scalar_stmt_cost. */
1, /* scalar load_cost. */
1, /* scalar_store_cost. */
@@ -1631,13 +1697,22 @@ struct processor_costs nocona_cost = {
COSTS_N_INSNS (3), /* cost of FABS instruction. */
COSTS_N_INSNS (3), /* cost of FCHS instruction. */
COSTS_N_INSNS (44), /* cost of FSQRT instruction. */
- {{libcall, {{12, loop_1_byte}, {-1, rep_prefix_4_byte}}},
+
+ {{{libcall, {{12, loop_1_byte}, {-1, rep_prefix_4_byte}}},
{libcall, {{32, loop}, {20000, rep_prefix_8_byte},
{100000, unrolled_loop}, {-1, libcall}}}},
- {{libcall, {{6, loop_1_byte}, {48, loop}, {20480, rep_prefix_4_byte},
+ {{libcall, {{12, loop_1_byte}, {-1, rep_prefix_4_byte}}},
+ {libcall, {{32, loop}, {20000, rep_prefix_8_byte},
+ {100000, unrolled_loop}, {-1, libcall}}}}},
+
+ {{{libcall, {{6, loop_1_byte}, {48, loop}, {20480, rep_prefix_4_byte},
{-1, libcall}}},
{libcall, {{24, loop}, {64, unrolled_loop},
{8192, rep_prefix_8_byte}, {-1, libcall}}}},
+ {{libcall, {{6, loop_1_byte}, {48, loop}, {20480, rep_prefix_4_byte},
+ {-1, libcall}}},
+ {libcall, {{24, loop}, {64, unrolled_loop},
+ {8192, rep_prefix_8_byte}, {-1, libcall}}}}},
1, /* scalar_stmt_cost. */
1, /* scalar load_cost. */
1, /* scalar_store_cost. */
@@ -1704,13 +1779,108 @@ struct processor_costs atom_cost = {
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}}}},
+
+ /* stringop_algs for memcpy.
+ SSE loops works best on Atom, but fall back into non-SSE unrolled loop variant
+ if that fails. */
+ {{{libcall, {{4096, sse_loop}, {4096, unrolled_loop}, {-1, libcall}}}, /* Known alignment. */
+ {libcall, {{4096, sse_loop}, {4096, unrolled_loop}, {-1, libcall}}}},
+ {{libcall, {{-1, libcall}}}, /* Unknown alignment. */
+ {libcall, {{2048, sse_loop}, {2048, unrolled_loop},
+ {-1, libcall}}}}},
+
+ /* stringop_algs for memset. */
+ {{{libcall, {{4096, sse_loop}, {4096, unrolled_loop}, {-1, libcall}}}, /* Known alignment. */
+ {libcall, {{4096, sse_loop}, {4096, unrolled_loop}, {-1, libcall}}}},
+ {{libcall, {{1024, sse_loop}, {1024, unrolled_loop}, /* Unknown alignment. */
+ {-1, libcall}}},
+ {libcall, {{2048, sse_loop}, {2048, unrolled_loop},
+ {-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. */
+};
+
+/* Core should produce code tuned for core variants. */
+static const
+struct processor_costs core_cost = {
+ COSTS_N_INSNS (1), /* cost of an add instruction */
+ /* On all chips taken into consideration lea is 2 cycles and more. With
+ this cost however our current implementation of synth_mult results in
+ use of unnecessary temporary registers causing regression on several
+ SPECfp benchmarks. */
+ COSTS_N_INSNS (1) + 1, /* cost of a lea instruction */
+ COSTS_N_INSNS (1), /* variable shift costs */
+ COSTS_N_INSNS (1), /* constant shift costs */
+ {COSTS_N_INSNS (3), /* cost of starting multiply for QI */
+ COSTS_N_INSNS (4), /* HI */
+ COSTS_N_INSNS (3), /* SI */
+ COSTS_N_INSNS (4), /* DI */
+ COSTS_N_INSNS (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 */
+ 4, /* 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. */
+ 512, /* size of l2 cache. */
+ 64, /* size of prefetch block */
+ 6, /* number of parallel prefetches */
+ /* Benchmarks shows large regressions on K8 sixtrack benchmark when this
+ value is increased to perhaps more appropriate value of 5. */
+ 3, /* Branch cost */
+ COSTS_N_INSNS (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. */
+
+ /* stringop_algs for memcpy. */
+ {{{libcall, {{16, loop}, {24, unrolled_loop}, {1024, rep_prefix_4_byte}, {-1, libcall}}}, /* Known alignment. */
+ {libcall, {{16, loop}, {24, unrolled_loop}, {1024, rep_prefix_8_byte}, {-1, libcall}}}},
+ {{libcall, {{16, loop}, {24, unrolled_loop}, {1024, rep_prefix_4_byte}, {-1, libcall}}}, /* Unknown alignment. */
+ {libcall, {{16, loop}, {24, unrolled_loop}, {1024, rep_prefix_8_byte}, {-1, libcall}}}}},
+
+ /* stringop_algs for memset. */
+ {{{libcall, {{256, rep_prefix_4_byte}}}, /* Known alignment. */
+ {libcall, {{256, rep_prefix_8_byte}}}},
+ {{libcall, {{256, rep_prefix_4_byte}}}, /* Unknown alignment. */
+ {libcall, {{256, rep_prefix_8_byte}}}}},
1, /* scalar_stmt_cost. */
1, /* scalar load_cost. */
1, /* scalar_store_cost. */
@@ -1724,7 +1894,7 @@ struct processor_costs atom_cost = {
1, /* cond_not_taken_branch_cost. */
};
-/* Generic64 should produce code tuned for Nocona and K8. */
+/* Generic64 should produce code tuned for Nocona, Core, K8, Amdfam10 and buldozer. */
static const
struct processor_costs generic64_cost = {
COSTS_N_INSNS (1), /* cost of an add instruction */
@@ -1784,10 +1954,16 @@ struct processor_costs generic64_cost = {
COSTS_N_INSNS (8), /* cost of FABS instruction. */
COSTS_N_INSNS (8), /* cost of FCHS instruction. */
COSTS_N_INSNS (40), /* cost of FSQRT instruction. */
- {DUMMY_STRINGOP_ALGS,
- {libcall, {{32, loop}, {8192, rep_prefix_8_byte}, {-1, libcall}}}},
- {DUMMY_STRINGOP_ALGS,
- {libcall, {{32, loop}, {8192, rep_prefix_8_byte}, {-1, libcall}}}},
+
+ {{DUMMY_STRINGOP_ALGS,
+ {libcall, {{16, rep_prefix_4_byte}, {128, rep_prefix_8_byte}, {4096, rep_prefix_1_byte}, {-1, libcall}}}},
+ {DUMMY_STRINGOP_ALGS,
+ {libcall, {{128, rep_prefix_4_byte}, {4096, rep_prefix_1_byte}, {-1, libcall}}}}},
+
+ {{DUMMY_STRINGOP_ALGS,
+ {libcall, {{16, rep_prefix_4_byte}, {512, unrolled_loop}, {4096, rep_prefix_1_byte}, {-1, libcall}}}},
+ {DUMMY_STRINGOP_ALGS,
+ {libcall, {{16, rep_prefix_4_byte}, {512, unrolled_loop}, {4096, rep_prefix_1_byte}, {-1, libcall}}}}},
1, /* scalar_stmt_cost. */
1, /* scalar load_cost. */
1, /* scalar_store_cost. */
@@ -1801,8 +1977,8 @@ struct processor_costs generic64_cost = {
1, /* cond_not_taken_branch_cost. */
};
-/* Generic32 should produce code tuned for PPro, Pentium4, Nocona,
- Athlon and K8. */
+/* Generic32 should produce code tuned for PPro, Pentium4, Nocona, Core
+ Athlon, K8, amdfam10, buldozer. */
static const
struct processor_costs generic32_cost = {
COSTS_N_INSNS (1), /* cost of an add instruction */
@@ -1856,10 +2032,16 @@ struct processor_costs generic32_cost = {
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, {{32, loop}, {8192, rep_prefix_4_byte}, {-1, libcall}}},
+ /* stringop_algs for memcpy. */
+ {{{libcall, {{32, loop}, {8192, rep_prefix_4_byte}, {-1, libcall}}},
DUMMY_STRINGOP_ALGS},
- {{libcall, {{32, loop}, {8192, rep_prefix_4_byte}, {-1, libcall}}},
+ {{libcall, {{32, loop}, {8192, rep_prefix_4_byte}, {-1, libcall}}},
+ DUMMY_STRINGOP_ALGS}},
+ /* stringop_algs for memset. */
+ {{{libcall, {{32, loop}, {8192, rep_prefix_4_byte}, {-1, libcall}}},
DUMMY_STRINGOP_ALGS},
+ {{libcall, {{32, loop}, {8192, rep_prefix_4_byte}, {-1, libcall}}},
+ DUMMY_STRINGOP_ALGS}},
1, /* scalar_stmt_cost. */
1, /* scalar load_cost. */
1, /* scalar_store_cost. */
@@ -2536,6 +2718,8 @@ 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);
+static rtx promote_duplicated_reg (enum machine_mode, rtx);
+static rtx promote_duplicated_reg_to_size (rtx, int, int, int);
#ifndef SUBTARGET32_DEFAULT_CPU
@@ -2582,13 +2766,13 @@ static const struct ptt processor_target_table[PROCESSOR_max] =
{&k8_cost, 16, 7, 16, 7, 16},
{&nocona_cost, 0, 0, 0, 0, 0},
/* Core 2 32-bit. */
- {&generic32_cost, 16, 10, 16, 10, 16},
+ {&core_cost, 16, 10, 16, 10, 16},
/* Core 2 64-bit. */
- {&generic64_cost, 16, 10, 16, 10, 16},
+ {&core_cost, 16, 10, 16, 10, 16},
/* Core i7 32-bit. */
- {&generic32_cost, 16, 10, 16, 10, 16},
+ {&core_cost, 16, 10, 16, 10, 16},
/* Core i7 64-bit. */
- {&generic64_cost, 16, 10, 16, 10, 16},
+ {&core_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},
@@ -9928,12 +10112,68 @@ ix86_finalize_stack_realign_flags (void)
/* After stack_realign_needed is finalized, we can't no longer
change it. */
gcc_assert (crtl->stack_realign_needed == stack_realign);
+ return;
}
- else
- {
- crtl->stack_realign_needed = stack_realign;
- crtl->stack_realign_finalized = true;
+
+ /* If the only reason for frame_pointer_needed is that we conservatively
+ assumed stack realignment might be needed, but in the end nothing that
+ needed the stack alignment had been spilled, clear frame_pointer_needed
+ and say we don't need stack realignment. */
+ if (stack_realign
+ && !crtl->need_drap
+ && frame_pointer_needed
+ && current_function_is_leaf
+ && flag_omit_frame_pointer
+ && current_function_sp_is_unchanging
+ && !ix86_current_function_calls_tls_descriptor
+ && !crtl->accesses_prior_frames
+ && !cfun->calls_alloca
+ && !crtl->calls_eh_return
+ && !(flag_stack_check && STACK_CHECK_MOVING_SP)
+ && !ix86_frame_pointer_required ()
+ && get_frame_size () == 0
+ && ix86_nsaved_sseregs () == 0
+ && ix86_varargs_gpr_size + ix86_varargs_fpr_size == 0)
+ {
+ HARD_REG_SET set_up_by_prologue, prologue_used;
+ basic_block bb;
+
+ CLEAR_HARD_REG_SET (prologue_used);
+ CLEAR_HARD_REG_SET (set_up_by_prologue);
+ add_to_hard_reg_set (&set_up_by_prologue, Pmode, STACK_POINTER_REGNUM);
+ add_to_hard_reg_set (&set_up_by_prologue, Pmode, ARG_POINTER_REGNUM);
+ add_to_hard_reg_set (&set_up_by_prologue, Pmode,
+ HARD_FRAME_POINTER_REGNUM);
+ FOR_EACH_BB (bb)
+ {
+ rtx insn;
+ FOR_BB_INSNS (bb, insn)
+ if (NONDEBUG_INSN_P (insn)
+ && requires_stack_frame_p (insn, prologue_used,
+ set_up_by_prologue))
+ {
+ crtl->stack_realign_needed = stack_realign;
+ crtl->stack_realign_finalized = true;
+ return;
+ }
+ }
+
+ frame_pointer_needed = false;
+ stack_realign = false;
+ crtl->max_used_stack_slot_alignment = incoming_stack_boundary;
+ crtl->stack_alignment_needed = incoming_stack_boundary;
+ crtl->stack_alignment_estimated = incoming_stack_boundary;
+ if (crtl->preferred_stack_boundary > incoming_stack_boundary)
+ crtl->preferred_stack_boundary = incoming_stack_boundary;
+ df_finish_pass (true);
+ df_scan_alloc (NULL);
+ df_scan_blocks ();
+ df_compute_regs_ever_live (true);
+ df_analyze ();
}
+
+ crtl->stack_realign_needed = stack_realign;
+ crtl->stack_realign_finalized = true;
}
/* Expand the prologue into a bunch of separate insns. */
@@ -10558,6 +10798,17 @@ ix86_emit_restore_sse_regs_using_mov (HOST_WIDE_INT cfa_offset,
}
}
+/* Emit vzeroupper if needed. */
+
+void
+ix86_maybe_emit_epilogue_vzeroupper (void)
+{
+ if (TARGET_VZEROUPPER
+ && !TREE_THIS_VOLATILE (cfun->decl)
+ && !cfun->machine->caller_return_avx256_p)
+ emit_insn (gen_avx_vzeroupper (GEN_INT (call_no_avx256)));
+}
+
/* Restore function stack, frame, and registers. */
void
@@ -10855,10 +11106,7 @@ ix86_expand_epilogue (int style)
}
/* Emit vzeroupper if needed. */
- if (TARGET_VZEROUPPER
- && !TREE_THIS_VOLATILE (cfun->decl)
- && !cfun->machine->caller_return_avx256_p)
- emit_insn (gen_avx_vzeroupper (GEN_INT (call_no_avx256)));
+ ix86_maybe_emit_epilogue_vzeroupper ();
if (crtl->args.pops_args && crtl->args.size)
{
@@ -13483,26 +13731,28 @@ print_reg (rtx x, int code, FILE *file)
code = GET_MODE_SIZE (GET_MODE (x));
/* Irritatingly, AMD extended registers use different naming convention
- from the normal registers. */
+ from the normal registers: "r%d[bwd]" */
if (REX_INT_REG_P (x))
{
gcc_assert (TARGET_64BIT);
+ putc ('r', file);
+ fprint_ul (file, REGNO (x) - FIRST_REX_INT_REG + 8);
switch (code)
{
case 0:
error ("extended registers have no high halves");
break;
case 1:
- fprintf (file, "r%ib", REGNO (x) - FIRST_REX_INT_REG + 8);
+ putc ('b', file);
break;
case 2:
- fprintf (file, "r%iw", REGNO (x) - FIRST_REX_INT_REG + 8);
+ putc ('w', file);
break;
case 4:
- fprintf (file, "r%id", REGNO (x) - FIRST_REX_INT_REG + 8);
+ putc ('d', file);
break;
case 8:
- fprintf (file, "r%i", REGNO (x) - FIRST_REX_INT_REG + 8);
+ /* no suffix */
break;
default:
error ("unsupported operand size for extended register");
@@ -20857,22 +21107,37 @@ counter_mode (rtx count_exp)
return SImode;
}
-/* When SRCPTR is non-NULL, output simple loop to move memory
+/* Helper function for expand_set_or_movmem_via_loop.
+
+ When SRCPTR is non-NULL, output simple loop to move memory
pointer to SRCPTR to DESTPTR via chunks of MODE unrolled UNROLL times,
overall size is COUNT specified in bytes. When SRCPTR is NULL, output the
equivalent loop to set memory by VALUE (supposed to be in MODE).
The size is rounded down to whole number of chunk size moved at once.
- SRCMEM and DESTMEM provide MEMrtx to feed proper aliasing info. */
+ SRCMEM and DESTMEM provide MEMrtx to feed proper aliasing info.
+ If ITER isn't NULL, than it'll be used in the generated loop without
+ initialization (that allows to generate several consequent loops using the
+ same iterator).
+ If CHANGE_PTRS is specified, DESTPTR and SRCPTR would be increased by
+ iterator value at the end of the function (as if they iterate in the loop).
+ Otherwise, their vaules'll stay unchanged.
-static void
-expand_set_or_movmem_via_loop (rtx destmem, rtx srcmem,
- rtx destptr, rtx srcptr, rtx value,
- rtx count, enum machine_mode mode, int unroll,
- int expected_size)
+ If EXPECTED_SIZE isn't -1, than it's used to compute branch-probabilities on
+ the loop backedge. When expected size is unknown (it's -1), the probability
+ is set to 80%.
+
+ Return value is rtx of iterator, used in the loop - it could be reused in
+ consequent calls of this function. */
+static rtx
+expand_set_or_movmem_via_loop_with_iter (rtx destmem, rtx srcmem,
+ rtx destptr, rtx srcptr, rtx value,
+ rtx count, rtx iter,
+ enum machine_mode mode, int unroll,
+ int expected_size, bool change_ptrs)
{
- rtx out_label, top_label, iter, tmp;
+ rtx out_label, top_label, tmp;
enum machine_mode iter_mode = counter_mode (count);
rtx piece_size = GEN_INT (GET_MODE_SIZE (mode) * unroll);
rtx piece_size_mask = GEN_INT (~((GET_MODE_SIZE (mode) * unroll) - 1));
@@ -20880,10 +21145,12 @@ expand_set_or_movmem_via_loop (rtx destmem, rtx srcmem,
rtx x_addr;
rtx y_addr;
int i;
+ bool reuse_iter = (iter != NULL_RTX);
top_label = gen_label_rtx ();
out_label = gen_label_rtx ();
- iter = gen_reg_rtx (iter_mode);
+ if (!reuse_iter)
+ iter = gen_reg_rtx (iter_mode);
size = expand_simple_binop (iter_mode, AND, count, piece_size_mask,
NULL, 1, OPTAB_DIRECT);
@@ -20894,18 +21161,21 @@ expand_set_or_movmem_via_loop (rtx destmem, rtx srcmem,
true, out_label);
predict_jump (REG_BR_PROB_BASE * 10 / 100);
}
- emit_move_insn (iter, const0_rtx);
+ if (!reuse_iter)
+ emit_move_insn (iter, const0_rtx);
emit_label (top_label);
tmp = convert_modes (Pmode, iter_mode, iter, true);
x_addr = gen_rtx_PLUS (Pmode, destptr, tmp);
- destmem = change_address (destmem, mode, x_addr);
+ destmem =
+ adjust_automodify_address_nv (copy_rtx (destmem), mode, x_addr, 0);
if (srcmem)
{
y_addr = gen_rtx_PLUS (Pmode, srcptr, copy_rtx (tmp));
- srcmem = change_address (srcmem, mode, y_addr);
+ srcmem =
+ adjust_automodify_address_nv (copy_rtx (srcmem), mode, y_addr, 0);
/* When unrolling for chips that reorder memory reads and writes,
we can save registers by using single temporary.
@@ -20977,19 +21247,43 @@ expand_set_or_movmem_via_loop (rtx destmem, rtx srcmem,
}
else
predict_jump (REG_BR_PROB_BASE * 80 / 100);
- iter = ix86_zero_extend_to_Pmode (iter);
- tmp = expand_simple_binop (Pmode, PLUS, destptr, iter, destptr,
- true, OPTAB_LIB_WIDEN);
- if (tmp != destptr)
- emit_move_insn (destptr, tmp);
- if (srcptr)
+ if (change_ptrs)
{
- tmp = expand_simple_binop (Pmode, PLUS, srcptr, iter, srcptr,
+ iter = ix86_zero_extend_to_Pmode (iter);
+ tmp = expand_simple_binop (Pmode, PLUS, destptr, iter, destptr,
true, OPTAB_LIB_WIDEN);
- if (tmp != srcptr)
- emit_move_insn (srcptr, tmp);
+ if (tmp != destptr)
+ emit_move_insn (destptr, tmp);
+ if (srcptr)
+ {
+ tmp = expand_simple_binop (Pmode, PLUS, srcptr, iter, srcptr,
+ true, OPTAB_LIB_WIDEN);
+ if (tmp != srcptr)
+ emit_move_insn (srcptr, tmp);
+ }
}
emit_label (out_label);
+ return iter;
+}
+
+/* When SRCPTR is non-NULL, output simple loop to move memory
+ pointer to SRCPTR to DESTPTR via chunks of MODE unrolled UNROLL times,
+ overall size is COUNT specified in bytes. When SRCPTR is NULL, output the
+ equivalent loop to set memory by VALUE (supposed to be in MODE).
+
+ The size is rounded down to whole number of chunk size moved at once.
+ SRCMEM and DESTMEM provide MEMrtx to feed proper aliasing info. */
+
+static void
+expand_set_or_movmem_via_loop (rtx destmem, rtx srcmem,
+ rtx destptr, rtx srcptr, rtx value,
+ rtx count, enum machine_mode mode, int unroll,
+ int expected_size)
+{
+ expand_set_or_movmem_via_loop_with_iter (destmem, srcmem,
+ destptr, srcptr, value,
+ count, NULL_RTX, mode, unroll,
+ expected_size, true);
}
/* Output "rep; mov" instruction.
@@ -21093,7 +21387,18 @@ emit_strmov (rtx destmem, rtx srcmem,
emit_insn (gen_strmov (destptr, dest, srcptr, src));
}
-/* Output code to copy at most count & (max_size - 1) bytes from SRC to DEST. */
+/* Emit strset instuction. If RHS is constant, and vector mode will be used,
+ then move this constant to a vector register before emitting strset. */
+static void
+emit_strset (rtx destmem, rtx value,
+ rtx destptr, enum machine_mode mode, int offset)
+{
+ rtx dest = adjust_automodify_address_nv (destmem, mode, destptr, offset);
+ emit_insn (gen_strset (destptr, dest, value));
+}
+
+/* Output code to copy (COUNT % MAX_SIZE) bytes from SRCPTR to DESTPTR.
+ SRCMEM and DESTMEM provide MEMrtx to feed proper aliasing info. */
static void
expand_movmem_epilogue (rtx destmem, rtx srcmem,
rtx destptr, rtx srcptr, rtx count, int max_size)
@@ -21104,43 +21409,55 @@ expand_movmem_epilogue (rtx destmem, rtx srcmem,
HOST_WIDE_INT countval = INTVAL (count);
int offset = 0;
- if ((countval & 0x10) && max_size > 16)
+ int remainder_size = countval % max_size;
+ enum machine_mode move_mode = Pmode;
+
+ /* Firstly, try to move data with the widest possible mode.
+ Remaining part we'll move using Pmode and narrower modes. */
+ if (TARGET_SSE)
{
- if (TARGET_64BIT)
- {
- emit_strmov (destmem, srcmem, destptr, srcptr, DImode, offset);
- emit_strmov (destmem, srcmem, destptr, srcptr, DImode, offset + 8);
- }
- else
- gcc_unreachable ();
- offset += 16;
+ if (max_size >= GET_MODE_SIZE (V4SImode))
+ move_mode = V4SImode;
+ else if (max_size >= GET_MODE_SIZE (DImode))
+ move_mode = DImode;
}
- if ((countval & 0x08) && max_size > 8)
+
+ while (remainder_size >= GET_MODE_SIZE (move_mode))
{
- if (TARGET_64BIT)
- emit_strmov (destmem, srcmem, destptr, srcptr, DImode, offset);
- else
- {
- emit_strmov (destmem, srcmem, destptr, srcptr, SImode, offset);
- emit_strmov (destmem, srcmem, destptr, srcptr, SImode, offset + 4);
- }
- offset += 8;
+ emit_strmov (destmem, srcmem, destptr, srcptr, move_mode, offset);
+ offset += GET_MODE_SIZE (move_mode);
+ remainder_size -= GET_MODE_SIZE (move_mode);
+ }
+
+ /* Move the remaining part of epilogue - its size might be
+ a size of the widest mode. */
+ move_mode = Pmode;
+ while (remainder_size >= GET_MODE_SIZE (move_mode))
+ {
+ emit_strmov (destmem, srcmem, destptr, srcptr, move_mode, offset);
+ offset += GET_MODE_SIZE (move_mode);
+ remainder_size -= GET_MODE_SIZE (move_mode);
}
- if ((countval & 0x04) && max_size > 4)
+
+ if (remainder_size >= 4)
{
- emit_strmov (destmem, srcmem, destptr, srcptr, SImode, offset);
+ emit_strmov (destmem, srcmem, destptr, srcptr, SImode, offset);
offset += 4;
+ remainder_size -= 4;
}
- if ((countval & 0x02) && max_size > 2)
+ if (remainder_size >= 2)
{
- emit_strmov (destmem, srcmem, destptr, srcptr, HImode, offset);
+ emit_strmov (destmem, srcmem, destptr, srcptr, HImode, offset);
offset += 2;
+ remainder_size -= 2;
}
- if ((countval & 0x01) && max_size > 1)
+ if (remainder_size >= 1)
{
- emit_strmov (destmem, srcmem, destptr, srcptr, QImode, offset);
+ emit_strmov (destmem, srcmem, destptr, srcptr, QImode, offset);
offset += 1;
+ remainder_size -= 1;
}
+ gcc_assert (remainder_size == 0);
return;
}
if (max_size > 8)
@@ -21246,87 +21563,121 @@ expand_setmem_epilogue_via_loop (rtx destmem, rtx destptr, rtx value,
1, max_size / 2);
}
-/* Output code to set at most count & (max_size - 1) bytes starting by DEST. */
+/* Output code to set with VALUE at most (COUNT % MAX_SIZE) bytes starting from
+ DESTPTR.
+ DESTMEM provides MEMrtx to feed proper aliasing info.
+ PROMOTED_TO_GPR_VALUE is rtx representing a GPR containing broadcasted VALUE.
+ PROMOTED_TO_VECTOR_VALUE is rtx representing a vector register containing
+ broadcasted VALUE.
+ PROMOTED_TO_GPR_VALUE and PROMOTED_TO_VECTOR_VALUE could be NULL if the
+ promotion hasn't been generated before. */
static void
-expand_setmem_epilogue (rtx destmem, rtx destptr, rtx value, rtx count, int max_size)
+expand_setmem_epilogue (rtx destmem, rtx destptr, rtx promoted_to_vector_value,
+ rtx promoted_to_gpr_value, rtx value, rtx count,
+ int max_size)
{
- rtx dest;
-
if (CONST_INT_P (count))
{
HOST_WIDE_INT countval = INTVAL (count);
int offset = 0;
- if ((countval & 0x10) && max_size > 16)
- {
- if (TARGET_64BIT)
- {
- dest = adjust_automodify_address_nv (destmem, DImode, destptr, offset);
- emit_insn (gen_strset (destptr, dest, value));
- dest = adjust_automodify_address_nv (destmem, DImode, destptr, offset + 8);
- emit_insn (gen_strset (destptr, dest, value));
- }
- else
- gcc_unreachable ();
- offset += 16;
- }
- if ((countval & 0x08) && max_size > 8)
+ int remainder_size = countval % max_size;
+ enum machine_mode move_mode = Pmode;
+
+ /* Firstly, try to move data with the widest possible mode.
+ Remaining part we'll move using Pmode and narrower modes. */
+
+ if (promoted_to_vector_value)
+ while (remainder_size >= 16)
+ {
+ if (GET_MODE (destmem) != move_mode)
+ destmem = adjust_automodify_address_nv (destmem, move_mode,
+ destptr, offset);
+ emit_strset (destmem, promoted_to_vector_value, destptr,
+ move_mode, offset);
+
+ offset += 16;
+ remainder_size -= 16;
+ }
+
+ /* Move the remaining part of epilogue - its size might be
+ a size of the widest mode. */
+ while (remainder_size >= GET_MODE_SIZE (Pmode))
{
- if (TARGET_64BIT)
- {
- dest = adjust_automodify_address_nv (destmem, DImode, destptr, offset);
- emit_insn (gen_strset (destptr, dest, value));
- }
- else
- {
- dest = adjust_automodify_address_nv (destmem, SImode, destptr, offset);
- emit_insn (gen_strset (destptr, dest, value));
- dest = adjust_automodify_address_nv (destmem, SImode, destptr, offset + 4);
- emit_insn (gen_strset (destptr, dest, value));
- }
- offset += 8;
+ if (!promoted_to_gpr_value)
+ promoted_to_gpr_value = promote_duplicated_reg (Pmode, value);
+ emit_strset (destmem, promoted_to_gpr_value, destptr, Pmode, offset);
+ offset += GET_MODE_SIZE (Pmode);
+ remainder_size -= GET_MODE_SIZE (Pmode);
}
- if ((countval & 0x04) && max_size > 4)
+
+ if (!promoted_to_gpr_value && remainder_size > 1)
+ promoted_to_gpr_value = promote_duplicated_reg (remainder_size >= 4
+ ? SImode : HImode, value);
+ if (remainder_size >= 4)
{
- dest = adjust_automodify_address_nv (destmem, SImode, destptr, offset);
- emit_insn (gen_strset (destptr, dest, gen_lowpart (SImode, value)));
+ emit_strset (destmem, gen_lowpart (SImode, promoted_to_gpr_value), destptr,
+ SImode, offset);
offset += 4;
+ remainder_size -= 4;
}
- if ((countval & 0x02) && max_size > 2)
+ if (remainder_size >= 2)
{
- dest = adjust_automodify_address_nv (destmem, HImode, destptr, offset);
- emit_insn (gen_strset (destptr, dest, gen_lowpart (HImode, value)));
- offset += 2;
+ emit_strset (destmem, gen_lowpart (HImode, promoted_to_gpr_value), destptr,
+ HImode, offset);
+ offset +=2;
+ remainder_size -= 2;
}
- if ((countval & 0x01) && max_size > 1)
+ if (remainder_size >= 1)
{
- dest = adjust_automodify_address_nv (destmem, QImode, destptr, offset);
- emit_insn (gen_strset (destptr, dest, gen_lowpart (QImode, value)));
+ emit_strset (destmem,
+ promoted_to_gpr_value ? gen_lowpart (QImode, promoted_to_gpr_value) : value,
+ destptr,
+ QImode, offset);
offset += 1;
+ remainder_size -= 1;
}
+ gcc_assert (remainder_size == 0);
return;
}
+
+ /* count isn't const. */
if (max_size > 32)
{
- expand_setmem_epilogue_via_loop (destmem, destptr, value, count, max_size);
+ expand_setmem_epilogue_via_loop (destmem, destptr, value, count,
+ max_size);
return;
}
+
+ if (!promoted_to_gpr_value)
+ promoted_to_gpr_value = promote_duplicated_reg_to_size (value,
+ GET_MODE_SIZE (Pmode),
+ GET_MODE_SIZE (Pmode),
+ GET_MODE_SIZE (Pmode));
+
if (max_size > 16)
{
rtx label = ix86_expand_aligntest (count, 16, true);
- if (TARGET_64BIT)
+ if (TARGET_SSE && promoted_to_vector_value)
+ {
+ destmem = change_address (destmem,
+ GET_MODE (promoted_to_vector_value),
+ destptr);
+ emit_insn (gen_strset (destptr, destmem, promoted_to_vector_value));
+ }
+ else if (TARGET_64BIT)
{
- dest = change_address (destmem, DImode, destptr);
- emit_insn (gen_strset (destptr, dest, value));
- emit_insn (gen_strset (destptr, dest, value));
+ destmem = change_address (destmem, DImode, destptr);
+ emit_insn (gen_strset (destptr, destmem, promoted_to_gpr_value));
+ emit_insn (gen_strset (destptr, destmem, promoted_to_gpr_value));
}
else
{
- dest = change_address (destmem, SImode, destptr);
- emit_insn (gen_strset (destptr, dest, value));
- emit_insn (gen_strset (destptr, dest, value));
- emit_insn (gen_strset (destptr, dest, value));
- emit_insn (gen_strset (destptr, dest, value));
+ destmem = change_address (destmem, SImode, destptr);
+ emit_insn (gen_strset (destptr, destmem, promoted_to_gpr_value));
+ emit_insn (gen_strset (destptr, destmem, promoted_to_gpr_value));
+ emit_insn (gen_strset (destptr, destmem, promoted_to_gpr_value));
+ emit_insn (gen_strset (destptr, destmem, promoted_to_gpr_value));
}
emit_label (label);
LABEL_NUSES (label) = 1;
@@ -21336,14 +21687,22 @@ expand_setmem_epilogue (rtx destmem, rtx destptr, rtx value, rtx count, int max_
rtx label = ix86_expand_aligntest (count, 8, true);
if (TARGET_64BIT)
{
- dest = change_address (destmem, DImode, destptr);
- emit_insn (gen_strset (destptr, dest, value));
+ destmem = change_address (destmem, DImode, destptr);
+ emit_insn (gen_strset (destptr, destmem, promoted_to_gpr_value));
+ }
+ /* FIXME: When this hunk it output, IRA classifies promoted_to_vector_value
+ as NO_REGS. */
+ else if (TARGET_SSE && promoted_to_vector_value && 0)
+ {
+ destmem = change_address (destmem, V2SImode, destptr);
+ emit_insn (gen_strset (destptr, destmem,
+ gen_lowpart (V2SImode, promoted_to_vector_value)));
}
else
{
- dest = change_address (destmem, SImode, destptr);
- emit_insn (gen_strset (destptr, dest, value));
- emit_insn (gen_strset (destptr, dest, value));
+ destmem = change_address (destmem, SImode, destptr);
+ emit_insn (gen_strset (destptr, destmem, promoted_to_gpr_value));
+ emit_insn (gen_strset (destptr, destmem, promoted_to_gpr_value));
}
emit_label (label);
LABEL_NUSES (label) = 1;
@@ -21351,24 +21710,27 @@ expand_setmem_epilogue (rtx destmem, rtx destptr, rtx value, rtx count, int max_
if (max_size > 4)
{
rtx label = ix86_expand_aligntest (count, 4, true);
- dest = change_address (destmem, SImode, destptr);
- emit_insn (gen_strset (destptr, dest, gen_lowpart (SImode, value)));
+ destmem = change_address (destmem, SImode, destptr);
+ emit_insn (gen_strset (destptr, destmem,
+ gen_lowpart (SImode, promoted_to_gpr_value)));
emit_label (label);
LABEL_NUSES (label) = 1;
}
if (max_size > 2)
{
rtx label = ix86_expand_aligntest (count, 2, true);
- dest = change_address (destmem, HImode, destptr);
- emit_insn (gen_strset (destptr, dest, gen_lowpart (HImode, value)));
+ destmem = change_address (destmem, HImode, destptr);
+ emit_insn (gen_strset (destptr, destmem,
+ gen_lowpart (HImode, promoted_to_gpr_value)));
emit_label (label);
LABEL_NUSES (label) = 1;
}
if (max_size > 1)
{
rtx label = ix86_expand_aligntest (count, 1, true);
- dest = change_address (destmem, QImode, destptr);
- emit_insn (gen_strset (destptr, dest, gen_lowpart (QImode, value)));
+ destmem = change_address (destmem, QImode, destptr);
+ emit_insn (gen_strset (destptr, destmem,
+ gen_lowpart (QImode, promoted_to_gpr_value)));
emit_label (label);
LABEL_NUSES (label) = 1;
}
@@ -21384,8 +21746,8 @@ expand_movmem_prologue (rtx destmem, rtx srcmem,
if (align <= 1 && desired_alignment > 1)
{
rtx label = ix86_expand_aligntest (destptr, 1, false);
- srcmem = change_address (srcmem, QImode, srcptr);
- destmem = change_address (destmem, QImode, destptr);
+ srcmem = adjust_automodify_address_nv (srcmem, QImode, srcptr, 0);
+ destmem = adjust_automodify_address_nv (destmem, QImode, destptr, 0);
emit_insn (gen_strmov (destptr, destmem, srcptr, srcmem));
ix86_adjust_counter (count, 1);
emit_label (label);
@@ -21394,8 +21756,8 @@ expand_movmem_prologue (rtx destmem, rtx srcmem,
if (align <= 2 && desired_alignment > 2)
{
rtx label = ix86_expand_aligntest (destptr, 2, false);
- srcmem = change_address (srcmem, HImode, srcptr);
- destmem = change_address (destmem, HImode, destptr);
+ srcmem = adjust_automodify_address_nv (srcmem, HImode, srcptr, 0);
+ destmem = adjust_automodify_address_nv (destmem, HImode, destptr, 0);
emit_insn (gen_strmov (destptr, destmem, srcptr, srcmem));
ix86_adjust_counter (count, 2);
emit_label (label);
@@ -21404,14 +21766,34 @@ expand_movmem_prologue (rtx destmem, rtx srcmem,
if (align <= 4 && desired_alignment > 4)
{
rtx label = ix86_expand_aligntest (destptr, 4, false);
- srcmem = change_address (srcmem, SImode, srcptr);
- destmem = change_address (destmem, SImode, destptr);
+ srcmem = adjust_automodify_address_nv (srcmem, SImode, srcptr, 0);
+ destmem = adjust_automodify_address_nv (destmem, SImode, destptr, 0);
emit_insn (gen_strmov (destptr, destmem, srcptr, srcmem));
ix86_adjust_counter (count, 4);
emit_label (label);
LABEL_NUSES (label) = 1;
}
- gcc_assert (desired_alignment <= 8);
+ if (align <= 8 && desired_alignment > 8)
+ {
+ rtx label = ix86_expand_aligntest (destptr, 8, false);
+ if (TARGET_64BIT || TARGET_SSE)
+ {
+ srcmem = adjust_automodify_address_nv (srcmem, DImode, srcptr, 0);
+ destmem = adjust_automodify_address_nv (destmem, DImode, destptr, 0);
+ emit_insn (gen_strmov (destptr, destmem, srcptr, srcmem));
+ }
+ else
+ {
+ srcmem = adjust_automodify_address_nv (srcmem, SImode, srcptr, 0);
+ destmem = adjust_automodify_address_nv (destmem, SImode, destptr, 0);
+ emit_insn (gen_strmov (destptr, destmem, srcptr, srcmem));
+ emit_insn (gen_strmov (destptr, destmem, srcptr, srcmem));
+ }
+ ix86_adjust_counter (count, 8);
+ emit_label (label);
+ LABEL_NUSES (label) = 1;
+ }
+ gcc_assert (desired_alignment <= 16);
}
/* Copy enough from DST to SRC to align DST known to DESIRED_ALIGN.
@@ -21466,6 +21848,37 @@ expand_constant_movmem_prologue (rtx dst, rtx *srcp, rtx destreg, rtx srcreg,
off = 4;
emit_insn (gen_strmov (destreg, dst, srcreg, src));
}
+ if (align_bytes & 8)
+ {
+ if (TARGET_64BIT || TARGET_SSE)
+ {
+ dst = adjust_automodify_address_nv (dst, DImode, destreg, off);
+ src = adjust_automodify_address_nv (src, DImode, srcreg, off);
+ emit_insn (gen_strmov (destreg, dst, srcreg, src));
+ }
+ else
+ {
+ dst = adjust_automodify_address_nv (dst, SImode, destreg, off);
+ src = adjust_automodify_address_nv (src, SImode, srcreg, off);
+ emit_insn (gen_strmov (destreg, dst, srcreg, src));
+ emit_insn (gen_strmov (destreg, dst, srcreg, src));
+ }
+ if (MEM_ALIGN (dst) < 8 * BITS_PER_UNIT)
+ set_mem_align (dst, 8 * BITS_PER_UNIT);
+ if (src_align_bytes >= 0)
+ {
+ unsigned int src_align = 0;
+ if ((src_align_bytes & 7) == (align_bytes & 7))
+ src_align = 8;
+ else if ((src_align_bytes & 3) == (align_bytes & 3))
+ src_align = 4;
+ else if ((src_align_bytes & 1) == (align_bytes & 1))
+ src_align = 2;
+ if (MEM_ALIGN (src) < src_align * BITS_PER_UNIT)
+ set_mem_align (src, src_align * BITS_PER_UNIT);
+ }
+ off = 8;
+ }
dst = adjust_automodify_address_nv (dst, BLKmode, destreg, off);
src = adjust_automodify_address_nv (src, BLKmode, srcreg, off);
if (MEM_ALIGN (dst) < (unsigned int) desired_align * BITS_PER_UNIT)
@@ -21473,7 +21886,9 @@ expand_constant_movmem_prologue (rtx dst, rtx *srcp, rtx destreg, rtx srcreg,
if (src_align_bytes >= 0)
{
unsigned int src_align = 0;
- if ((src_align_bytes & 7) == (align_bytes & 7))
+ if ((src_align_bytes & 15) == (align_bytes & 15))
+ src_align = 16;
+ else if ((src_align_bytes & 7) == (align_bytes & 7))
src_align = 8;
else if ((src_align_bytes & 3) == (align_bytes & 3))
src_align = 4;
@@ -21501,7 +21916,7 @@ expand_setmem_prologue (rtx destmem, rtx destptr, rtx value, rtx count,
if (align <= 1 && desired_alignment > 1)
{
rtx label = ix86_expand_aligntest (destptr, 1, false);
- destmem = change_address (destmem, QImode, destptr);
+ destmem = adjust_automodify_address_nv (destmem, QImode, destptr, 0);
emit_insn (gen_strset (destptr, destmem, gen_lowpart (QImode, value)));
ix86_adjust_counter (count, 1);
emit_label (label);
@@ -21510,7 +21925,7 @@ expand_setmem_prologue (rtx destmem, rtx destptr, rtx value, rtx count,
if (align <= 2 && desired_alignment > 2)
{
rtx label = ix86_expand_aligntest (destptr, 2, false);
- destmem = change_address (destmem, HImode, destptr);
+ destmem = adjust_automodify_address_nv (destmem, HImode, destptr, 0);
emit_insn (gen_strset (destptr, destmem, gen_lowpart (HImode, value)));
ix86_adjust_counter (count, 2);
emit_label (label);
@@ -21519,13 +21934,23 @@ expand_setmem_prologue (rtx destmem, rtx destptr, rtx value, rtx count,
if (align <= 4 && desired_alignment > 4)
{
rtx label = ix86_expand_aligntest (destptr, 4, false);
- destmem = change_address (destmem, SImode, destptr);
+ destmem = adjust_automodify_address_nv (destmem, SImode, destptr, 0);
emit_insn (gen_strset (destptr, destmem, gen_lowpart (SImode, value)));
ix86_adjust_counter (count, 4);
emit_label (label);
LABEL_NUSES (label) = 1;
}
- gcc_assert (desired_alignment <= 8);
+ if (align <= 8 && desired_alignment > 8)
+ {
+ rtx label = ix86_expand_aligntest (destptr, 8, false);
+ destmem = adjust_automodify_address_nv (destmem, SImode, destptr, 0);
+ emit_insn (gen_strset (destptr, destmem, gen_lowpart (SImode, value)));
+ emit_insn (gen_strset (destptr, destmem, gen_lowpart (SImode, value)));
+ ix86_adjust_counter (count, 8);
+ emit_label (label);
+ LABEL_NUSES (label) = 1;
+ }
+ gcc_assert (desired_alignment <= 16);
}
/* Set enough from DST to align DST known to by aligned by ALIGN to
@@ -21561,6 +21986,19 @@ expand_constant_setmem_prologue (rtx dst, rtx destreg, rtx value,
emit_insn (gen_strset (destreg, dst,
gen_lowpart (SImode, value)));
}
+ if (align_bytes & 8)
+ {
+ dst = adjust_automodify_address_nv (dst, SImode, destreg, off);
+ emit_insn (gen_strset (destreg, dst,
+ gen_lowpart (SImode, value)));
+ off = 4;
+ dst = adjust_automodify_address_nv (dst, SImode, destreg, off);
+ emit_insn (gen_strset (destreg, dst,
+ gen_lowpart (SImode, value)));
+ if (MEM_ALIGN (dst) < 8 * BITS_PER_UNIT)
+ set_mem_align (dst, 8 * BITS_PER_UNIT);
+ off = 4;
+ }
dst = adjust_automodify_address_nv (dst, BLKmode, destreg, off);
if (MEM_ALIGN (dst) < (unsigned int) desired_align * BITS_PER_UNIT)
set_mem_align (dst, desired_align * BITS_PER_UNIT);
@@ -21572,7 +22010,7 @@ expand_constant_setmem_prologue (rtx dst, rtx destreg, rtx value,
/* Given COUNT and EXPECTED_SIZE, decide on codegen of string operation. */
static enum stringop_alg
decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size, bool memset,
- int *dynamic_check)
+ int *dynamic_check, bool align_unknown)
{
const struct stringop_algs * algs;
bool optimize_for_speed;
@@ -21581,7 +22019,7 @@ decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size, bool memset,
consider such algorithms if the user has appropriated those
registers for their own purposes. */
bool rep_prefix_usable = !(fixed_regs[CX_REG] || fixed_regs[DI_REG]
- || (memset
+ || (memset
? fixed_regs[AX_REG] : fixed_regs[SI_REG]));
#define ALG_USABLE_P(alg) (rep_prefix_usable \
@@ -21594,7 +22032,7 @@ decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size, bool memset,
of time processing large blocks. */
if (optimize_function_for_size_p (cfun)
|| (optimize_insn_for_size_p ()
- && expected_size != -1 && expected_size < 256))
+ && expected_size != -1 && expected_size < 256))
optimize_for_speed = false;
else
optimize_for_speed = true;
@@ -21603,9 +22041,9 @@ decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size, bool memset,
*dynamic_check = -1;
if (memset)
- algs = &cost->memset[TARGET_64BIT != 0];
+ algs = &cost->memset[align_unknown][TARGET_64BIT != 0];
else
- algs = &cost->memcpy[TARGET_64BIT != 0];
+ algs = &cost->memcpy[align_unknown][TARGET_64BIT != 0];
if (ix86_stringop_alg != no_stringop && ALG_USABLE_P (ix86_stringop_alg))
return ix86_stringop_alg;
/* rep; movq or rep; movl is the smallest variant. */
@@ -21669,29 +22107,33 @@ decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size, bool memset,
enum stringop_alg alg;
int i;
bool any_alg_usable_p = true;
+ bool only_libcall_fits = true;
for (i = 0; i < MAX_STRINGOP_ALGS; i++)
- {
- enum stringop_alg candidate = algs->size[i].alg;
- any_alg_usable_p = any_alg_usable_p && ALG_USABLE_P (candidate);
+ {
+ enum stringop_alg candidate = algs->size[i].alg;
+ any_alg_usable_p = any_alg_usable_p && ALG_USABLE_P (candidate);
- if (candidate != libcall && candidate
- && ALG_USABLE_P (candidate))
- max = algs->size[i].max;
- }
+ if (candidate != libcall && candidate
+ && ALG_USABLE_P (candidate))
+ {
+ max = algs->size[i].max;
+ only_libcall_fits = false;
+ }
+ }
/* If there aren't any usable algorithms, then recursing on
- smaller sizes isn't going to find anything. Just return the
- simple byte-at-a-time copy loop. */
- if (!any_alg_usable_p)
- {
- /* Pick something reasonable. */
- if (TARGET_INLINE_STRINGOPS_DYNAMICALLY)
- *dynamic_check = 128;
- return loop_1_byte;
- }
+ smaller sizes isn't going to find anything. Just return the
+ simple byte-at-a-time copy loop. */
+ if (!any_alg_usable_p || only_libcall_fits)
+ {
+ /* Pick something reasonable. */
+ if (TARGET_INLINE_STRINGOPS_DYNAMICALLY)
+ *dynamic_check = 128;
+ return loop_1_byte;
+ }
if (max == -1)
max = 4096;
- alg = decide_alg (count, max / 2, memset, dynamic_check);
+ alg = decide_alg (count, max / 2, memset, dynamic_check, align_unknown);
gcc_assert (*dynamic_check == -1);
gcc_assert (alg != libcall);
if (TARGET_INLINE_STRINGOPS_DYNAMICALLY)
@@ -21715,9 +22157,14 @@ decide_alignment (int align,
case no_stringop:
gcc_unreachable ();
case loop:
+ desired_align = GET_MODE_SIZE (Pmode);
+ break;
case unrolled_loop:
desired_align = GET_MODE_SIZE (Pmode);
break;
+ case sse_loop:
+ desired_align = 16;
+ break;
case rep_prefix_8_byte:
desired_align = 8;
break;
@@ -21805,6 +22252,11 @@ ix86_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp,
enum stringop_alg alg;
int dynamic_check;
bool need_zero_guard = false;
+ bool align_unknown;
+ int unroll_factor;
+ enum machine_mode move_mode;
+ rtx loop_iter = NULL_RTX;
+ int dst_offset, src_offset;
if (CONST_INT_P (align_exp))
align = INTVAL (align_exp);
@@ -21828,9 +22280,17 @@ ix86_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp,
/* Step 0: Decide on preferred algorithm, desired alignment and
size of chunks to be copied by main loop. */
-
- alg = decide_alg (count, expected_size, false, &dynamic_check);
+ dst_offset = get_mem_align_offset (dst, MOVE_MAX*BITS_PER_UNIT);
+ src_offset = get_mem_align_offset (src, MOVE_MAX*BITS_PER_UNIT);
+ align_unknown = (dst_offset < 0
+ || src_offset < 0
+ || src_offset != dst_offset);
+ alg = decide_alg (count, expected_size, false, &dynamic_check, align_unknown);
desired_align = decide_alignment (align, alg, expected_size);
+ if (align_unknown)
+ desired_align = align;
+ unroll_factor = 1;
+ move_mode = Pmode;
if (!TARGET_ALIGN_STRINGOPS)
align = desired_align;
@@ -21849,11 +22309,22 @@ ix86_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp,
gcc_unreachable ();
case loop:
need_zero_guard = true;
- size_needed = GET_MODE_SIZE (Pmode);
+ move_mode = Pmode;
+ unroll_factor = 1;
+ size_needed = GET_MODE_SIZE (move_mode) * unroll_factor;
break;
case unrolled_loop:
need_zero_guard = true;
- size_needed = GET_MODE_SIZE (Pmode) * (TARGET_64BIT ? 4 : 2);
+ move_mode = Pmode;
+ unroll_factor = TARGET_64BIT ? 4 : 2;
+ size_needed = GET_MODE_SIZE (move_mode) * unroll_factor;
+ break;
+ case sse_loop:
+ need_zero_guard = true;
+ /* Use SSE instructions, if possible. */
+ move_mode = align_unknown ? DImode : V4SImode;
+ unroll_factor = TARGET_64BIT ? 4 : 2;
+ size_needed = GET_MODE_SIZE (move_mode) * unroll_factor;
break;
case rep_prefix_8_byte:
size_needed = 8;
@@ -21914,6 +22385,12 @@ ix86_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp,
}
else
{
+ /* SSE and unrolled algs re-use iteration counter in the epilogue. */
+ if (alg == sse_loop || alg == unrolled_loop)
+ {
+ loop_iter = gen_reg_rtx (counter_mode (count_exp));
+ emit_move_insn (loop_iter, const0_rtx);
+ }
label = gen_label_rtx ();
emit_cmp_and_jump_insns (count_exp,
GEN_INT (epilogue_size_needed),
@@ -21965,6 +22442,8 @@ ix86_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp,
dst = change_address (dst, BLKmode, destreg);
expand_movmem_prologue (dst, src, destreg, srcreg, count_exp, align,
desired_align);
+ set_mem_align (src, desired_align*BITS_PER_UNIT);
+ set_mem_align (dst, desired_align*BITS_PER_UNIT);
}
else
{
@@ -22021,12 +22500,16 @@ ix86_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp,
expand_set_or_movmem_via_loop (dst, src, destreg, srcreg, NULL,
count_exp, Pmode, 1, expected_size);
break;
+ case sse_loop:
case unrolled_loop:
- /* Unroll only by factor of 2 in 32bit mode, since we don't have enough
- registers for 4 temporaries anyway. */
- expand_set_or_movmem_via_loop (dst, src, destreg, srcreg, NULL,
- count_exp, Pmode, TARGET_64BIT ? 4 : 2,
- expected_size);
+ /* In some cases we want to use the same iterator in several adjacent
+ loops, so here we save loop iterator rtx and don't update addresses. */
+ loop_iter = expand_set_or_movmem_via_loop_with_iter (dst, src, destreg,
+ srcreg, NULL,
+ count_exp, loop_iter,
+ move_mode,
+ unroll_factor,
+ expected_size, false);
break;
case rep_prefix_8_byte:
expand_movmem_via_rep_mov (dst, src, destreg, srcreg, count_exp,
@@ -22077,9 +22560,41 @@ ix86_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp,
LABEL_NUSES (label) = 1;
}
+ /* We haven't updated addresses, so we'll do it now.
+ Also, if the epilogue seems to be big, we'll generate a loop (not
+ unrolled) in it. We'll do it only if alignment is unknown, because in
+ this case in epilogue we have to perform memmove by bytes, which is very
+ slow. */
+ if (alg == sse_loop || alg == unrolled_loop)
+ {
+ rtx tmp;
+ if (align_unknown && unroll_factor > 1)
+ {
+ /* Reduce epilogue's size by creating not-unrolled loop. If we won't
+ do this, we can have very big epilogue - when alignment is statically
+ unknown we'll have the epilogue byte by byte which may be very slow. */
+ loop_iter = expand_set_or_movmem_via_loop_with_iter (dst, src, destreg,
+ srcreg, NULL, count_exp,
+ loop_iter, move_mode, 1,
+ expected_size, false);
+ src = change_address (src, BLKmode, srcreg);
+ dst = change_address (dst, BLKmode, destreg);
+ epilogue_size_needed = GET_MODE_SIZE (move_mode);
+ }
+ tmp = expand_simple_binop (Pmode, PLUS, destreg, loop_iter, destreg,
+ true, OPTAB_LIB_WIDEN);
+ if (tmp != destreg)
+ emit_move_insn (destreg, tmp);
+
+ tmp = expand_simple_binop (Pmode, PLUS, srcreg, loop_iter, srcreg,
+ true, OPTAB_LIB_WIDEN);
+ if (tmp != srcreg)
+ emit_move_insn (srcreg, tmp);
+ }
if (count_exp != const0_rtx && epilogue_size_needed > 1)
expand_movmem_epilogue (dst, src, destreg, srcreg, count_exp,
epilogue_size_needed);
+
if (jump_around_label)
emit_label (jump_around_label);
return true;
@@ -22097,7 +22612,37 @@ promote_duplicated_reg (enum machine_mode mode, rtx val)
rtx tmp;
int nops = mode == DImode ? 3 : 2;
+ if (VECTOR_MODE_P (mode))
+ {
+ enum machine_mode inner = GET_MODE_INNER (mode);
+ rtx promoted_val, vec_reg;
+ if (CONST_INT_P (val))
+ return ix86_build_const_vector (mode, true, val);
+
+ promoted_val = promote_duplicated_reg (inner, val);
+ vec_reg = gen_reg_rtx (mode);
+ switch (mode)
+ {
+ case V2DImode:
+ emit_insn (gen_vec_dupv2di (vec_reg, promoted_val));
+ break;
+ case V4SImode:
+ emit_insn (gen_vec_dupv4si (vec_reg, promoted_val));
+ break;
+ default:
+ gcc_unreachable ();
+ break;
+ }
+
+ return vec_reg;
+ }
gcc_assert (mode == SImode || mode == DImode);
+ if (mode == DImode && !TARGET_64BIT)
+ {
+ rtx vec_reg = promote_duplicated_reg (V4SImode, val);
+ vec_reg = convert_to_mode (V2DImode, vec_reg, 1);
+ return vec_reg;
+ }
if (val == const0_rtx)
return copy_to_mode_reg (mode, const0_rtx);
if (CONST_INT_P (val))
@@ -22163,11 +22708,27 @@ promote_duplicated_reg (enum machine_mode mode, rtx val)
static rtx
promote_duplicated_reg_to_size (rtx val, int size_needed, int desired_align, int align)
{
- rtx promoted_val;
+ rtx promoted_val = NULL_RTX;
- if (TARGET_64BIT
- && (size_needed > 4 || (desired_align > align && desired_align > 4)))
- promoted_val = promote_duplicated_reg (DImode, val);
+ if (size_needed > 8 || (desired_align > align && desired_align > 8))
+ {
+ /* We want to promote to vector register, so we expect that at least SSE
+ is available. */
+ gcc_assert (TARGET_SSE);
+
+ /* In case of promotion to vector register, we expect that val is a
+ constant or already promoted to GPR value. */
+ gcc_assert (GET_MODE (val) == Pmode || CONSTANT_P (val));
+ if (TARGET_64BIT)
+ promoted_val = promote_duplicated_reg (V2DImode, val);
+ else
+ promoted_val = promote_duplicated_reg (V4SImode, val);
+ }
+ else if (size_needed > 4 || (desired_align > align && desired_align > 4))
+ {
+ gcc_assert (TARGET_64BIT);
+ promoted_val = promote_duplicated_reg (DImode, val);
+ }
else if (size_needed > 2 || (desired_align > align && desired_align > 2))
promoted_val = promote_duplicated_reg (SImode, val);
else if (size_needed > 1 || (desired_align > align && desired_align > 1))
@@ -22195,10 +22756,14 @@ ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp,
int size_needed = 0, epilogue_size_needed;
int desired_align = 0, align_bytes = 0;
enum stringop_alg alg;
- rtx promoted_val = NULL;
- bool force_loopy_epilogue = false;
+ rtx gpr_promoted_val = NULL;
+ rtx vec_promoted_val = NULL;
int dynamic_check;
bool need_zero_guard = false;
+ bool align_unknown;
+ unsigned int unroll_factor;
+ enum machine_mode move_mode;
+ rtx loop_iter = NULL_RTX;
if (CONST_INT_P (align_exp))
align = INTVAL (align_exp);
@@ -22218,8 +22783,11 @@ ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp,
/* Step 0: Decide on preferred algorithm, desired alignment and
size of chunks to be copied by main loop. */
- alg = decide_alg (count, expected_size, true, &dynamic_check);
+ align_unknown = CONST_INT_P (align_exp) && INTVAL (align_exp) > 0;
+ alg = decide_alg (count, expected_size, true, &dynamic_check, align_unknown);
desired_align = decide_alignment (align, alg, expected_size);
+ unroll_factor = 1;
+ move_mode = Pmode;
if (!TARGET_ALIGN_STRINGOPS)
align = desired_align;
@@ -22237,11 +22805,28 @@ ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp,
gcc_unreachable ();
case loop:
need_zero_guard = true;
- size_needed = GET_MODE_SIZE (Pmode);
+ move_mode = Pmode;
+ size_needed = GET_MODE_SIZE (move_mode) * unroll_factor;
break;
case unrolled_loop:
need_zero_guard = true;
- size_needed = GET_MODE_SIZE (Pmode) * 4;
+ move_mode = Pmode;
+ unroll_factor = 1;
+ /* Select maximal available 1,2 or 4 unroll factor. */
+ while (GET_MODE_SIZE (move_mode) * unroll_factor * 2 < count
+ && unroll_factor < 4)
+ unroll_factor *= 2;
+ size_needed = GET_MODE_SIZE (move_mode) * unroll_factor;
+ break;
+ case sse_loop:
+ need_zero_guard = true;
+ move_mode = TARGET_64BIT ? V2DImode : V4SImode;
+ unroll_factor = 1;
+ /* Select maximal available 1,2 or 4 unroll factor. */
+ while (GET_MODE_SIZE (move_mode) * unroll_factor * 2 < count
+ && unroll_factor < 4)
+ unroll_factor *= 2;
+ size_needed = GET_MODE_SIZE (move_mode) * unroll_factor;
break;
case rep_prefix_8_byte:
size_needed = 8;
@@ -22286,8 +22871,10 @@ ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp,
main loop and epilogue (ie one load of the big constant in the
front of all code. */
if (CONST_INT_P (val_exp))
- promoted_val = promote_duplicated_reg_to_size (val_exp, size_needed,
- desired_align, align);
+ gpr_promoted_val = promote_duplicated_reg_to_size (val_exp,
+ GET_MODE_SIZE (Pmode),
+ GET_MODE_SIZE (Pmode),
+ align);
/* Ensure that alignment prologue won't copy past end of block. */
if (size_needed > 1 || (desired_align > 1 && desired_align > align))
{
@@ -22296,12 +22883,6 @@ ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp,
Make sure it is power of 2. */
epilogue_size_needed = smallest_pow2_greater_than (epilogue_size_needed);
- /* To improve performance of small blocks, we jump around the VAL
- promoting mode. This mean that if the promoted VAL is not constant,
- we might not use it in the epilogue and have to use byte
- loop variant. */
- if (epilogue_size_needed > 2 && !promoted_val)
- force_loopy_epilogue = true;
if (count)
{
if (count < (unsigned HOST_WIDE_INT)epilogue_size_needed)
@@ -22316,6 +22897,12 @@ ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp,
}
else
{
+ /* SSE and unrolled_lopo algs re-use iteration counter in the epilogue. */
+ if (alg == sse_loop || alg == unrolled_loop)
+ {
+ loop_iter = gen_reg_rtx (counter_mode (count_exp));
+ emit_move_insn (loop_iter, const0_rtx);
+ }
label = gen_label_rtx ();
emit_cmp_and_jump_insns (count_exp,
GEN_INT (epilogue_size_needed),
@@ -22341,9 +22928,11 @@ ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp,
/* Step 2: Alignment prologue. */
/* Do the expensive promotion once we branched off the small blocks. */
- if (!promoted_val)
- promoted_val = promote_duplicated_reg_to_size (val_exp, size_needed,
- desired_align, align);
+ if (!gpr_promoted_val)
+ gpr_promoted_val = promote_duplicated_reg_to_size (val_exp,
+ GET_MODE_SIZE (Pmode),
+ GET_MODE_SIZE (Pmode),
+ align);
gcc_assert (desired_align >= 1 && align >= 1);
if (desired_align > align)
@@ -22355,17 +22944,20 @@ ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp,
the pain to maintain it for the first move, so throw away
the info early. */
dst = change_address (dst, BLKmode, destreg);
- expand_setmem_prologue (dst, destreg, promoted_val, count_exp, align,
+ expand_setmem_prologue (dst, destreg, gpr_promoted_val, count_exp, align,
desired_align);
+ set_mem_align (dst, desired_align*BITS_PER_UNIT);
}
else
{
/* If we know how many bytes need to be stored before dst is
sufficiently aligned, maintain aliasing info accurately. */
- dst = expand_constant_setmem_prologue (dst, destreg, promoted_val,
+ dst = expand_constant_setmem_prologue (dst, destreg, gpr_promoted_val,
desired_align, align_bytes);
count_exp = plus_constant (count_exp, -align_bytes);
count -= align_bytes;
+ if (count < (unsigned HOST_WIDE_INT) size_needed)
+ goto epilogue;
}
if (need_zero_guard
&& (count < (unsigned HOST_WIDE_INT) size_needed
@@ -22393,7 +22985,7 @@ ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp,
emit_label (label);
LABEL_NUSES (label) = 1;
label = NULL;
- promoted_val = val_exp;
+ gpr_promoted_val = val_exp;
epilogue_size_needed = 1;
}
else if (label == NULL_RTX)
@@ -22407,27 +22999,40 @@ ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp,
case no_stringop:
gcc_unreachable ();
case loop_1_byte:
- expand_set_or_movmem_via_loop (dst, NULL, destreg, NULL, promoted_val,
+ expand_set_or_movmem_via_loop (dst, NULL, destreg, NULL, val_exp,
count_exp, QImode, 1, expected_size);
break;
case loop:
- expand_set_or_movmem_via_loop (dst, NULL, destreg, NULL, promoted_val,
+ expand_set_or_movmem_via_loop (dst, NULL, destreg, NULL, gpr_promoted_val,
count_exp, Pmode, 1, expected_size);
break;
case unrolled_loop:
- expand_set_or_movmem_via_loop (dst, NULL, destreg, NULL, promoted_val,
- count_exp, Pmode, 4, expected_size);
+ loop_iter = expand_set_or_movmem_via_loop_with_iter (dst, NULL, destreg,
+ NULL, gpr_promoted_val, count_exp,
+ loop_iter, move_mode, unroll_factor,
+ expected_size, false);
+ break;
+ case sse_loop:
+ vec_promoted_val =
+ promote_duplicated_reg_to_size (gpr_promoted_val,
+ GET_MODE_SIZE (move_mode),
+ desired_align, align);
+ loop_iter = expand_set_or_movmem_via_loop_with_iter (dst, NULL, destreg,
+ NULL, vec_promoted_val, count_exp,
+ loop_iter, move_mode, unroll_factor,
+ expected_size, false);
break;
case rep_prefix_8_byte:
- expand_setmem_via_rep_stos (dst, destreg, promoted_val, count_exp,
+ gcc_assert (TARGET_64BIT);
+ expand_setmem_via_rep_stos (dst, destreg, gpr_promoted_val, count_exp,
DImode, val_exp);
break;
case rep_prefix_4_byte:
- expand_setmem_via_rep_stos (dst, destreg, promoted_val, count_exp,
+ expand_setmem_via_rep_stos (dst, destreg, gpr_promoted_val, count_exp,
SImode, val_exp);
break;
case rep_prefix_1_byte:
- expand_setmem_via_rep_stos (dst, destreg, promoted_val, count_exp,
+ expand_setmem_via_rep_stos (dst, destreg, gpr_promoted_val, count_exp,
QImode, val_exp);
break;
}
@@ -22458,16 +23063,43 @@ ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp,
}
emit_label (label);
LABEL_NUSES (label) = 1;
+ /* We can not rely on fact that promoved value is known. */
+ vec_promoted_val = 0;
+ gpr_promoted_val = 0;
}
epilogue:
- if (count_exp != const0_rtx && epilogue_size_needed > 1)
+ if (alg == unrolled_loop || alg == sse_loop)
{
- if (force_loopy_epilogue)
- expand_setmem_epilogue_via_loop (dst, destreg, val_exp, count_exp,
- epilogue_size_needed);
- else
- expand_setmem_epilogue (dst, destreg, promoted_val, count_exp,
- epilogue_size_needed);
+ rtx tmp;
+ if (align_unknown && unroll_factor > 1
+ && epilogue_size_needed >= GET_MODE_SIZE (move_mode)
+ && vec_promoted_val)
+ {
+ /* Reduce epilogue's size by creating not-unrolled loop. If we won't
+ do this, we can have very big epilogue - when alignment is statically
+ unknown we'll have the epilogue byte by byte which may be very slow. */
+ loop_iter = expand_set_or_movmem_via_loop_with_iter (dst, NULL, destreg,
+ NULL, vec_promoted_val, count_exp,
+ loop_iter, move_mode, 1,
+ expected_size, false);
+ dst = change_address (dst, BLKmode, destreg);
+ epilogue_size_needed = GET_MODE_SIZE (move_mode);
+ }
+ tmp = expand_simple_binop (Pmode, PLUS, destreg, loop_iter, destreg,
+ true, OPTAB_LIB_WIDEN);
+ if (tmp != destreg)
+ emit_move_insn (destreg, tmp);
+ }
+ if (count_exp == const0_rtx)
+ ;
+ else if (!gpr_promoted_val && epilogue_size_needed > 1)
+ expand_setmem_epilogue_via_loop (dst, destreg, val_exp, count_exp,
+ epilogue_size_needed);
+ else
+ {
+ if (epilogue_size_needed > 1)
+ expand_setmem_epilogue (dst, destreg, vec_promoted_val, gpr_promoted_val,
+ val_exp, count_exp, epilogue_size_needed);
}
if (jump_around_label)
emit_label (jump_around_label);
@@ -35821,6 +36453,8 @@ expand_vec_perm_interleave2 (struct expand_vec_perm_d *d)
dremap.perm[i * 2] = i;
dremap.perm[i * 2 + 1] = i + nelt;
}
+ if (!TARGET_SSE2 && d->vmode == V4SImode)
+ dremap.vmode = V4SFmode;
}
else if ((contents & (h2 | h4)) == contents)
{
@@ -35832,6 +36466,8 @@ expand_vec_perm_interleave2 (struct expand_vec_perm_d *d)
dremap.perm[i * 2] = i + nelt2;
dremap.perm[i * 2 + 1] = i + nelt + nelt2;
}
+ if (!TARGET_SSE2 && d->vmode == V4SImode)
+ dremap.vmode = V4SFmode;
}
else if ((contents & (h1 | h4)) == contents)
{
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 7721c465832..b10a13cad8a 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -159,8 +159,12 @@ struct processor_costs {
const int fchs; /* cost of FCHS instruction. */
const int fsqrt; /* cost of FSQRT instruction. */
/* Specify what algorithm
- to use for stringops on unknown size. */
- struct stringop_algs memcpy[2], memset[2];
+ to use for stringops on unknown size.
+ First index is used to specify whether
+ alignment is known or not.
+ Second - to specify whether 32 or 64 bits
+ are used. */
+ struct stringop_algs memcpy[2][2], memset[2][2];
const int scalar_stmt_cost; /* Cost of any scalar operation, excluding
load and store. */
const int scalar_load_cost; /* Cost of scalar load. */
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 35273d95683..bc602532304 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -5551,7 +5551,7 @@
(define_insn "*lea_3_zext"
[(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI
- (subreg:SI (match_operand:DI 1 "lea_address_operand" "p") 0)))]
+ (subreg:SI (match_operand:DI 1 "lea_address_operand" "j") 0)))]
"TARGET_64BIT"
"lea{l}\t{%a1, %k0|%k0, %a1}"
[(set_attr "type" "lea")
@@ -5560,7 +5560,7 @@
(define_insn "*lea_4_zext"
[(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI
- (match_operand:SI 1 "lea_address_operand" "p")))]
+ (match_operand:SI 1 "lea_address_operand" "j")))]
"TARGET_64BIT"
"lea{l}\t{%a1, %k0|%k0, %a1}"
[(set_attr "type" "lea")
@@ -11736,6 +11736,7 @@
[(simple_return)]
"ix86_can_use_return_insn_p ()"
{
+ ix86_maybe_emit_epilogue_vzeroupper ();
if (crtl->args.pops_args)
{
rtx popc = GEN_INT (crtl->args.pops_args);
@@ -11752,6 +11753,7 @@
[(simple_return)]
"!TARGET_SEH"
{
+ ix86_maybe_emit_epilogue_vzeroupper ();
if (crtl->args.pops_args)
{
rtx popc = GEN_INT (crtl->args.pops_args);
diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
index 6c516e7b869..e797362d2dc 100644
--- a/gcc/config/i386/i386.opt
+++ b/gcc/config/i386/i386.opt
@@ -324,6 +324,9 @@ Enum(stringop_alg) String(loop) Value(loop)
EnumValue
Enum(stringop_alg) String(unrolled_loop) Value(unrolled_loop)
+EnumValue
+Enum(stringop_alg) String(sse_loop) Value(sse_loop)
+
mtls-dialect=
Target RejectNegative Joined Var(ix86_tls_dialect) Enum(tls_dialect) Init(TLS_DIALECT_GNU)
Use given thread-local storage dialect
diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
index 3745b497c19..1dda585bfde 100644
--- a/gcc/config/i386/predicates.md
+++ b/gcc/config/i386/predicates.md
@@ -808,8 +808,9 @@
(match_operand 0 "const0_operand")))
;; Return true if op if a valid address for LEA, and does not contain
-;; a segment override.
-(define_predicate "lea_address_operand"
+;; a segment override. Defined as a special predicate to allow
+;; mode-less const_int operands pass to address_operand.
+(define_special_predicate "lea_address_operand"
(match_operand 0 "address_operand")
{
struct ix86_address parts;
diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md
index eff3158cb28..4938abffce5 100644
--- a/gcc/config/i386/sse.md
+++ b/gcc/config/i386/sse.md
@@ -7501,6 +7501,16 @@
(set_attr "prefix" "maybe_vex,orig,vex,maybe_vex,orig,orig")
(set_attr "mode" "V2SF,TI,TI,TI,V4SF,V2SF")])
+(define_expand "vec_dupv4si"
+ [(set (match_operand:V4SI 0 "register_operand" "")
+ (vec_duplicate:V4SI
+ (match_operand:SI 1 "nonimmediate_operand" "")))]
+ "TARGET_SSE"
+{
+ if (!TARGET_AVX)
+ operands[1] = force_reg (V4SImode, operands[1]);
+})
+
(define_insn "*vec_dupv4si"
[(set (match_operand:V4SI 0 "register_operand" "=x,x,x")
(vec_duplicate:V4SI
@@ -7517,6 +7527,16 @@
(set_attr "prefix" "maybe_vex,vex,orig")
(set_attr "mode" "TI,V4SF,V4SF")])
+(define_expand "vec_dupv2di"
+ [(set (match_operand:V2DI 0 "register_operand" "")
+ (vec_duplicate:V2DI
+ (match_operand:DI 1 "nonimmediate_operand" "")))]
+ "TARGET_SSE"
+{
+ if (!TARGET_AVX)
+ operands[1] = force_reg (V2DImode, operands[1]);
+})
+
(define_insn "*vec_dupv2di"
[(set (match_operand:V2DI 0 "register_operand" "=x,x,x,x")
(vec_duplicate:V2DI
diff --git a/gcc/config/pa/pa-linux.h b/gcc/config/pa/pa-linux.h
index 6c6cf210aa4..addc0e18c8b 100644
--- a/gcc/config/pa/pa-linux.h
+++ b/gcc/config/pa/pa-linux.h
@@ -136,3 +136,6 @@ along with GCC; see the file COPYING3. If not see
/* Linux always uses gas. */
#undef TARGET_GAS
#define TARGET_GAS 1
+
+#undef TARGET_SYNC_LIBCALL
+#define TARGET_SYNC_LIBCALL 1
diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c
index 66574bad2fa..134f1f88be8 100644
--- a/gcc/config/pa/pa.c
+++ b/gcc/config/pa/pa.c
@@ -5587,6 +5587,9 @@ pa_init_libfuncs (void)
set_conv_libfunc (ufloat_optab, TFmode, DImode,
"_U_Qfcnvxf_udbl_to_quad");
}
+
+ if (TARGET_SYNC_LIBCALL)
+ init_sync_libfuncs (UNITS_PER_WORD);
}
/* HP's millicode routines mean something special to the assembler.
diff --git a/gcc/config/pa/pa.h b/gcc/config/pa/pa.h
index 2f1295b0fbf..c52e3d50877 100644
--- a/gcc/config/pa/pa.h
+++ b/gcc/config/pa/pa.h
@@ -74,6 +74,11 @@ extern unsigned long total_code_bytes;
#define HPUX_LONG_DOUBLE_LIBRARY 0
#endif
+/* Linux kernel atomic operation support. */
+#ifndef TARGET_SYNC_LIBCALL
+#define TARGET_SYNC_LIBCALL 0
+#endif
+
/* The following three defines are potential target switches. The current
defines are optimal given the current capabilities of GAS and GNU ld. */
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 89b79abc2f3..87c84d9844e 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -6169,6 +6169,7 @@ rs6000_legitimize_reload_address (rtx x, enum machine_mode mode,
#if TARGET_MACHO
&& DEFAULT_ABI == ABI_DARWIN
&& (flag_pic || MACHO_DYNAMIC_NO_PIC_P)
+ && machopic_symbol_defined_p (x)
#else
&& DEFAULT_ABI == ABI_V4
&& !flag_pic
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index 331aa79aac0..93b0b6c70be 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -6787,7 +6787,7 @@
; register allocation so that it can allocate the memory slot if it
; needed
(define_insn_and_split "fix_trunc<mode>si2_stfiwx"
- [(set (match_operand:SI 0 "general_operand" "=rm")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
(fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "d")))
(clobber (match_scratch:DI 2 "=d"))]
"TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
@@ -6883,7 +6883,7 @@
}")
(define_insn_and_split "fixuns_trunc<mode>si2_stfiwx"
- [(set (match_operand:SI 0 "general_operand" "=rm")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
(unsigned_fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "d")))
(clobber (match_scratch:DI 2 "=d"))]
"TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT> && TARGET_FCTIWUZ
diff --git a/gcc/config/sh/linux.h b/gcc/config/sh/linux.h
index edfd99be652..7a75341cbd5 100644
--- a/gcc/config/sh/linux.h
+++ b/gcc/config/sh/linux.h
@@ -131,3 +131,7 @@ along with GCC; see the file COPYING3. If not see
#define SH_DIV_STRATEGY_DEFAULT SH_DIV_CALL2
#undef SH_DIV_STR_FOR_SIZE
#define SH_DIV_STR_FOR_SIZE "call2"
+
+/* Install the __sync libcalls. */
+#undef TARGET_INIT_LIBFUNCS
+#define TARGET_INIT_LIBFUNCS sh_init_sync_libfuncs
diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c
index 03c3c48c0e4..2545a63e724 100644
--- a/gcc/config/sh/sh.c
+++ b/gcc/config/sh/sh.c
@@ -302,6 +302,8 @@ static void sh_trampoline_init (rtx, tree, rtx);
static rtx sh_trampoline_adjust_address (rtx);
static void sh_conditional_register_usage (void);
static bool sh_legitimate_constant_p (enum machine_mode, rtx);
+
+static void sh_init_sync_libfuncs (void) ATTRIBUTE_UNUSED;
static const struct attribute_spec sh_attribute_table[] =
{
@@ -12499,4 +12501,10 @@ sh_legitimate_constant_p (enum machine_mode mode, rtx x)
enum sh_divide_strategy_e sh_div_strategy = SH_DIV_STRATEGY_DEFAULT;
+static void
+sh_init_sync_libfuncs (void)
+{
+ init_sync_libfuncs (UNITS_PER_WORD);
+}
+
#include "gt-sh.h"
diff --git a/gcc/config/sh/sh.h b/gcc/config/sh/sh.h
index cc26e05a764..1b98745866e 100644
--- a/gcc/config/sh/sh.h
+++ b/gcc/config/sh/sh.h
@@ -417,7 +417,23 @@ do { \
#define SH_DIV_STR_FOR_SIZE "call"
#endif
-#define DRIVER_SELF_SPECS "%{m2a:%{ml:%eSH2a does not support little-endian}}"
+/* SH2A does not support little-endian. Catch such combinations
+ taking into account the default configuration. */
+#if TARGET_ENDIAN_DEFAULT == MASK_BIG_ENDIAN
+#define IS_LITTLE_ENDIAN_OPTION "%{ml:"
+#else
+#define IS_LITTLE_ENDIAN_OPTION "%{!mb:"
+#endif
+
+#if TARGET_CPU_DEFAULT & MASK_HARD_SH2A
+#define UNSUPPORTED_SH2A IS_LITTLE_ENDIAN_OPTION \
+"%{m2a*|!m1:%{!m2*:%{!m3*:%{!m4*:{!m5*:%eSH2a does not support little-endian}}}}}}"
+#else
+#define UNSUPPORTED_SH2A IS_LITTLE_ENDIAN_OPTION \
+"%{m2a*:%eSH2a does not support little-endian}}"
+#endif
+
+#define DRIVER_SELF_SPECS UNSUPPORTED_SH2A
#define ASSEMBLER_DIALECT assembler_dialect
diff --git a/gcc/config/sparc/linux.h b/gcc/config/sparc/linux.h
index 443c7966405..60dc86976e3 100644
--- a/gcc/config/sparc/linux.h
+++ b/gcc/config/sparc/linux.h
@@ -118,15 +118,6 @@ do { \
#undef LOCAL_LABEL_PREFIX
#define LOCAL_LABEL_PREFIX "."
-/* This is how to store into the string LABEL
- the symbol_ref name of an internal numbered label where
- PREFIX is the class of label and NUM is the number within the class.
- This is suitable for output with `assemble_name'. */
-
-#undef ASM_GENERATE_INTERNAL_LABEL
-#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \
- sprintf (LABEL, "*.L%s%ld", PREFIX, (long)(NUM))
-
/* Define for support of TFmode long double.
SPARC ABI says that long double is 4 words. */
diff --git a/gcc/config/sparc/linux64.h b/gcc/config/sparc/linux64.h
index bec279de8c9..14966b97fc3 100644
--- a/gcc/config/sparc/linux64.h
+++ b/gcc/config/sparc/linux64.h
@@ -236,15 +236,6 @@ do { \
#undef LOCAL_LABEL_PREFIX
#define LOCAL_LABEL_PREFIX "."
-/* This is how to store into the string LABEL
- the symbol_ref name of an internal numbered label where
- PREFIX is the class of label and NUM is the number within the class.
- This is suitable for output with `assemble_name'. */
-
-#undef ASM_GENERATE_INTERNAL_LABEL
-#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \
- sprintf (LABEL, "*.L%s%ld", PREFIX, (long)(NUM))
-
/* DWARF bits. */
/* Follow Irix 6 and not the Dwarf2 draft in using 64-bit offsets.
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index 1f2a27ab1ce..55759a03bd1 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -11285,357 +11285,88 @@ output_v8plus_mult (rtx insn, rtx *operands, const char *opcode)
}
}
-/* Subroutine of sparc_expand_vector_init. Emit code to initialize TARGET to
- the N_ELTS values for individual fields contained in LOCS by means of VIS2
- BSHUFFLE insn. MODE and INNER_MODE are the modes describing TARGET. */
+/* Subroutine of sparc_expand_vector_init. Emit code to initialize
+ all fields of TARGET to ELT by means of VIS2 BSHUFFLE insn. MODE
+ and INNER_MODE are the modes describing TARGET. */
static void
-vector_init_bshuffle (rtx target, rtx *locs, int n_elts,
- enum machine_mode mode,
+vector_init_bshuffle (rtx target, rtx elt, enum machine_mode mode,
enum machine_mode inner_mode)
{
- rtx mid_target, r0_high, r0_low, r1_high, r1_low;
- enum machine_mode partial_mode;
- int bmask, i, idxs[8];
+ rtx t1, final_insn;
+ int bmask;
- partial_mode = (mode == V4HImode
- ? V2HImode
- : (mode == V8QImode
- ? V4QImode : mode));
+ t1 = gen_reg_rtx (mode);
- r0_high = r0_low = NULL_RTX;
- r1_high = r1_low = NULL_RTX;
+ elt = convert_modes (SImode, inner_mode, elt, true);
+ emit_move_insn (gen_lowpart(SImode, t1), elt);
- /* Move the pieces into place, as needed, and calculate the nibble
- indexes for the bmask calculation. After we execute this loop the
- locs[] array is no longer needed. Therefore, to simplify things,
- we set entries that have been processed already to NULL_RTX. */
-
- for (i = 0; i < n_elts; i++)
- {
- int j;
-
- if (locs[i] == NULL_RTX)
- continue;
-
- if (!r0_low)
- {
- r0_low = locs[i];
- idxs[i] = 0x7;
- }
- else if (!r1_low)
- {
- r1_low = locs[i];
- idxs[i] = 0xf;
- }
- else if (!r0_high)
- {
- r0_high = gen_highpart (partial_mode, r0_low);
- emit_move_insn (r0_high, gen_lowpart (partial_mode, locs[i]));
- idxs[i] = 0x3;
- }
- else if (!r1_high)
- {
- r1_high = gen_highpart (partial_mode, r1_low);
- emit_move_insn (r1_high, gen_lowpart (partial_mode, locs[i]));
- idxs[i] = 0xb;
- }
- else
- gcc_unreachable ();
-
- for (j = i + 1; j < n_elts; j++)
- {
- if (locs[j] == locs[i])
- {
- locs[j] = NULL_RTX;
- idxs[j] = idxs[i];
- }
- }
- locs[i] = NULL_RTX;
- }
-
- bmask = 0;
- for (i = 0; i < n_elts; i++)
- {
- int v = idxs[i];
-
- switch (GET_MODE_SIZE (inner_mode))
- {
- case 2:
- bmask <<= 8;
- bmask |= (((v - 1) << 4) | v);
- break;
-
- case 1:
- bmask <<= 4;
- bmask |= v;
- break;
-
- default:
- gcc_unreachable ();
- }
- }
-
- emit_insn (gen_bmasksi_vis (gen_reg_rtx (SImode), CONST0_RTX (SImode),
- force_reg (SImode, GEN_INT (bmask))));
-
- mid_target = target;
- if (GET_MODE_SIZE (mode) == 4)
- {
- mid_target = gen_reg_rtx (mode == V2HImode
- ? V4HImode : V8QImode);
- }
-
- if (!r1_low)
- r1_low = r0_low;
-
- switch (GET_MODE (mid_target))
+ switch (mode)
{
+ case V2SImode:
+ final_insn = gen_bshufflev2si_vis (target, t1, t1);
+ bmask = 0x45674567;
+ break;
case V4HImode:
- emit_insn (gen_bshufflev4hi_vis (mid_target, r0_low, r1_low));
+ final_insn = gen_bshufflev4hi_vis (target, t1, t1);
+ bmask = 0x67676767;
break;
case V8QImode:
- emit_insn (gen_bshufflev8qi_vis (mid_target, r0_low, r1_low));
+ final_insn = gen_bshufflev8qi_vis (target, t1, t1);
+ bmask = 0x77777777;
break;
default:
gcc_unreachable ();
}
- if (mid_target != target)
- emit_move_insn (target, gen_lowpart (partial_mode, mid_target));
-}
-
-/* Subroutine of sparc_expand_vector_init. Emit code to initialize TARGET to
- values for individual fields VALS by means of simple word moves if this is
- possible. MODE and INNER_MODE are the modes describing TARGET. Return true
- on success. */
-
-static bool
-vector_init_move_words (rtx target, rtx vals, enum machine_mode mode,
- enum machine_mode inner_mode)
-{
- switch (mode)
- {
- case V1SImode:
- case V1DImode:
- emit_move_insn (gen_lowpart (inner_mode, target),
- gen_lowpart (inner_mode, XVECEXP (vals, 0, 0)));
- return true;
-
- case V2SImode:
- emit_move_insn (gen_highpart (SImode, target), XVECEXP (vals, 0, 0));
- emit_move_insn (gen_lowpart (SImode, target), XVECEXP (vals, 0, 1));
- return true;
-
- default:
- break;
- }
- return false;
+ emit_insn (gen_bmasksi_vis (gen_reg_rtx (SImode), CONST0_RTX (SImode),
+ force_reg (SImode, GEN_INT (bmask))));
+ emit_insn (final_insn);
}
-/* Subroutine of sparc_expand_vector_init. Move the N_ELTS elements in VALS
- into registers compatible with MODE and INNER_MODE. Store the RTX for
- these regs into the corresponding array entry of LOCS. */
-
static void
-vector_init_prepare_elts (rtx *locs, rtx vals, int n_elts,
- enum machine_mode mode,
- enum machine_mode inner_mode)
+vector_init_fpmerge (rtx target, rtx elt, enum machine_mode inner_mode)
{
- enum machine_mode loc_mode;
- int i;
+ rtx t1, t2, t3, t3_low;
- switch (mode)
- {
- case V2HImode:
- loc_mode = V4HImode;
- break;
+ t1 = gen_reg_rtx (V4QImode);
+ elt = convert_modes (SImode, inner_mode, elt, true);
+ emit_move_insn (gen_lowpart (SImode, t1), elt);
- case V4QImode:
- loc_mode = V8QImode;
- break;
+ t2 = gen_reg_rtx (V4QImode);
+ emit_move_insn (t2, t1);
- case V4HImode:
- case V8QImode:
- loc_mode = mode;
- break;
-
- default:
- gcc_unreachable ();
- }
+ t3 = gen_reg_rtx (V8QImode);
+ t3_low = gen_lowpart (V4QImode, t3);
- gcc_assert (GET_MODE_SIZE (inner_mode) <= 4);
- for (i = 0; i < n_elts; i++)
- {
- rtx dst, elt = XVECEXP (vals, 0, i);
- int j;
-
- /* Did we see this already? If so just record it's location. */
- dst = NULL_RTX;
- for (j = 0; j < i; j++)
- {
- if (XVECEXP (vals, 0, j) == elt)
- {
- dst = locs[j];
- break;
- }
- }
-
- if (! dst)
- {
- enum rtx_code code = GET_CODE (elt);
+ emit_insn (gen_fpmerge_vis (t3, t1, t2));
+ emit_move_insn (t1, t3_low);
+ emit_move_insn (t2, t3_low);
- dst = gen_reg_rtx (loc_mode);
+ emit_insn (gen_fpmerge_vis (t3, t1, t2));
+ emit_move_insn (t1, t3_low);
+ emit_move_insn (t2, t3_low);
- /* We use different strategies based upon whether the element
- is in memory or in a register. When we start in a register
- and we're VIS3 capable, it's always cheaper to use the VIS3
- int-->fp register moves since we avoid having to use stack
- memory. */
- if ((TARGET_VIS3 && (code == REG || code == SUBREG))
- || (CONSTANT_P (elt)
- && (const_zero_operand (elt, inner_mode)
- || const_all_ones_operand (elt, inner_mode))))
- {
- elt = convert_modes (SImode, inner_mode, elt, true);
-
- emit_clobber (dst);
- emit_move_insn (gen_lowpart (SImode, dst), elt);
- }
- else
- {
- rtx m = elt;
-
- if (CONSTANT_P (elt))
- {
- m = force_const_mem (inner_mode, elt);
- }
- else if (code != MEM)
- {
- rtx stk
- = assign_stack_temp (inner_mode, GET_MODE_SIZE(inner_mode),
- 0);
- emit_move_insn (stk, elt);
- m = stk;
- }
-
- switch (loc_mode)
- {
- case V4HImode:
- emit_insn (gen_zero_extend_v4hi_vis (dst, m));
- break;
- case V8QImode:
- emit_insn (gen_zero_extend_v8qi_vis (dst, m));
- break;
- default:
- gcc_unreachable ();
- }
- }
- }
- locs[i] = dst;
- }
+ emit_insn (gen_fpmerge_vis (gen_lowpart (V8QImode, target), t1, t2));
}
-/* Subroutine of sparc_expand_vector_init. Emit code to initialize TARGET to
- the N_ELTS values for individual fields contained in LOCS by means of VIS2
- instructions, among which N_UNIQUE are unique. MODE and INNER_MODE are the
- modes describing TARGET. */
-
static void
-sparc_expand_vector_init_vis2 (rtx target, rtx *locs, int n_elts, int n_unique,
- enum machine_mode mode,
- enum machine_mode inner_mode)
+vector_init_faligndata (rtx target, rtx elt, enum machine_mode inner_mode)
{
- if (n_unique <= 4)
- {
- vector_init_bshuffle (target, locs, n_elts, mode, inner_mode);
- }
- else
- {
- int i;
+ rtx t1 = gen_reg_rtx (V4HImode);
- gcc_assert (mode == V8QImode);
+ elt = convert_modes (SImode, inner_mode, elt, true);
- emit_insn (gen_alignaddrsi_vis (gen_reg_rtx (SImode),
- force_reg (SImode, GEN_INT (7)),
- CONST0_RTX (SImode)));
- i = n_elts - 1;
- emit_insn (gen_faligndatav8qi_vis (target, locs[i], locs[i]));
- while (--i >= 0)
- emit_insn (gen_faligndatav8qi_vis (target, locs[i], target));
- }
-}
-
-/* Subroutine of sparc_expand_vector_init. Emit code to initialize TARGET to
- the N_ELTS values for individual fields contained in LOCS by means of VIS1
- instructions, among which N_UNIQUE are unique. MODE is TARGET's mode. */
-
-static void
-sparc_expand_vector_init_vis1 (rtx target, rtx *locs, int n_elts, int n_unique,
- enum machine_mode mode)
-{
- enum machine_mode full_mode = mode;
- rtx (*emitter)(rtx, rtx, rtx);
- int alignaddr_val, i;
- rtx tmp = target;
-
- if (n_unique == 1 && mode == V8QImode)
- {
- rtx t2, t2_low, t1;
-
- t1 = gen_reg_rtx (V4QImode);
- emit_move_insn (t1, gen_lowpart (V4QImode, locs[0]));
-
- t2 = gen_reg_rtx (V8QImode);
- t2_low = gen_lowpart (V4QImode, t2);
-
- /* xxxxxxAA --> xxxxxxxxxxxxAAAA
- xxxxAAAA --> xxxxxxxxAAAAAAAA
- AAAAAAAA --> AAAAAAAAAAAAAAAA */
- emit_insn (gen_fpmerge_vis (t2, t1, t1));
- emit_move_insn (t1, t2_low);
- emit_insn (gen_fpmerge_vis (t2, t1, t1));
- emit_move_insn (t1, t2_low);
- emit_insn (gen_fpmerge_vis (target, t1, t1));
- return;
- }
-
- switch (mode)
- {
- case V2HImode:
- full_mode = V4HImode;
- /* FALLTHRU */
- case V4HImode:
- emitter = gen_faligndatav4hi_vis;
- alignaddr_val = 6;
- break;
-
- case V4QImode:
- full_mode = V8QImode;
- /* FALLTHRU */
- case V8QImode:
- emitter = gen_faligndatav8qi_vis;
- alignaddr_val = 7;
- break;
-
- default:
- gcc_unreachable ();
- }
-
- if (full_mode != mode)
- tmp = gen_reg_rtx (full_mode);
+ emit_move_insn (gen_lowpart (SImode, t1), elt);
emit_insn (gen_alignaddrsi_vis (gen_reg_rtx (SImode),
- force_reg (SImode, GEN_INT (alignaddr_val)),
+ force_reg (SImode, GEN_INT (6)),
CONST0_RTX (SImode)));
- i = n_elts - 1;
- emit_insn (emitter (tmp, locs[i], locs[i]));
- while (--i >= 0)
- emit_insn (emitter (tmp, locs[i], tmp));
-
- if (tmp != target)
- emit_move_insn (target, gen_highpart (mode, tmp));
+ emit_insn (gen_faligndatav4hi_vis (target, t1, target));
+ emit_insn (gen_faligndatav4hi_vis (target, t1, target));
+ emit_insn (gen_faligndatav4hi_vis (target, t1, target));
+ emit_insn (gen_faligndatav4hi_vis (target, t1, target));
}
/* Emit code to initialize TARGET to values for individual fields VALS. */
@@ -11646,30 +11377,19 @@ sparc_expand_vector_init (rtx target, rtx vals)
enum machine_mode mode = GET_MODE (target);
enum machine_mode inner_mode = GET_MODE_INNER (mode);
int n_elts = GET_MODE_NUNITS (mode);
- int i, n_var = 0, n_unique = 0;
- rtx locs[8];
-
- gcc_assert (n_elts <= 8);
+ int i, n_var = 0;
+ bool all_same;
+ rtx mem;
+ all_same = true;
for (i = 0; i < n_elts; i++)
{
rtx x = XVECEXP (vals, 0, i);
- bool found = false;
- int j;
-
if (!CONSTANT_P (x))
n_var++;
- for (j = 0; j < i; j++)
- {
- if (rtx_equal_p (x, XVECEXP (vals, 0, j)))
- {
- found = true;
- break;
- }
- }
- if (!found)
- n_unique++;
+ if (i > 0 && !rtx_equal_p (x, XVECEXP (vals, 0, 0)))
+ all_same = false;
}
if (n_var == 0)
@@ -11678,16 +11398,56 @@ sparc_expand_vector_init (rtx target, rtx vals)
return;
}
- if (vector_init_move_words (target, vals, mode, inner_mode))
- return;
+ if (GET_MODE_SIZE (inner_mode) == GET_MODE_SIZE (mode))
+ {
+ if (GET_MODE_SIZE (inner_mode) == 4)
+ {
+ emit_move_insn (gen_lowpart (SImode, target),
+ gen_lowpart (SImode, XVECEXP (vals, 0, 0)));
+ return;
+ }
+ else if (GET_MODE_SIZE (inner_mode) == 8)
+ {
+ emit_move_insn (gen_lowpart (DImode, target),
+ gen_lowpart (DImode, XVECEXP (vals, 0, 0)));
+ return;
+ }
+ }
+ else if (GET_MODE_SIZE (inner_mode) == GET_MODE_SIZE (word_mode)
+ && GET_MODE_SIZE (mode) == 2 * GET_MODE_SIZE (word_mode))
+ {
+ emit_move_insn (gen_highpart (word_mode, target),
+ gen_lowpart (word_mode, XVECEXP (vals, 0, 0)));
+ emit_move_insn (gen_lowpart (word_mode, target),
+ gen_lowpart (word_mode, XVECEXP (vals, 0, 1)));
+ return;
+ }
- vector_init_prepare_elts (locs, vals, n_elts, mode, inner_mode);
+ if (all_same && GET_MODE_SIZE (mode) == 8)
+ {
+ if (TARGET_VIS2)
+ {
+ vector_init_bshuffle (target, XVECEXP (vals, 0, 0), mode, inner_mode);
+ return;
+ }
+ if (mode == V8QImode)
+ {
+ vector_init_fpmerge (target, XVECEXP (vals, 0, 0), inner_mode);
+ return;
+ }
+ if (mode == V4HImode)
+ {
+ vector_init_faligndata (target, XVECEXP (vals, 0, 0), inner_mode);
+ return;
+ }
+ }
- if (TARGET_VIS2)
- sparc_expand_vector_init_vis2 (target, locs, n_elts, n_unique,
- mode, inner_mode);
- else
- sparc_expand_vector_init_vis1 (target, locs, n_elts, n_unique, mode);
+ mem = assign_stack_temp (mode, GET_MODE_SIZE (mode), 0);
+ for (i = 0; i < n_elts; i++)
+ emit_move_insn (adjust_address_nv (mem, inner_mode,
+ i * GET_MODE_SIZE (inner_mode)),
+ XVECEXP (vals, 0, i));
+ emit_move_insn (target, mem);
}
/* Implement TARGET_SECONDARY_RELOAD. */
diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md
index bf750b29e42..c059dc5e730 100644
--- a/gcc/config/sparc/sparc.md
+++ b/gcc/config/sparc/sparc.md
@@ -7830,60 +7830,6 @@
DONE;
})
-(define_expand "zero_extend_v8qi_vis"
- [(set (match_operand:V8QI 0 "register_operand" "")
- (vec_merge:V8QI
- (vec_duplicate:V8QI
- (match_operand:QI 1 "memory_operand" ""))
- (match_dup 2)
- (const_int 254)))]
- "TARGET_VIS"
-{
- if (! REG_P (XEXP (operands[1], 0)))
- {
- rtx addr = force_reg (Pmode, XEXP (operands[1], 0));
- operands[1] = replace_equiv_address (operands[1], addr);
- }
- operands[2] = CONST0_RTX (V8QImode);
-})
-
-(define_expand "zero_extend_v4hi_vis"
- [(set (match_operand:V4HI 0 "register_operand" "")
- (vec_merge:V4HI
- (vec_duplicate:V4HI
- (match_operand:HI 1 "memory_operand" ""))
- (match_dup 2)
- (const_int 14)))]
- "TARGET_VIS"
-{
- if (! REG_P (XEXP (operands[1], 0)))
- {
- rtx addr = force_reg (Pmode, XEXP (operands[1], 0));
- operands[1] = replace_equiv_address (operands[1], addr);
- }
- operands[2] = CONST0_RTX (V4HImode);
-})
-
-(define_insn "*zero_extend_v8qi_<P:mode>_insn"
- [(set (match_operand:V8QI 0 "register_operand" "=e")
- (vec_merge:V8QI
- (vec_duplicate:V8QI
- (mem:QI (match_operand:P 1 "register_operand" "r")))
- (match_operand:V8QI 2 "const_zero_operand" "Y")
- (const_int 254)))]
- "TARGET_VIS"
- "ldda\t[%1] 0xd0, %0")
-
-(define_insn "*zero_extend_v4hi_<P:mode>_insn"
- [(set (match_operand:V4HI 0 "register_operand" "=e")
- (vec_merge:V4HI
- (vec_duplicate:V4HI
- (mem:HI (match_operand:P 1 "register_operand" "r")))
- (match_operand:V4HI 2 "const_zero_operand" "Y")
- (const_int 14)))]
- "TARGET_VIS"
- "ldda\t[%1] 0xd2, %0")
-
(define_expand "vec_init<mode>"
[(match_operand:VMALL 0 "register_operand" "")
(match_operand:VMALL 1 "" "")]
diff --git a/gcc/configure b/gcc/configure
index 99334ce44fd..d8654121837 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -10453,7 +10453,7 @@ CFLAGS="$CFLAGS -I${srcdir} -I${srcdir}/../include"
saved_CXXFLAGS="$CXXFLAGS"
CXXFLAGS="$CXXFLAGS -I${srcdir} -I${srcdir}/../include"
for ac_func in getenv atol asprintf sbrk abort atof getcwd getwd \
- strsignal strstr strverscmp \
+ strsignal strstr stpcpy strverscmp \
errno snprintf vsnprintf vasprintf malloc realloc calloc \
free basename getopt clock getpagesize clearerr_unlocked feof_unlocked ferror_unlocked fflush_unlocked fgetc_unlocked fgets_unlocked fileno_unlocked fprintf_unlocked fputc_unlocked fputs_unlocked fread_unlocked fwrite_unlocked getchar_unlocked getc_unlocked putchar_unlocked putc_unlocked
do
diff --git a/gcc/configure.ac b/gcc/configure.ac
index c7654259c4a..af5b748b0f5 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -1102,7 +1102,7 @@ CFLAGS="$CFLAGS -I${srcdir} -I${srcdir}/../include"
saved_CXXFLAGS="$CXXFLAGS"
CXXFLAGS="$CXXFLAGS -I${srcdir} -I${srcdir}/../include"
gcc_AC_CHECK_DECLS(getenv atol asprintf sbrk abort atof getcwd getwd \
- strsignal strstr strverscmp \
+ strsignal strstr stpcpy strverscmp \
errno snprintf vsnprintf vasprintf malloc realloc calloc \
free basename getopt clock getpagesize gcc_UNLOCKED_FUNCS, , ,[
#include "ansidecl.h"
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 9c5a2bcc142..a33332cc6a9 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,51 @@
+2011-11-12 Jason Merrill <jason@redhat.com>
+
+ PR c++/986
+ * call.c (set_up_extended_ref_temp): Warn about references
+ bound to non-static reference members.
+ * init.c (perform_member_init): Pass in the member.
+
+ PR c++/51060
+ * cp-gimplify.c (cp_gimplify_expr): Leave clobbers alone.
+
+2011-11-11 Ed Smith-Rowland <3dw4rd@verizon.net>
+
+ PR c++/50976
+ * typeck.c (check_literal_operator_args): Reorganize test for string
+ operators so size_t search depends on finding string first.
+
+2011-11-10 Jason Merrill <jason@redhat.com>
+
+ PR c++/50372
+ * pt.c (convert_nontype_argument_function): Allow decls with
+ internal linkage in C++11.
+ (convert_nontype_argument): Likewise.
+
+ PR c++/50973
+ * decl2.c (mark_used): Defer synthesis of virtual functions.
+ * method.c (use_thunk): Make sure the target function has
+ DECL_INTERFACE_KNOWN.
+
+ PR c++/51079, DR 495
+ * call.c (joust): Check the second conversion sequence
+ before checking templates.
+
+2011-11-09 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/50837
+ * pt.c (tsubst_copy_and_build) [IDENTIFIER_NODE]: In C++11 mode
+ pass allow_non_integral_constant_expression_p = true to
+ finish_id_expression.
+
2011-11-09 Jason Merrill <jason@redhat.com>
+ PR c++/50972
+ * pt.c (maybe_instantiate_noexcept): Check the return value of
+ push_tinst_level.
+
+ PR c++/51046
+ * parser.c (cp_parser_range_for): check_for_bare_parameter_packs.
+
PR c++/51029
* class.c (build_base_path): Don't ICE in fold_non_dependent_expr.
@@ -41,6 +87,10 @@
2011-11-09 Dodji Seketeli <dodji@redhat.com>
+ PR c++/51043
+ * cp-tree.h (TYPE_ALIAS_P, TYPE_TEMPLATE_INFO): Don't crash on
+ NULL TYPE_NAME.
+
PR c++/51027
* parser.c (cp_parser_alias_declaration): Require ';' at the end
of the declaration.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 578905e41e6..ab0654273a3 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -8109,6 +8109,22 @@ joust (struct z_candidate *cand1, struct z_candidate *cand2, bool warn)
if (winner)
return winner;
+ /* DR 495 moved this tiebreaker above the template ones. */
+ /* or, if not that,
+ the context is an initialization by user-defined conversion (see
+ _dcl.init_ and _over.match.user_) and the standard conversion
+ sequence from the return type of F1 to the destination type (i.e.,
+ the type of the entity being initialized) is a better conversion
+ sequence than the standard conversion sequence from the return type
+ of F2 to the destination type. */
+
+ if (cand1->second_conv)
+ {
+ winner = compare_ics (cand1->second_conv, cand2->second_conv);
+ if (winner)
+ return winner;
+ }
+
/* or, if not that,
F1 is a non-template function and F2 is a template function
specialization. */
@@ -8137,21 +8153,6 @@ joust (struct z_candidate *cand1, struct z_candidate *cand2, bool warn)
return winner;
}
- /* or, if not that,
- the context is an initialization by user-defined conversion (see
- _dcl.init_ and _over.match.user_) and the standard conversion
- sequence from the return type of F1 to the destination type (i.e.,
- the type of the entity being initialized) is a better conversion
- sequence than the standard conversion sequence from the return type
- of F2 to the destination type. */
-
- if (cand1->second_conv)
- {
- winner = compare_ics (cand1->second_conv, cand2->second_conv);
- if (winner)
- return winner;
- }
-
/* Check whether we can discard a builtin candidate, either because we
have two identical ones or matching builtin and non-builtin candidates.
@@ -8606,6 +8607,14 @@ set_up_extended_ref_temp (tree decl, tree expr, VEC(tree,gc) **cleanups,
if (TREE_CODE (expr) != TARGET_EXPR)
expr = get_target_expr (expr);
+ if (TREE_CODE (decl) == FIELD_DECL
+ && extra_warnings && !TREE_NO_WARNING (decl))
+ {
+ warning (OPT_Wextra, "a temporary bound to %qD only persists "
+ "until the constructor exits", decl);
+ TREE_NO_WARNING (decl) = true;
+ }
+
/* Recursively extend temps in this initializer. */
TARGET_EXPR_INITIAL (expr)
= extend_ref_init_temps (decl, TARGET_EXPR_INITIAL (expr), cleanups);
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index af45f591846..9968c3dd7ee 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -569,7 +569,8 @@ cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
else if ((is_gimple_lvalue (op1) || INDIRECT_REF_P (op1)
|| (TREE_CODE (op1) == CONSTRUCTOR
- && CONSTRUCTOR_NELTS (op1) == 0)
+ && CONSTRUCTOR_NELTS (op1) == 0
+ && !TREE_CLOBBER_P (op1))
|| (TREE_CODE (op1) == CALL_EXPR
&& !CALL_EXPR_RETURN_SLOT_OPT (op1)))
&& is_really_empty_class (TREE_TYPE (op0)))
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 5ba18856d16..b306976c62c 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -2550,8 +2550,9 @@ extern void decl_shadowed_for_var_insert (tree, tree);
/* Nonzero for a type which is an alias for another type; i.e, a type
which declaration was written 'using name-of-type =
another-type'. */
-#define TYPE_ALIAS_P(NODE) \
- (TYPE_P (NODE) \
+#define TYPE_ALIAS_P(NODE) \
+ (TYPE_P (NODE) \
+ && TYPE_NAME (NODE) \
&& TYPE_DECL_ALIAS_P (TYPE_NAME (NODE)))
/* For a class type: if this structure has many fields, we'll sort them
@@ -2605,15 +2606,15 @@ extern void decl_shadowed_for_var_insert (tree, tree);
->template_info)
/* Template information for an ENUMERAL_, RECORD_, or UNION_TYPE. */
-#define TYPE_TEMPLATE_INFO(NODE) \
- (TREE_CODE (NODE) == ENUMERAL_TYPE \
- ? ENUM_TEMPLATE_INFO (NODE) : \
- (TREE_CODE (NODE) == BOUND_TEMPLATE_TEMPLATE_PARM \
- ? TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (NODE) : \
- ((CLASS_TYPE_P (NODE) && !TYPE_ALIAS_P (NODE)) \
- ? CLASSTYPE_TEMPLATE_INFO (NODE) \
- : (DECL_LANG_SPECIFIC (TYPE_NAME (NODE)) \
- ? (DECL_TEMPLATE_INFO (TYPE_NAME (NODE))) \
+#define TYPE_TEMPLATE_INFO(NODE) \
+ (TREE_CODE (NODE) == ENUMERAL_TYPE \
+ ? ENUM_TEMPLATE_INFO (NODE) : \
+ (TREE_CODE (NODE) == BOUND_TEMPLATE_TEMPLATE_PARM \
+ ? TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (NODE) : \
+ ((CLASS_TYPE_P (NODE) && !TYPE_ALIAS_P (NODE)) \
+ ? CLASSTYPE_TEMPLATE_INFO (NODE) \
+ : ((TYPE_NAME (NODE) && DECL_LANG_SPECIFIC (TYPE_NAME (NODE))) \
+ ? (DECL_TEMPLATE_INFO (TYPE_NAME (NODE))) \
: NULL_TREE))))
/* Set the template information for an ENUMERAL_, RECORD_, or
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 4e24755e2a5..05f4b42ac73 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -4347,6 +4347,14 @@ mark_used (tree decl)
&& !DECL_DEFAULTED_OUTSIDE_CLASS_P (decl)
&& ! DECL_INITIAL (decl))
{
+ /* Defer virtual destructors so that thunks get the right
+ linkage. */
+ if (DECL_VIRTUAL_P (decl) && !at_eof)
+ {
+ note_vague_linkage_fn (decl);
+ return true;
+ }
+
/* Remember the current location for a function we will end up
synthesizing. Then we can inform the user where it was
required in the case of error. */
@@ -4358,7 +4366,7 @@ mark_used (tree decl)
on the stack (such as overload resolution candidates).
We could just let cp_write_global_declarations handle synthesizing
- this function, since we just added it to deferred_fns, but doing
+ this function by adding it to deferred_fns, but doing
it at the use site produces better error messages. */
++function_depth;
synthesize_method (decl);
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 77fe42e4dc6..5c20e32a79f 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -599,7 +599,7 @@ perform_member_init (tree member, tree init)
if (init == error_mark_node)
return;
/* Use 'this' as the decl, as it has the lifetime we want. */
- init = extend_ref_init_temps (current_class_ptr, init, &cleanups);
+ init = extend_ref_init_temps (member, init, &cleanups);
if (TREE_CODE (type) == ARRAY_TYPE
&& TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (type)))
init = build_vec_init_expr (type, init, tf_warning_or_error);
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index bb58312b689..8101f8a11c7 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -339,6 +339,7 @@ use_thunk (tree thunk_fndecl, bool emit_p)
DECL_EXTERNAL (thunk_fndecl) = 0;
/* The linkage of the function may have changed. FIXME in linkage
rewrite. */
+ gcc_assert (DECL_INTERFACE_KNOWN (function));
TREE_PUBLIC (thunk_fndecl) = TREE_PUBLIC (function);
DECL_VISIBILITY (thunk_fndecl) = DECL_VISIBILITY (function);
DECL_VISIBILITY_SPECIFIED (thunk_fndecl)
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 3cb6dbf61a0..fc8f3c82bac 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -9292,6 +9292,8 @@ cp_parser_range_for (cp_parser *parser, tree scope, tree init, tree range_decl)
at instantiation. If not, it is done just ahead. */
if (processing_template_decl)
{
+ if (check_for_bare_parameter_packs (range_expr))
+ range_expr = error_mark_node;
stmt = begin_range_for_stmt (scope, init);
finish_range_for_decl (stmt, range_decl, range_expr);
if (!type_dependent_expression_p (range_expr)
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 71a98b0de19..97380260ae4 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -5324,6 +5324,7 @@ convert_nontype_argument_function (tree type, tree expr)
{
tree fns = expr;
tree fn, fn_no_ptr;
+ linkage_kind linkage;
fn = instantiate_type (type, fns, tf_none);
if (fn == error_mark_node)
@@ -5340,12 +5341,19 @@ convert_nontype_argument_function (tree type, tree expr)
A template-argument for a non-type, non-template template-parameter
shall be one of:
[...]
- -- the address of an object or function with external linkage. */
- if (!DECL_EXTERNAL_LINKAGE_P (fn_no_ptr))
+ -- the address of an object or function with external [C++11: or
+ internal] linkage. */
+ linkage = decl_linkage (fn_no_ptr);
+ if (cxx_dialect >= cxx0x ? linkage == lk_none : linkage != lk_external)
{
- error ("%qE is not a valid template argument for type %qT "
- "because function %qD has not external linkage",
- expr, type, fn_no_ptr);
+ if (cxx_dialect >= cxx0x)
+ error ("%qE is not a valid template argument for type %qT "
+ "because %qD has no linkage",
+ expr, type, fn_no_ptr);
+ else
+ error ("%qE is not a valid template argument for type %qT "
+ "because %qD does not have external linkage",
+ expr, type, fn_no_ptr);
return NULL_TREE;
}
@@ -5838,13 +5846,20 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
expr, type, decl);
return NULL_TREE;
}
- else if (!DECL_EXTERNAL_LINKAGE_P (decl))
+ else if (cxx_dialect < cxx0x && !DECL_EXTERNAL_LINKAGE_P (decl))
{
error ("%qE is not a valid template argument of type %qT "
"because %qD does not have external linkage",
expr, type, decl);
return NULL_TREE;
}
+ else if (cxx_dialect >= cxx0x && decl_linkage (decl) == lk_none)
+ {
+ error ("%qE is not a valid template argument of type %qT "
+ "because %qD has no linkage",
+ expr, type, decl);
+ return NULL_TREE;
+ }
}
expr = decay_conversion (expr);
@@ -13233,7 +13248,7 @@ tsubst_copy_and_build (tree t,
decl = finish_id_expression (t, decl, NULL_TREE,
&idk,
integral_constant_expression_p,
- /*allow_non_integral_constant_expression_p=*/false,
+ /*allow_non_integral_constant_expression_p=*/(cxx_dialect >= cxx0x),
&non_integral_constant_expression_p,
/*template_p=*/false,
/*done=*/true,
@@ -18166,17 +18181,22 @@ maybe_instantiate_noexcept (tree fn)
if (TREE_CODE (noex) == DEFERRED_NOEXCEPT)
{
- push_tinst_level (fn);
- push_access_scope (fn);
- input_location = DECL_SOURCE_LOCATION (fn);
- noex = tsubst_copy_and_build (DEFERRED_NOEXCEPT_PATTERN (noex),
- DEFERRED_NOEXCEPT_ARGS (noex),
- tf_warning_or_error, fn, /*function_p=*/false,
- /*integral_constant_expression_p=*/true);
- pop_access_scope (fn);
- pop_tinst_level ();
- spec = build_noexcept_spec (noex, tf_warning_or_error);
- if (spec == error_mark_node)
+ if (push_tinst_level (fn))
+ {
+ push_access_scope (fn);
+ input_location = DECL_SOURCE_LOCATION (fn);
+ noex = tsubst_copy_and_build (DEFERRED_NOEXCEPT_PATTERN (noex),
+ DEFERRED_NOEXCEPT_ARGS (noex),
+ tf_warning_or_error, fn,
+ /*function_p=*/false,
+ /*integral_constant_expression_p=*/true);
+ pop_access_scope (fn);
+ pop_tinst_level ();
+ spec = build_noexcept_spec (noex, tf_warning_or_error);
+ if (spec == error_mark_node)
+ spec = noexcept_false_spec;
+ }
+ else
spec = noexcept_false_spec;
}
else
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 2964952241a..722cec5b5b9 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -8425,9 +8425,6 @@ check_literal_operator_args (const_tree decl,
tree argtype;
int arity;
int max_arity = 2;
- bool found_string_p = false;
- bool maybe_raw_p = false;
- bool found_size_p = false;
*long_long_unsigned_p = false;
*long_double_p = false;
@@ -8442,29 +8439,30 @@ check_literal_operator_args (const_tree decl,
if (TREE_CODE (t) == POINTER_TYPE)
{
+ bool maybe_raw_p = false;
t = TREE_TYPE (t);
if (cp_type_quals (t) != TYPE_QUAL_CONST)
return false;
t = TYPE_MAIN_VARIANT (t);
- if (same_type_p (t, char_type_node))
+ if ((maybe_raw_p = same_type_p (t, char_type_node))
+ || same_type_p (t, wchar_type_node)
+ || same_type_p (t, char16_type_node)
+ || same_type_p (t, char32_type_node))
{
- found_string_p = true;
- maybe_raw_p = true;
+ argtype = TREE_CHAIN (argtype);
+ if (!argtype)
+ return false;
+ t = TREE_VALUE (argtype);
+ if (maybe_raw_p && argtype == void_list_node)
+ return true;
+ else if (same_type_p (t, size_type_node))
+ {
+ ++arity;
+ continue;
+ }
+ else
+ return false;
}
- else if (same_type_p (t, wchar_type_node))
- found_string_p = true;
- else if (same_type_p (t, char16_type_node))
- found_string_p = true;
- else if (same_type_p (t, char32_type_node))
- found_string_p = true;
- else
- return false;
- }
- else if (same_type_p (t, size_type_node))
- {
- if (!found_string_p)
- return false;
- found_size_p = true;
}
else if (same_type_p (t, long_long_unsigned_type_node))
{
@@ -8493,9 +8491,6 @@ check_literal_operator_args (const_tree decl,
if (arity > max_arity)
return false;
- if (found_string_p && !maybe_raw_p && !found_size_p)
- return false;
-
return true;
}
}
diff --git a/gcc/cprop.c b/gcc/cprop.c
index d90f769e546..9ee1efb1af6 100644
--- a/gcc/cprop.c
+++ b/gcc/cprop.c
@@ -69,7 +69,7 @@ typedef struct occr *occr_t;
DEF_VEC_P (occr_t);
DEF_VEC_ALLOC_P (occr_t, heap);
-/* Hash table entry for an assignment expressions. */
+/* Hash table entry for assignment expressions. */
struct expr
{
@@ -83,8 +83,8 @@ struct expr
struct expr *next_same_hash;
/* List of available occurrence in basic blocks in the function.
An "available occurrence" is one that is the last occurrence in the
- basic block and the operands are not modified by following statements in
- the basic block [including this insn]. */
+ basic block and whose operands are not modified by following statements
+ in the basic block [including this insn]. */
struct occr *avail_occr;
};
@@ -136,7 +136,6 @@ static int local_copy_prop_count;
static int global_const_prop_count;
/* Number of global copies propagated. */
static int global_copy_prop_count;
-
#define GOBNEW(T) ((T *) cprop_alloc (sizeof (T)))
#define GOBNEWVAR(T, S) ((T *) cprop_alloc ((S)))
@@ -256,14 +255,13 @@ cprop_constant_p (const_rtx x)
return CONSTANT_P (x) && (GET_CODE (x) != CONST || shared_const_p (x));
}
-/* Scan pattern PAT of INSN and add an entry to the hash TABLE (set or
- expression one). */
+/* Scan SET present in INSN and add an entry to the hash TABLE. */
static void
-hash_scan_set (rtx pat, rtx insn, struct hash_table_d *table)
+hash_scan_set (rtx set, rtx insn, struct hash_table_d *table)
{
- rtx src = SET_SRC (pat);
- rtx dest = SET_DEST (pat);
+ rtx src = SET_SRC (set);
+ rtx dest = SET_DEST (set);
if (REG_P (dest)
&& ! HARD_REGISTER_P (dest)
@@ -288,7 +286,7 @@ hash_scan_set (rtx pat, rtx insn, struct hash_table_d *table)
&& REG_NOTE_KIND (note) == REG_EQUAL
&& !REG_P (src)
&& cprop_constant_p (XEXP (note, 0)))
- src = XEXP (note, 0), pat = gen_rtx_SET (VOIDmode, dest, src);
+ src = XEXP (note, 0), set = gen_rtx_SET (VOIDmode, dest, src);
/* Record sets for constant/copy propagation. */
if ((REG_P (src)
@@ -300,16 +298,7 @@ hash_scan_set (rtx pat, rtx insn, struct hash_table_d *table)
}
}
-/* Process INSN and add hash table entries as appropriate.
-
- Only available expressions that set a single pseudo-reg are recorded.
-
- Single sets in a PARALLEL could be handled, but it's an extra complication
- that isn't dealt with right now. The trick is handling the CLOBBERs that
- are also in the PARALLEL. Later.
-
- If SET_P is nonzero, this is for the assignment hash table,
- otherwise it is for the expression hash table. */
+/* Process INSN and add hash table entries as appropriate. */
static void
hash_scan_insn (rtx insn, struct hash_table_d *table)
@@ -332,6 +321,8 @@ hash_scan_insn (rtx insn, struct hash_table_d *table)
}
}
+/* Dump the hash table TABLE to file FILE under the name NAME. */
+
static void
dump_hash_table (FILE *file, const char *name, struct hash_table_d *table)
{
@@ -373,6 +364,7 @@ dump_hash_table (FILE *file, const char *name, struct hash_table_d *table)
}
/* Record as unavailable all registers that are DEF operands of INSN. */
+
static void
make_set_regs_unavailable (rtx insn)
{
@@ -383,7 +375,7 @@ make_set_regs_unavailable (rtx insn)
SET_REGNO_REG_SET (reg_set_bitmap, DF_REF_REGNO (*def_rec));
}
-/* Top level function to create an assignments hash table.
+/* Top level function to create an assignment hash table.
Assignment entries are placed in the hash table if
- they are of the form (set (pseudo-reg) src),
@@ -541,13 +533,12 @@ mark_oprs_set (rtx insn)
for (def_rec = DF_INSN_INFO_DEFS (insn_info); *def_rec; def_rec++)
SET_REGNO_REG_SET (reg_set_bitmap, DF_REF_REGNO (*def_rec));
}
-
/* Compute copy/constant propagation working variables. */
/* Local properties of assignments. */
-static sbitmap *cprop_pavloc;
-static sbitmap *cprop_absaltered;
+static sbitmap *cprop_avloc;
+static sbitmap *cprop_kill;
/* Global properties of assignments (computed from the local properties). */
static sbitmap *cprop_avin;
@@ -559,8 +550,8 @@ static sbitmap *cprop_avout;
static void
alloc_cprop_mem (int n_blocks, int n_sets)
{
- cprop_pavloc = sbitmap_vector_alloc (n_blocks, n_sets);
- cprop_absaltered = sbitmap_vector_alloc (n_blocks, n_sets);
+ cprop_avloc = sbitmap_vector_alloc (n_blocks, n_sets);
+ cprop_kill = sbitmap_vector_alloc (n_blocks, n_sets);
cprop_avin = sbitmap_vector_alloc (n_blocks, n_sets);
cprop_avout = sbitmap_vector_alloc (n_blocks, n_sets);
@@ -571,8 +562,8 @@ alloc_cprop_mem (int n_blocks, int n_sets)
static void
free_cprop_mem (void)
{
- sbitmap_vector_free (cprop_pavloc);
- sbitmap_vector_free (cprop_absaltered);
+ sbitmap_vector_free (cprop_avloc);
+ sbitmap_vector_free (cprop_kill);
sbitmap_vector_free (cprop_avin);
sbitmap_vector_free (cprop_avout);
}
@@ -582,23 +573,23 @@ free_cprop_mem (void)
Local properties are those that are defined by the block, irrespective of
other blocks.
- An expression is transparent in a block if its operands are not modified
- in the block.
+ An expression is killed in a block if its operands, either DEST or SRC, are
+ modified in the block.
An expression is computed (locally available) in a block if it is computed
at least once and expression would contain the same value if the
computation was moved to the end of the block.
- TRANSP and COMP are destination sbitmaps for recording local properties. */
+ KILL and COMP are destination sbitmaps for recording local properties. */
static void
-compute_local_properties (sbitmap *transp, sbitmap *comp,
+compute_local_properties (sbitmap *kill, sbitmap *comp,
struct hash_table_d *table)
{
unsigned int i;
/* Initialize the bitmaps that were passed in. */
- sbitmap_vector_zero (transp, last_basic_block);
+ sbitmap_vector_zero (kill, last_basic_block);
sbitmap_vector_zero (comp, last_basic_block);
for (i = 0; i < table->size; i++)
@@ -611,20 +602,21 @@ compute_local_properties (sbitmap *transp, sbitmap *comp,
df_ref def;
struct occr *occr;
- /* The expression is transparent in a block if it is not killed,
- i.e. DEST and SRC are not set or clobbered in the block.
- We start by assuming all are transparent [none are killed],
- and then set the bits for those that are. */
+ /* For each definition of the destination pseudo-reg, the expression
+ is killed in the block where the definition is. */
for (def = DF_REG_DEF_CHAIN (REGNO (expr->dest));
def; def = DF_REF_NEXT_REG (def))
- SET_BIT (transp[DF_REF_BB (def)->index], indx);
+ SET_BIT (kill[DF_REF_BB (def)->index], indx);
+
+ /* If the source is a pseudo-reg, for each definition of the source,
+ the expression is killed in the block where the definition is. */
if (REG_P (expr->src))
for (def = DF_REG_DEF_CHAIN (REGNO (expr->src));
def; def = DF_REF_NEXT_REG (def))
- SET_BIT (transp[DF_REF_BB (def)->index], indx);
+ SET_BIT (kill[DF_REF_BB (def)->index], indx);
/* The occurrences recorded in avail_occr are exactly those that
- we want to set to nonzero in COMP. */
+ are locally available in the block where they are. */
for (occr = expr->avail_occr; occr != NULL; occr = occr->next)
{
SET_BIT (comp[BLOCK_FOR_INSN (occr->insn)->index], indx);
@@ -641,9 +633,8 @@ compute_local_properties (sbitmap *transp, sbitmap *comp,
static void
compute_cprop_data (void)
{
- compute_local_properties (cprop_absaltered, cprop_pavloc, &set_hash_table);
- compute_available (cprop_pavloc, cprop_absaltered,
- cprop_avout, cprop_avin);
+ compute_local_properties (cprop_kill, cprop_avloc, &set_hash_table);
+ compute_available (cprop_avloc, cprop_kill, cprop_avout, cprop_avin);
}
/* Copy/constant propagation. */
@@ -748,9 +739,9 @@ try_replace_reg (rtx from, rtx to, rtx insn)
simplify_replace_rtx (XEXP (note, 0), from, to));
if (!success && set && reg_mentioned_p (from, SET_SRC (set)))
{
- /* If above failed and this is a single set, try to simplify the source of
- the set given our substitution. We could perhaps try this for multiple
- SETs, but it probably won't buy us anything. */
+ /* If above failed and this is a single set, try to simplify the source
+ of the set given our substitution. We could perhaps try this for
+ multiple SETs, but it probably won't buy us anything. */
src = simplify_replace_rtx (SET_SRC (set), from, to);
if (!rtx_equal_p (src, SET_SRC (set))
@@ -770,7 +761,7 @@ try_replace_reg (rtx from, rtx to, rtx insn)
We could perhaps try this for multiple SETs, but it probably
won't buy us anything. */
rtx dest = simplify_replace_rtx (SET_DEST (set), from, to);
-
+
if (!rtx_equal_p (dest, SET_DEST (set))
&& validate_change (insn, &SET_DEST (set), dest, 0))
success = 1;
@@ -786,7 +777,7 @@ try_replace_reg (rtx from, rtx to, rtx insn)
return success;
}
-/* Find a set of REGNOs that are available on entry to INSN's block. Returns
+/* Find a set of REGNOs that are available on entry to INSN's block. Return
NULL no such set is found. */
static struct expr *
@@ -856,7 +847,7 @@ find_avail_set (int regno, rtx insn)
JUMP_INSNS. JUMP must be a conditional jump. If SETCC is non-NULL
it is the instruction that immediately precedes JUMP, and must be a
single SET of a register. FROM is what we will try to replace,
- SRC is the constant we will try to substitute for it. Returns nonzero
+ SRC is the constant we will try to substitute for it. Return nonzero
if a change was made. */
static int
@@ -940,8 +931,8 @@ cprop_jump (basic_block bb, rtx setcc, rtx jump, rtx from, rtx src)
if (dump_file != NULL)
{
fprintf (dump_file,
- "GLOBAL CONST-PROP: Replacing reg %d in jump_insn %d with constant ",
- REGNO (from), INSN_UID (jump));
+ "GLOBAL CONST-PROP: Replacing reg %d in jump_insn %d with"
+ "constant ", REGNO (from), INSN_UID (jump));
print_rtl (dump_file, src);
fprintf (dump_file, "\n");
}
@@ -968,8 +959,12 @@ cprop_jump (basic_block bb, rtx setcc, rtx jump, rtx from, rtx src)
return 1;
}
-static bool
-constprop_register (rtx insn, rtx from, rtx to)
+/* Subroutine of cprop_insn that tries to propagate constants. FROM is what
+ we will try to replace, SRC is the constant we will try to substitute for
+ it and INSN is the instruction where this will be happening. */
+
+static int
+constprop_register (rtx from, rtx src, rtx insn)
{
rtx sset;
@@ -981,13 +976,13 @@ constprop_register (rtx insn, rtx from, rtx to)
{
rtx dest = SET_DEST (sset);
if ((REG_P (dest) || CC0_P (dest))
- && cprop_jump (BLOCK_FOR_INSN (insn), insn, NEXT_INSN (insn), from, to))
+ && cprop_jump (BLOCK_FOR_INSN (insn), insn, NEXT_INSN (insn),
+ from, src))
return 1;
}
/* Handle normal insns next. */
- if (NONJUMP_INSN_P (insn)
- && try_replace_reg (from, to, insn))
+ if (NONJUMP_INSN_P (insn) && try_replace_reg (from, src, insn))
return 1;
/* Try to propagate a CONST_INT into a conditional jump.
@@ -997,12 +992,12 @@ constprop_register (rtx insn, rtx from, rtx to)
Right now the insn in question must look like
(set (pc) (if_then_else ...)) */
else if (any_condjump_p (insn) && onlyjump_p (insn))
- return cprop_jump (BLOCK_FOR_INSN (insn), NULL, insn, from, to);
+ return cprop_jump (BLOCK_FOR_INSN (insn), NULL, insn, from, src);
return 0;
}
/* Perform constant and copy propagation on INSN.
- The result is nonzero if a change was made. */
+ Return nonzero if a change was made. */
static int
cprop_insn (rtx insn)
@@ -1044,14 +1039,16 @@ retry:
/* Constant propagation. */
if (cprop_constant_p (src))
{
- if (constprop_register (insn, reg_used, src))
+ if (constprop_register (reg_used, src, insn))
{
changed_this_round = changed = 1;
global_const_prop_count++;
if (dump_file != NULL)
{
- fprintf (dump_file, "GLOBAL CONST-PROP: Replacing reg %d in ", regno);
- fprintf (dump_file, "insn %d with constant ", INSN_UID (insn));
+ fprintf (dump_file,
+ "GLOBAL CONST-PROP: Replacing reg %d in ", regno);
+ fprintf (dump_file, "insn %d with constant ",
+ INSN_UID (insn));
print_rtl (dump_file, src);
fprintf (dump_file, "\n");
}
@@ -1069,7 +1066,8 @@ retry:
global_copy_prop_count++;
if (dump_file != NULL)
{
- fprintf (dump_file, "GLOBAL COPY-PROP: Replacing reg %d in insn %d",
+ fprintf (dump_file,
+ "GLOBAL COPY-PROP: Replacing reg %d in insn %d",
regno, INSN_UID (insn));
fprintf (dump_file, " with reg %d\n", REGNO (src));
}
@@ -1175,7 +1173,7 @@ do_local_cprop (rtx x, rtx insn)
|| ! MEM_P (XEXP (note, 0))))
newreg = this_rtx;
}
- if (newcnst && constprop_register (insn, x, newcnst))
+ if (newcnst && constprop_register (x, newcnst, insn))
{
if (dump_file != NULL)
{
@@ -1409,7 +1407,7 @@ find_implicit_sets (void)
static int bypass_last_basic_block;
/* Find a set of REGNO to a constant that is available at the end of basic
- block BB. Returns NULL if no such set is found. Based heavily upon
+ block BB. Return NULL if no such set is found. Based heavily upon
find_avail_set. */
static struct expr *
@@ -1444,7 +1442,6 @@ find_bypass_set (int regno, int bb)
return result;
}
-
/* Subroutine of bypass_block that checks whether a pseudo is killed by
any of the instructions inserted on an edge. Jump bypassing places
condition code setters on CFG edges using insert_insn_on_edge. This
@@ -1520,8 +1517,8 @@ bypass_block (basic_block bb, rtx setcc, rtx jump)
}
/* The irreducible loops created by redirecting of edges entering the
- loop from outside would decrease effectiveness of some of the following
- optimizations, so prevent this. */
+ loop from outside would decrease effectiveness of some of the
+ following optimizations, so prevent this. */
if (may_be_loop_header
&& !(e->flags & EDGE_DFS_BACK))
{
@@ -1559,7 +1556,6 @@ bypass_block (basic_block bb, rtx setcc, rtx jump)
edges of the CFG. We can't bypass an outgoing edge that
has instructions associated with it, as these insns won't
get executed if the incoming edge is redirected. */
-
if (new_rtx == pc_rtx)
{
edest = FALLTHRU_EDGE (bb);
@@ -1579,7 +1575,6 @@ bypass_block (basic_block bb, rtx setcc, rtx jump)
/* Avoid unification of the edge with other edges from original
branch. We would end up emitting the instruction on "both"
edges. */
-
if (dest && setcc && !CC0_P (SET_DEST (PATTERN (setcc)))
&& find_edge (e->src, dest))
dest = NULL;
@@ -1623,7 +1618,7 @@ bypass_block (basic_block bb, rtx setcc, rtx jump)
/* Find basic blocks with more than one predecessor that only contain a
single conditional jump. If the result of the comparison is known at
compile-time from any incoming edge, redirect that edge to the
- appropriate target. Returns nonzero if a change was made.
+ appropriate target. Return nonzero if a change was made.
This function is now mis-named, because we also handle indirect jumps. */
@@ -1687,7 +1682,7 @@ bypass_conditional_jumps (void)
return changed;
}
-/* Return true if the graph is too expensive to optimize. PASS is the
+/* Return true if the graph is too expensive to optimize. PASS is the
optimization about to be performed. */
static bool
@@ -1726,7 +1721,6 @@ is_too_expensive (const char *pass)
return false;
}
-
/* Main function for the CPROP pass. */
@@ -1800,7 +1794,8 @@ one_cprop_pass (void)
/* Allocate vars to track sets of regs. */
reg_set_bitmap = ALLOC_REG_SET (NULL);
- FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR->next_bb->next_bb, EXIT_BLOCK_PTR, next_bb)
+ FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR->next_bb->next_bb, EXIT_BLOCK_PTR,
+ next_bb)
{
/* Reset tables used to keep track of what's still valid [since
the start of the block]. */
@@ -1841,7 +1836,6 @@ one_cprop_pass (void)
return changed;
}
-
/* All the passes implemented in this file. Each pass has its
own gate and execute function, and at the end of the file a
diff --git a/gcc/defaults.h b/gcc/defaults.h
index 70c63cecc31..40e3263c9e1 100644
--- a/gcc/defaults.h
+++ b/gcc/defaults.h
@@ -142,7 +142,10 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#ifndef ASM_OUTPUT_LABEL
#define ASM_OUTPUT_LABEL(FILE,NAME) \
- do { assemble_name ((FILE), (NAME)); fputs (":\n", (FILE)); } while (0)
+ do { \
+ assemble_name ((FILE), (NAME)); \
+ fputs (":\n", (FILE)); \
+ } while (0)
#endif
/* This is how to output the definition of a user-level label named
@@ -165,7 +168,11 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
/* This is how to output a reference to a user-level label named NAME. */
#ifndef ASM_OUTPUT_LABELREF
-#define ASM_OUTPUT_LABELREF(FILE,NAME) asm_fprintf ((FILE), "%U%s", (NAME))
+#define ASM_OUTPUT_LABELREF(FILE,NAME) \
+ do { \
+ fputs (user_label_prefix, (FILE)); \
+ fputs ((NAME), (FILE)); \
+ } while (0);
#endif
/* Allow target to print debug info labels specially. This is useful for
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index c7e8ede9cb0..15238c1b39e 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -7002,6 +7002,27 @@ All memory models are valid.
@end deftypefn
+@deftypefn {Built-in Function} bool __atomic_test_and_set (bool *ptr, int memmodel)
+
+This built-in function performs an atomic test-and-set operation on
+@code{*@var{ptr}}. @code{*@var{ptr}} is set to the value 1 and
+the previous contents are returned.
+
+All memory models are valid.
+
+@end deftypefn
+
+@deftypefn {Built-in Function} void __atomic_clear (bool *ptr, int memmodel)
+
+This built-in function performs an atomic clear operation on
+@code{*@var{ptr}}. After the operation, @code{*@var{ptr}} will contain 0.
+
+The valid memory model variants are
+@code{__ATOMIC_RELAXED}, @code{__ATOMIC_SEQ_CST}, and
+@code{__ATOMIC_RELEASE}.
+
+@end deftypefn
+
@deftypefn {Built-in Function} void __atomic_thread_fence (int memmodel)
This built-in function acts as a synchronization fence between threads
diff --git a/gcc/doc/gcov.texi b/gcc/doc/gcov.texi
index e635b69a0eb..640d52e1284 100644
--- a/gcc/doc/gcov.texi
+++ b/gcc/doc/gcov.texi
@@ -113,7 +113,7 @@ compatible with any other profiling or test coverage mechanism.
@section Invoking @command{gcov}
@smallexample
-gcov @r{[}@var{options}@r{]} @var{sourcefiles}
+gcov @r{[}@var{options}@r{]} @var{files}
@end smallexample
@command{gcov} accepts the following options:
@@ -124,13 +124,16 @@ 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{-u}|@option{--unconditional-branches}]
[@option{-n}|@option{--no-output}]
[@option{-l}|@option{--long-file-names}]
[@option{-p}|@option{--preserve-paths}]
+ [@option{-r}|@option{--relative-only}]
[@option{-f}|@option{--function-summaries}]
- [@option{-o}|@option{--object-directory} @var{directory|file}] @var{sourcefiles}
- [@option{-u}|@option{--unconditional-branches}]
+ [@option{-o}|@option{--object-directory} @var{directory|file}]
+ [@option{-s}|@option{--source-prefix} @var{directory}]
[@option{-d}|@option{--display-progress}]
+ @var{files}
@c man end
@c man begin SEEALSO
gpl(7), gfdl(7), fsf-funding(7), gcc(1) and the Info entry for @file{gcc}.
@@ -176,11 +179,12 @@ Do not create the @command{gcov} output file.
@itemx --long-file-names
Create long file names for included source files. For example, if the
header file @file{x.h} contains code, and was included in the file
-@file{a.c}, then running @command{gcov} on the file @file{a.c} will produce
-an output file called @file{a.c##x.h.gcov} instead of @file{x.h.gcov}.
-This can be useful if @file{x.h} is included in multiple source
-files. If you use the @samp{-p} option, both the including and
-included file names will be complete path names.
+@file{a.c}, then running @command{gcov} on the file @file{a.c} will
+produce an output file called @file{a.c##x.h.gcov} instead of
+@file{x.h.gcov}. This can be useful if @file{x.h} is included in
+multiple source files and you want to see the individual
+contributions. If you use the @samp{-p} option, both the including
+and included file names will be complete path names.
@item -p
@itemx --preserve-paths
@@ -188,9 +192,16 @@ Preserve complete path information in the names of generated
@file{.gcov} files. Without this option, just the filename component is
used. With this option, all directories are used, with @samp{/} characters
translated to @samp{#} characters, @file{.} directory components
-removed and @file{..}
+removed and unremoveable @file{..}
components renamed to @samp{^}. This is useful if sourcefiles are in several
-different directories. It also affects the @samp{-l} option.
+different directories.
+
+@item -r
+@itemx --relative-only
+Only output information about source files with a relative pathname
+(after source prefix elision). Absolute paths are usually system
+header files and coverage of any inline functions therein is normally
+uninteresting.
@item -f
@itemx --function-summaries
@@ -203,9 +214,16 @@ Specify either the directory containing the gcov data files, or the
object path name. The @file{.gcno}, and
@file{.gcda} data files are searched for using this option. If a directory
is specified, the data files are in that directory and named after the
-source file name, without its extension. If a file is specified here,
-the data files are named after that file, without its extension. If this
-option is not supplied, it defaults to the current directory.
+input file name, without its extension. If a file is specified here,
+the data files are named after that file, without its extension.
+
+@item -s @var{directory}
+@itemx --source-prefix @var{directory}
+A prefix for source file names to remove when generating the output
+coverage files. This option is useful when building in a separate
+directory, and the pathname to the source directory is not wanted when
+determining the output file names. Note that this prefix detection is
+applied before determining whether the source file is absolute.
@item -u
@itemx --unconditional-branches
@@ -223,12 +241,17 @@ when you invoked the compiler. Otherwise it will not be able to locate
the source files. @command{gcov} produces files called
@file{@var{mangledname}.gcov} in the current directory. These contain
the coverage information of the source file they correspond to.
-One @file{.gcov} file is produced for each source file containing code,
+One @file{.gcov} file is produced for each source (or header) file
+containing code,
which was compiled to produce the data files. The @var{mangledname} part
of the output file name is usually simply the source file name, but can
be something more complicated if the @samp{-l} or @samp{-p} options are
given. Refer to those options for details.
+If you invoke @command{gcov} with multiple input files, the
+contributions from each input file are summed. Typically you would
+invoke it with the same list of files as the final link of your executable.
+
The @file{.gcov} files contain the @samp{:} separated fields along with
program source code. The format is
diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
index 643ba7208e6..1daddb865e4 100644
--- a/gcc/doc/install.texi
+++ b/gcc/doc/install.texi
@@ -4476,7 +4476,7 @@ both 64-bit x86-64 and 32-bit x86 code (via the @option{-m32} switch).
@html
<hr />
@end html
-@heading @anchor{x86-64-x-solaris2.10}x86_64-*-solaris2.1[0-9]*
+@heading @anchor{x86-64-x-solaris210}x86_64-*-solaris2.1[0-9]*
GCC also supports the x86-64 architecture implemented by the AMD64
processor (@samp{amd64-*-*} is an alias for @samp{x86_64-*-*}) on
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 54e4a48d11d..1fc44372e32 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -3556,7 +3556,7 @@ To suppress this warning use the @samp{unused} attribute
@opindex Wunused-result
@opindex Wno-unused-result
Do not warn if a caller of a function marked with attribute
-@code{warn_unused_result} (@pxref{Variable Attributes}) does not use
+@code{warn_unused_result} (@pxref{Function Attributes}) does not use
its return value. The default is @option{-Wunused-result}.
@item -Wunused-variable
diff --git a/gcc/dwarf2asm.c b/gcc/dwarf2asm.c
index 0b7480ba3c4..fe305d3ed4e 100644
--- a/gcc/dwarf2asm.c
+++ b/gcc/dwarf2asm.c
@@ -47,8 +47,7 @@ dw2_assemble_integer (int size, rtx x)
{
fputs (op, asm_out_file);
if (CONST_INT_P (x))
- fprintf (asm_out_file, HOST_WIDE_INT_PRINT_HEX,
- (unsigned HOST_WIDE_INT) INTVAL (x));
+ fprint_whex (asm_out_file, (unsigned HOST_WIDE_INT) INTVAL (x));
else
output_addr_const (asm_out_file, x);
}
@@ -100,16 +99,19 @@ dw2_asm_output_data (int size, unsigned HOST_WIDE_INT value,
value &= ~(~(unsigned HOST_WIDE_INT) 0 << (size * 8));
if (op)
- fprintf (asm_out_file, "%s" HOST_WIDE_INT_PRINT_HEX, op, value);
+ {
+ fputs (op, asm_out_file);
+ fprint_whex (asm_out_file, value);
+ }
else
assemble_integer (GEN_INT (value), size, BITS_PER_UNIT, 1);
if (flag_debug_asm && comment)
{
- fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
+ fputs ("\t" ASM_COMMENT_START " ", asm_out_file);
vfprintf (asm_out_file, comment, ap);
}
- fputc ('\n', asm_out_file);
+ putc ('\n', asm_out_file);
va_end (ap);
}
@@ -590,7 +592,8 @@ dw2_asm_output_data_uleb128 (unsigned HOST_WIDE_INT value,
va_start (ap, comment);
#ifdef HAVE_AS_LEB128
- fprintf (asm_out_file, "\t.uleb128 " HOST_WIDE_INT_PRINT_HEX , value);
+ fputs ("\t.uleb128 ", asm_out_file);
+ fprint_whex (asm_out_file, value);
if (flag_debug_asm && comment)
{
@@ -635,7 +638,7 @@ dw2_asm_output_data_uleb128 (unsigned HOST_WIDE_INT value,
}
}
#endif
- fputc ('\n', asm_out_file);
+ putc ('\n', asm_out_file);
va_end (ap);
}
@@ -739,7 +742,7 @@ dw2_asm_output_delta_uleb128 (const char *lab1 ATTRIBUTE_UNUSED,
#ifdef HAVE_AS_LEB128
fputs ("\t.uleb128 ", asm_out_file);
assemble_name (asm_out_file, lab1);
- fputc ('-', asm_out_file);
+ putc ('-', asm_out_file);
assemble_name (asm_out_file, lab2);
#else
gcc_unreachable ();
@@ -769,7 +772,7 @@ dw2_asm_output_delta_sleb128 (const char *lab1 ATTRIBUTE_UNUSED,
#ifdef HAVE_AS_LEB128
fputs ("\t.sleb128 ", asm_out_file);
assemble_name (asm_out_file, lab1);
- fputc ('-', asm_out_file);
+ putc ('-', asm_out_file);
assemble_name (asm_out_file, lab2);
#else
gcc_unreachable ();
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 39be9a16e9c..768ecaf6669 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -20371,6 +20371,10 @@ set_cur_line_info_table (section *sec)
VEC_safe_push (dw_line_info_table_p, gc, separate_line_info, table);
}
+ if (DWARF2_ASM_LINE_DEBUG_INFO)
+ table->is_stmt = (cur_line_info_table
+ ? cur_line_info_table->is_stmt
+ : DWARF_LINE_DEFAULT_IS_STMT_START);
cur_line_info_table = table;
}
@@ -20468,12 +20472,27 @@ dwarf2out_source_line (unsigned int line, const char *filename,
if (DWARF2_ASM_LINE_DEBUG_INFO)
{
/* Emit the .loc directive understood by GNU as. */
- fprintf (asm_out_file, "\t.loc %d %d 0", file_num, line);
+ /* "\t.loc %u %u 0 is_stmt %u discriminator %u",
+ file_num, line, is_stmt, discriminator */
+ fputs ("\t.loc ", asm_out_file);
+ fprint_ul (asm_out_file, file_num);
+ putc (' ', asm_out_file);
+ fprint_ul (asm_out_file, line);
+ putc (' ', asm_out_file);
+ putc ('0', asm_out_file);
+
if (is_stmt != table->is_stmt)
- fprintf (asm_out_file, " is_stmt %d", is_stmt ? 1 : 0);
+ {
+ fputs (" is_stmt ", asm_out_file);
+ putc (is_stmt ? '1' : '0', asm_out_file);
+ }
if (SUPPORTS_DISCRIMINATOR && discriminator != 0)
- fprintf (asm_out_file, " discriminator %d", discriminator);
- fputc ('\n', asm_out_file);
+ {
+ gcc_assert (discriminator > 0);
+ fputs (" discriminator ", asm_out_file);
+ fprint_ul (asm_out_file, (unsigned long) discriminator);
+ }
+ putc ('\n', asm_out_file);
}
else
{
diff --git a/gcc/final.c b/gcc/final.c
index bd4e7a762a7..cc3a199692e 100644
--- a/gcc/final.c
+++ b/gcc/final.c
@@ -3585,7 +3585,7 @@ output_addr_const (FILE *file, rtx x)
break;
case CONST_INT:
- fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
+ fprint_w (file, INTVAL (x));
break;
case CONST:
@@ -3699,6 +3699,124 @@ output_quoted_string (FILE *asm_file, const char *string)
#endif
}
+/* Write a HOST_WIDE_INT number in hex form 0x1234, fast. */
+
+void
+fprint_whex (FILE *f, unsigned HOST_WIDE_INT value)
+{
+ char buf[2 + CHAR_BIT * sizeof (value) / 4];
+ if (value == 0)
+ putc ('0', f);
+ else
+ {
+ char *p = buf + sizeof (buf);
+ do
+ *--p = "0123456789abcdef"[value % 16];
+ while ((value /= 16) != 0);
+ *--p = 'x';
+ *--p = '0';
+ fwrite (p, 1, buf + sizeof (buf) - p, f);
+ }
+}
+
+/* Internal function that prints an unsigned long in decimal in reverse.
+ The output string IS NOT null-terminated. */
+
+static int
+sprint_ul_rev (char *s, unsigned long value)
+{
+ int i = 0;
+ do
+ {
+ s[i] = "0123456789"[value % 10];
+ value /= 10;
+ i++;
+ /* alternate version, without modulo */
+ /* oldval = value; */
+ /* value /= 10; */
+ /* s[i] = "0123456789" [oldval - 10*value]; */
+ /* i++ */
+ }
+ while (value != 0);
+ return i;
+}
+
+/* Write a signed HOST_WIDE_INT as decimal to a file, fast. */
+
+void
+fprint_w (FILE *f, HOST_WIDE_INT value)
+{
+ /* python says: len(str(2**64)) == 20 */
+ char s[20];
+ int i;
+
+ if (value >= 0)
+ i = sprint_ul_rev (s, (unsigned long) value);
+ else
+ {
+ /* Cast to long long to output max negative correctly! */
+ i = sprint_ul_rev (s, ((unsigned long long) value) * -1);
+ putc('-', f);
+ }
+
+ /* It's probably too small to bother with string reversal and fputs. */
+ do
+ {
+ i--;
+ putc (s[i], f);
+ }
+ while (i != 0);
+}
+
+/* Write an unsigned long as decimal to a file, fast. */
+
+void
+fprint_ul (FILE *f, unsigned long value)
+{
+ /* python says: len(str(2**64)) == 20 */
+ char s[20];
+ int i;
+
+ i = sprint_ul_rev (s, value);
+
+ /* It's probably too small to bother with string reversal and fputs. */
+ do
+ {
+ i--;
+ putc (s[i], f);
+ }
+ while (i != 0);
+}
+
+/* Write an unsigned long as decimal to a string, fast.
+ s must be wide enough to not overflow, at least 21 chars.
+ Returns the length of the string (without terminating '\0'). */
+
+int
+sprint_ul (char *s, unsigned long value)
+{
+ int len;
+ char tmp_c;
+ int i;
+ int j;
+
+ len = sprint_ul_rev (s, value);
+ s[len] = '\0';
+
+ /* Reverse the string. */
+ i = 0;
+ j = len - 1;
+ while (i < j)
+ {
+ tmp_c = s[i];
+ s[i] = s[j];
+ s[j] = tmp_c;
+ i++; j--;
+ }
+
+ return len;
+}
+
/* A poor man's fprintf, with the added features of %I, %R, %L, and %U.
%R prints the value of REGISTER_PREFIX.
%L prints the value of LOCAL_LABEL_PREFIX.
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index e4c258903f7..167573b17b3 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -9528,6 +9528,86 @@ get_pointer_modulus_and_residue (tree expr, unsigned HOST_WIDE_INT *residue,
return 1;
}
+/* Helper function for fold_vec_perm. Store elements of VECTOR_CST or
+ CONSTRUCTOR ARG into array ELTS and return true if successful. */
+
+static bool
+vec_cst_ctor_to_array (tree arg, tree *elts)
+{
+ unsigned int nelts = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)), i;
+
+ if (TREE_CODE (arg) == VECTOR_CST)
+ {
+ tree t;
+
+ for (i = 0, t = TREE_VECTOR_CST_ELTS (arg);
+ i < nelts && t; i++, t = TREE_CHAIN (t))
+ elts[i] = TREE_VALUE (t);
+ if (t)
+ return false;
+ }
+ else if (TREE_CODE (arg) == CONSTRUCTOR)
+ {
+ constructor_elt *elt;
+
+ FOR_EACH_VEC_ELT (constructor_elt, CONSTRUCTOR_ELTS (arg), i, elt)
+ if (i >= nelts)
+ return false;
+ else
+ elts[i] = elt->value;
+ }
+ else
+ return false;
+ for (; i < nelts; i++)
+ elts[i]
+ = fold_convert (TREE_TYPE (TREE_TYPE (arg)), integer_zero_node);
+ return true;
+}
+
+/* Attempt to fold vector permutation of ARG0 and ARG1 vectors using SEL
+ selector. Return the folded VECTOR_CST or CONSTRUCTOR if successful,
+ NULL_TREE otherwise. */
+
+static tree
+fold_vec_perm (tree type, tree arg0, tree arg1, const unsigned char *sel)
+{
+ unsigned int nelts = TYPE_VECTOR_SUBPARTS (type), i;
+ tree *elts;
+ bool need_ctor = false;
+
+ gcc_assert (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)) == nelts
+ && TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg1)) == nelts);
+ if (TREE_TYPE (TREE_TYPE (arg0)) != TREE_TYPE (type)
+ || TREE_TYPE (TREE_TYPE (arg1)) != TREE_TYPE (type))
+ return NULL_TREE;
+
+ elts = XALLOCAVEC (tree, nelts * 3);
+ if (!vec_cst_ctor_to_array (arg0, elts)
+ || !vec_cst_ctor_to_array (arg1, elts + nelts))
+ return NULL_TREE;
+
+ for (i = 0; i < nelts; i++)
+ {
+ if (!CONSTANT_CLASS_P (elts[sel[i]]))
+ need_ctor = true;
+ elts[i + 2 * nelts] = unshare_expr (elts[sel[i]]);
+ }
+
+ if (need_ctor)
+ {
+ VEC(constructor_elt,gc) *v = VEC_alloc (constructor_elt, gc, nelts);
+ for (i = 0; i < nelts; i++)
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, elts[2 * nelts + i]);
+ return build_constructor (type, v);
+ }
+ else
+ {
+ tree vals = NULL_TREE;
+ for (i = 0; i < nelts; i++)
+ vals = tree_cons (NULL_TREE, elts[3 * nelts - i - 1], vals);
+ return build_vector (type, vals);
+ }
+}
/* Fold a binary expression of code CODE and type TYPE with operands
OP0 and OP1. LOC is the location of the resulting expression.
@@ -13381,6 +13461,41 @@ fold_binary_loc (location_t loc,
/* An ASSERT_EXPR should never be passed to fold_binary. */
gcc_unreachable ();
+ case VEC_EXTRACT_EVEN_EXPR:
+ case VEC_EXTRACT_ODD_EXPR:
+ case VEC_INTERLEAVE_HIGH_EXPR:
+ case VEC_INTERLEAVE_LOW_EXPR:
+ if ((TREE_CODE (arg0) == VECTOR_CST
+ || TREE_CODE (arg0) == CONSTRUCTOR)
+ && (TREE_CODE (arg1) == VECTOR_CST
+ || TREE_CODE (arg1) == CONSTRUCTOR))
+ {
+ unsigned int nelts = TYPE_VECTOR_SUBPARTS (type), i;
+ unsigned char *sel = XALLOCAVEC (unsigned char, nelts);
+
+ for (i = 0; i < nelts; i++)
+ switch (code)
+ {
+ case VEC_EXTRACT_EVEN_EXPR:
+ sel[i] = i * 2;
+ break;
+ case VEC_EXTRACT_ODD_EXPR:
+ sel[i] = i * 2 + 1;
+ break;
+ case VEC_INTERLEAVE_HIGH_EXPR:
+ sel[i] = (i + nelts) / 2 + ((i & 1) ? nelts : 0);
+ break;
+ case VEC_INTERLEAVE_LOW_EXPR:
+ sel[i] = i / 2 + ((i & 1) ? nelts : 0);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ return fold_vec_perm (type, arg0, arg1, sel);
+ }
+ return NULL_TREE;
+
default:
return NULL_TREE;
} /* switch (code) */
@@ -13767,6 +13882,55 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
return fold_fma (loc, type, arg0, arg1, arg2);
+ case VEC_PERM_EXPR:
+ if (TREE_CODE (arg2) == VECTOR_CST)
+ {
+ unsigned int nelts = TYPE_VECTOR_SUBPARTS (type), i;
+ unsigned char *sel = XALLOCAVEC (unsigned char, nelts);
+ tree t;
+ bool need_mask_canon = false;
+
+ gcc_assert (nelts == TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg2)));
+ for (i = 0, t = TREE_VECTOR_CST_ELTS (arg2);
+ i < nelts && t; i++, t = TREE_CHAIN (t))
+ {
+ if (TREE_CODE (TREE_VALUE (t)) != INTEGER_CST)
+ return NULL_TREE;
+
+ sel[i] = TREE_INT_CST_LOW (TREE_VALUE (t)) & (2 * nelts - 1);
+ if (TREE_INT_CST_HIGH (TREE_VALUE (t))
+ || ((unsigned HOST_WIDE_INT)
+ TREE_INT_CST_LOW (TREE_VALUE (t)) != sel[i]))
+ need_mask_canon = true;
+ }
+ if (t)
+ return NULL_TREE;
+ for (; i < nelts; i++)
+ sel[i] = 0;
+
+ if ((TREE_CODE (arg0) == VECTOR_CST
+ || TREE_CODE (arg0) == CONSTRUCTOR)
+ && (TREE_CODE (arg1) == VECTOR_CST
+ || TREE_CODE (arg1) == CONSTRUCTOR))
+ {
+ t = fold_vec_perm (type, arg0, arg1, sel);
+ if (t != NULL_TREE)
+ return t;
+ }
+
+ if (need_mask_canon && arg2 == op2)
+ {
+ tree list = NULL_TREE, eltype = TREE_TYPE (TREE_TYPE (arg2));
+ for (i = 0; i < nelts; i++)
+ list = tree_cons (NULL_TREE,
+ build_int_cst (eltype, sel[nelts - i - 1]),
+ list);
+ t = build_vector (TREE_TYPE (arg2), list);
+ return build3_loc (loc, VEC_PERM_EXPR, type, op0, op1, t);
+ }
+ }
+ return NULL_TREE;
+
default:
return NULL_TREE;
} /* switch (code) */
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 019680dfa1a..01abd74f890 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,7 +1,18 @@
+2011-11-14 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/51073
+ * trans-decl.c (generate_coarray_sym_init): Handle zero-sized arrays.
+
+2011-11-09 Tobias Burnus <burnus@net-b.de>
+
+ * symbol.c (clear_sym_mark, traverse_ns): Remove functions.
+ (count_st_nodes, do_traverse_symtree, fill_st_vector): New functions.
+ (gfc_traverse_symtree, gfc_traverse_ns): Call do_traverse_symtree.
+
2011-11-09 Janne Blomqvist <jb@gcc.gnu.org>
- PR libfortran/50016
- * gfortran.texi (Data consistency and durability): New section.
+ PR libfortran/50016
+ * gfortran.texi (Data consistency and durability): New section.
2011-11-09 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
@@ -638,7 +649,7 @@
2011-10-23 Steven G. Kargl <kargl@gcc.gnu.org>
* simplify.c (simplify_transformation_to_array): Fix memory leak.
-
+
2011-10-20 Steven G. Kargl <kargl@gcc.gnu.org>
PR fortran/50821
diff --git a/gcc/fortran/symbol.c b/gcc/fortran/symbol.c
index 67d65cb16b9..33ec706f40a 100644
--- a/gcc/fortran/symbol.c
+++ b/gcc/fortran/symbol.c
@@ -3310,46 +3310,81 @@ gfc_symbol_done_2 (void)
}
-/* Clear mark bits from symbol nodes associated with a symtree node. */
+/* Count how many nodes a symtree has. */
-static void
-clear_sym_mark (gfc_symtree *st)
+static unsigned
+count_st_nodes (const gfc_symtree *st)
{
+ unsigned nodes;
+ if (!st)
+ return 0;
- st->n.sym->mark = 0;
+ nodes = count_st_nodes (st->left);
+ nodes++;
+ nodes += count_st_nodes (st->right);
+
+ return nodes;
}
-/* Recursively traverse the symtree nodes. */
+/* Convert symtree tree into symtree vector. */
-void
-gfc_traverse_symtree (gfc_symtree *st, void (*func) (gfc_symtree *))
+static unsigned
+fill_st_vector (gfc_symtree *st, gfc_symtree **st_vec, unsigned node_cntr)
{
if (!st)
- return;
+ return node_cntr;
+
+ node_cntr = fill_st_vector (st->left, st_vec, node_cntr);
+ st_vec[node_cntr++] = st;
+ node_cntr = fill_st_vector (st->right, st_vec, node_cntr);
- gfc_traverse_symtree (st->left, func);
- (*func) (st);
- gfc_traverse_symtree (st->right, func);
+ return node_cntr;
}
-/* Recursive namespace traversal function. */
+/* Traverse namespace. As the functions might modify the symtree, we store the
+ symtree as a vector and operate on this vector. Note: We assume that
+ sym_func or st_func never deletes nodes from the symtree - only adding is
+ allowed. Additionally, newly added nodes are not traversed. */
static void
-traverse_ns (gfc_symtree *st, void (*func) (gfc_symbol *))
+do_traverse_symtree (gfc_symtree *st, void (*st_func) (gfc_symtree *),
+ void (*sym_func) (gfc_symbol *))
{
+ gfc_symtree **st_vec;
+ unsigned nodes, i, node_cntr;
- if (st == NULL)
- return;
+ gcc_assert ((st_func && !sym_func) || (!st_func && sym_func));
+ nodes = count_st_nodes (st);
+ st_vec = XALLOCAVEC (gfc_symtree *, nodes);
+ node_cntr = 0;
+ fill_st_vector (st, st_vec, node_cntr);
+
+ if (sym_func)
+ {
+ /* Clear marks. */
+ for (i = 0; i < nodes; i++)
+ st_vec[i]->n.sym->mark = 0;
+ for (i = 0; i < nodes; i++)
+ if (!st_vec[i]->n.sym->mark)
+ {
+ (*sym_func) (st_vec[i]->n.sym);
+ st_vec[i]->n.sym->mark = 1;
+ }
+ }
+ else
+ for (i = 0; i < nodes; i++)
+ (*st_func) (st_vec[i]);
+}
- traverse_ns (st->left, func);
- if (st->n.sym->mark == 0)
- (*func) (st->n.sym);
- st->n.sym->mark = 1;
+/* Recursively traverse the symtree nodes. */
- traverse_ns (st->right, func);
+void
+gfc_traverse_symtree (gfc_symtree *st, void (*st_func) (gfc_symtree *))
+{
+ do_traverse_symtree (st, st_func, NULL);
}
@@ -3357,12 +3392,9 @@ traverse_ns (gfc_symtree *st, void (*func) (gfc_symbol *))
care that each gfc_symbol node is called exactly once. */
void
-gfc_traverse_ns (gfc_namespace *ns, void (*func) (gfc_symbol *))
+gfc_traverse_ns (gfc_namespace *ns, void (*sym_func) (gfc_symbol *))
{
-
- gfc_traverse_symtree (ns->sym_root, clear_sym_mark);
-
- traverse_ns (ns->sym_root, func);
+ do_traverse_symtree (ns->sym_root, NULL, sym_func);
}
diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
index b90b0ab25b6..80e4f555d1c 100644
--- a/gcc/fortran/trans-decl.c
+++ b/gcc/fortran/trans-decl.c
@@ -4234,12 +4234,16 @@ generate_coarray_sym_init (gfc_symbol *sym)
size = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (decl)));
+ /* Ensure that we do not have size=0 for zero-sized arrays. */
+ size = fold_build2_loc (input_location, MAX_EXPR, size_type_node,
+ fold_convert (size_type_node, size),
+ build_int_cst (size_type_node, 1));
+
if (GFC_TYPE_ARRAY_RANK (TREE_TYPE (decl)))
{
tmp = GFC_TYPE_ARRAY_SIZE (TREE_TYPE (decl));
size = fold_build2_loc (input_location, MULT_EXPR, size_type_node,
- fold_convert (size_type_node, tmp),
- fold_convert (size_type_node, size));
+ fold_convert (size_type_node, tmp), size);
}
gcc_assert (GFC_TYPE_ARRAY_CAF_TOKEN (TREE_TYPE (decl)) != NULL_TREE);
diff --git a/gcc/function.c b/gcc/function.c
index 0cbbbc5e404..0ee69ef22b6 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -5284,7 +5284,7 @@ prologue_epilogue_contains (const_rtx insn)
PROLOGUE_USED contains the hard registers used in the function
prologue. SET_UP_BY_PROLOGUE is the set of registers we expect the
prologue to set up for the function. */
-static bool
+bool
requires_stack_frame_p (rtx insn, HARD_REG_SET prologue_used,
HARD_REG_SET set_up_by_prologue)
{
diff --git a/gcc/function.h b/gcc/function.h
index 42e52acaad5..ce67add2748 100644
--- a/gcc/function.h
+++ b/gcc/function.h
@@ -753,6 +753,10 @@ extern void used_types_insert (tree);
extern int get_next_funcdef_no (void);
extern int get_last_funcdef_no (void);
+#ifdef HAVE_simple_return
+extern bool requires_stack_frame_p (rtx, HARD_REG_SET, HARD_REG_SET);
+#endif
+
/* In predict.c */
extern bool optimize_function_for_size_p (struct function *);
extern bool optimize_function_for_speed_p (struct function *);
diff --git a/gcc/gcov.c b/gcc/gcov.c
index 6711f7e6a47..dffb827bdf7 100644
--- a/gcc/gcov.c
+++ b/gcc/gcov.c
@@ -181,9 +181,9 @@ typedef struct function_info
gcov_type *counts;
unsigned num_counts;
- /* First line number. */
+ /* First line number & file. */
unsigned line;
- struct source_info *src;
+ unsigned src;
/* Next function in same source file. */
struct function_info *line_next;
@@ -231,9 +231,8 @@ typedef struct line_info
typedef struct source_info
{
- /* Name of source file. */
+ /* Canonical name of source file. */
char *name;
- unsigned index;
time_t file_time;
/* Array of line information. */
@@ -245,23 +244,26 @@ typedef struct source_info
/* Functions in this source file. These are in ascending line
number order. */
function_t *functions;
-
- /* Next source file. */
- struct source_info *next;
} source_t;
+typedef struct name_map
+{
+ char *name; /* Source file name */
+ unsigned src; /* Source file */
+} name_map_t;
+
/* Holds a list of function basic block graphs. */
static function_t *functions;
+static function_t **fn_end = &functions;
-/* This points to the head of the sourcefile structure list. New elements
- are always prepended. */
+static source_t *sources; /* Array of source files */
+static unsigned n_sources; /* Number of sources */
+static unsigned a_sources; /* Allocated sources */
-static source_t *sources;
-
-/* Next index for a source file. */
-
-static unsigned source_index;
+static name_map_t *names; /* Mapping of file names to sources */
+static unsigned n_names; /* Number of names */
+static unsigned a_names; /* Allocated names */
/* This holds data summary information. */
@@ -331,6 +333,17 @@ static int flag_function_summary = 0;
static char *object_directory = 0;
+/* Source directory prefix. This is removed from source pathnames
+ that match, when generating the output file name. */
+
+static char *source_prefix = 0;
+static size_t source_length = 0;
+
+/* Only show data for sources with relative pathnames. Absolute ones
+ usually indicate a system header file, which although it may
+ contain inline functions, is usually uninteresting. */
+static int flag_relative_only = 0;
+
/* Preserve all pathname components. Needed when object files and
source files are in subdirectories. '/' is mangled as '#', '.' is
elided and '..' mangled to '^'. */
@@ -349,9 +362,12 @@ static void print_version (void) ATTRIBUTE_NORETURN;
static void process_file (const char *);
static void generate_results (const char *);
static void create_file_names (const char *);
-static source_t *find_source (const char *);
-static int read_graph_file (void);
-static int read_count_file (void);
+static int name_search (const void *, const void *);
+static int name_sort (const void *, const void *);
+static char *canonicalize_name (const char *);
+static unsigned find_source (const char *);
+static function_t *read_graph_file (void);
+static int read_count_file (function_t *);
static void solve_flow_graph (function_t *);
static void add_branch_counts (coverage_t *, const arc_t *);
static void add_line_counts (coverage_t *, function_t *);
@@ -361,6 +377,7 @@ static void accumulate_line_counts (source_t *);
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 char *mangle_name (const char *, char *);
static void release_structures (void);
static void release_function (function_t *);
extern int main (int, char **);
@@ -422,7 +439,7 @@ print_usage (int error_p)
FILE *file = error_p ? stderr : stdout;
int status = error_p ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE;
- fnotice (file, "Usage: gcov [OPTION]... SOURCEFILE...\n\n");
+ fnotice (file, "Usage: gcov [OPTION]... SOURCE|OBJ...\n\n");
fnotice (file, "Print code coverage information.\n\n");
fnotice (file, " -h, --help Print this help, then exit\n");
fnotice (file, " -v, --version Print version number, then exit\n");
@@ -435,6 +452,8 @@ print_usage (int error_p)
source files\n");
fnotice (file, " -f, --function-summaries Output summaries for each function\n");
fnotice (file, " -o, --object-directory DIR|FILE Search for object files in DIR or called FILE\n");
+ fnotice (file, " -s, --source-prefix DIR Source prefix to elide\n");
+ fnotice (file, " -r, --relative-only Only show data for relative sources\n");
fnotice (file, " -p, --preserve-paths Preserve all pathname components\n");
fnotice (file, " -u, --unconditional-branches Show unconditional branch counts too\n");
fnotice (file, " -d, --display-progress Display progress information\n");
@@ -469,8 +488,10 @@ static const struct option options[] =
{ "long-file-names", no_argument, NULL, 'l' },
{ "function-summaries", no_argument, NULL, 'f' },
{ "preserve-paths", no_argument, NULL, 'p' },
+ { "relative-only", no_argument, NULL, 'r' },
{ "object-directory", required_argument, NULL, 'o' },
{ "object-file", required_argument, NULL, 'o' },
+ { "source-prefix", required_argument, NULL, 's' },
{ "unconditional-branches", no_argument, NULL, 'u' },
{ "display-progress", no_argument, NULL, 'd' },
{ 0, 0, 0, 0 }
@@ -483,7 +504,7 @@ process_args (int argc, char **argv)
{
int opt;
- while ((opt = getopt_long (argc, argv, "abcdfhlno:puv", options, NULL)) != -1)
+ while ((opt = getopt_long (argc, argv, "abcdfhlno:s:pruv", options, NULL)) != -1)
{
switch (opt)
{
@@ -511,6 +532,13 @@ process_args (int argc, char **argv)
case 'o':
object_directory = optarg;
break;
+ case 's':
+ source_prefix = optarg;
+ source_length = strlen (source_prefix);
+ break;
+ case 'r':
+ flag_relative_only = 1;
+ break;
case 'p':
flag_preserve_paths = 1;
break;
@@ -532,62 +560,90 @@ process_args (int argc, char **argv)
return optind;
}
-/* Process a single source file. */
+/* Process a single input file. */
static void
process_file (const char *file_name)
{
- function_t *fn;
- function_t **fn_p;
- function_t *old_functions;
-
- /* Save and clear the list of current functions. They will be appended
- later. */
- old_functions = functions;
- functions = NULL;
+ function_t *fns;
create_file_names (file_name);
- if (read_graph_file ())
+ fns = read_graph_file ();
+ if (!fns)
return;
-
- if (!functions)
+
+ read_count_file (fns);
+ while (fns)
{
- fnotice (stderr, "%s:no functions found\n", bbg_file_name);
- return;
- }
-
- if (read_count_file ())
- return;
+ function_t *fn = fns;
- fn_p = &functions;
- while ((fn = *fn_p) != NULL)
- {
+ fns = fn->next;
+ fn->next = NULL;
if (fn->counts)
{
+ unsigned src = fn->src;
+ unsigned line = fn->line;
+ unsigned block_no;
+ function_t *probe, **prev;
+
+ /* Now insert it into the source file's list of
+ functions. Normally functions will be encountered in
+ ascending order, so a simple scan is quick. Note we're
+ building this list in reverse order. */
+ for (prev = &sources[src].functions;
+ (probe = *prev); prev = &probe->line_next)
+ if (probe->line <= line)
+ break;
+ fn->line_next = probe;
+ *prev = fn;
+
+ /* Mark last line in files touched by function. */
+ for (block_no = 0; block_no != fn->num_blocks; block_no++)
+ {
+ unsigned *enc = fn->blocks[block_no].u.line.encoding;
+ unsigned num = fn->blocks[block_no].u.line.num;
+
+ for (; num--; enc++)
+ if (!*enc)
+ {
+ if (enc[1] != src)
+ {
+ if (line >= sources[src].num_lines)
+ sources[src].num_lines = line + 1;
+ line = 0;
+ src = enc[1];
+ }
+ enc++;
+ num--;
+ }
+ else if (*enc > line)
+ line = *enc;
+ }
+ if (line >= sources[src].num_lines)
+ sources[src].num_lines = line + 1;
+
solve_flow_graph (fn);
- fn_p = &fn->next;
+ *fn_end = fn;
+ fn_end = &fn->next;
}
else
- {
- /* The function was not in the executable -- some other
- instance must have been selected. */
- function_t *next = fn->next;
- release_function (fn);
- *fn_p = next;
- }
+ /* The function was not in the executable -- some other
+ instance must have been selected. */
+ release_function (fn);
}
-
- *fn_p = old_functions;
}
static void
generate_results (const char *file_name)
{
+ unsigned ix;
source_t *src;
function_t *fn;
- for (src = sources; src; src = src->next)
- src->lines = XCNEWVEC (line_t, src->num_lines);
+ for (ix = n_sources, src = sources; ix--; src++)
+ if (src->num_lines)
+ src->lines = XCNEWVEC (line_t, src->num_lines);
+
for (fn = functions; fn; fn = fn->next)
{
coverage_t coverage;
@@ -602,28 +658,52 @@ generate_results (const char *file_name)
}
}
- for (src = sources; src; src = src->next)
+ if (file_name)
{
+ name_map_t *name_map = (name_map_t *)bsearch
+ (file_name, names, n_names, sizeof (*names), name_search);
+ if (name_map)
+ file_name = sources[name_map->src].coverage.name;
+ else
+ file_name = canonicalize_name (file_name);
+ }
+
+ for (ix = n_sources, src = sources; ix--; src++)
+ {
+ if (flag_relative_only)
+ {
+ /* Ignore this source, if it is an absolute path (after
+ source prefix removal). */
+ char first = src->coverage.name[0];
+
+#if HAVE_DOS_BASED_FILE_SYSTEM
+ if (first && src->coverage.name[1] == ':')
+ first = src->coverage.name[2];
+#endif
+ if (IS_DIR_SEPARATOR (first))
+ continue;
+ }
+
accumulate_line_counts (src);
function_summary (&src->coverage, "File");
if (flag_gcov_file && src->coverage.lines)
{
- char *gcov_file_name = make_gcov_file_name (file_name, src->name);
+ char *gcov_file_name
+ = make_gcov_file_name (file_name, src->coverage.name);
FILE *gcov_file = fopen (gcov_file_name, "w");
if (gcov_file)
{
- fnotice (stdout, "%s:creating '%s'\n",
- src->name, gcov_file_name);
+ fnotice (stdout, "Creating '%s'\n", gcov_file_name);
output_lines (gcov_file, src);
if (ferror (gcov_file))
- fnotice (stderr, "%s:error writing output file '%s'\n",
- src->name, gcov_file_name);
+ fnotice (stderr, "Error writing output file '%s'\n",
+ gcov_file_name);
fclose (gcov_file);
}
else
- fnotice (stderr, "%s:could not open output file '%s'\n",
- src->name, gcov_file_name);
+ fnotice (stderr, "Could not open output file '%s'\n",
+ gcov_file_name);
free (gcov_file_name);
}
fnotice (stdout, "\n");
@@ -657,16 +737,16 @@ release_function (function_t *fn)
static void
release_structures (void)
{
+ unsigned ix;
function_t *fn;
- source_t *src;
- while ((src = sources))
- {
- sources = src->next;
-
- free (src->name);
- free (src->lines);
- }
+ for (ix = n_sources; ix--;)
+ free (sources[ix].lines);
+ free (sources);
+
+ for (ix = n_names; ix--;)
+ free (names[ix].name);
+ free (names);
while ((fn = functions))
{
@@ -743,77 +823,167 @@ create_file_names (const char *file_name)
return;
}
+/* A is a string and B is a pointer to name_map_t. Compare for file
+ name orderability. */
+
+static int
+name_search (const void *a_, const void *b_)
+{
+ const char *a = (const char *)a_;
+ const name_map_t *b = (const name_map_t *)b_;
+
+#if HAVE_DOS_BASED_FILE_SYSTEM
+ return strcasecmp (a, b->name);
+#else
+ return strcmp (a, b->name);
+#endif
+}
+
+/* A and B are a pointer to name_map_t. Compare for file name
+ orderability. */
+
+static int
+name_sort (const void *a_, const void *b_)
+{
+ const name_map_t *a = (const name_map_t *)a_;
+ return name_search (a->name, b_);
+}
+
/* Find or create a source file structure for FILE_NAME. Copies
FILE_NAME on creation */
-static source_t *
+static unsigned
find_source (const char *file_name)
{
- source_t *src;
+ name_map_t *name_map;
+ char *canon;
+ unsigned idx;
struct stat status;
if (!file_name)
file_name = "<unknown>";
+ name_map = (name_map_t *)bsearch
+ (file_name, names, n_names, sizeof (*names), name_search);
+ if (name_map)
+ {
+ idx = name_map->src;
+ goto check_date;
+ }
- for (src = sources; src; src = src->next)
- if (!filename_cmp (file_name, src->name))
- break;
-
- if (!src)
+ if (n_names + 2 > a_names)
{
- src = XCNEW (source_t);
- src->name = xstrdup (file_name);
- src->coverage.name = src->name;
- src->index = source_index++;
- src->next = sources;
- sources = src;
+ /* Extend the name map array -- we'll be inserting one or two
+ entries. */
+ if (!a_names)
+ a_names = 10;
+ a_names *= 2;
+ name_map = XNEWVEC (name_map_t, a_names);
+ memcpy (name_map, names, n_names * sizeof (*names));
+ free (names);
+ names = name_map;
+ }
+
+ /* Not found, try the canonical name. */
+ canon = canonicalize_name (file_name);
+ name_map = (name_map_t *)bsearch
+ (canon, names, n_names, sizeof (*names), name_search);
+ if (!name_map)
+ {
+ /* Not found with canonical name, create a new source. */
+ source_t *src;
+
+ if (n_sources == a_sources)
+ {
+ if (!a_sources)
+ a_sources = 10;
+ a_sources *= 2;
+ src = XNEWVEC (source_t, a_sources);
+ memcpy (src, sources, n_sources * sizeof (*sources));
+ free (sources);
+ sources = src;
+ }
+
+ idx = n_sources;
- if (!stat (file_name, &status))
+ name_map = &names[n_names++];
+ name_map->name = canon;
+ name_map->src = idx;
+
+ src = &sources[n_sources++];
+ memset (src, 0, sizeof (*src));
+ src->name = canon;
+ src->coverage.name = src->name;
+ if (source_length
+#if HAVE_DOS_BASED_FILE_SYSTEM
+ /* You lose if separators don't match exactly in the
+ prefix. */
+ && !strncasecmp (source_prefix, src->coverage.name, source_length)
+#else
+ && !strncmp (source_prefix, src->coverage.name, source_length)
+#endif
+ && IS_DIR_SEPARATOR (src->coverage.name[source_length]))
+ src->coverage.name += source_length + 1;
+ if (!stat (src->name, &status))
src->file_time = status.st_mtime;
}
+ else
+ idx = name_map->src;
- if (src->file_time > bbg_file_time)
+ if (name_search (file_name, name_map))
+ {
+ /* Append the non-canonical name. */
+ name_map = &names[n_names++];
+ name_map->name = xstrdup (file_name);
+ name_map->src = idx;
+ }
+
+ /* Resort the name map. */
+ qsort (names, n_names, sizeof (*names), name_sort);
+
+ check_date:
+ if (sources[idx].file_time > bbg_file_time)
{
static int info_emitted;
fnotice (stderr, "%s:source file is newer than graph file '%s'\n",
- src->name, bbg_file_name);
+ file_name, bbg_file_name);
if (!info_emitted)
{
fnotice (stderr,
"(the message is only displayed one per source file)\n");
info_emitted = 1;
}
- src->file_time = 0;
+ sources[idx].file_time = 0;
}
- return src;
+ return idx;
}
-/* Read the graph file. Return nonzero on fatal error. */
+/* Read the graph file. Return list of functions read -- in reverse order. */
-static int
+static function_t *
read_graph_file (void)
{
unsigned version;
unsigned current_tag = 0;
- struct function_info *fn = NULL;
- function_t *old_functions_head = functions;
- source_t *src = NULL;
+ function_t *fn = NULL;
+ function_t *fns = NULL;
+ function_t **fns_end = &fns;
+ unsigned src_idx = 0;
unsigned ix;
unsigned tag;
if (!gcov_open (bbg_file_name, 1))
{
fnotice (stderr, "%s:cannot open graph file\n", bbg_file_name);
- return 1;
+ return fns;
}
bbg_file_time = gcov_time ();
if (!gcov_magic (gcov_read_unsigned (), GCOV_NOTE_MAGIC))
{
fnotice (stderr, "%s:not a gcov graph file\n", bbg_file_name);
gcov_close ();
- return 1;
+ return fns;
}
version = gcov_read_unsigned ();
@@ -839,14 +1009,12 @@ read_graph_file (void)
char *function_name;
unsigned ident, lineno;
unsigned lineno_checksum, cfg_checksum;
- source_t *src;
- function_t *probe, *prev;
ident = gcov_read_unsigned ();
lineno_checksum = gcov_read_unsigned ();
cfg_checksum = gcov_read_unsigned ();
function_name = xstrdup (gcov_read_string ());
- src = find_source (gcov_read_string ());
+ src_idx = find_source (gcov_read_string ());
lineno = gcov_read_unsigned ();
fn = XCNEW (function_t);
@@ -854,27 +1022,14 @@ read_graph_file (void)
fn->ident = ident;
fn->lineno_checksum = lineno_checksum;
fn->cfg_checksum = cfg_checksum;
- fn->src = src;
+ fn->src = src_idx;
fn->line = lineno;
- fn->next = functions;
- functions = fn;
+ fn->line_next = NULL;
+ fn->next = NULL;
+ *fns_end = fn;
+ fns_end = &fn->next;
current_tag = tag;
-
- if (lineno >= src->num_lines)
- src->num_lines = lineno + 1;
- /* Now insert it into the source file's list of
- functions. Normally functions will be encountered in
- ascending order, so a simple scan is quick. */
- for (probe = src->functions, prev = NULL;
- probe && probe->line > lineno;
- prev = probe, probe = probe->line_next)
- continue;
- fn->line_next = probe;
- if (prev)
- prev->line_next = fn;
- else
- src->functions = fn;
}
else if (fn && tag == GCOV_TAG_BLOCKS)
{
@@ -966,11 +1121,9 @@ read_graph_file (void)
if (!ix)
{
line_nos[ix++] = 0;
- line_nos[ix++] = src->index;
+ line_nos[ix++] = src_idx;
}
line_nos[ix++] = lineno;
- if (lineno >= src->num_lines)
- src->num_lines = lineno + 1;
}
else
{
@@ -978,10 +1131,9 @@ read_graph_file (void)
if (!file_name)
break;
- src = find_source (file_name);
-
+ src_idx = find_source (file_name);
line_nos[ix++] = 0;
- line_nos[ix++] = src->index;
+ line_nos[ix++] = src_idx;
}
}
@@ -998,72 +1150,22 @@ read_graph_file (void)
{
corrupt:;
fnotice (stderr, "%s:corrupted\n", bbg_file_name);
- gcov_close ();
- return 1;
+ break;
}
}
gcov_close ();
- /* We built everything backwards, so nreverse them all. */
-
- /* Reverse sources. Not strictly necessary, but we'll then process
- them in the 'expected' order. */
- {
- source_t *src, *src_p, *src_n;
-
- for (src_p = NULL, src = sources; src; src_p = src, src = src_n)
- {
- src_n = src->next;
- src->next = src_p;
- }
- sources = src_p;
- }
-
- /* Reverse functions. */
- {
- function_t *fn, *fn_p, *fn_n;
-
- for (fn_p = old_functions_head, fn = functions;
- fn != old_functions_head;
- fn_p = fn, fn = fn_n)
- {
- unsigned ix;
+ if (!fns)
+ fnotice (stderr, "%s:no functions found\n", bbg_file_name);
- fn_n = fn->next;
- fn->next = fn_p;
-
- /* Reverse the arcs. */
- for (ix = fn->num_blocks; ix--;)
- {
- arc_t *arc, *arc_p, *arc_n;
-
- for (arc_p = NULL, arc = fn->blocks[ix].succ; arc;
- arc_p = arc, arc = arc_n)
- {
- arc_n = arc->succ_next;
- arc->succ_next = arc_p;
- }
- fn->blocks[ix].succ = arc_p;
-
- for (arc_p = NULL, arc = fn->blocks[ix].pred; arc;
- arc_p = arc, arc = arc_n)
- {
- arc_n = arc->pred_next;
- arc->pred_next = arc_p;
- }
- fn->blocks[ix].pred = arc_p;
- }
- }
- functions = fn_p;
- }
- return 0;
+ return fns;
}
/* Reads profiles from the count file and attach to each
function. Return nonzero if fatal error. */
static int
-read_count_file (void)
+read_count_file (function_t *fns)
{
unsigned ix;
unsigned version;
@@ -1125,7 +1227,7 @@ read_count_file (void)
/* Try to find the function in the list. To speed up the
search, first start from the last function found. */
ident = gcov_read_unsigned ();
- fn_n = functions;
+ fn_n = fns;
for (fn = fn ? fn->next : NULL; ; fn = fn->next)
{
if (fn)
@@ -1190,6 +1292,28 @@ solve_flow_graph (function_t *fn)
block_t *valid_blocks = NULL; /* valid, but unpropagated blocks. */
block_t *invalid_blocks = NULL; /* invalid, but inferable blocks. */
+ /* The arcs were built in reverse order. Fix that now. */
+ for (ix = fn->num_blocks; ix--;)
+ {
+ arc_t *arc_p, *arc_n;
+
+ for (arc_p = NULL, arc = fn->blocks[ix].succ; arc;
+ arc_p = arc, arc = arc_n)
+ {
+ arc_n = arc->succ_next;
+ arc->succ_next = arc_p;
+ }
+ fn->blocks[ix].succ = arc_p;
+
+ for (arc_p = NULL, arc = fn->blocks[ix].pred; arc;
+ arc_p = arc, arc = arc_n)
+ {
+ arc_n = arc->pred_next;
+ arc->pred_next = arc_p;
+ }
+ fn->blocks[ix].pred = arc_p;
+ }
+
if (fn->num_blocks < 2)
fnotice (stderr, "%s:'%s' lacks entry and/or exit blocks\n",
bbg_file_name, fn->name);
@@ -1525,97 +1649,169 @@ function_summary (const coverage_t *coverage, const char *title)
}
}
-/* Generate an output file name. LONG_OUTPUT_NAMES and PRESERVE_PATHS
- affect name generation. With preserve_paths we create a filename
- from all path components of the source file, replacing '/' with
- '#', without it we simply take the basename component. With
+/* Canonicalize the filename NAME by canonicalizing directory
+ separators, eliding . components and resolving .. components
+ appropriately. Always returns a unique string. */
+
+static char *
+canonicalize_name (const char *name)
+{
+ /* The canonical name cannot be longer than the incoming name. */
+ char *result = XNEWVEC (char, strlen (name) + 1);
+ const char *base = name, *probe;
+ char *ptr = result;
+ char *dd_base;
+ int slash = 0;
+
+#if HAVE_DOS_BASED_FILE_SYSTEM
+ if (base[0] && base[1] == ':')
+ {
+ result[0] = base[0];
+ result[1] = ':';
+ base += 2;
+ ptr += 2;
+ }
+#endif
+ for (dd_base = ptr; *base; base = probe)
+ {
+ size_t len;
+
+ for (probe = base; *probe; probe++)
+ if (IS_DIR_SEPARATOR (*probe))
+ break;
+
+ len = probe - base;
+ if (len == 1 && base[0] == '.')
+ /* Elide a '.' directory */
+ ;
+ else if (len == 2 && base[0] == '.' && base[1] == '.')
+ {
+ /* '..', we can only elide it and the previous directory, if
+ we're not a symlink. */
+ struct stat buf;
+
+ *ptr = 0;
+ if (dd_base == ptr || stat (result, &buf) || S_ISLNK (buf.st_mode))
+ {
+ /* Cannot elide, or unreadable or a symlink. */
+ dd_base = ptr + 2 + slash;
+ goto regular;
+ }
+ while (ptr != dd_base && *ptr != '/')
+ ptr--;
+ slash = ptr != result;
+ }
+ else
+ {
+ regular:
+ /* Regular pathname component. */
+ if (slash)
+ *ptr++ = '/';
+ memcpy (ptr, base, len);
+ ptr += len;
+ slash = 1;
+ }
+
+ for (; IS_DIR_SEPARATOR (*probe); probe++)
+ continue;
+ }
+ *ptr = 0;
+
+ return result;
+}
+
+/* Generate an output file name. INPUT_NAME is the canonicalized main
+ input file and SRC_NAME is the canonicalized file name.
+ LONG_OUTPUT_NAMES and PRESERVE_PATHS affect name generation. With
long_output_names we prepend the processed name of the input file
to each output name (except when the current source file is the
input file, so you don't get a double concatenation). The two
- components are separated by '##'. Also '.' filename components are
- removed and '..' components are renamed to '^'. */
+ components are separated by '##'. With preserve_paths we create a
+ filename from all path components of the source file, replacing '/'
+ with '#', and .. with '^', without it we simply take the basename
+ component. (Remember, the canonicalized name will already have
+ elided '.' components and converted \\ separators.) */
static char *
make_gcov_file_name (const char *input_name, const char *src_name)
{
- const char *cptr;
- char *name;
+ char *ptr;
+ char *result;
if (flag_long_names && input_name && strcmp (src_name, input_name))
{
- name = XNEWVEC (char, strlen (src_name) + strlen (input_name) + 10);
- name[0] = 0;
/* Generate the input filename part. */
- cptr = flag_preserve_paths ? NULL : lbasename (input_name);
- strcat (name, cptr ? cptr : input_name);
- strcat (name, "##");
+ result = XNEWVEC (char, strlen (input_name) + strlen (src_name) + 10);
+
+ ptr = result;
+ ptr = mangle_name (input_name, ptr);
+ ptr[0] = ptr[1] = '#';
+ ptr += 2;
}
else
{
- name = XNEWVEC (char, strlen (src_name) + 10);
- name[0] = 0;
+ result = XNEWVEC (char, strlen (src_name) + 10);
+ ptr = result;
}
- /* Generate the source filename part. */
-
- cptr = flag_preserve_paths ? NULL : lbasename (src_name);
- strcat (name, cptr ? cptr : src_name);
+ ptr = mangle_name (src_name, ptr);
+ strcpy (ptr, ".gcov");
+
+ return result;
+}
- if (flag_preserve_paths)
+static char *
+mangle_name (char const *base, char *ptr)
+{
+ size_t len;
+
+ /* Generate the source filename part. */
+ if (!flag_preserve_paths)
+ {
+ base = lbasename (base);
+ len = strlen (base);
+ memcpy (ptr, base, len);
+ ptr += len;
+ }
+ else
{
- /* Convert '/' and '\' to '#', remove '/./', convert '/../' to '#^#',
+ /* Convert '/' to '#', convert '..' to '^',
convert ':' to '~' on DOS based file system. */
- char *pnew = name, *pold = name;
+ const char *probe;
- /* First check for leading drive separator. */
-
- while (*pold != '\0')
+#if HAVE_DOS_BASED_FILE_SYSTEM
+ if (base[0] && base[1] == ':')
{
-#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
- if (*pold == ':')
- {
- *pnew++ = '~';
- pold++;
- }
- else
+ ptr[0] = base[0];
+ ptr[1] = '~';
+ ptr += 2;
+ base += 2;
+ }
#endif
- if ((*pold == '/'
- && (strstr (pold, "/./") == pold
- || strstr (pold, "/.\\") == pold))
- || (*pold == '\\'
- && (strstr (pold, "\\.\\") == pold
- || strstr (pold, "\\./") == pold)))
- pold += 3;
- else if (*pold == '/'
- && (strstr (pold, "/../") == pold
- || strstr (pold, "/..\\") == pold))
- {
- strcpy (pnew, "#^#");
- pnew += 3;
- pold += 4;
- }
- else if (*pold == '\\'
- && (strstr (pold, "\\..\\") == pold
- || strstr (pold, "\\../") == pold))
+ for (; *base; base = probe)
+ {
+ size_t len;
+
+ for (probe = base; *probe; probe++)
+ if (*probe == '/')
+ break;
+ len = probe - base;
+ if (len == 2 && base[0] == '.' && base[1] == '.')
+ *ptr++ = '^';
+ else
{
- strcpy (pnew, "#^#");
- pnew += 3;
- pold += 4;
+ memcpy (ptr, base, len);
+ ptr += len;
}
- else if (*pold == '/' || *pold == '\\')
+ if (*probe)
{
- *pnew++ = '#';
- pold++;
+ *ptr++ = '#';
+ probe++;
}
- else
- *pnew++ = *pold++;
}
-
- *pnew = '\0';
}
-
- strcat (name, ".gcov");
- return name;
+
+ return ptr;
}
/* Scan through the bb_data for each line in the block, increment
@@ -1643,10 +1839,7 @@ add_line_counts (coverage_t *coverage, function_t *fn)
jx != block->u.line.num; jx++, encoding++)
if (!*encoding)
{
- unsigned src_n = *++encoding;
-
- for (src = sources; src->index != src_n; src = src->next)
- continue;
+ src = &sources[*++encoding];
jx++;
}
else
@@ -1671,7 +1864,10 @@ add_line_counts (coverage_t *coverage, function_t *fn)
/* Entry or exit block */;
else if (flag_all_blocks)
{
- line_t *block_line = line ? line : &fn->src->lines[fn->line];
+ line_t *block_line = line;
+
+ if (!block_line)
+ block_line = &sources[fn->src].lines[fn->line];
block->chain = block_line->u.blocks;
block_line->u.blocks = block;
@@ -1929,7 +2125,7 @@ output_lines (FILE *gcov_file, const source_t *src)
char const *retval = ""; /* status of source file reading. */
function_t *fn = NULL;
- fprintf (gcov_file, "%9s:%5d:Source:%s\n", "-", 0, src->name);
+ fprintf (gcov_file, "%9s:%5d:Source:%s\n", "-", 0, src->coverage.name);
if (!multiple_files)
{
fprintf (gcov_file, "%9s:%5d:Graph:%s\n", "-", 0, bbg_file_name);
@@ -1942,7 +2138,7 @@ output_lines (FILE *gcov_file, const source_t *src)
source_file = fopen (src->name, "r");
if (!source_file)
{
- fnotice (stderr, "%s:cannot open source file\n", src->name);
+ fnotice (stderr, "Cannot open source file %s\n", src->name);
retval = NULL;
}
else if (src->file_time == 0)
diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c
index df703b4ce75..f0e7c50e60e 100644
--- a/gcc/gimple-pretty-print.c
+++ b/gcc/gimple-pretty-print.c
@@ -1768,6 +1768,8 @@ dump_gimple_omp_atomic_load (pretty_printer *buffer, gimple gs, int spc,
else
{
pp_string (buffer, "#pragma omp atomic_load");
+ if (gimple_omp_atomic_need_value_p (gs))
+ pp_string (buffer, " [needed]");
newline_and_indent (buffer, spc + 2);
dump_generic_node (buffer, gimple_omp_atomic_load_lhs (gs),
spc, flags, false);
@@ -1795,7 +1797,10 @@ dump_gimple_omp_atomic_store (pretty_printer *buffer, gimple gs, int spc,
}
else
{
- pp_string (buffer, "#pragma omp atomic_store (");
+ pp_string (buffer, "#pragma omp atomic_store ");
+ if (gimple_omp_atomic_need_value_p (gs))
+ pp_string (buffer, "[needed] ");
+ pp_character (buffer, '(');
dump_generic_node (buffer, gimple_omp_atomic_store_val (gs),
spc, flags, false);
pp_character (buffer, ')');
diff --git a/gcc/gimple.c b/gcc/gimple.c
index 57f15af313c..6168d33ac05 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -2457,8 +2457,6 @@ gimple_set_modified (gimple s, bool modifiedp)
bool
gimple_has_side_effects (const_gimple s)
{
- unsigned i;
-
if (is_gimple_debug (s))
return false;
@@ -2474,47 +2472,15 @@ gimple_has_side_effects (const_gimple s)
if (is_gimple_call (s))
{
- unsigned nargs = gimple_call_num_args (s);
- tree fn;
+ int flags = gimple_call_flags (s);
- if (!(gimple_call_flags (s) & (ECF_CONST | ECF_PURE)))
- return true;
- else if (gimple_call_flags (s) & ECF_LOOPING_CONST_OR_PURE)
- /* An infinite loop is considered a side effect. */
+ /* An infinite loop is considered a side effect. */
+ if (!(flags & (ECF_CONST | ECF_PURE))
+ || (flags & ECF_LOOPING_CONST_OR_PURE))
return true;
- if (gimple_call_lhs (s)
- && TREE_SIDE_EFFECTS (gimple_call_lhs (s)))
- {
- gcc_checking_assert (gimple_has_volatile_ops (s));
- return true;
- }
-
- fn = gimple_call_fn (s);
- if (fn && TREE_SIDE_EFFECTS (fn))
- return true;
-
- for (i = 0; i < nargs; i++)
- if (TREE_SIDE_EFFECTS (gimple_call_arg (s, i)))
- {
- gcc_checking_assert (gimple_has_volatile_ops (s));
- return true;
- }
-
return false;
}
- else
- {
- for (i = 0; i < gimple_num_ops (s); i++)
- {
- tree op = gimple_op (s, i);
- if (op && TREE_SIDE_EFFECTS (op))
- {
- gcc_checking_assert (gimple_has_volatile_ops (s));
- return true;
- }
- }
- }
return false;
}
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 9845b692211..cfe6696f590 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -4554,6 +4554,16 @@ gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
gcc_assert (TREE_CODE (*expr_p) == MODIFY_EXPR
|| TREE_CODE (*expr_p) == INIT_EXPR);
+ /* Trying to simplify a clobber using normal logic doesn't work,
+ so handle it here. */
+ if (TREE_CLOBBER_P (*from_p))
+ {
+ gcc_assert (!want_value && TREE_CODE (*to_p) == VAR_DECL);
+ gimplify_seq_add_stmt (pre_p, gimple_build_assign (*to_p, *from_p));
+ *expr_p = NULL;
+ return GS_ALL_DONE;
+ }
+
/* Insert pointer conversions required by the middle-end that are not
required by the frontend. This fixes middle-end type checking for
for example gcc.dg/redecl-6.c. */
@@ -5335,6 +5345,8 @@ gimplify_target_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
if (init)
{
+ tree cleanup = NULL_TREE;
+
/* TARGET_EXPR temps aren't part of the enclosing block, so add it
to the temps list. Handle also variable length TARGET_EXPRs. */
if (TREE_CODE (DECL_SIZE (temp)) != INTEGER_CST)
@@ -5369,8 +5381,30 @@ gimplify_target_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
/* If needed, push the cleanup for the temp. */
if (TARGET_EXPR_CLEANUP (targ))
- gimple_push_cleanup (temp, TARGET_EXPR_CLEANUP (targ),
- CLEANUP_EH_ONLY (targ), pre_p);
+ {
+ if (CLEANUP_EH_ONLY (targ))
+ gimple_push_cleanup (temp, TARGET_EXPR_CLEANUP (targ),
+ CLEANUP_EH_ONLY (targ), pre_p);
+ else
+ cleanup = TARGET_EXPR_CLEANUP (targ);
+ }
+
+ /* Add a clobber for the temporary going out of scope, like
+ gimplify_bind_expr. */
+ if (needs_to_live_in_memory (temp))
+ {
+ tree clobber = build_constructor (TREE_TYPE (temp), NULL);
+ TREE_THIS_VOLATILE (clobber) = true;
+ clobber = build2 (MODIFY_EXPR, TREE_TYPE (temp), temp, clobber);
+ if (cleanup)
+ cleanup = build2 (COMPOUND_EXPR, void_type_node, cleanup,
+ clobber);
+ else
+ cleanup = clobber;
+ }
+
+ if (cleanup)
+ gimple_push_cleanup (temp, cleanup, false, pre_p);
/* Only expand this once. */
TREE_OPERAND (targ, 3) = init;
diff --git a/gcc/ipa.c b/gcc/ipa.c
index dfd8eef99ca..2f798460c4a 100644
--- a/gcc/ipa.c
+++ b/gcc/ipa.c
@@ -647,7 +647,7 @@ cgraph_externally_visible_p (struct cgraph_node *node,
/* Return true when variable VNODE should be considered externally visible. */
-static bool
+bool
varpool_externally_visible_p (struct varpool_node *vnode, bool aliased)
{
if (!DECL_COMDAT (vnode->decl) && !TREE_PUBLIC (vnode->decl))
diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog
index 26b98983ea1..3c176e823b4 100644
--- a/gcc/objc/ChangeLog
+++ b/gcc/objc/ChangeLog
@@ -1,3 +1,8 @@
+2011-11-12 Iain Sandoe <iains@gcc.gnu.org>
+
+ * objc-next-runtime-abi-01.c (objc_eh_personality): Use gcc personality
+ for Objective-C m32.
+
2011-10-29 Iain Sandoe <iains@gcc.gnu.org>
PR target/47997
diff --git a/gcc/objc/objc-next-runtime-abi-01.c b/gcc/objc/objc-next-runtime-abi-01.c
index c1e60b392d5..7d6a2125632 100644
--- a/gcc/objc/objc-next-runtime-abi-01.c
+++ b/gcc/objc/objc-next-runtime-abi-01.c
@@ -2872,12 +2872,15 @@ make_err_class:
return eh_id;
}
+/* For NeXT ABI 0 and 1, the personality routines are just those of the
+ underlying language. */
+
static tree
objc_eh_personality (void)
{
if (!objc_eh_personality_decl)
#ifndef OBJCPLUS
- objc_eh_personality_decl = build_personality_function ("objc");
+ objc_eh_personality_decl = build_personality_function ("gcc");
#else
objc_eh_personality_decl = build_personality_function ("gxx");
#endif
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index dc61c0bdf54..a4bfb8413fe 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -4977,25 +4977,125 @@ expand_omp_synch (struct omp_region *region)
operation as a normal volatile load. */
static bool
-expand_omp_atomic_load (basic_block load_bb, tree addr, tree loaded_val)
+expand_omp_atomic_load (basic_block load_bb, tree addr,
+ tree loaded_val, int index)
{
- /* FIXME */
- (void) load_bb;
- (void) addr;
- (void) loaded_val;
- return false;
+ enum built_in_function tmpbase;
+ gimple_stmt_iterator gsi;
+ basic_block store_bb;
+ location_t loc;
+ gimple stmt;
+ tree decl, call, type, itype;
+
+ gsi = gsi_last_bb (load_bb);
+ stmt = gsi_stmt (gsi);
+ gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
+ loc = gimple_location (stmt);
+
+ /* ??? If the target does not implement atomic_load_optab[mode], and mode
+ is smaller than word size, then expand_atomic_load assumes that the load
+ is atomic. We could avoid the builtin entirely in this case. */
+
+ tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
+ decl = builtin_decl_explicit (tmpbase);
+ if (decl == NULL_TREE)
+ return false;
+
+ type = TREE_TYPE (loaded_val);
+ itype = TREE_TYPE (TREE_TYPE (decl));
+
+ call = build_call_expr_loc (loc, decl, 2, addr,
+ build_int_cst (NULL, MEMMODEL_RELAXED));
+ if (!useless_type_conversion_p (type, itype))
+ call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
+ call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
+
+ force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
+ gsi_remove (&gsi, true);
+
+ store_bb = single_succ (load_bb);
+ gsi = gsi_last_bb (store_bb);
+ gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
+ gsi_remove (&gsi, true);
+
+ if (gimple_in_ssa_p (cfun))
+ update_ssa (TODO_update_ssa_no_phi);
+
+ return true;
}
/* A subroutine of expand_omp_atomic. Attempt to implement the atomic
operation as a normal volatile store. */
static bool
-expand_omp_atomic_store (basic_block load_bb, tree addr)
+expand_omp_atomic_store (basic_block load_bb, tree addr,
+ tree loaded_val, tree stored_val, int index)
{
- /* FIXME */
- (void) load_bb;
- (void) addr;
- return false;
+ enum built_in_function tmpbase;
+ gimple_stmt_iterator gsi;
+ basic_block store_bb = single_succ (load_bb);
+ location_t loc;
+ gimple stmt;
+ tree decl, call, type, itype;
+ enum machine_mode imode;
+ bool exchange;
+
+ gsi = gsi_last_bb (load_bb);
+ stmt = gsi_stmt (gsi);
+ gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
+
+ /* If the load value is needed, then this isn't a store but an exchange. */
+ exchange = gimple_omp_atomic_need_value_p (stmt);
+
+ gsi = gsi_last_bb (store_bb);
+ stmt = gsi_stmt (gsi);
+ gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
+ loc = gimple_location (stmt);
+
+ /* ??? If the target does not implement atomic_store_optab[mode], and mode
+ is smaller than word size, then expand_atomic_store assumes that the store
+ is atomic. We could avoid the builtin entirely in this case. */
+
+ tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
+ tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
+ decl = builtin_decl_explicit (tmpbase);
+ if (decl == NULL_TREE)
+ return false;
+
+ type = TREE_TYPE (stored_val);
+
+ /* Dig out the type of the function's second argument. */
+ itype = TREE_TYPE (decl);
+ itype = TYPE_ARG_TYPES (itype);
+ itype = TREE_CHAIN (itype);
+ itype = TREE_VALUE (itype);
+ imode = TYPE_MODE (itype);
+
+ if (exchange && !can_atomic_exchange_p (imode, true))
+ return false;
+
+ if (!useless_type_conversion_p (itype, type))
+ stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
+ call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
+ build_int_cst (NULL, MEMMODEL_RELAXED));
+ if (exchange)
+ {
+ if (!useless_type_conversion_p (type, itype))
+ call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
+ call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
+ }
+
+ force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
+ gsi_remove (&gsi, true);
+
+ /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
+ gsi = gsi_last_bb (load_bb);
+ gsi_remove (&gsi, true);
+
+ if (gimple_in_ssa_p (cfun))
+ update_ssa (TODO_update_ssa_no_phi);
+
+ return true;
}
/* A subroutine of expand_omp_atomic. Attempt to implement the atomic
@@ -5335,7 +5435,7 @@ expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
loaded_val = *addr;
and replace
- GIMPLE_OMP_ATOMIC_ATORE (stored_val) with
+ GIMPLE_OMP_ATOMIC_STORE (stored_val) with
*addr = stored_val;
*/
@@ -5403,33 +5503,30 @@ expand_omp_atomic (struct omp_region *region)
/* __sync builtins require strict data alignment. */
if (exact_log2 (align) >= index)
{
- /* Atomic load. FIXME: have some target hook signalize what loads
- are actually atomic? */
+ /* Atomic load. */
if (loaded_val == stored_val
&& (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
|| GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
&& GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
- && expand_omp_atomic_load (load_bb, addr, loaded_val))
+ && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
return;
- /* Atomic store. FIXME: have some target hook signalize what
- stores are actually atomic? */
+ /* Atomic store. */
if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
|| GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
&& GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
&& store_bb == single_succ (load_bb)
&& first_stmt (store_bb) == store
- && expand_omp_atomic_store (load_bb, addr))
+ && expand_omp_atomic_store (load_bb, addr, loaded_val,
+ stored_val, index))
return;
/* When possible, use specialized atomic update functions. */
if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
- && store_bb == single_succ (load_bb))
- {
- if (expand_omp_atomic_fetch_op (load_bb, addr,
- loaded_val, stored_val, index))
- return;
- }
+ && store_bb == single_succ (load_bb)
+ && expand_omp_atomic_fetch_op (load_bb, addr,
+ loaded_val, stored_val, index))
+ return;
/* If we don't have specialized __sync builtins, try and implement
as a compare and swap loop. */
diff --git a/gcc/optabs.c b/gcc/optabs.c
index b2388ec5c74..171756be7ef 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -7236,6 +7236,26 @@ can_compare_and_swap_p (enum machine_mode mode, bool allow_libcall)
return false;
}
+/* Return true if an atomic exchange can be performed. */
+
+bool
+can_atomic_exchange_p (enum machine_mode mode, bool allow_libcall)
+{
+ enum insn_code icode;
+
+ /* Check for __atomic_exchange. */
+ icode = direct_optab_handler (atomic_exchange_optab, mode);
+ if (icode != CODE_FOR_nothing)
+ return true;
+
+ /* Don't check __sync_test_and_set, as on some platforms that
+ has reduced functionality. Targets that really do support
+ a proper exchange should simply be updated to the __atomics. */
+
+ return can_compare_and_swap_p (mode, allow_libcall);
+}
+
+
/* Helper function to find the MODE_CC set in a sync_compare_and_swap
pattern. */
@@ -7875,8 +7895,15 @@ expand_atomic_fetch_op (rtx target, rtx mem, rtx val, enum rtx_code code,
Fetch_before == after REVERSE_OP val. */
if (!after)
code = optab.reverse_code;
- result = expand_simple_binop (mode, code, result, val, target, true,
- OPTAB_LIB_WIDEN);
+ if (code == NOT)
+ {
+ result = expand_simple_binop (mode, AND, result, val, NULL_RTX,
+ true, OPTAB_LIB_WIDEN);
+ result = expand_simple_unop (mode, NOT, result, target, true);
+ }
+ else
+ result = expand_simple_binop (mode, code, result, val, target,
+ true, OPTAB_LIB_WIDEN);
return result;
}
}
diff --git a/gcc/optabs.h b/gcc/optabs.h
index bc705dceb61..654d2766f40 100644
--- a/gcc/optabs.h
+++ b/gcc/optabs.h
@@ -971,6 +971,9 @@ enum insn_code can_float_p (enum machine_mode, enum machine_mode, int);
/* Return true if there is an inline compare and swap pattern. */
extern bool can_compare_and_swap_p (enum machine_mode, bool);
+/* Return true if there is an inline atomic exchange pattern. */
+extern bool can_atomic_exchange_p (enum machine_mode, bool);
+
/* Generate code for a compare and swap. */
extern bool expand_atomic_compare_and_swap (rtx *, rtx *, rtx, rtx, rtx, bool,
enum memmodel, enum memmodel);
diff --git a/gcc/opts-common.c b/gcc/opts-common.c
index 00edbe6601c..354bce07dc2 100644
--- a/gcc/opts-common.c
+++ b/gcc/opts-common.c
@@ -304,6 +304,8 @@ generate_canonical_option (size_t opt_index, const char *arg, int value,
decoded->canonical_option[0] = concat (opt_text, arg, NULL);
decoded->canonical_option[1] = NULL;
decoded->canonical_option_num_elements = 1;
+ if (opt_text != option->opt_text)
+ free (CONST_CAST (char *, opt_text));
}
}
else
diff --git a/gcc/output.h b/gcc/output.h
index e47eddf2735..e73c4a4c6bc 100644
--- a/gcc/output.h
+++ b/gcc/output.h
@@ -129,6 +129,11 @@ typedef HOST_WIDE_INT __gcc_host_wide_int__;
#define ATTRIBUTE_ASM_FPRINTF(m, n) ATTRIBUTE_NONNULL(m)
#endif
+extern void fprint_w (FILE *, HOST_WIDE_INT);
+extern void fprint_whex (FILE *, unsigned HOST_WIDE_INT);
+extern void fprint_ul (FILE *, unsigned long);
+extern int sprint_ul (char *, unsigned long);
+
extern void asm_fprintf (FILE *file, const char *p, ...)
ATTRIBUTE_ASM_FPRINTF(2, 3);
@@ -659,6 +664,10 @@ extern void file_end_indicate_split_stack (void);
extern void default_elf_asm_output_external (FILE *file, tree,
const char *);
+extern void default_elf_asm_output_limited_string (FILE *, const char *);
+extern void default_elf_asm_output_ascii (FILE *, const char *, unsigned int);
+extern void default_elf_internal_label (FILE *, const char *, unsigned long);
+
extern void default_elf_init_array_asm_out_constructor (rtx, int);
extern void default_elf_fini_array_asm_out_destructor (rtx, int);
extern int maybe_assemble_visibility (tree);
diff --git a/gcc/sync-builtins.def b/gcc/sync-builtins.def
index 1a2df9ac018..15ff479bb5e 100644
--- a/gcc/sync-builtins.def
+++ b/gcc/sync-builtins.def
@@ -259,6 +259,12 @@ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_SYNCHRONIZE, "__sync_synchronize",
/* __sync* builtins for the C++ memory model. */
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_TEST_AND_SET, "__atomic_test_and_set",
+ BT_FN_BOOL_VPTR_INT, ATTR_NOTHROW_LEAF_LIST)
+
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_CLEAR, "__atomic_clear", BT_FN_VOID_VPTR_INT,
+ ATTR_NOTHROW_LEAF_LIST)
+
DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_EXCHANGE,
"__atomic_exchange",
BT_FN_VOID_SIZE_VPTR_PTR_PTR_INT, ATTR_NOTHROW_LEAF_LIST)
diff --git a/gcc/system.h b/gcc/system.h
index 7c7d07ea3ee..0a943a3a3fe 100644
--- a/gcc/system.h
+++ b/gcc/system.h
@@ -442,6 +442,10 @@ extern void *sbrk (int);
extern char *strstr (const char *, const char *);
#endif
+#if defined (HAVE_DECL_STPCPY) && !HAVE_DECL_STPCPY
+extern char *stpcpy (char *, const char *);
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 4052135cf2c..57e5eb57ea5 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,6 +1,168 @@
+2011-11-14 Zolotukhin Michael <michael.v.zolotukhin@gmail.com>
+ Jan Hubicka <jh@suse.cz>
+
+ * gcc.target/i386/sw-1.c: Force rep;movsb.
+
+2011-11-14 Iain Sandoe <iains@gcc.gnu.org>
+
+ PR testsuite/51059
+ * gcc.misc-tests/gcov-14.c (dg-options): Adjust to use
+ dg-additional-options.
+
+2011-11-13 Oleg Endo <oleg.endo@t-online.de>
+
+ * gcc.target/sh/pr21255-2-ml.c: Skip if -mb or -m5* is
+ specified. Remove redundant runtime checks.
+ * gcc.target/sh/20080410-1.c: Skip if -mb is specified.
+ Allow for other than -m4. Fix typos in comments.
+
+2011-11-12 Jason Merrill <jason@redhat.com>
+
+ PR c++/986
+ * g++.dg/warn/ref-temp1.C: New.
+
+ PR c++/51060
+ * g++.dg/opt/stack2.C: New.
+
+2011-11-12 Uros Bizjak <ubizjak@gmail.com>
+
+ * lib/gcc-simulate-thread.exp (simulate-thread): Do not run on
+ alpha*-*-linux* targets.
+
+2011-11-12 Iain Sandoe <iains@gcc.gnu.org>
+
+ PR testsuite/51059
+ * gcc.misc-tests/gcov-14.c (dg-options): Force flat namespace for
+ Darwin targets and allow external symbols to be undefined.
+
+2011-11-12 Nathan Sidwell <nathan@acm.org>
+
+ * gcc.misc-tests/gcov-15.c: New.
+
+2011-11-11 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/51058
+ * gcc.dg/vect/fast-math-vect-call-1.c: Add f4 test.
+ * gfortran.dg/vect/pr51058-2.f90: New test.
+
+2011-11-10 Jason Merrill <jason@redhat.com>
+
+ * g++.dg/template/linkage1.C: New.
+ * g++.dg/ext/visibility/anon8.C: Adjust for C++11.
+ * g++.old-deja/g++.other/linkage4.C: Likewise.
+
+ PR c++/50973
+ * g++.dg/cpp0x/defaulted33.C: New.
+
+2011-11-10 Andrew MacLeod <amacleod@redhat.com>
+
+ PR middle-end/51038
+ * gcc.dg/atomic-invalid.c: Add test for invalid __atomic_clear models.
+ * gcc.dg/atomic-flag.c: New. Test __atomic_test_and_set and
+ __atomic_clear.
+
+2011-11-10 Andrew MacLeod <amacleod@redhat.com>
+
+ PR rtl-optimization/51040
+ * testsuite/gcc.dg/atomic-noinline[-aux].c: Test no-inline NAND and
+ patchup code.
+
+2011-11-10 Jason Merrill <jason@redhat.com>
+
+ PR c++/51079
+ * g++.dg/template/conv12.C: New.
+
+ PR debug/50983
+ * gcc.dg/debug/dwarf2/asm-line1.c: New.
+
+2011-11-10 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/atomic6_1.adb: New test.
+ * gnat.dg/atomic6_2.adb: Likewise.
+ * gnat.dg/atomic6_3.adb: Likewise.
+ * gnat.dg/atomic6_4.adb: Likewise.
+ * gnat.dg/atomic6_5.adb: Likewise.
+ * gnat.dg/atomic6_6.adb: Likewise.
+ * gnat.dg/atomic6_7.adb: Likewise.
+ * gnat.dg/atomic6_8.adb: Likewise.
+ * gnat.dg/atomic6_pkg.ads: New helper.
+
+2011-11-10 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/51077
+ * gcc.c-torture/compile/pr51077.c: New test.
+
+ PR rtl-optimization/51023
+ * gcc.c-torture/execute/pr51023.c: New test.
+
+2011-11-10 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/51042
+ * gcc.dg/torture/pr51042.c: New testcase.
+
+2011-11-10 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/51070
+ * gcc.dg/torture/pr51070.c: New testcase.
+
+2011-11-10 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/51030
+ * gcc.dg/tree-ssa/phi-opt-6.c: New testcase.
+
+2011-11-10 Richard Guenther <rguenther@suse.de>
+
+ PR middle-end/51071
+ * gcc.dg/torture/pr51071.c: New testcase.
+
+2011-11-10 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/loop_optimization9.ad[sb]: New test.
+
+2011-11-10 Ira Rosen <ira.rosen@linaro.org>
+
+ PR tree-optimization/51058
+ * gfortran.dg/vect/pr51058.f90: New test.
+
+2011-11-10 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/51000
+ * gcc.dg/vect/pr51000.c: New test.
+
+2011-11-09 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/50837
+ * g++.dg/cpp0x/static_assert5.C: New.
+ * g++.dg/template/nontype13.C: Tweak.
+
+2011-11-09 Jason Merrill <jason@redhat.com>
+
+ PR c++/50972
+ * g++.dg/cpp0x/noexcept16.C: New.
+
+ PR c++/51046
+ * g++.dg/cpp0x/variadic119.C: New.
+
+2011-11-09 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/50911
+ * gcc.dg/torture/vshuf-16.inc: Add interleave low and high
+ permutations.
+ * gcc.dg/torture/vshuf-32.inc: Likewise.
+ * gcc.dg/torture/vshuf-4.inc: Likewise.
+ * gcc.dg/torture/vshuf-8.inc: Likewise.
+
+ * gcc.dg/tm/memopt-1.c: Fix up regexp.
+
+2011-11-09 Ian Lance Taylor <iant@google.com>
+
+ * lib/target-supports.exp (check_effective_target_ucontext_h): New
+ procedure.
+ * gcc.dg/split-5.c: New test.
+
2011-11-09 Patrick Marlier <patrick.marlier@gmail.com>
- * gcc.dg/tm/memopt-1.c: Adjust regexp.
+ * gcc.dg/tm/memopt-1.c: Adjust regexp.
2011-11-09 Jason Merrill <jason@redhat.com>
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted33.C b/gcc/testsuite/g++.dg/cpp0x/defaulted33.C
new file mode 100644
index 00000000000..2f11c1369d8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted33.C
@@ -0,0 +1,32 @@
+// PR c++/50973
+// { dg-do compile { target c++11 } }
+
+class HD
+{
+ public:
+ virtual ~HD() {};
+};
+class InputHD : public virtual HD
+{
+};
+class OutputHD : public virtual HD
+{
+};
+class IOHD : public InputHD, public OutputHD
+{
+};
+template <typename T, unsigned int N>
+class ArrayNHD : public IOHD
+{
+ public:
+ ~ArrayNHD() = default;
+};
+class TLText
+{
+ ~TLText();
+ ArrayNHD<int, 1>* m_argsHD;
+};
+TLText::~TLText()
+{
+ delete m_argsHD;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept16.C b/gcc/testsuite/g++.dg/cpp0x/noexcept16.C
new file mode 100644
index 00000000000..10e0be95887
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept16.C
@@ -0,0 +1,130 @@
+// PR c++/50972
+// { dg-do compile { target c++11 } }
+// Ignore all errors, we're just testing that this doesn't ICE
+// { dg-prune-output "error" }
+
+namespace std
+typedef long unsigned int size_t;
+template<typename...>
+struct __and_;
+template<typename _Tp>
+struct is_nothrow_move_constructible
+{
+};
+template<typename _Tp>
+struct is_nothrow_move_assignable
+struct __add_rvalue_reference_helper<_Tp, true>
+{ typedef _Tp&& type; };
+template<typename _Tp>
+struct add_rvalue_reference
+ : public __add_rvalue_reference_helper<_Tp>
+{
+};
+template<typename _Tp>
+inline typename add_rvalue_reference<_Tp>::type
+declval() noexcept
+{
+}
+}
+namespace __gnu_cxx __attribute__ ((__visibility__ ("default")))
+template<typename _Tp>
+class new_allocator
+{
+};
+}
+namespace std __attribute__ ((__visibility__ ("default")))
+class allocator: public __gnu_cxx::new_allocator<_Tp>
+{
+ template<typename _Tp1>
+ struct rebind
+ { typedef allocator<_Tp1> other; };
+};
+}
+namespace std __attribute__ ((__visibility__ ("default")))
+template<typename _Alloc, typename _Tp>
+struct __alloctr_rebind<_Alloc, _Tp, true>
+{
+ typedef typename _Alloc::template rebind<_Tp>::other __type;
+};
+template<typename _Alloc>
+struct allocator_traits
+{
+ template<typename _Tp>
+ struct __rebind_alloc
+ {
+ typedef typename __alloctr_rebind<_Alloc, _Tp>::__type __type;
+ };
+}
+ }
+namespace __gnu_cxx __attribute__ ((__visibility__ ("default")))
+template<typename _Alloc>
+struct __alloc_traits
+{
+ typedef std::allocator_traits<_Alloc> _Base_type;
+ static constexpr bool _S_nothrow_swap()
+ {
+ return !_S_propagate_on_swap()
+ || noexcept(swap(std::declval<_Alloc&>(), std::declval<_Alloc&>()));
+ }
+ template<typename _Tp>
+ struct rebind
+ { typedef typename _Base_type::template __rebind_alloc<_Tp>::__type other; };
+};
+}
+namespace std __attribute__ ((__visibility__ ("default")))
+template<typename _Tp, typename _Alloc>
+struct _Vector_base
+{
+ typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template
+ rebind<_Tp>::other _Tp_alloc_type;
+};
+template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
+class vector : protected _Vector_base<_Tp, _Alloc>
+{
+ typedef _Vector_base<_Tp, _Alloc> _Base;
+ typedef typename _Base::_Tp_alloc_type _Tp_alloc_type;
+ typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Alloc_traits;
+ swap(vector& __x)
+ noexcept(_Alloc_traits::_S_nothrow_swap());
+};
+}
+namespace lexertl
+namespace detail
+}
+namespace detail
+template<typename id_type>
+struct basic_internals
+{
+ typedef std::vector<id_type> id_type_vector;
+};
+};
+template<typename char_type, typename id_type = std::size_t>
+class basic_state_machine
+{
+ typedef detail::basic_internals<id_type> internals;
+ void minimise ()
+ {
+ minimise_dfa (dfa_alphabet_, *dfa_, size_);
+ }
+ typedef typename internals::id_type_vector id_type_vector;
+ void minimise_dfa (const id_type dfa_alphabet_,
+ id_type_vector &dfa_, std::size_t size_)
+ {
+ id_type_vector new_dfa_ (front_, front_ + dfa_alphabet_);
+ dfa_.swap (new_dfa_);
+ }
+}
+ }
+namespace std __attribute__ ((__visibility__ ("default")))
+template<typename _Tp>
+void
+swap(_Tp&, _Tp&)
+ noexcept(__and_<is_nothrow_move_constructible<_Tp>,
+ is_nothrow_move_assignable<_Tp>>::value)
+ ;
+typedef lexertl::basic_state_machine<char32_t> lexstate;
+lexstate m_state_machine;
+GenerateLexer()
+{
+ m_state_machine.minimise();
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/static_assert5.C b/gcc/testsuite/g++.dg/cpp0x/static_assert5.C
new file mode 100644
index 00000000000..b918796220c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/static_assert5.C
@@ -0,0 +1,21 @@
+// PR c++/50837
+// { dg-options "-std=c++0x" }
+
+template<class T>
+struct z
+{
+ static constexpr bool test_constexpr()
+ {
+ return true;
+ }
+
+ static void test()
+ {
+ static_assert(test_constexpr(), "test1");
+ }
+};
+
+int main()
+{
+ z<int>::test();
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic119.C b/gcc/testsuite/g++.dg/cpp0x/variadic119.C
new file mode 100644
index 00000000000..78cd23e2051
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic119.C
@@ -0,0 +1,13 @@
+// PR c++/51046
+// { dg-do compile { target c++11 } }
+
+template<int... IS>
+void f()
+{
+ for (int i : IS); // { dg-error "not expanded" }
+}
+
+int main()
+{
+ f<0, 1, 2>();
+}
diff --git a/gcc/testsuite/g++.dg/ext/visibility/anon8.C b/gcc/testsuite/g++.dg/ext/visibility/anon8.C
index 8ef8d682336..5e58b551994 100644
--- a/gcc/testsuite/g++.dg/ext/visibility/anon8.C
+++ b/gcc/testsuite/g++.dg/ext/visibility/anon8.C
@@ -26,10 +26,8 @@ int main ()
static void fn2 () {}
};
call<&B1::fn1> ();
- call<&B2::fn2> (); // { dg-error "not external linkage|no matching" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 29 }
+ call<&B2::fn2> (); // { dg-error "linkage|no matching" }
call<&fn3> ();
call<&B1::fn4> ();
- call<&fn5> (); // { dg-error "not external linkage|no matching" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 33 }
+ call<&fn5> (); // { dg-error "linkage|no matching" "" { target c++98 } }
}
diff --git a/gcc/testsuite/g++.dg/opt/stack2.C b/gcc/testsuite/g++.dg/opt/stack2.C
new file mode 100644
index 00000000000..8468e1a6883
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/stack2.C
@@ -0,0 +1,33 @@
+// PR c++/51060
+// { dg-options "-Os -Wframe-larger-than=2000 -Werror" }
+
+// Shows a problem of not re-using stack space:
+// Compile as: g++ -c test_stack_reuse.cpp -o /dev/null -Wframe-larger-than=2048 -Werror -Os
+// Result: warning: the frame size of 10240 bytes is larger than 2048 bytes [-Wframe-larger-than=]
+//
+
+struct StackObject
+{
+ StackObject();
+ char buffer[1024];
+};
+
+void Test()
+{
+#define TEST_SUB() \
+ StackObject();
+
+#define TEST() \
+ TEST_SUB() \
+ TEST_SUB() \
+ TEST_SUB() \
+ TEST_SUB() \
+ TEST_SUB() \
+ TEST_SUB() \
+ TEST_SUB() \
+ TEST_SUB() \
+ TEST_SUB() \
+ TEST_SUB()
+
+ TEST()
+}
diff --git a/gcc/testsuite/g++.dg/parse/template21.C b/gcc/testsuite/g++.dg/parse/template21.C
index e1ac76916e7..963d269028d 100644
--- a/gcc/testsuite/g++.dg/parse/template21.C
+++ b/gcc/testsuite/g++.dg/parse/template21.C
@@ -2,4 +2,4 @@
template <const int*> class Helper { };
const int foo = 0;
-typedef Helper<&foo> HelperType; // { dg-error "linkage|type" }
+typedef Helper<&foo> HelperType; // { dg-error "linkage|type" "" { target c++98 } }
diff --git a/gcc/testsuite/g++.dg/template/conv12.C b/gcc/testsuite/g++.dg/template/conv12.C
new file mode 100644
index 00000000000..e6af05481d7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/conv12.C
@@ -0,0 +1,25 @@
+// PR c++/51079
+
+#if __cplusplus > 199711L
+struct C1
+{
+ template <class T>
+ operator T() = delete; // { dg-message "declared here" "" { target c++11 } }
+ operator bool() { return false; }
+} c1;
+
+int ic1 = c1; // { dg-error "deleted" "" { target c++11 } }
+int ac1 = c1 + c1; // { dg-error "deleted" "" { target c++11 } }
+#endif
+
+struct C2
+{
+private:
+ template <class T>
+ operator T(); // { dg-error "private" }
+public:
+ operator bool() { return false; }
+} c2;
+
+int ic2 = c2; // { dg-error "" }
+int ac2 = c2 + c2; // { dg-error "" }
diff --git a/gcc/testsuite/g++.dg/template/linkage1.C b/gcc/testsuite/g++.dg/template/linkage1.C
new file mode 100644
index 00000000000..02aa9672963
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/linkage1.C
@@ -0,0 +1,18 @@
+// PR c++/50372
+// Test that a template instantiation has the same linkage as its argument.
+// { dg-final { scan-assembler "(weak|glob)\[^\n\]*_Z3fooIXadL_Z13external_funcvEEEvv" } }
+// { dg-final { scan-assembler-not "(weak|glob)\[^\n\]*_Z3fooIXadL_ZL11static_funcvEEEvv" } }
+
+template<void (*fptr)(void)>
+void foo() { }
+
+static void static_func() {}
+void external_func() { }
+
+void test()
+{
+#if __cplusplus > 199711L
+ foo<&static_func>();
+#endif
+ foo<&external_func>();
+}
diff --git a/gcc/testsuite/g++.dg/template/nontype13.C b/gcc/testsuite/g++.dg/template/nontype13.C
index 4b3e862ba80..d604da94454 100644
--- a/gcc/testsuite/g++.dg/template/nontype13.C
+++ b/gcc/testsuite/g++.dg/template/nontype13.C
@@ -11,7 +11,7 @@ struct Dummy
template<bool B>
void tester()
{
- bar<evil>()(); // { dg-error "constant" }
+ bar<evil>()(); // { dg-error "constant|template" }
}
template<bool B>
struct bar
diff --git a/gcc/testsuite/g++.dg/warn/ref-temp1.C b/gcc/testsuite/g++.dg/warn/ref-temp1.C
new file mode 100644
index 00000000000..26f1ca5de84
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/ref-temp1.C
@@ -0,0 +1,11 @@
+// PR c++/986
+// { dg-options "-Wall -Wextra" }
+
+struct X { X (int); };
+
+struct Y {
+ Y ();
+ const X &x; // note the ampersand
+};
+
+Y::Y () : x(1) {} // { dg-warning "temporary" }
diff --git a/gcc/testsuite/g++.old-deja/g++.other/linkage4.C b/gcc/testsuite/g++.old-deja/g++.other/linkage4.C
index 7531f451664..450733fab34 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/linkage4.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/linkage4.C
@@ -8,4 +8,4 @@ void f () {}
// Check that the strlen declaration here is given internal linkage by
// using it as a non-type template argument, and expecting an error.
-template void f<strlen>(); // { dg-error "" } no matching template
+template void f<strlen>(); // { dg-error "" "" { target c++98 } } no matching template
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr51077.c b/gcc/testsuite/gcc.c-torture/compile/pr51077.c
new file mode 100644
index 00000000000..de2b97e58e9
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr51077.c
@@ -0,0 +1,15 @@
+/* PR middle-end/51077 */
+
+struct S { unsigned char s, t[256]; };
+
+void
+foo (const struct S *x, struct S *y, int z)
+{
+ int i;
+ for (i = 0; i < 8; i++)
+ {
+ const struct S *a = &x[i];
+ __builtin___memcpy_chk (y->t, a->t, z, __builtin_object_size (y->t, 0));
+ y = (struct S *) &y->t[z];
+ }
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr51023.c b/gcc/testsuite/gcc.c-torture/execute/pr51023.c
new file mode 100644
index 00000000000..34252ea0ae0
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr51023.c
@@ -0,0 +1,18 @@
+/* PR rtl-optimization/51023 */
+
+extern void abort (void);
+
+short int
+foo (long int x)
+{
+ return x;
+}
+
+int
+main ()
+{
+ long int a = 0x4272AL;
+ if (foo (a) == a)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/atomic-flag.c b/gcc/testsuite/gcc.dg/atomic-flag.c
new file mode 100644
index 00000000000..771df2c6091
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/atomic-flag.c
@@ -0,0 +1,32 @@
+/* Test __atomic routines for existence and execution. */
+/* { dg-do run } */
+
+#include <stdbool.h>
+
+/* Test that __atomic_test_and_set and __atomic_clear builtins execute. */
+
+extern void abort(void);
+bool a;
+
+main ()
+{
+ bool b;
+
+ __atomic_clear (&a, __ATOMIC_RELAXED);
+ if (a != 0)
+ abort ();
+
+ b = __atomic_test_and_set (&a, __ATOMIC_SEQ_CST);
+ if (a != 1 || b != 0)
+ abort ();
+
+ b = __atomic_test_and_set (&a, __ATOMIC_ACQ_REL);
+ if (b != 1 || a != 1)
+ abort ();
+
+ __atomic_clear (&a, __ATOMIC_SEQ_CST);
+ if (a != 0)
+ abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/atomic-invalid.c b/gcc/testsuite/gcc.dg/atomic-invalid.c
index 2b73c91e7c0..48de91f6c75 100644
--- a/gcc/testsuite/gcc.dg/atomic-invalid.c
+++ b/gcc/testsuite/gcc.dg/atomic-invalid.c
@@ -4,9 +4,11 @@
/* { dg-require-effective-target sync_int_long } */
#include <stddef.h>
+#include <stdbool.h>
int i, e, b;
size_t s;
+bool x;
main ()
{
@@ -26,4 +28,9 @@ main ()
i = __atomic_always_lock_free (s, NULL); /* { dg-error "non-constant argument" } */
__atomic_load_n (&i, 44); /* { dg-warning "invalid memory model" } */
+
+ __atomic_clear (&x, __ATOMIC_ACQUIRE); /* { dg-error "invalid memory model" } */
+
+ __atomic_clear (&x, __ATOMIC_ACQ_REL); /* { dg-error "invalid memory model" } */
+
}
diff --git a/gcc/testsuite/gcc.dg/atomic-noinline-aux.c b/gcc/testsuite/gcc.dg/atomic-noinline-aux.c
index b92fcfcd60f..b05460e469b 100644
--- a/gcc/testsuite/gcc.dg/atomic-noinline-aux.c
+++ b/gcc/testsuite/gcc.dg/atomic-noinline-aux.c
@@ -40,11 +40,24 @@ char __atomic_fetch_add_1 (char *p, char v, int i)
*p = 1;
}
-short __atomic_fetch_add_2 (short *p, short v, short i)
+short __atomic_fetch_add_2 (short *p, short v, int i)
{
*p = 1;
}
+/* Really perform a NAND. PR51040 showed incorrect calculation of a
+ non-inlined fetch_nand. */
+unsigned char
+__atomic_fetch_nand_1 (unsigned char *p, unsigned char v, int i)
+{
+ unsigned char ret;
+
+ ret = *p;
+ *p = ~(*p & v);
+
+ return ret;
+}
+
int __atomic_is_lock_free (int i, void *p)
{
return 10;
diff --git a/gcc/testsuite/gcc.dg/atomic-noinline.c b/gcc/testsuite/gcc.dg/atomic-noinline.c
index 06a93e0058e..eb0866e549e 100644
--- a/gcc/testsuite/gcc.dg/atomic-noinline.c
+++ b/gcc/testsuite/gcc.dg/atomic-noinline.c
@@ -49,6 +49,13 @@ main ()
if (__atomic_is_lock_free (4, 0) != 10)
abort ();
+ /* PR 51040 was caused by arithmetic code not patching up nand_fetch properly
+ when used an an external function. Look for proper return value here. */
+ ac = 0x3C;
+ bc = __atomic_nand_fetch (&ac, 0x0f, __ATOMIC_RELAXED);
+ if (bc != ac)
+ abort ();
+
return 0;
}
diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/asm-line1.c b/gcc/testsuite/gcc.dg/debug/dwarf2/asm-line1.c
new file mode 100644
index 00000000000..1d2e1481e5a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/dwarf2/asm-line1.c
@@ -0,0 +1,20 @@
+/* PR debug/50983 */
+/* { dg-do compile { target *-*-linux-gnu } } */
+/* { dg-options "-O0 -gdwarf-2" } */
+/* { dg-final { scan-assembler "is_stmt 1" } } */
+
+int i;
+void f() __attribute ((section ("foo")));
+void f() { if (i) ++i; else --i; }
+
+void fun()
+{
+ return;
+}
+
+int main()
+{
+ f();
+ fun();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/split-5.c b/gcc/testsuite/gcc.dg/split-5.c
new file mode 100644
index 00000000000..601640f22e9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/split-5.c
@@ -0,0 +1,171 @@
+/* { dg-do run } */
+/* { dg-require-effective-target split_stack } */
+/* { dg-require-effective-target pthread_h } */
+/* { dg-require-effective-target ucontext_h } */
+/* { dg-options "-pthread -fsplit-stack" } */
+
+#include <stdlib.h>
+#include <pthread.h>
+#include <ucontext.h>
+
+extern void __splitstack_getcontext (void *context[10]);
+
+extern void __splitstack_setcontext (void *context[10]);
+
+extern void *__splitstack_makecontext (size_t, void *context[10], size_t *);
+
+extern void __splitstack_block_signals (int *, int *);
+
+extern void __splitstack_block_signals_context (void *context[10], int *,
+ int *);
+
+extern void *__splitstack_find (void *, void *, size_t *, void **, void **,
+ void **);
+
+extern void *__splitstack_find_context (void *context[10], size_t *, void **,
+ void **, void **);
+
+static ucontext_t c1;
+static void *s1[10];
+
+static ucontext_t c2;
+static void *s2[10];
+
+static void swap (ucontext_t *, void *fs[10], ucontext_t *, void *ts[10])
+ __attribute__ ((no_split_stack));
+
+static void
+swap (ucontext_t *fu, void *fs[10], ucontext_t *tu, void *ts[10])
+{
+ __splitstack_getcontext (fs);
+ __splitstack_setcontext (ts);
+ swapcontext (fu, tu);
+ __splitstack_setcontext (fs);
+}
+
+/* Use a noinline function to ensure that the buffer is not removed
+ from the stack. */
+static void use_buffer (char *buf) __attribute__ ((noinline));
+static void
+use_buffer (char *buf)
+{
+ buf[0] = '\0';
+}
+
+static void
+down (int i, const char *msg, ucontext_t *me, void *mes[10],
+ ucontext_t *other, void *others[10])
+{
+ char buf[10000];
+
+ if (i > 0)
+ {
+ use_buffer (buf);
+ swap (me, mes, other, others);
+ down (i - 1, msg, me, mes, other, others);
+ }
+ else
+ {
+ int c = 0;
+ void *stack;
+ size_t stack_size;
+ void *next_segment = NULL;
+ void *next_sp = NULL;
+ void *initial_sp = NULL;
+
+ stack = __splitstack_find_context (mes, &stack_size, &next_segment,
+ &next_sp, &initial_sp);
+ if (stack != NULL)
+ {
+ ++c;
+ while (__splitstack_find (next_segment, next_sp, &stack_size,
+ &next_segment, &next_sp, &initial_sp)
+ != NULL)
+ ++c;
+ }
+ }
+}
+
+static void
+go1 (void)
+{
+ down (1000, "go1", &c1, s1, &c2, s2);
+ pthread_exit (NULL);
+}
+
+static void
+go2 (void)
+{
+ down (1000, "go2", &c2, s2, &c1, s1);
+ pthread_exit (NULL);
+}
+
+struct thread_context
+{
+ ucontext_t *u;
+ void **s;
+};
+
+static void *start_thread (void *) __attribute__ ((no_split_stack));
+
+static void *
+start_thread (void *context)
+{
+ struct thread_context *tc = (struct thread_context *) context;
+ int block;
+
+ block = 0;
+ __splitstack_block_signals (&block, NULL);
+ __splitstack_setcontext (tc->s);
+ setcontext (tc->u);
+ abort ();
+}
+
+int
+main (int argc __attribute__ ((unused)), char **argv __attribute__ ((unused)))
+{
+ pthread_t tid;
+ int err;
+ size_t size;
+ struct thread_context tc;
+ int block;
+
+ if (getcontext (&c1) < 0)
+ abort ();
+
+ c2 = c1;
+
+ c1.uc_stack.ss_sp = __splitstack_makecontext (8192, &s1[0], &size);
+ if (c1.uc_stack.ss_sp == NULL)
+ abort ();
+ c1.uc_stack.ss_flags = 0;
+ c1.uc_stack.ss_size = size;
+ c1.uc_link = NULL;
+ block = 0;
+ __splitstack_block_signals_context (&s1[0], &block, NULL);
+ makecontext (&c1, go1, 0);
+
+ c2.uc_stack.ss_sp = __splitstack_makecontext (8192, &s2[0], &size);
+ if (c2.uc_stack.ss_sp == NULL)
+ abort ();
+ c2.uc_stack.ss_flags = 0;
+ c2.uc_stack.ss_size = size;
+ c2.uc_link = NULL;
+ __splitstack_block_signals_context (&s2[0], &block, NULL);
+ makecontext (&c2, go2, 0);
+
+ block = 0;
+ __splitstack_block_signals (&block, NULL);
+
+ tc.u = &c1;
+ tc.s = &s1[0];
+ err = pthread_create (&tid, NULL, start_thread, &tc);
+ if (err != 0)
+ abort ();
+
+ err = pthread_join (tid, NULL);
+ if (err != 0)
+ abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/tm/memopt-1.c b/gcc/testsuite/gcc.dg/tm/memopt-1.c
index dcfec15fd8f..b78a6d417dc 100644
--- a/gcc/testsuite/gcc.dg/tm/memopt-1.c
+++ b/gcc/testsuite/gcc.dg/tm/memopt-1.c
@@ -22,7 +22,7 @@ f()
}
}
-/* { dg-final { scan-tree-dump-times "transforming: .*_ITM_RaWU[248] \\(&g\\);" 1 "tmmemopt" } } */
+/* { dg-final { scan-tree-dump-times "transforming: .*_ITM_RaWU\[248\] \\(&g\\);" 1 "tmmemopt" } } */
/* { dg-final { scan-tree-dump-times "transforming: .*_ITM_WaRU4 \\(&i," 1 "tmmemopt" } } */
/* { dg-final { scan-tree-dump-times "transforming: .*_ITM_RaWU4 \\(&i\\);" 1 "tmmemopt" } } */
/* { dg-final { scan-tree-dump-times "transforming: .*_ITM_WaWU4 \\(&i," 1 "tmmemopt" } } */
diff --git a/gcc/testsuite/gcc.dg/torture/pr51042.c b/gcc/testsuite/gcc.dg/torture/pr51042.c
new file mode 100644
index 00000000000..05961c4acf5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr51042.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+
+int a, b;
+
+void
+foo (int x)
+{
+ int e[2];
+ int d;
+ while (x)
+ {
+ for (d = 0; d <= 1; d = 1)
+ if (e[a])
+ break;
+ for (b = 0; b <= 0; b = 1)
+ {
+ e[a] = a;
+ if (a)
+ break;
+ }
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr51070.c b/gcc/testsuite/gcc.dg/torture/pr51070.c
new file mode 100644
index 00000000000..cc06a90c843
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr51070.c
@@ -0,0 +1,34 @@
+/* { dg-do compile } */
+
+int
+func_4 (int si1, int si2)
+{
+ return si1;
+}
+
+int
+func_14 (int left, int right)
+{
+ return 1;
+}
+
+int
+func_37 (int left, int right)
+{
+ return left;
+}
+
+int g_92[1024];
+int g_95[1024];
+int g_224;
+int g_352[1024];
+int
+func_9 ()
+{
+ for (; g_224; g_224 += 1)
+ {
+ g_95[0] = func_4 (func_37 (g_92[g_224], 0), 0);
+ g_92[g_224] = 0, g_352[g_224] = func_14 (0, 0);
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr51071.c b/gcc/testsuite/gcc.dg/torture/pr51071.c
new file mode 100644
index 00000000000..99af9587d05
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr51071.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+
+void foo (void);
+void bar (void *);
+extern int t;
+
+static void kmalloc_large (int size, int flags)
+{
+ (void) size;
+ (void) flags;
+ foo ();
+ bar (({__here:&&__here;}));
+}
+
+static void kmalloc (int size, int flags)
+{
+ if (size)
+ {
+ if ((unsigned long) size > 0x1000)
+ kmalloc_large (size, flags);
+
+ if (flags)
+ bar (({__here:&&__here;}));
+ }
+}
+
+void compress_file_range (int i, int j, int k)
+{
+ int nr_pages = ({j < k;});
+
+ if (i || t)
+ kmalloc (0x1000UL * nr_pages, 0x40UL);
+}
diff --git a/gcc/testsuite/gcc.dg/torture/vshuf-16.inc b/gcc/testsuite/gcc.dg/torture/vshuf-16.inc
index 89ef544a11a..abefdcba22b 100644
--- a/gcc/testsuite/gcc.dg/torture/vshuf-16.inc
+++ b/gcc/testsuite/gcc.dg/torture/vshuf-16.inc
@@ -19,7 +19,9 @@ T (15, 1, 30, 27, 31, 9, 18, 25, 12, 7, 4, 2, 16, 25, 20, 10, 3) \
T (16, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30) \
T (17, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31) \
T (18, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3) \
-T (19, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
+T (19, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) \
+T (20, 0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23) \
+T (21, 8, 24, 9, 25, 10, 26, 11, 27, 12, 28, 13, 29, 14, 30, 15, 31)
#define EXPTESTS \
T (116, 28, 13, 27, 11, 21, 1, 5, 22, 29, 14, 15, 6, 3, 10, 16, 30) \
T (117, 22, 26, 1, 13, 29, 3, 18, 18, 11, 21, 12, 28, 19, 5, 7, 4) \
diff --git a/gcc/testsuite/gcc.dg/torture/vshuf-32.inc b/gcc/testsuite/gcc.dg/torture/vshuf-32.inc
index bbeebaabeeb..583364a8161 100644
--- a/gcc/testsuite/gcc.dg/torture/vshuf-32.inc
+++ b/gcc/testsuite/gcc.dg/torture/vshuf-32.inc
@@ -19,7 +19,9 @@ T (15, 2, 43, 49, 34, 28, 35, 29, 36, 51, 9, 17, 48, 10, 37, 45, 21, 52, 19, 25,
T (16, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62) \
T (17, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63) \
T (18, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3) \
-T (19, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
+T (19, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) \
+T (20, 0, 32, 1, 33, 2, 34, 3, 35, 4, 36, 5, 37, 6, 38, 7, 39, 8, 40, 9, 41, 10, 42, 11, 43, 12, 44, 13, 45, 14, 46, 15, 47) \
+T (21, 16, 48, 17, 49, 18, 50, 19, 51, 20, 52, 21, 53, 22, 54, 23, 55, 24, 56, 25, 57, 26, 58, 27, 59, 28, 60, 29, 61, 30, 62, 31, 63)
#define EXPTESTS \
T (116, 13, 38, 47, 3, 17, 8, 38, 20, 59, 61, 39, 26, 7, 49, 63, 43, 57, 16, 40, 19, 4, 32, 27, 7, 52, 19, 46, 55, 36, 41, 48, 6) \
T (117, 39, 35, 59, 20, 56, 18, 58, 63, 57, 14, 2, 16, 5, 61, 35, 4, 53, 9, 52, 51, 27, 33, 61, 12, 3, 35, 36, 40, 37, 7, 45, 42) \
diff --git a/gcc/testsuite/gcc.dg/torture/vshuf-4.inc b/gcc/testsuite/gcc.dg/torture/vshuf-4.inc
index 94bdb777dfe..cdba12cd27c 100644
--- a/gcc/testsuite/gcc.dg/torture/vshuf-4.inc
+++ b/gcc/testsuite/gcc.dg/torture/vshuf-4.inc
@@ -19,7 +19,9 @@ T (15, 6, 1, 3, 4) \
T (16, 0, 2, 4, 6) \
T (17, 1, 3, 5, 7) \
T (18, 3, 3, 3, 3) \
-T (19, 3, 2, 1, 0)
+T (19, 3, 2, 1, 0) \
+T (20, 0, 4, 1, 5) \
+T (21, 2, 6, 3, 7)
#define EXPTESTS \
T (116, 1, 2, 4, 3) \
T (117, 7, 3, 3, 0) \
diff --git a/gcc/testsuite/gcc.dg/torture/vshuf-8.inc b/gcc/testsuite/gcc.dg/torture/vshuf-8.inc
index 66586fabe73..b865162133a 100644
--- a/gcc/testsuite/gcc.dg/torture/vshuf-8.inc
+++ b/gcc/testsuite/gcc.dg/torture/vshuf-8.inc
@@ -19,7 +19,9 @@ T (15, 0, 5, 11, 7, 4, 6, 14, 1) \
T (16, 0, 2, 4, 6, 8, 10, 12, 14) \
T (17, 1, 3, 5, 7, 9, 11, 13, 15) \
T (18, 3, 3, 3, 3, 3, 3, 3, 3) \
-T (19, 7, 6, 5, 4, 3, 2, 1, 0)
+T (19, 7, 6, 5, 4, 3, 2, 1, 0) \
+T (20, 0, 8, 1, 9, 2, 10, 3, 11) \
+T (21, 4, 12, 5, 13, 6, 14, 7, 15)
#define EXPTESTS \
T (116, 9, 3, 9, 4, 7, 0, 0, 6) \
T (117, 4, 14, 12, 8, 9, 6, 0, 10) \
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-6.c b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-6.c
new file mode 100644
index 00000000000..6ec7b72247f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-6.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-phiopt1" } */
+
+struct C { int i; };
+int *g(struct C *p)
+{
+ if (p)
+ return &p->i;
+ return (int *)0;
+}
+
+/* { dg-final { scan-tree-dump-not "if" "phiopt1" } } */
+/* { dg-final { cleanup-tree-dump "phiopt1" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/fast-math-vect-call-1.c b/gcc/testsuite/gcc.dg/vect/fast-math-vect-call-1.c
index 835f8bc2bbe..db6df7e7511 100644
--- a/gcc/testsuite/gcc.dg/vect/fast-math-vect-call-1.c
+++ b/gcc/testsuite/gcc.dg/vect/fast-math-vect-call-1.c
@@ -38,6 +38,18 @@ f3 (void)
a[i] = copysignf (b[i], c[i]) + 1.0f + sqrtf (d[i]);
}
+__attribute__((noinline, noclone)) void
+f4 (int n)
+{
+ int i;
+ for (i = 0; i < 2 * n; i++)
+ {
+ a[3 * i + 0] = copysignf (b[3 * i + 0], c[3 * i + 0]) + 1.0f + sqrtf (d[3 * i + 0]);
+ a[3 * i + 1] = copysignf (b[3 * i + 1], c[3 * i + 1]) + 2.0f + sqrtf (d[3 * i + 1]);
+ a[3 * i + 2] = copysignf (b[3 * i + 2], c[3 * i + 2]) + 3.0f + sqrtf (d[3 * i + 2]);
+ }
+}
+
__attribute__((noinline, noclone)) int
main1 ()
{
@@ -66,6 +78,12 @@ main1 ()
for (i = 0; i < 64; i++)
if (fabsf (((i & 2) ? -4 * i : 4 * i) + 1 + i - a[i]) >= 0.0001f)
abort ();
+ else
+ a[i] = 131.25;
+ f4 (10);
+ for (i = 0; i < 60; i++)
+ if (fabsf (((i & 2) ? -4 * i : 4 * i) + 1 + (i % 3) + i - a[i]) >= 0.0001f)
+ abort ();
return 0;
}
@@ -76,6 +94,6 @@ main ()
return main1 ();
}
-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 3 "vect" { target { vect_call_copysignf && vect_call_sqrtf } } } } */
-/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 2 "vect" { target { vect_call_copysignf && vect_call_sqrtf } } } } */
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 4 "vect" { target { vect_call_copysignf && vect_call_sqrtf } } } } */
+/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 3 "vect" { target { vect_call_copysignf && vect_call_sqrtf } } } } */
/* { dg-final { cleanup-tree-dump "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/pr51000.c b/gcc/testsuite/gcc.dg/vect/pr51000.c
new file mode 100644
index 00000000000..75af2d8a298
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr51000.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+
+_Bool a[2048];
+int b[2048];
+
+void
+foo ()
+{
+ int i;
+ for (i = 0; i < 2048; i += 4)
+ {
+ a[i] = b[i] <= 10;
+ a[i + 3] = b[i + 1] <= 10;
+ a[i + 2] = b[i + 2] <= 10;
+ a[i + 1] = b[i + 3] <= 10;
+ }
+}
+
+/* { dg-final { cleanup-tree-dump "vect" } } */
diff --git a/gcc/testsuite/gcc.misc-tests/gcov-14.c b/gcc/testsuite/gcc.misc-tests/gcov-14.c
index 0eaf284a9c4..9e16cee52cb 100644
--- a/gcc/testsuite/gcc.misc-tests/gcov-14.c
+++ b/gcc/testsuite/gcc.misc-tests/gcov-14.c
@@ -1,6 +1,8 @@
/* Test gcov extern inline. */
/* { dg-options "-O2 -fprofile-arcs -ftest-coverage" } */
+/* The following line arranges that Darwin has behavior like elf weak import. */
+/* { dg-additional-options "-flat_namespace -undefined suppress" { target *-*-darwin* } } */
/* { dg-require-weak "" } */
/* { dg-do run { target native } } */
diff --git a/gcc/testsuite/gcc.misc-tests/gcov-15.c b/gcc/testsuite/gcc.misc-tests/gcov-15.c
new file mode 100644
index 00000000000..04273fcec42
--- /dev/null
+++ b/gcc/testsuite/gcc.misc-tests/gcov-15.c
@@ -0,0 +1,30 @@
+/* Test gcov multiple paths to file. */
+
+/* { dg-options "-fprofile-arcs -ftest-coverage" } */
+/* { dg-do run { target native } } */
+
+#if !RECURSIVE
+#define RECURSIVE 1
+#include "./gcov-15.c"
+#undef RECURSIVE
+#endif
+
+static void __attribute__ ((noinline)) Recursive (void);
+
+
+#if RECURSIVE
+static void __attribute__ ((noinline))
+Recursive ()
+{
+ return; /* count(1) */
+}
+
+#else
+int main ()
+{
+ Recursive (); /* count(1) */
+ return 0;
+}
+#endif
+
+/* { dg-final { run-gcov { -a gcov-15.c } } } */
diff --git a/gcc/testsuite/gcc.target/i386/sw-1.c b/gcc/testsuite/gcc.target/i386/sw-1.c
index 483d117ecb7..e3d3b914860 100644
--- a/gcc/testsuite/gcc.target/i386/sw-1.c
+++ b/gcc/testsuite/gcc.target/i386/sw-1.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fshrink-wrap -fdump-rtl-pro_and_epilogue" } */
+/* { dg-options "-O2 -fshrink-wrap -fdump-rtl-pro_and_epilogue -mstringop-strategy=rep_byte" } */
#include <string.h>
diff --git a/gcc/testsuite/gcc.target/sh/20080410-1.c b/gcc/testsuite/gcc.target/sh/20080410-1.c
index 0ba7792c078..63e517e94d5 100644
--- a/gcc/testsuite/gcc.target/sh/20080410-1.c
+++ b/gcc/testsuite/gcc.target/sh/20080410-1.c
@@ -1,8 +1,9 @@
/* { dg-do compile { target "sh-*-*" } } */
-/* { dg-options "-O0 -m4 -ml" } */
+/* { dg-options "-O0" } */
+/* { dg-skip-if "" { "sh*-*-*" } "-mb" "" } */
/* { dg-final { scan-assembler-not "add\tr0,r0" } } */
-/* This test checks that chain reloads conflict. I they don't
+/* This test checks chain reloads conflicts. If they don't
conflict, the same hard register R0 is used for the both reloads
but in this case the second reload needs an intermediate register
(which is the reload register). As the result we have the
diff --git a/gcc/testsuite/gcc.target/sh/pr21255-2-ml.c b/gcc/testsuite/gcc.target/sh/pr21255-2-ml.c
index c63a573ea9d..570e7dd0b50 100644
--- a/gcc/testsuite/gcc.target/sh/pr21255-2-ml.c
+++ b/gcc/testsuite/gcc.target/sh/pr21255-2-ml.c
@@ -1,5 +1,6 @@
/* { dg-do compile { target "sh*-*-*" } } */
-/* { dg-options "-ml -O2 -fomit-frame-pointer" } */
+/* { dg-options "-O2 -fomit-frame-pointer" } */
+/* { dg-skip-if "" { "sh*-*-*" } { "-mb" && "-m5*"} { "" } } */
/* { dg-final { scan-assembler "mov @\\(4,r.\\),r.; mov @r.,r." } } */
double d;
@@ -7,13 +8,6 @@ double
f (void)
{
double r;
-
-/* If -mb from the target options is passed after -ml from dg-options, we
- end up with th reverse endianness. */
-#if TARGET_SHMEDIA || defined (__BIG_ENDIAN__)
- asm ("mov @(4,r1),r4; mov @r1,r3");
-#else
asm ("mov %S1,%S0; mov %R1,%R0" : "=&r" (r) : "m" (d));
-#endif
return r;
}
diff --git a/gcc/testsuite/gfortran.dg/vect/pr51058-2.f90 b/gcc/testsuite/gfortran.dg/vect/pr51058-2.f90
new file mode 100644
index 00000000000..f647e6cdb4f
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/vect/pr51058-2.f90
@@ -0,0 +1,20 @@
+! PR tree-optimization/51058
+! { dg-do compile }
+subroutine pr51058(n, u, v, w, z)
+ double precision :: x(3,-2:16384), y(3,-2:16384), b, u, v, w, z
+ integer :: i, n
+ common /c/ x, y
+ do i = 1, n
+ b = u * int(x(1,i)) + sign(z,x(1,i))
+ x(1,i) = x(1,i) - b
+ y(1,i) = y(1,i) - b
+ b = v * int(x(2,i)) + sign(z,x(2,i))
+ x(2,i) = x(2,i) - b
+ y(2,i) = y(2,i) - b
+ b = w * int(x(3,i)) + sign(z,x(3,i))
+ x(3,i) = x(3,i) - b
+ y(3,i) = y(3,i) - b
+ end do
+end subroutine
+
+! { dg-final { cleanup-tree-dump "vect" } }
diff --git a/gcc/testsuite/gfortran.dg/vect/pr51058.f90 b/gcc/testsuite/gfortran.dg/vect/pr51058.f90
new file mode 100644
index 00000000000..abee4c8af99
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/vect/pr51058.f90
@@ -0,0 +1,19 @@
+! { dg-do compile }
+
+ SUBROUTINE MLIST(MOLsp,PBCx,PBCy,PBCz, X0)
+ IMPLICIT NONE
+ INTEGER, PARAMETER :: NM=16384
+ INTEGER :: MOLsp, i
+ REAL :: PBCx, PBCy, PBCz, boxjmp, HALf=1./2.
+ REAL :: X0(2,-2:NM)
+
+ DO i = 1 , MOLsp
+ boxjmp = PBCx*INT(X0(1,i)+SIGN(HALf,X0(1,i)))
+ X0(1,i) = X0(1,i) - boxjmp
+ boxjmp = PBCy*INT(X0(2,i)+SIGN(HALf,X0(2,i)))
+ X0(2,i) = X0(2,i) - boxjmp
+ ENDDO
+ END
+
+! { dg-final { cleanup-tree-dump "vect" } }
+
diff --git a/gcc/testsuite/gnat.dg/atomic6_1.adb b/gcc/testsuite/gnat.dg/atomic6_1.adb
new file mode 100644
index 00000000000..714ceb6d232
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/atomic6_1.adb
@@ -0,0 +1,39 @@
+-- { dg-do compile }
+-- { dg-options "-fdump-tree-gimple" }
+
+with Atomic6_Pkg; use Atomic6_Pkg;
+
+procedure Atomic6_1 is
+ Temp : Integer;
+begin
+
+ Counter1 := Counter2;
+
+ Timer1 := Timer2;
+
+ Counter1 := Int(Timer1);
+ Timer1 := Integer(Counter1);
+
+ Temp := Integer(Counter1);
+ Counter1 := Int(Temp);
+
+ Temp := Timer1;
+ Timer1 := Temp;
+
+end;
+
+-- { dg-final { scan-tree-dump-times "atomic_load\[^\n\r\]*&atomic6_pkg__counter1" 2 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_load\[^\n\r\]*&atomic6_pkg__counter2" 1 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_load\[^\n\r\]*&atomic6_pkg__timer1" 2 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_load\[^\n\r\]*&atomic6_pkg__timer2" 1 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_load\[^\n\r\]*&temp" 0 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_load\[^\n\r\]*ptr" 0 "gimple"} }
+
+-- { dg-final { scan-tree-dump-times "atomic_store\[^\n\r\]*&atomic6_pkg__counter1" 3 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_store\[^\n\r\]*&atomic6_pkg__counter2" 0 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_store\[^\n\r\]*&atomic6_pkg__timer1" 3 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_store\[^\n\r\]*&atomic6_pkg__timer2" 0 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_store\[^\n\r\]*&temp" 0 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_store\[^\n\r\]*ptr" 0 "gimple"} }
+
+-- { dg-final { cleanup-tree-dump "gimple" } }
diff --git a/gcc/testsuite/gnat.dg/atomic6_2.adb b/gcc/testsuite/gnat.dg/atomic6_2.adb
new file mode 100644
index 00000000000..4ecef9b18ba
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/atomic6_2.adb
@@ -0,0 +1,45 @@
+-- { dg-do compile }
+-- { dg-options "-fdump-tree-gimple" }
+
+with Atomic6_Pkg; use Atomic6_Pkg;
+
+procedure Atomic6_2 is
+ Temp : Integer;
+begin
+
+ Counter1 := Counter1 + Counter2;
+
+ Timer1 := Timer1 + Timer2;
+
+ Counter1 := Counter1 + Int(Timer1);
+ Timer1 := Timer1 + Integer(Counter1);
+
+ Temp := Integer(Counter1) + Timer1;
+ Counter1 := Int(Timer1) + Int(Temp);
+ Timer1 := Integer(Counter1) + Temp;
+
+ if Counter1 /= Counter2 then
+ raise Program_Error;
+ end if;
+
+ if Timer1 /= Timer2 then
+ raise Program_Error;
+ end if;
+
+end;
+
+-- { dg-final { scan-tree-dump-times "atomic_load\[^\n\r\]*&atomic6_pkg__counter1" 6 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_load\[^\n\r\]*&atomic6_pkg__counter2" 2 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_load\[^\n\r\]*&atomic6_pkg__timer1" 6 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_load\[^\n\r\]*&atomic6_pkg__timer2" 2 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_load\[^\n\r\]*&temp" 0 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_load\[^\n\r\]*ptr" 0 "gimple"} }
+
+-- { dg-final { scan-tree-dump-times "atomic_store\[^\n\r\]*&atomic6_pkg__counter1" 3 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_store\[^\n\r\]*&atomic6_pkg__counter2" 0 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_store\[^\n\r\]*&atomic6_pkg__timer1" 3 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_store\[^\n\r\]*&atomic6_pkg__timer2" 0 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_store\[^\n\r\]*&temp" 0 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_store\[^\n\r\]*ptr" 0 "gimple"} }
+
+-- { dg-final { cleanup-tree-dump "gimple" } }
diff --git a/gcc/testsuite/gnat.dg/atomic6_3.adb b/gcc/testsuite/gnat.dg/atomic6_3.adb
new file mode 100644
index 00000000000..86b6d814202
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/atomic6_3.adb
@@ -0,0 +1,58 @@
+-- { dg-do compile }
+-- { dg-options "-fdump-tree-gimple" }
+
+with Atomic6_Pkg; use Atomic6_Pkg;
+
+procedure Atomic6_3 is
+
+ function F (I : Integer) return Integer is
+ begin
+ return I;
+ end;
+
+ function F2 return Integer is
+ begin
+ return Integer(Counter1);
+ end;
+
+ function F3 return Integer is
+ begin
+ return Timer1;
+ end;
+
+ Temp : Integer;
+begin
+
+ Counter1 := Int(F(Integer(Counter2)));
+
+ Timer1 := F(Timer2);
+
+ Counter1 := Int(F(Timer1));
+ Timer1 := F(Integer(Counter1));
+
+ Temp := F(Integer(Counter1));
+ Counter1 := Int(F(Temp));
+
+ Temp := F(Timer1);
+ Timer1 := F(Temp);
+
+ Temp := F2;
+ Temp := F3;
+
+end;
+
+-- { dg-final { scan-tree-dump-times "atomic_load\[^\n\r\]*&atomic6_pkg__counter1" 3 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_load\[^\n\r\]*&atomic6_pkg__counter2" 1 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_load\[^\n\r\]*&atomic6_pkg__timer1" 3 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_load\[^\n\r\]*&atomic6_pkg__timer2" 1 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_load\[^\n\r\]*&temp" 0 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_load\[^\n\r\]*ptr" 0 "gimple"} }
+
+-- { dg-final { scan-tree-dump-times "atomic_store\[^\n\r\]*&atomic6_pkg__counter1" 3 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_store\[^\n\r\]*&atomic6_pkg__counter2" 0 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_store\[^\n\r\]*&atomic6_pkg__timer1" 3 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_store\[^\n\r\]*&atomic6_pkg__timer2" 0 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_store\[^\n\r\]*&temp" 0 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_store\[^\n\r\]*ptr" 0 "gimple"} }
+
+-- { dg-final { cleanup-tree-dump "gimple" } }
diff --git a/gcc/testsuite/gnat.dg/atomic6_4.adb b/gcc/testsuite/gnat.dg/atomic6_4.adb
new file mode 100644
index 00000000000..cf960fb69cc
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/atomic6_4.adb
@@ -0,0 +1,45 @@
+-- { dg-do compile }
+-- { dg-options "-fdump-tree-gimple" }
+
+with Atomic6_Pkg; use Atomic6_Pkg;
+
+procedure Atomic6_4 is
+
+ procedure P (I1 : out Integer; I2 : in Integer) is
+ begin
+ I1 := I2;
+ end;
+
+ Temp : Integer;
+begin
+
+ P (Integer(Counter1), Integer(Counter2));
+
+ P (Timer1, Timer2);
+
+ P (Integer(Counter1), Timer1);
+ P (Timer1, Integer(Counter1));
+
+ P (Temp, Integer(Counter1));
+ P (Integer(Counter1), Temp);
+
+ P (Temp, Timer1);
+ P (Timer1, Temp);
+
+end;
+
+-- { dg-final { scan-tree-dump-times "atomic_load\[^\n\r\]*&atomic6_pkg__counter1" 2 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_load\[^\n\r\]*&atomic6_pkg__counter2" 1 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_load\[^\n\r\]*&atomic6_pkg__timer1" 2 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_load\[^\n\r\]*&atomic6_pkg__timer2" 1 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_load\[^\n\r\]*&temp" 0 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_load\[^\n\r\]*ptr" 0 "gimple"} }
+
+-- { dg-final { scan-tree-dump-times "atomic_store\[^\n\r\]*&atomic6_pkg__counter1" 3 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_store\[^\n\r\]*&atomic6_pkg__counter2" 0 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_store\[^\n\r\]*&atomic6_pkg__timer1" 3 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_store\[^\n\r\]*&atomic6_pkg__timer2" 0 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_store\[^\n\r\]*&temp" 0 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_store\[^\n\r\]*ptr" 0 "gimple"} }
+
+-- { dg-final { cleanup-tree-dump "gimple" } }
diff --git a/gcc/testsuite/gnat.dg/atomic6_5.adb b/gcc/testsuite/gnat.dg/atomic6_5.adb
new file mode 100644
index 00000000000..5490f3a90c0
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/atomic6_5.adb
@@ -0,0 +1,38 @@
+-- { dg-do compile }
+-- { dg-options "-fdump-tree-gimple" }
+
+with Atomic6_Pkg; use Atomic6_Pkg;
+
+procedure Atomic6_5 is
+ type Arr is array (Integer range 1 .. 4) of Boolean;
+ A : Arr;
+ B : Boolean;
+begin
+
+ A (Integer(Counter1)) := True;
+ B := A (Timer1);
+
+ declare
+ pragma Suppress (Index_Check);
+ begin
+ A (Integer(Counter1)) := True;
+ B := A (Timer1);
+ end;
+
+end;
+
+-- { dg-final { scan-tree-dump-times "atomic_load\[^\n\r\]*&atomic6_pkg__counter1" 2 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_load\[^\n\r\]*&atomic6_pkg__counter2" 0 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_load\[^\n\r\]*&atomic6_pkg__timer1" 2 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_load\[^\n\r\]*&atomic6_pkg__timer2" 0 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_load\[^\n\r\]*&temp" 0 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_load\[^\n\r\]*ptr" 0 "gimple"} }
+
+-- { dg-final { scan-tree-dump-times "atomic_store\[^\n\r\]*&atomic6_pkg__counter1" 0 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_store\[^\n\r\]*&atomic6_pkg__counter2" 0 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_store\[^\n\r\]*&atomic6_pkg__timer1" 0 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_store\[^\n\r\]*&atomic6_pkg__timer2" 0 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_store\[^\n\r\]*&temp" 0 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_store\[^\n\r\]*ptr" 0 "gimple"} }
+
+-- { dg-final { cleanup-tree-dump "gimple" } }
diff --git a/gcc/testsuite/gnat.dg/atomic6_6.adb b/gcc/testsuite/gnat.dg/atomic6_6.adb
new file mode 100644
index 00000000000..2c217f68f9a
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/atomic6_6.adb
@@ -0,0 +1,39 @@
+-- { dg-do compile }
+-- { dg-options "-fdump-tree-gimple" }
+
+with Atomic6_Pkg; use Atomic6_Pkg;
+
+procedure Atomic6_6 is
+ Temp : Integer;
+begin
+
+ Counter(1) := Counter(2);
+
+ Timer(1) := Timer(2);
+
+ Counter(1) := Int(Timer(1));
+ Timer(1) := Integer(Counter(1));
+
+ Temp := Integer(Counter(1));
+ Counter(1) := Int(Temp);
+
+ Temp := Timer(1);
+ Timer(1) := Temp;
+
+end;
+
+-- { dg-final { scan-tree-dump-times "atomic_load\[^\n\r\]*&atomic6_pkg__counter\\\[1" 2 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_load\[^\n\r\]*&atomic6_pkg__counter\\\[2" 1 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_load\[^\n\r\]*&atomic6_pkg__timer\\\[1" 2 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_load\[^\n\r\]*&atomic6_pkg__timer\\\[2" 1 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_load\[^\n\r\]*&temp" 0 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_load\[^\n\r\]*ptr" 0 "gimple"} }
+
+-- { dg-final { scan-tree-dump-times "atomic_store\[^\n\r\]*&atomic6_pkg__counter\\\[1" 3 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_store\[^\n\r\]*&atomic6_pkg__counter\\\[2" 0 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_store\[^\n\r\]*&atomic6_pkg__timer\\\[1" 3 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_store\[^\n\r\]*&atomic6_pkg__timer\\\[2" 0 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_store\[^\n\r\]*&temp" 0 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_store\[^\n\r\]*ptr" 0 "gimple"} }
+
+-- { dg-final { cleanup-tree-dump "gimple" } }
diff --git a/gcc/testsuite/gnat.dg/atomic6_7.adb b/gcc/testsuite/gnat.dg/atomic6_7.adb
new file mode 100644
index 00000000000..8b48bf5165d
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/atomic6_7.adb
@@ -0,0 +1,40 @@
+-- { dg-do compile }
+-- { dg-options "-fdump-tree-gimple" }
+
+with Atomic6_Pkg; use Atomic6_Pkg;
+
+procedure Atomic6_7 is
+ My_Atomic : R;
+ Temp : Integer;
+begin
+
+ My_Atomic.Counter1 := Counter2;
+
+ My_Atomic.Timer1 := Timer2;
+
+ My_Atomic.Counter1 := Int(My_Atomic.Timer1);
+ My_Atomic.Timer1 := Integer(My_Atomic.Counter1);
+
+ Temp := Integer(My_Atomic.Counter1);
+ My_Atomic.Counter1 := Int(Temp);
+
+ Temp := My_Atomic.Timer1;
+ My_Atomic.Timer1 := Temp;
+
+end;
+
+-- { dg-final { scan-tree-dump-times "atomic_load\[^\n\r\]*&my_atomic.counter1" 2 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_load\[^\n\r\]*&atomic6_pkg__counter2" 1 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_load\[^\n\r\]*&my_atomic.timer1" 2 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_load\[^\n\r\]*&atomic6_pkg__timer2" 1 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_load\[^\n\r\]*&temp" 0 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_load\[^\n\r\]*ptr" 0 "gimple"} }
+
+-- { dg-final { scan-tree-dump-times "atomic_store\[^\n\r\]*&my_atomic.counter1" 3 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_store\[^\n\r\]*&atomic6_pkg__counter2" 0 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_store\[^\n\r\]*&my_atomic.timer1" 3 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_store\[^\n\r\]*&atomic6_pkg__timer2" 0 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_store\[^\n\r\]*&temp" 0 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_store\[^\n\r\]*ptr" 0 "gimple"} }
+
+-- { dg-final { cleanup-tree-dump "gimple" } }
diff --git a/gcc/testsuite/gnat.dg/atomic6_8.adb b/gcc/testsuite/gnat.dg/atomic6_8.adb
new file mode 100644
index 00000000000..7d39396866a
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/atomic6_8.adb
@@ -0,0 +1,37 @@
+-- { dg-do compile }
+-- { dg-options "-fdump-tree-gimple" }
+
+with Atomic6_Pkg; use Atomic6_Pkg;
+
+procedure Atomic6_8 is
+ Ptr : Int_Ptr := new Int;
+ Temp : Integer;
+begin
+
+ Ptr.all := Counter1;
+
+ Counter1 := Ptr.all;
+
+ Ptr.all := Int(Timer1);
+ Timer1 := Integer(Ptr.all);
+
+ Temp := Integer(Ptr.all);
+ Ptr.all := Int(Temp);
+
+end;
+
+-- { dg-final { scan-tree-dump-times "atomic_load\[^\n\r\]*&atomic6_pkg__counter1" 1 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_load\[^\n\r\]*&atomic6_pkg__counter2" 0 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_load\[^\n\r\]*&atomic6_pkg__timer1" 1 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_load\[^\n\r\]*&atomic6_pkg__timer2" 0 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_load\[^\n\r\]*&temp" 0 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_load\[^\n\r\]*ptr" 3 "gimple"} }
+
+-- { dg-final { scan-tree-dump-times "atomic_store\[^\n\r\]*&atomic6_pkg__counter1" 1 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_store\[^\n\r\]*&atomic6_pkg__counter2" 0 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_store\[^\n\r\]*&atomic6_pkg__timer1" 1 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_store\[^\n\r\]*&atomic6_pkg__timer2" 0 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_store\[^\n\r\]*&temp" 0 "gimple"} }
+-- { dg-final { scan-tree-dump-times "atomic_store\[^\n\r\]*ptr" 3 "gimple"} }
+
+-- { dg-final { cleanup-tree-dump "gimple" } }
diff --git a/gcc/testsuite/gnat.dg/atomic6_pkg.ads b/gcc/testsuite/gnat.dg/atomic6_pkg.ads
new file mode 100644
index 00000000000..aad24357ebc
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/atomic6_pkg.ads
@@ -0,0 +1,34 @@
+package Atomic6_Pkg is
+
+ type Int is new Integer;
+ pragma Atomic (Int);
+
+ Counter1 : Int;
+ Counter2 : Int;
+
+ Timer1 : Integer;
+ pragma Atomic (Timer1);
+
+ Timer2 : Integer;
+ pragma Atomic (Timer2);
+
+ type Arr1 is array (1..8) of Int;
+ Counter : Arr1;
+
+ type Arr2 is array (1..8) of Integer;
+ pragma Atomic_Components (Arr2);
+ Timer : Arr2;
+
+ type R is record
+ Counter1 : Int;
+ Timer1 : Integer;
+ pragma Atomic (Timer1);
+ Counter2 : Int;
+ Timer2 : Integer;
+ pragma Atomic (Timer2);
+ Dummy : Integer;
+ end record;
+
+ type Int_Ptr is access all Int;
+
+end Atomic6_Pkg;
diff --git a/gcc/testsuite/gnat.dg/loop_optimization9.adb b/gcc/testsuite/gnat.dg/loop_optimization9.adb
new file mode 100644
index 00000000000..56d85e210c7
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/loop_optimization9.adb
@@ -0,0 +1,124 @@
+-- { dg-do compile }
+-- { dg-options "-gnatws -O3" }
+-- { dg-options "-gnatws -O3 -msse" { target i?86-*-* x86_64-*-* } }
+
+with System.Soft_Links;
+
+package body Loop_Optimization9 is
+
+ package SSL renames System.Soft_Links;
+
+ First_Temp_File_Name : constant String := "GNAT-TEMP-000000.TMP";
+
+ Current_Temp_File_Name : String := First_Temp_File_Name;
+
+ Temp_File_Name_Last_Digit : constant Positive :=
+ First_Temp_File_Name'Last - 4;
+
+ function Argument_String_To_List
+ (Arg_String : String) return Argument_List_Access
+ is
+ Max_Args : constant Integer := Arg_String'Length;
+ New_Argv : Argument_List (1 .. Max_Args);
+ New_Argc : Natural := 0;
+ Idx : Integer;
+
+ begin
+ Idx := Arg_String'First;
+
+ loop
+ exit when Idx > Arg_String'Last;
+
+ declare
+ Quoted : Boolean := False;
+ Backqd : Boolean := False;
+ Old_Idx : Integer;
+
+ begin
+ Old_Idx := Idx;
+
+ loop
+ -- An unquoted space is the end of an argument
+
+ if not (Backqd or Quoted)
+ and then Arg_String (Idx) = ' '
+ then
+ exit;
+
+ -- Start of a quoted string
+
+ elsif not (Backqd or Quoted)
+ and then Arg_String (Idx) = '"'
+ then
+ Quoted := True;
+
+ -- End of a quoted string and end of an argument
+
+ elsif (Quoted and not Backqd)
+ and then Arg_String (Idx) = '"'
+ then
+ Idx := Idx + 1;
+ exit;
+
+ -- Following character is backquoted
+
+ elsif Arg_String (Idx) = '\' then
+ Backqd := True;
+
+ -- Turn off backquoting after advancing one character
+
+ elsif Backqd then
+ Backqd := False;
+
+ end if;
+
+ Idx := Idx + 1;
+ exit when Idx > Arg_String'Last;
+ end loop;
+
+ -- Found an argument
+
+ New_Argc := New_Argc + 1;
+ New_Argv (New_Argc) :=
+ new String'(Arg_String (Old_Idx .. Idx - 1));
+ end;
+ end loop;
+
+ return new Argument_List'(New_Argv (1 .. New_Argc));
+ end Argument_String_To_List;
+
+ procedure Create_Temp_File_Internal
+ (FD : out File_Descriptor;
+ Name : out String_Access)
+ is
+ Pos : Positive;
+ begin
+ File_Loop : loop
+ Locked : begin
+ Pos := Temp_File_Name_Last_Digit;
+
+ Digit_Loop :
+ loop
+ case Current_Temp_File_Name (Pos) is
+ when '0' .. '8' =>
+ Current_Temp_File_Name (Pos) :=
+ Character'Succ (Current_Temp_File_Name (Pos));
+ exit Digit_Loop;
+
+ when '9' =>
+ Current_Temp_File_Name (Pos) := '0';
+ Pos := Pos - 1;
+
+ when others =>
+
+ SSL.Unlock_Task.all;
+ FD := 0;
+ Name := null;
+ exit File_Loop;
+ end case;
+ end loop Digit_Loop;
+ end Locked;
+ end loop File_Loop;
+ end Create_Temp_File_Internal;
+
+end Loop_Optimization9;
diff --git a/gcc/testsuite/gnat.dg/loop_optimization9.ads b/gcc/testsuite/gnat.dg/loop_optimization9.ads
new file mode 100644
index 00000000000..95f8221bd90
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/loop_optimization9.ads
@@ -0,0 +1,18 @@
+with GNAT.Strings; use GNAT.Strings;
+
+package Loop_Optimization9 is
+
+ type File_Descriptor is new Integer;
+
+ procedure Create_Temp_File_Internal
+ (FD : out File_Descriptor;
+ Name : out String_Access);
+
+ subtype Argument_List is String_List;
+
+ subtype Argument_List_Access is String_List_Access;
+
+ function Argument_String_To_List
+ (Arg_String : String) return Argument_List_Access;
+
+end Loop_Optimization9;
diff --git a/gcc/testsuite/lib/gcc-simulate-thread.exp b/gcc/testsuite/lib/gcc-simulate-thread.exp
index ba2416acdd7..b2487d2d8c7 100644
--- a/gcc/testsuite/lib/gcc-simulate-thread.exp
+++ b/gcc/testsuite/lib/gcc-simulate-thread.exp
@@ -22,6 +22,11 @@
# Call 'fail' if a given test printed "FAIL:", otherwise call 'pass'.
proc simulate-thread { args } {
+
+ # ??? Exit immediately if this is alpha*-*-linux* target, single-stepping
+ # executable between ldl_l and stl_c insns in gdb breaks LL/SC chaining.
+ if { [istarget alpha*-*-linux*] } { return }
+
if { ![isnative] || [is_remote target] } { return }
if { [llength $args] == 1 } {
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index 944a66853a2..94309102034 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -4401,3 +4401,11 @@ proc check_effective_target_non_strict_align {} {
void foo(void) { z = (c *) y; }
} "-Wcast-align"]
}
+
+# Return 1 if the target has <ucontext.h>.
+
+proc check_effective_target_ucontext_h { } {
+ return [check_no_compiler_messages ucontext_h assembly {
+ #include <ucontext.h>
+ }]
+}
diff --git a/gcc/tree-emutls.c b/gcc/tree-emutls.c
index f046363c3d4..abf5657ab9d 100644
--- a/gcc/tree-emutls.c
+++ b/gcc/tree-emutls.c
@@ -262,7 +262,7 @@ get_emutls_init_templ_addr (tree decl)
if (DECL_EXTERNAL (to))
varpool_node (to);
else
- varpool_finalize_decl (to);
+ varpool_add_new_variable (to);
return build_fold_addr_expr (to);
}
@@ -334,7 +334,7 @@ new_emutls_decl (tree decl, tree alias_of)
if (DECL_EXTERNAL (to))
varpool_node (to);
else if (!alias_of)
- varpool_finalize_decl (to);
+ varpool_add_new_variable (to);
else
varpool_create_variable_alias (to,
varpool_node_for_asm
diff --git a/gcc/tree-loop-distribution.c b/gcc/tree-loop-distribution.c
index 810b974b256..0daef06b954 100644
--- a/gcc/tree-loop-distribution.c
+++ b/gcc/tree-loop-distribution.c
@@ -63,6 +63,48 @@ static bitmap remaining_stmts;
predecessor a node that writes to memory. */
static bitmap upstream_mem_writes;
+/* Returns true when DEF is an SSA_NAME defined in LOOP and used after
+ the LOOP. */
+
+static bool
+ssa_name_has_uses_outside_loop_p (tree def, loop_p loop)
+{
+ imm_use_iterator imm_iter;
+ use_operand_p use_p;
+
+ FOR_EACH_IMM_USE_FAST (use_p, imm_iter, def)
+ if (loop != loop_containing_stmt (USE_STMT (use_p)))
+ return true;
+
+ return false;
+}
+
+/* Returns true when STMT defines a scalar variable used after the
+ loop. */
+
+static bool
+stmt_has_scalar_dependences_outside_loop (gimple stmt)
+{
+ tree name;
+
+ switch (gimple_code (stmt))
+ {
+ case GIMPLE_ASSIGN:
+ name = gimple_assign_lhs (stmt);
+ break;
+
+ case GIMPLE_PHI:
+ name = gimple_phi_result (stmt);
+ break;
+
+ default:
+ return false;
+ }
+
+ return TREE_CODE (name) == SSA_NAME
+ && ssa_name_has_uses_outside_loop_p (name, loop_containing_stmt (stmt));
+}
+
/* Update the PHI nodes of NEW_LOOP. NEW_LOOP is a duplicate of
ORIG_LOOP. */
@@ -330,10 +372,18 @@ generate_builtin (struct loop *loop, bitmap partition, bool copy_p)
{
gimple stmt = gsi_stmt (bsi);
- if (gimple_code (stmt) != GIMPLE_LABEL
- && !is_gimple_debug (stmt)
- && bitmap_bit_p (partition, x++)
- && is_gimple_assign (stmt)
+ if (gimple_code (stmt) == GIMPLE_LABEL
+ || is_gimple_debug (stmt))
+ continue;
+
+ if (!bitmap_bit_p (partition, x++))
+ continue;
+
+ /* If the stmt has uses outside of the loop fail. */
+ if (stmt_has_scalar_dependences_outside_loop (stmt))
+ goto end;
+
+ if (is_gimple_assign (stmt)
&& !is_gimple_reg (gimple_assign_lhs (stmt)))
{
/* Don't generate the builtins when there are more than
@@ -824,48 +874,6 @@ fuse_partitions_with_similar_memory_accesses (struct graph *rdg,
}
}
-/* Returns true when DEF is an SSA_NAME defined in LOOP and used after
- the LOOP. */
-
-static bool
-ssa_name_has_uses_outside_loop_p (tree def, loop_p loop)
-{
- imm_use_iterator imm_iter;
- use_operand_p use_p;
-
- FOR_EACH_IMM_USE_FAST (use_p, imm_iter, def)
- if (loop != loop_containing_stmt (USE_STMT (use_p)))
- return true;
-
- return false;
-}
-
-/* Returns true when STMT defines a scalar variable used after the
- loop. */
-
-static bool
-stmt_has_scalar_dependences_outside_loop (gimple stmt)
-{
- tree name;
-
- switch (gimple_code (stmt))
- {
- case GIMPLE_ASSIGN:
- name = gimple_assign_lhs (stmt);
- break;
-
- case GIMPLE_PHI:
- name = gimple_phi_result (stmt);
- break;
-
- default:
- return false;
- }
-
- return TREE_CODE (name) == SSA_NAME
- && ssa_name_has_uses_outside_loop_p (name, loop_containing_stmt (stmt));
-}
-
/* Returns true when STMT will be code generated in a partition of RDG
different than PART and that will not be code generated as a
builtin. */
@@ -1311,6 +1319,7 @@ struct gimple_opt_pass pass_loop_distribution =
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
- 0 /* todo_flags_finish */
+ TODO_ggc_collect
+ | TODO_verify_ssa /* todo_flags_finish */
}
};
diff --git a/gcc/tree-object-size.c b/gcc/tree-object-size.c
index 017f8c5e933..326b2e4c21b 100644
--- a/gcc/tree-object-size.c
+++ b/gcc/tree-object-size.c
@@ -175,7 +175,7 @@ addr_object_size (struct object_size_info *osi, const_tree ptr,
unsigned HOST_WIDE_INT sz;
if (!osi || (object_size_type & 1) != 0
- || TREE_CODE (pt_var) != SSA_NAME)
+ || TREE_CODE (TREE_OPERAND (pt_var, 0)) != SSA_NAME)
{
sz = compute_builtin_object_size (TREE_OPERAND (pt_var, 0),
object_size_type & ~1);
diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c
index 96d46122195..b739bbc125c 100644
--- a/gcc/tree-ssa-phiopt.c
+++ b/gcc/tree-ssa-phiopt.c
@@ -591,6 +591,38 @@ conditional_replacement (basic_block cond_bb, basic_block middle_bb,
return true;
}
+/* Update *ARG which is defined in STMT so that it contains the
+ computed value if that seems profitable. Return true if the
+ statement is made dead by that rewriting. */
+
+static bool
+jump_function_from_stmt (tree *arg, gimple stmt)
+{
+ enum tree_code code = gimple_assign_rhs_code (stmt);
+ if (code == ADDR_EXPR)
+ {
+ /* For arg = &p->i transform it to p, if possible. */
+ tree rhs1 = gimple_assign_rhs1 (stmt);
+ HOST_WIDE_INT offset;
+ tree tem = get_addr_base_and_unit_offset (TREE_OPERAND (rhs1, 0),
+ &offset);
+ if (tem
+ && TREE_CODE (tem) == MEM_REF
+ && double_int_zero_p
+ (double_int_add (mem_ref_offset (tem),
+ shwi_to_double_int (offset))))
+ {
+ *arg = TREE_OPERAND (tem, 0);
+ return true;
+ }
+ }
+ /* TODO: Much like IPA-CP jump-functions we want to handle constant
+ additions symbolically here, and we'd need to update the comparison
+ code that compares the arg + cst tuples in our caller. For now the
+ code above exactly handles the VEC_BASE pattern from vec.h. */
+ return false;
+}
+
/* The function value_replacement does the main work of doing the value
replacement. Return true if the replacement is done. Otherwise return
false.
@@ -602,6 +634,7 @@ value_replacement (basic_block cond_bb, basic_block middle_bb,
edge e0, edge e1, gimple phi,
tree arg0, tree arg1)
{
+ gimple_stmt_iterator gsi;
gimple cond;
edge true_edge, false_edge;
enum tree_code code;
@@ -611,8 +644,32 @@ value_replacement (basic_block cond_bb, basic_block middle_bb,
if (HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg1))))
return false;
- if (!empty_block_p (middle_bb))
- return false;
+ /* Allow a single statement in MIDDLE_BB that defines one of the PHI
+ arguments. */
+ gsi = gsi_after_labels (middle_bb);
+ if (!gsi_end_p (gsi))
+ {
+ if (is_gimple_debug (gsi_stmt (gsi)))
+ gsi_next_nondebug (&gsi);
+ if (!gsi_end_p (gsi))
+ {
+ gimple stmt = gsi_stmt (gsi);
+ tree lhs;
+ gsi_next_nondebug (&gsi);
+ if (!gsi_end_p (gsi))
+ return false;
+ if (!is_gimple_assign (stmt))
+ return false;
+ /* Now try to adjust arg0 or arg1 according to the computation
+ in the single statement. */
+ lhs = gimple_assign_lhs (stmt);
+ if (!((lhs == arg0
+ && jump_function_from_stmt (&arg0, stmt))
+ || (lhs == arg1
+ && jump_function_from_stmt (&arg1, stmt))))
+ return false;
+ }
+ }
cond = last_stmt (cond_bb);
code = gimple_cond_code (cond);
diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c
index 60ae35cef73..557b56a110d 100644
--- a/gcc/tree-ssa-pre.c
+++ b/gcc/tree-ssa-pre.c
@@ -1527,7 +1527,7 @@ phi_translate_1 (pre_expr expr, bitmap_set_t set1, bitmap_set_t set2,
tree newvuse = vuse;
VEC (vn_reference_op_s, heap) *newoperands = NULL;
bool changed = false, same_valid = true;
- unsigned int i, j;
+ unsigned int i, j, n;
vn_reference_op_t operand;
vn_reference_t newref;
@@ -1536,100 +1536,83 @@ phi_translate_1 (pre_expr expr, bitmap_set_t set1, bitmap_set_t set2,
{
pre_expr opresult;
pre_expr leader;
- tree oldop0 = operand->op0;
- tree oldop1 = operand->op1;
- tree oldop2 = operand->op2;
- tree op0 = oldop0;
- tree op1 = oldop1;
- tree op2 = oldop2;
+ tree op[3];
tree type = operand->type;
vn_reference_op_s newop = *operand;
-
- if (op0 && TREE_CODE (op0) == SSA_NAME)
+ op[0] = operand->op0;
+ op[1] = operand->op1;
+ op[2] = operand->op2;
+ for (n = 0; n < 3; ++n)
{
- unsigned int op_val_id = VN_INFO (op0)->value_id;
- leader = find_leader_in_sets (op_val_id, set1, set2);
- opresult = phi_translate (leader, set1, set2, pred, phiblock);
- if (opresult && opresult != leader)
+ unsigned int op_val_id;
+ if (!op[n])
+ continue;
+ if (TREE_CODE (op[n]) != SSA_NAME)
{
- tree name = get_representative_for (opresult);
- if (!name)
+ /* We can't possibly insert these. */
+ if (n != 0
+ && !is_gimple_min_invariant (op[n]))
break;
- op0 = name;
+ continue;
}
- else if (!opresult)
- break;
- }
- changed |= op0 != oldop0;
-
- if (op1 && TREE_CODE (op1) == SSA_NAME)
- {
- unsigned int op_val_id = VN_INFO (op1)->value_id;
+ op_val_id = VN_INFO (op[n])->value_id;
leader = find_leader_in_sets (op_val_id, set1, set2);
- opresult = phi_translate (leader, set1, set2, pred, phiblock);
- if (opresult && opresult != leader)
+ if (!leader)
+ break;
+ /* Make sure we do not recursively translate ourselves
+ like for translating a[n_1] with the leader for
+ n_1 being a[n_1]. */
+ if (get_expression_id (leader) != get_expression_id (expr))
{
- tree name = get_representative_for (opresult);
- if (!name)
+ opresult = phi_translate (leader, set1, set2,
+ pred, phiblock);
+ if (!opresult)
break;
- op1 = name;
+ if (opresult != leader)
+ {
+ tree name = get_representative_for (opresult);
+ if (!name)
+ break;
+ changed |= name != op[n];
+ op[n] = name;
+ }
}
- else if (!opresult)
- break;
}
- /* We can't possibly insert these. */
- else if (op1 && !is_gimple_min_invariant (op1))
- break;
- changed |= op1 != oldop1;
- if (op2 && TREE_CODE (op2) == SSA_NAME)
+ if (n != 3)
{
- unsigned int op_val_id = VN_INFO (op2)->value_id;
- leader = find_leader_in_sets (op_val_id, set1, set2);
- opresult = phi_translate (leader, set1, set2, pred, phiblock);
- if (opresult && opresult != leader)
- {
- tree name = get_representative_for (opresult);
- if (!name)
- break;
- op2 = name;
- }
- else if (!opresult)
- break;
+ if (newoperands)
+ VEC_free (vn_reference_op_s, heap, newoperands);
+ return NULL;
}
- /* We can't possibly insert these. */
- else if (op2 && !is_gimple_min_invariant (op2))
- break;
- changed |= op2 != oldop2;
-
if (!newoperands)
newoperands = VEC_copy (vn_reference_op_s, heap, operands);
/* We may have changed from an SSA_NAME to a constant */
- if (newop.opcode == SSA_NAME && TREE_CODE (op0) != SSA_NAME)
- newop.opcode = TREE_CODE (op0);
+ if (newop.opcode == SSA_NAME && TREE_CODE (op[0]) != SSA_NAME)
+ newop.opcode = TREE_CODE (op[0]);
newop.type = type;
- newop.op0 = op0;
- newop.op1 = op1;
- newop.op2 = op2;
+ newop.op0 = op[0];
+ newop.op1 = op[1];
+ newop.op2 = op[2];
/* If it transforms a non-constant ARRAY_REF into a constant
one, adjust the constant offset. */
if (newop.opcode == ARRAY_REF
&& newop.off == -1
- && TREE_CODE (op0) == INTEGER_CST
- && TREE_CODE (op1) == INTEGER_CST
- && TREE_CODE (op2) == INTEGER_CST)
+ && TREE_CODE (op[0]) == INTEGER_CST
+ && TREE_CODE (op[1]) == INTEGER_CST
+ && TREE_CODE (op[2]) == INTEGER_CST)
{
- double_int off = tree_to_double_int (op0);
+ double_int off = tree_to_double_int (op[0]);
off = double_int_add (off,
double_int_neg
- (tree_to_double_int (op1)));
- off = double_int_mul (off, tree_to_double_int (op2));
+ (tree_to_double_int (op[1])));
+ off = double_int_mul (off, tree_to_double_int (op[2]));
if (double_int_fits_in_shwi_p (off))
newop.off = off.low;
}
VEC_replace (vn_reference_op_s, newoperands, j, &newop);
/* If it transforms from an SSA_NAME to an address, fold with
a preceding indirect reference. */
- if (j > 0 && op0 && TREE_CODE (op0) == ADDR_EXPR
+ if (j > 0 && op[0] && TREE_CODE (op[0]) == ADDR_EXPR
&& VEC_index (vn_reference_op_s,
newoperands, j - 1)->opcode == MEM_REF)
vn_reference_fold_indirect (&newoperands, &j);
diff --git a/gcc/tree-ssa-propagate.c b/gcc/tree-ssa-propagate.c
index 05abaa58549..80b33e11d80 100644
--- a/gcc/tree-ssa-propagate.c
+++ b/gcc/tree-ssa-propagate.c
@@ -602,6 +602,16 @@ valid_gimple_rhs_p (tree expr)
break;
default:
+ if (get_gimple_rhs_class (code) == GIMPLE_TERNARY_RHS)
+ {
+ if (((code == VEC_COND_EXPR || code == COND_EXPR)
+ ? !is_gimple_condexpr (TREE_OPERAND (expr, 0))
+ : !is_gimple_val (TREE_OPERAND (expr, 0)))
+ || !is_gimple_val (TREE_OPERAND (expr, 1))
+ || !is_gimple_val (TREE_OPERAND (expr, 2)))
+ return false;
+ break;
+ }
return false;
}
break;
diff --git a/gcc/tree-stdarg.c b/gcc/tree-stdarg.c
index ef898ee5bbd..9b7a126b1ef 100644
--- a/gcc/tree-stdarg.c
+++ b/gcc/tree-stdarg.c
@@ -1,5 +1,5 @@
/* Pass computing data for optimizing stdarg functions.
- Copyright (C) 2004, 2005, 2007, 2008, 2009, 2010
+ Copyright (C) 2004, 2005, 2007, 2008, 2009, 2010, 2011
Free Software Foundation, Inc.
Contributed by Jakub Jelinek <jakub@redhat.com>
@@ -847,8 +847,12 @@ execute_optimize_stdarg (void)
if (get_gimple_rhs_class (gimple_assign_rhs_code (stmt))
== GIMPLE_SINGLE_RHS)
{
+ /* Check for ap ={v} {}. */
+ if (TREE_CLOBBER_P (rhs))
+ continue;
+
/* Check for tem = ap. */
- if (va_list_ptr_read (&si, rhs, lhs))
+ else if (va_list_ptr_read (&si, rhs, lhs))
continue;
/* Check for the last insn in:
@@ -875,6 +879,7 @@ execute_optimize_stdarg (void)
/* Check for ap ={v} {}. */
if (TREE_CLOBBER_P (rhs))
continue;
+
/* Check for ap[0].field = temp. */
else if (va_list_counter_struct_op (&si, lhs, rhs, true))
continue;
diff --git a/gcc/tree-vect-generic.c b/gcc/tree-vect-generic.c
index 6555932a4cc..dc01ce7b24c 100644
--- a/gcc/tree-vect-generic.c
+++ b/gcc/tree-vect-generic.c
@@ -649,7 +649,7 @@ lower_vec_perm (gimple_stmt_iterator *gsi)
tree vals = TREE_VECTOR_CST_ELTS (mask);
for (i = 0; i < elements; ++i, vals = TREE_CHAIN (vals))
- sel_int[i] = TREE_INT_CST_LOW (TREE_VALUE (vals));
+ sel_int[i] = TREE_INT_CST_LOW (TREE_VALUE (vals)) & (2 * elements - 1);
if (can_vec_perm_p (TYPE_MODE (vect_type), false, sel_int))
return;
diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c
index dca1c34a1f6..fb15d6e3d03 100644
--- a/gcc/tree-vect-loop.c
+++ b/gcc/tree-vect-loop.c
@@ -872,21 +872,8 @@ destroy_loop_vec_info (loop_vec_info loop_vinfo, bool clean_stmts)
for (si = gsi_start_bb (bb); !gsi_end_p (si); )
{
gimple stmt = gsi_stmt (si);
- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
-
- if (stmt_info)
- {
- /* Check if this statement has a related "pattern stmt"
- (introduced by the vectorizer during the pattern recognition
- pass). Free pattern's stmt_vec_info. */
- if (STMT_VINFO_IN_PATTERN_P (stmt_info)
- && vinfo_for_stmt (STMT_VINFO_RELATED_STMT (stmt_info)))
- free_stmt_vec_info (STMT_VINFO_RELATED_STMT (stmt_info));
-
- /* Free stmt_vec_info. */
- free_stmt_vec_info (stmt);
- }
-
+ /* Free stmt_vec_info. */
+ free_stmt_vec_info (stmt);
gsi_next (&si);
}
}
@@ -5349,14 +5336,14 @@ vect_transform_loop (loop_vec_info loop_vinfo)
/* Interleaving. If IS_STORE is TRUE, the vectorization of the
interleaving chain was completed - free all the stores in
the chain. */
+ gsi_next (&si);
vect_remove_stores (GROUP_FIRST_ELEMENT (stmt_info));
- gsi_remove (&si, true);
continue;
}
else
{
/* Free the attached stmt_vec_info and remove the stmt. */
- free_stmt_vec_info (stmt);
+ free_stmt_vec_info (gsi_stmt (si));
gsi_remove (&si, true);
continue;
}
diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c
index 19b75e9e465..d260e801bca 100644
--- a/gcc/tree-vect-patterns.c
+++ b/gcc/tree-vect-patterns.c
@@ -2041,7 +2041,8 @@ vect_recog_bool_pattern (VEC (gimple, heap) **stmts, tree *type_in,
rhs_code = gimple_assign_rhs_code (last_stmt);
if (CONVERT_EXPR_CODE_P (rhs_code))
{
- if (TREE_CODE (TREE_TYPE (lhs)) != INTEGER_TYPE)
+ if (TREE_CODE (TREE_TYPE (lhs)) != INTEGER_TYPE
+ || TYPE_PRECISION (TREE_TYPE (lhs)) == 1)
return NULL;
vectype = get_vectype_for_scalar_type (TREE_TYPE (lhs));
if (vectype == NULL_TREE)
@@ -2096,6 +2097,7 @@ vect_recog_bool_pattern (VEC (gimple, heap) **stmts, tree *type_in,
STMT_VINFO_DR_STEP (pattern_stmt_info) = STMT_VINFO_DR_STEP (stmt_vinfo);
STMT_VINFO_DR_ALIGNED_TO (pattern_stmt_info)
= STMT_VINFO_DR_ALIGNED_TO (stmt_vinfo);
+ DR_STMT (STMT_VINFO_DATA_REF (stmt_vinfo)) = pattern_stmt;
*type_out = vectype;
*type_in = vectype;
VEC_safe_push (gimple, heap, *stmts, last_stmt);
diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c
index f54a8a77280..23330b2882f 100644
--- a/gcc/tree-vect-slp.c
+++ b/gcc/tree-vect-slp.c
@@ -75,8 +75,9 @@ vect_free_slp_tree (slp_tree node)
return;
FOR_EACH_VEC_ELT (slp_void_p, SLP_TREE_CHILDREN (node), i, child)
- vect_free_slp_tree ((slp_tree)child);
+ vect_free_slp_tree ((slp_tree) child);
+ VEC_free (slp_void_p, heap, SLP_TREE_CHILDREN (node));
VEC_free (gimple, heap, SLP_TREE_SCALAR_STMTS (node));
if (SLP_TREE_VEC_STMTS (node))
@@ -102,7 +103,7 @@ vect_free_slp_instance (slp_instance instance)
static slp_tree
vect_create_new_slp_node (VEC (gimple, heap) *scalar_stmts)
{
- slp_tree node = XNEW (struct _slp_tree);
+ slp_tree node;
gimple stmt = VEC_index (gimple, scalar_stmts, 0);
unsigned int nops;
@@ -117,6 +118,7 @@ vect_create_new_slp_node (VEC (gimple, heap) *scalar_stmts)
else
return NULL;
+ node = XNEW (struct _slp_tree);
SLP_TREE_SCALAR_STMTS (node) = scalar_stmts;
SLP_TREE_VEC_STMTS (node) = NULL;
SLP_TREE_CHILDREN (node) = VEC_alloc (slp_void_p, heap, nops);
@@ -152,21 +154,19 @@ vect_create_oprnd_info (int nops, int group_size)
}
-/* Free operands info. Free def-stmts in FREE_DEF_STMTS is true.
- (FREE_DEF_STMTS is true when the SLP analysis fails, and false when it
- succeds. In the later case we don't need the operands info that we used to
- check isomorphism of the stmts, but we still need the def-stmts - they are
- used as scalar stmts in SLP nodes. */
+/* Free operands info. */
+
static void
-vect_free_oprnd_info (VEC (slp_oprnd_info, heap) **oprnds_info,
- bool free_def_stmts)
+vect_free_oprnd_info (VEC (slp_oprnd_info, heap) **oprnds_info)
{
int i;
slp_oprnd_info oprnd_info;
- if (free_def_stmts)
- FOR_EACH_VEC_ELT (slp_oprnd_info, *oprnds_info, i, oprnd_info)
+ FOR_EACH_VEC_ELT (slp_oprnd_info, *oprnds_info, i, oprnd_info)
+ {
VEC_free (gimple, heap, oprnd_info->def_stmts);
+ XDELETE (oprnd_info);
+ }
VEC_free (slp_oprnd_info, heap, *oprnds_info);
}
@@ -502,7 +502,7 @@ vect_build_slp_tree (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM);
}
- vect_free_oprnd_info (&oprnds_info, true);
+ vect_free_oprnd_info (&oprnds_info);
return false;
}
@@ -516,7 +516,7 @@ vect_build_slp_tree (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM);
}
- vect_free_oprnd_info (&oprnds_info, true);
+ vect_free_oprnd_info (&oprnds_info);
return false;
}
@@ -532,7 +532,7 @@ vect_build_slp_tree (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM);
}
- vect_free_oprnd_info (&oprnds_info, true);
+ vect_free_oprnd_info (&oprnds_info);
return false;
}
@@ -546,7 +546,7 @@ vect_build_slp_tree (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
print_generic_expr (vect_dump, scalar_type, TDF_SLIM);
}
- vect_free_oprnd_info (&oprnds_info, true);
+ vect_free_oprnd_info (&oprnds_info);
return false;
}
@@ -576,7 +576,7 @@ vect_build_slp_tree (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM);
}
- vect_free_oprnd_info (&oprnds_info, true);
+ vect_free_oprnd_info (&oprnds_info);
return false;
}
}
@@ -611,7 +611,7 @@ vect_build_slp_tree (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
{
if (vect_print_dump_info (REPORT_SLP))
fprintf (vect_dump, "Build SLP failed: no optab.");
- vect_free_oprnd_info (&oprnds_info, true);
+ vect_free_oprnd_info (&oprnds_info);
return false;
}
icode = (int) optab_handler (optab, vec_mode);
@@ -620,7 +620,7 @@ vect_build_slp_tree (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
if (vect_print_dump_info (REPORT_SLP))
fprintf (vect_dump, "Build SLP failed: "
"op not supported by target.");
- vect_free_oprnd_info (&oprnds_info, true);
+ vect_free_oprnd_info (&oprnds_info);
return false;
}
optab_op2_mode = insn_data[icode].operand[2].mode;
@@ -657,7 +657,7 @@ vect_build_slp_tree (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM);
}
- vect_free_oprnd_info (&oprnds_info, true);
+ vect_free_oprnd_info (&oprnds_info);
return false;
}
@@ -671,7 +671,7 @@ vect_build_slp_tree (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM);
}
- vect_free_oprnd_info (&oprnds_info, true);
+ vect_free_oprnd_info (&oprnds_info);
return false;
}
@@ -691,7 +691,7 @@ vect_build_slp_tree (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM);
}
- vect_free_oprnd_info (&oprnds_info, true);
+ vect_free_oprnd_info (&oprnds_info);
return false;
}
}
@@ -707,7 +707,7 @@ vect_build_slp_tree (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
stmt, ncopies_for_cost,
(i == 0), &oprnds_info))
{
- vect_free_oprnd_info (&oprnds_info, true);
+ vect_free_oprnd_info (&oprnds_info);
return false;
}
}
@@ -727,7 +727,7 @@ vect_build_slp_tree (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM);
}
- vect_free_oprnd_info (&oprnds_info, true);
+ vect_free_oprnd_info (&oprnds_info);
return false;
}
@@ -744,7 +744,7 @@ vect_build_slp_tree (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM);
}
- vect_free_oprnd_info (&oprnds_info, true);
+ vect_free_oprnd_info (&oprnds_info);
return false;
}
@@ -765,7 +765,7 @@ vect_build_slp_tree (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM);
}
- vect_free_oprnd_info (&oprnds_info, true);
+ vect_free_oprnd_info (&oprnds_info);
return false;
}
}
@@ -785,7 +785,7 @@ vect_build_slp_tree (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM);
}
- vect_free_oprnd_info (&oprnds_info, true);
+ vect_free_oprnd_info (&oprnds_info);
return false;
}
@@ -821,7 +821,7 @@ vect_build_slp_tree (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
}
/* FORNOW: Not strided loads are not supported. */
- vect_free_oprnd_info (&oprnds_info, true);
+ vect_free_oprnd_info (&oprnds_info);
return false;
}
@@ -838,7 +838,7 @@ vect_build_slp_tree (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM);
}
- vect_free_oprnd_info (&oprnds_info, true);
+ vect_free_oprnd_info (&oprnds_info);
return false;
}
@@ -857,7 +857,7 @@ vect_build_slp_tree (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM);
}
- vect_free_oprnd_info (&oprnds_info, true);
+ vect_free_oprnd_info (&oprnds_info);
return false;
}
}
@@ -867,7 +867,7 @@ vect_build_slp_tree (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
ncopies_for_cost, (i == 0),
&oprnds_info))
{
- vect_free_oprnd_info (&oprnds_info, true);
+ vect_free_oprnd_info (&oprnds_info);
return false;
}
}
@@ -898,6 +898,7 @@ vect_build_slp_tree (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
*loads_permuted = true;
}
+ vect_free_oprnd_info (&oprnds_info);
return true;
}
@@ -916,15 +917,18 @@ vect_build_slp_tree (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
max_nunits, load_permutation, loads,
vectorization_factor, loads_permuted))
{
- free (child);
- vect_free_oprnd_info (&oprnds_info, true);
+ if (child)
+ oprnd_info->def_stmts = NULL;
+ vect_free_slp_tree (child);
+ vect_free_oprnd_info (&oprnds_info);
return false;
}
+ oprnd_info->def_stmts = NULL;
VEC_quick_push (slp_void_p, SLP_TREE_CHILDREN (*node), child);
}
- vect_free_oprnd_info (&oprnds_info, false);
+ vect_free_oprnd_info (&oprnds_info);
return true;
}
@@ -2191,7 +2195,7 @@ vect_get_constant_vectors (tree op, slp_tree slp_node,
VEC (tree, heap) *voprnds = VEC_alloc (tree, heap, number_of_vectors);
bool constant_p, is_store;
tree neutral_op = NULL;
- enum tree_code code = gimple_assign_rhs_code (stmt);
+ enum tree_code code = gimple_expr_code (stmt);
gimple def_stmt;
struct loop *loop;
@@ -2287,21 +2291,31 @@ vect_get_constant_vectors (tree op, slp_tree slp_node,
{
if (is_store)
op = gimple_assign_rhs1 (stmt);
- else if (gimple_assign_rhs_code (stmt) != COND_EXPR)
- op = gimple_op (stmt, op_num + 1);
- else
+ else
{
- if (op_num == 0 || op_num == 1)
+ switch (code)
{
- tree cond = gimple_assign_rhs1 (stmt);
- op = TREE_OPERAND (cond, op_num);
- }
- else
- {
- if (op_num == 2)
- op = gimple_assign_rhs2 (stmt);
- else
- op = gimple_assign_rhs3 (stmt);
+ case COND_EXPR:
+ if (op_num == 0 || op_num == 1)
+ {
+ tree cond = gimple_assign_rhs1 (stmt);
+ op = TREE_OPERAND (cond, op_num);
+ }
+ else
+ {
+ if (op_num == 2)
+ op = gimple_assign_rhs2 (stmt);
+ else
+ op = gimple_assign_rhs3 (stmt);
+ }
+ break;
+
+ case CALL_EXPR:
+ op = gimple_call_arg (stmt, op_num);
+ break;
+
+ default:
+ op = gimple_op (stmt, op_num + 1);
}
}
@@ -2888,6 +2902,46 @@ vect_schedule_slp_instance (slp_tree node, slp_instance instance,
return is_store;
}
+/* Replace scalar calls from SLP node NODE with setting of their lhs to zero.
+ For loop vectorization this is done in vectorizable_call, but for SLP
+ it needs to be deferred until end of vect_schedule_slp, because multiple
+ SLP instances may refer to the same scalar stmt. */
+
+static void
+vect_remove_slp_scalar_calls (slp_tree node)
+{
+ gimple stmt, new_stmt;
+ gimple_stmt_iterator gsi;
+ int i;
+ slp_void_p child;
+ tree lhs;
+ stmt_vec_info stmt_info;
+
+ if (!node)
+ return;
+
+ FOR_EACH_VEC_ELT (slp_void_p, SLP_TREE_CHILDREN (node), i, child)
+ vect_remove_slp_scalar_calls ((slp_tree) child);
+
+ FOR_EACH_VEC_ELT (gimple, SLP_TREE_SCALAR_STMTS (node), i, stmt)
+ {
+ if (!is_gimple_call (stmt) || gimple_bb (stmt) == NULL)
+ continue;
+ stmt_info = vinfo_for_stmt (stmt);
+ if (stmt_info == NULL
+ || is_pattern_stmt_p (stmt_info)
+ || !PURE_SLP_STMT (stmt_info))
+ continue;
+ lhs = gimple_call_lhs (stmt);
+ new_stmt = gimple_build_assign (lhs, build_zero_cst (TREE_TYPE (lhs)));
+ set_vinfo_for_stmt (new_stmt, stmt_info);
+ set_vinfo_for_stmt (stmt, NULL);
+ STMT_VINFO_STMT (stmt_info) = new_stmt;
+ gsi = gsi_for_stmt (stmt);
+ gsi_replace (&gsi, new_stmt, false);
+ SSA_NAME_DEF_STMT (gimple_assign_lhs (new_stmt)) = new_stmt;
+ }
+}
/* Generate vector code for all SLP instances in the loop/basic block. */
@@ -2927,6 +2981,8 @@ vect_schedule_slp (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo)
unsigned int j;
gimple_stmt_iterator gsi;
+ vect_remove_slp_scalar_calls (root);
+
for (j = 0; VEC_iterate (gimple, SLP_TREE_SCALAR_STMTS (root), j, store)
&& j < SLP_INSTANCE_GROUP_SIZE (instance); j++)
{
diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
index 705e7df531a..8589a850df9 100644
--- a/gcc/tree-vect-stmts.c
+++ b/gcc/tree-vect-stmts.c
@@ -1886,6 +1886,9 @@ vectorizable_call (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
it defines is mapped to the new definition. So just replace
rhs of the statement with something harmless. */
+ if (slp_node)
+ return true;
+
type = TREE_TYPE (scalar_dest);
if (is_pattern_stmt_p (stmt_info))
lhs = gimple_call_lhs (STMT_VINFO_RELATED_STMT (stmt_info));
@@ -1893,8 +1896,7 @@ vectorizable_call (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
lhs = gimple_call_lhs (stmt);
new_stmt = gimple_build_assign (lhs, build_zero_cst (type));
set_vinfo_for_stmt (new_stmt, stmt_info);
- if (!slp_node)
- set_vinfo_for_stmt (stmt, NULL);
+ set_vinfo_for_stmt (stmt, NULL);
STMT_VINFO_STMT (stmt_info) = new_stmt;
gsi_replace (gsi, new_stmt, false);
SSA_NAME_DEF_STMT (gimple_assign_lhs (new_stmt)) = new_stmt;
@@ -4966,7 +4968,7 @@ vectorizable_condition (gimple stmt, gimple_stmt_iterator *gsi,
tree cond_expr, then_clause, else_clause;
stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
tree vectype = STMT_VINFO_VECTYPE (stmt_info);
- tree comp_vectype;
+ tree comp_vectype = NULL_TREE;
tree vec_cond_lhs = NULL_TREE, vec_cond_rhs = NULL_TREE;
tree vec_then_clause = NULL_TREE, vec_else_clause = NULL_TREE;
tree vec_compare, vec_cond_expr;
@@ -5567,10 +5569,14 @@ vect_remove_stores (gimple first_stmt)
while (next)
{
+ stmt_vec_info stmt_info = vinfo_for_stmt (next);
+
+ tmp = GROUP_NEXT_ELEMENT (stmt_info);
+ if (is_pattern_stmt_p (stmt_info))
+ next = STMT_VINFO_RELATED_STMT (stmt_info);
/* Free the attached stmt_vec_info and remove the stmt. */
next_si = gsi_for_stmt (next);
gsi_remove (&next_si, true);
- tmp = GROUP_NEXT_ELEMENT (vinfo_for_stmt (next));
free_stmt_vec_info (next);
next = tmp;
}
@@ -5660,6 +5666,22 @@ free_stmt_vec_info (gimple stmt)
if (!stmt_info)
return;
+ /* Check if this statement has a related "pattern stmt"
+ (introduced by the vectorizer during the pattern recognition
+ pass). Free pattern's stmt_vec_info and def stmt's stmt_vec_info
+ too. */
+ if (STMT_VINFO_IN_PATTERN_P (stmt_info))
+ {
+ stmt_vec_info patt_info
+ = vinfo_for_stmt (STMT_VINFO_RELATED_STMT (stmt_info));
+ if (patt_info)
+ {
+ if (STMT_VINFO_PATTERN_DEF_STMT (patt_info))
+ free_stmt_vec_info (STMT_VINFO_PATTERN_DEF_STMT (patt_info));
+ free_stmt_vec_info (STMT_VINFO_RELATED_STMT (stmt_info));
+ }
+ }
+
VEC_free (dr_p, heap, STMT_VINFO_SAME_ALIGN_REFS (stmt_info));
set_vinfo_for_stmt (stmt, NULL);
free (stmt_info);
diff --git a/gcc/varasm.c b/gcc/varasm.c
index ed27dce7b0a..cfbb9ca1f2e 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -564,7 +564,7 @@ default_function_section (tree decl, enum node_frequency freq,
/* Return the section for function DECL.
If DECL is NULL_TREE, return the text section. We can be passed
- NULL_TREE under some circumstances by dbxout.c at least.
+ NULL_TREE under some circumstances by dbxout.c at least.
If FORCE_COLD is true, return cold function section ignoring
the frequency info of cgraph_node. */
@@ -1928,7 +1928,7 @@ assemble_variable (tree decl, int top_level ATTRIBUTE_UNUSED,
/* Emulated TLS had better not get this far. */
gcc_checking_assert (targetm.have_tls || !DECL_THREAD_LOCAL_P (decl));
-
+
last_assemble_variable_decl = 0;
/* Normally no need to say anything here for external references,
@@ -2852,7 +2852,7 @@ compare_constant (const tree t1, const tree t2)
return 0;
link2 = TREE_CHAIN (link2);
}
-
+
return 1;
}
@@ -5754,7 +5754,7 @@ finish_aliases_1 (void)
&& ! lookup_attribute ("weakref", DECL_ATTRIBUTES (p->decl)))
{
error ("%q+D aliased to external symbol %qE",
- p->decl, p->target);
+ p->decl, p->target);
p->emitted_diags |= ALIAS_DIAG_TO_EXTERN;
}
}
@@ -5820,7 +5820,7 @@ assemble_alias (tree decl, tree target)
if (lookup_attribute ("ifunc", DECL_ATTRIBUTES (decl)))
error_at (DECL_SOURCE_LOCATION (decl),
"ifunc is not supported in this configuration");
- else
+ else
error_at (DECL_SOURCE_LOCATION (decl),
"only weak aliases are supported in this configuration");
return;
@@ -6019,7 +6019,7 @@ finish_tm_clone_pairs (void)
the visibility type VIS, which must not be VISIBILITY_DEFAULT. */
void
-default_assemble_visibility (tree decl ATTRIBUTE_UNUSED,
+default_assemble_visibility (tree decl ATTRIBUTE_UNUSED,
int vis ATTRIBUTE_UNUSED)
{
#ifdef HAVE_GAS_HIDDEN
@@ -7519,6 +7519,120 @@ make_debug_expr_from_rtl (const_rtx exp)
return dval;
}
+#ifdef ELF_ASCII_ESCAPES
+/* Default ASM_OUTPUT_LIMITED_STRING for ELF targets. */
+
+void
+default_elf_asm_output_limited_string (FILE *f, const char *s)
+{
+ int escape;
+ unsigned char c;
+
+ fputs (STRING_ASM_OP, f);
+ putc ('"', f);
+ while (*s != '\0')
+ {
+ c = *s;
+ escape = ELF_ASCII_ESCAPES[c];
+ switch (escape)
+ {
+ case 0:
+ putc (c, f);
+ break;
+ case 1:
+ /* TODO: Print in hex with fast function, important for -flto. */
+ fprintf (f, "\\%03o", c);
+ break;
+ default:
+ putc ('\\', f);
+ putc (escape, f);
+ break;
+ }
+ s++;
+ }
+ putc ('\"', f);
+ putc ('\n', f);
+}
+
+/* Default ASM_OUTPUT_ASCII for ELF targets. */
+
+void
+default_elf_asm_output_ascii (FILE *f, const char *s, unsigned int len)
+{
+ const char *limit = s + len;
+ const char *last_null = NULL;
+ unsigned bytes_in_chunk = 0;
+ unsigned char c;
+ int escape;
+
+ for (; s < limit; s++)
+ {
+ const char *p;
+
+ if (bytes_in_chunk >= 60)
+ {
+ putc ('\"', f);
+ putc ('\n', f);
+ bytes_in_chunk = 0;
+ }
+
+ if (s > last_null)
+ {
+ for (p = s; p < limit && *p != '\0'; p++)
+ continue;
+ last_null = p;
+ }
+ else
+ p = last_null;
+
+ if (p < limit && (p - s) <= (long) ELF_STRING_LIMIT)
+ {
+ if (bytes_in_chunk > 0)
+ {
+ putc ('\"', f);
+ putc ('\n', f);
+ bytes_in_chunk = 0;
+ }
+
+ default_elf_asm_output_limited_string (f, s);
+ s = p;
+ }
+ else
+ {
+ if (bytes_in_chunk == 0)
+ fputs (ASCII_DATA_ASM_OP "\"", f);
+
+ c = *s;
+ escape = ELF_ASCII_ESCAPES[c];
+ switch (escape)
+ {
+ case 0:
+ putc (c, f);
+ bytes_in_chunk++;
+ break;
+ case 1:
+ /* TODO: Print in hex with fast function, important for -flto. */
+ fprintf (f, "\\%03o", c);
+ bytes_in_chunk += 4;
+ break;
+ default:
+ putc ('\\', f);
+ putc (escape, f);
+ bytes_in_chunk += 2;
+ break;
+ }
+
+ }
+ }
+
+ if (bytes_in_chunk > 0)
+ {
+ putc ('\"', f);
+ putc ('\n', f);
+ }
+}
+#endif
+
static GTY(()) section *elf_init_array_section;
static GTY(()) section *elf_fini_array_section;
diff --git a/gcc/varpool.c b/gcc/varpool.c
index e342a9109d9..74fc1ba712b 100644
--- a/gcc/varpool.c
+++ b/gcc/varpool.c
@@ -414,6 +414,20 @@ varpool_finalize_decl (tree decl)
varpool_assemble_pending_decls ();
}
+/* Add the variable DECL to the varpool.
+ Unlike varpool_finalize_decl function is intended to be used
+ by middle end and allows insertion of new variable at arbitrary point
+ of compilation. */
+void
+varpool_add_new_variable (tree decl)
+{
+ struct varpool_node *node;
+ varpool_finalize_decl (decl);
+ node = varpool_node (decl);
+ if (varpool_externally_visible_p (node, false))
+ node->externally_visible = true;
+}
+
/* Return variable availability. See cgraph.h for description of individual
return values. */
enum availability
diff --git a/gcc/vec.h b/gcc/vec.h
index 789e8e2d4df..d47795879f1 100644
--- a/gcc/vec.h
+++ b/gcc/vec.h
@@ -549,7 +549,12 @@ typedef struct VEC(T,A) \
} VEC(T,A)
/* Convert to base type. */
+#if GCC_VERSION >= 4000
+#define VEC_BASE(P) \
+ ((offsetof (__typeof (*P), base) == 0 || (P)) ? &(P)->base : 0)
+#else
#define VEC_BASE(P) ((P) ? &(P)->base : 0)
+#endif
/* Vector of integer-like object. */
#define DEF_VEC_I(T) \
diff --git a/libada/ChangeLog b/libada/ChangeLog
index fbcff774051..921b1bd7789 100644
--- a/libada/ChangeLog
+++ b/libada/ChangeLog
@@ -1,3 +1,8 @@
+2011-11-12 Iain Sandoe <iains@gcc.gnu.org>
+
+ Makefile.in: Change dependency on oscons to depend on the generator
+ tool.
+
2011-10-12 Eric Botcazou <ebotcazou@adacore.com>
* Makefile.in (LOOSE_WARN): Delete.
diff --git a/libada/Makefile.in b/libada/Makefile.in
index 86aff529dbd..5389dd005de 100644
--- a/libada/Makefile.in
+++ b/libada/Makefile.in
@@ -64,6 +64,7 @@ target_noncanonical:=@target_noncanonical@
version := $(shell cat $(srcdir)/../gcc/BASE-VER)
libsubdir := $(libdir)/gcc/$(target_noncanonical)/$(version)$(MULTISUBDIR)
ADA_RTS_DIR=$(GCC_DIR)/ada/rts$(subst /,_,$(MULTISUBDIR))
+ADA_RTS_SUBDIR=./rts$(subst /,_,$(MULTISUBDIR))
# exeext should not be used because it's the *host* exeext. We're building
# a *target* library, aren't we?!? Likewise for CC. Still, provide bogus
@@ -90,10 +91,10 @@ LIBADA_FLAGS_TO_PASS = \
"CFLAGS=$(CFLAGS)"
# Rules to build gnatlib.
-.PHONY: gnatlib gnatlib-plain gnatlib-sjlj gnatlib-zcx gnatlib-shared oscons
+.PHONY: gnatlib gnatlib-plain gnatlib-sjlj gnatlib-zcx gnatlib-shared osconstool
gnatlib: @default_gnatlib_target@
-gnatlib-plain: oscons $(GCC_DIR)/ada/Makefile
+gnatlib-plain: osconstool $(GCC_DIR)/ada/Makefile
test -f stamp-libada || \
$(MAKE) -C $(GCC_DIR)/ada $(LIBADA_FLAGS_TO_PASS) gnatlib \
&& touch stamp-libada
@@ -102,7 +103,7 @@ gnatlib-plain: oscons $(GCC_DIR)/ada/Makefile
$(LN_S) $(ADA_RTS_DIR) adainclude
$(LN_S) $(ADA_RTS_DIR) adalib
-gnatlib-sjlj gnatlib-zcx gnatlib-shared: oscons $(GCC_DIR)/ada/Makefile
+gnatlib-sjlj gnatlib-zcx gnatlib-shared: osconstool $(GCC_DIR)/ada/Makefile
test -f stamp-libada || \
$(MAKE) -C $(GCC_DIR)/ada $(LIBADA_FLAGS_TO_PASS) $@ \
&& touch stamp-libada
@@ -111,8 +112,8 @@ gnatlib-sjlj gnatlib-zcx gnatlib-shared: oscons $(GCC_DIR)/ada/Makefile
$(LN_S) $(ADA_RTS_DIR) adainclude
$(LN_S) $(ADA_RTS_DIR) adalib
-oscons:
- $(MAKE) -C $(GCC_DIR) $(LIBADA_FLAGS_TO_PASS) ada/s-oscons.ads
+osconstool:
+ $(MAKE) -C $(GCC_DIR)/ada $(LIBADA_FLAGS_TO_PASS) ./bldtools/oscons/xoscons
install-gnatlib: $(GCC_DIR)/ada/Makefile
$(MAKE) -C $(GCC_DIR)/ada $(LIBADA_FLAGS_TO_PASS) install-gnatlib
diff --git a/libffi/ChangeLog b/libffi/ChangeLog
index a9d240a6128..2c34801a354 100644
--- a/libffi/ChangeLog
+++ b/libffi/ChangeLog
@@ -1,3 +1,8 @@
+2011-11-10 Richard Henderson <rth@redhat.com>
+
+ * configure.ac (GCC_AS_CFI_PSEUDO_OP): Use it instead of inline check.
+ * configure, aclocal.m4: Rebuild.
+
2011-09-04 Iain Sandoe <iains@gcc.gnu.org>
PR libffi/49594
diff --git a/libffi/aclocal.m4 b/libffi/aclocal.m4
index f7ef2f8e286..9d6a6694fd2 100644
--- a/libffi/aclocal.m4
+++ b/libffi/aclocal.m4
@@ -1025,6 +1025,7 @@ AC_SUBST([am__tar])
AC_SUBST([am__untar])
]) # _AM_PROG_TAR
+m4_include([../config/asmcfi.m4])
m4_include([../config/depstand.m4])
m4_include([../config/lead-dot.m4])
m4_include([../config/multi.m4])
diff --git a/libffi/configure b/libffi/configure
index 64787470333..57ccc55f4ad 100755
--- a/libffi/configure
+++ b/libffi/configure
@@ -12282,11 +12282,11 @@ $as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler .cfi pseudo-op support" >&5
$as_echo_n "checking assembler .cfi pseudo-op support... " >&6; }
-if test "${libffi_cv_as_cfi_pseudo_op+set}" = set; then :
+if test "${gcc_cv_as_cfi_pseudo_op+set}" = set; then :
$as_echo_n "(cached) " >&6
else
- libffi_cv_as_cfi_pseudo_op=unknown
+ gcc_cv_as_cfi_pseudo_op=unknown
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
asm (".cfi_startproc\n\t.cfi_endproc");
@@ -12299,20 +12299,21 @@ main ()
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
- libffi_cv_as_cfi_pseudo_op=yes
+ gcc_cv_as_cfi_pseudo_op=yes
else
- libffi_cv_as_cfi_pseudo_op=no
+ gcc_cv_as_cfi_pseudo_op=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libffi_cv_as_cfi_pseudo_op" >&5
-$as_echo "$libffi_cv_as_cfi_pseudo_op" >&6; }
-if test "x$libffi_cv_as_cfi_pseudo_op" = xyes; then
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_cfi_pseudo_op" >&5
+$as_echo "$gcc_cv_as_cfi_pseudo_op" >&6; }
+ if test "x$gcc_cv_as_cfi_pseudo_op" = xyes; then
$as_echo "#define HAVE_AS_CFI_PSEUDO_OP 1" >>confdefs.h
-fi
+ fi
+
if test x$TARGET = xSPARC; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler and linker support unaligned pc related relocs" >&5
diff --git a/libffi/configure.ac b/libffi/configure.ac
index d16155a40fb..2c673354ff2 100644
--- a/libffi/configure.ac
+++ b/libffi/configure.ac
@@ -228,17 +228,7 @@ AC_SUBST(HAVE_LONG_DOUBLE)
AC_C_BIGENDIAN
-AC_CACHE_CHECK([assembler .cfi pseudo-op support],
- libffi_cv_as_cfi_pseudo_op, [
- libffi_cv_as_cfi_pseudo_op=unknown
- AC_TRY_COMPILE([asm (".cfi_startproc\n\t.cfi_endproc");],,
- [libffi_cv_as_cfi_pseudo_op=yes],
- [libffi_cv_as_cfi_pseudo_op=no])
-])
-if test "x$libffi_cv_as_cfi_pseudo_op" = xyes; then
- AC_DEFINE(HAVE_AS_CFI_PSEUDO_OP, 1,
- [Define if your assembler supports .cfi_* directives.])
-fi
+GCC_AS_CFI_PSEUDO_OP
if test x$TARGET = xSPARC; then
AC_CACHE_CHECK([assembler and linker support unaligned pc related relocs],
diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog
index 0e99994c059..c10667bd428 100644
--- a/libgcc/ChangeLog
+++ b/libgcc/ChangeLog
@@ -1,3 +1,44 @@
+2011-11-13 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
+
+ * config.host (hppa*64*-*-hpux11*): Remove pa/t-stublib64 from
+ tmake_file list.
+ * config/pa/t-stublib: Merge rules from config/pa/t-stublib64.
+ * config/pa/t-stublib64: Delete.
+
+2011-11-12 Richard Henderson <rth@redhat.com>
+
+ * config/rs6000/linux-unwind.h (frob_update_context): Properly
+ cast the pointer argument to _Unwind_SetGRPtr.
+
+2011-11-11 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * config/spu/t-elf (LIB2ADD): Use LIB2FUNCS_EXCLUDE instead.
+
+2011-11-09 Ian Lance Taylor <iant@google.com>
+
+ * generic-morestack.c: Include <string.h>.
+ (uintptr_type): Define.
+ (struct initial_sp): Add dont_block_signals field. Reduce size of
+ extra array by 1.
+ (allocate_segment): Set prev field to NULL. Don't set
+ __morestack_current_segment or __morestack_segments.
+ (__generic_morestack): Update current->prev and *pp after calling
+ allocate_segment.
+ (__morestack_block_signals): Don't do anything if
+ dont_block_signals is set.
+ (__morestack_unblock_signals): Likewise.
+ (__generic_findstack): Check for initial_sp == NULL. Add casts to
+ uintptr_type.
+ (__splitstack_block_signals): New function.
+ (enum __splitstack_content_offsets): Define.
+ (__splitstack_getcontext, __splitstack_setcontext): New functions.
+ (__splitstack_makecontext): New function.
+ (__splitstack_block_signals_context): New function.
+ (__splitstack_find_context): New function.
+ * config/i386/morestack.S (__morestack_get_guard): New function.
+ (__morestack_set_guard, __morestack_make_guard): New functions.
+ * libgcc-std.ver.in: Add new functions to GCC_4.7.0.
+
2011-11-09 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
* config.host (i[34567]86-*-cygwin*): Move i386/t-mingw-pthread ...
diff --git a/libgcc/config.host b/libgcc/config.host
index 03f94d972df..342d60c6be7 100644
--- a/libgcc/config.host
+++ b/libgcc/config.host
@@ -486,7 +486,7 @@ hppa[12]*-*-hpux10*)
md_unwind_header=pa/hpux-unwind.h
;;
hppa*64*-*-hpux11*)
- tmake_file="$tmake_file pa/t-hpux pa/t-pa64 pa/t-stublib pa/t-stublib64 t-libgcc-pic t-slibgcc"
+ tmake_file="$tmake_file pa/t-hpux pa/t-pa64 pa/t-stublib t-libgcc-pic t-slibgcc"
# Set the libgcc version number
if test x$enable_sjlj_exceptions = xyes; then
tmake_file="$tmake_file pa/t-slibgcc-sjlj-ver"
diff --git a/libgcc/config/i386/morestack.S b/libgcc/config/i386/morestack.S
index 85c20ed7e93..0667590bcf0 100644
--- a/libgcc/config/i386/morestack.S
+++ b/libgcc/config/i386/morestack.S
@@ -1,5 +1,5 @@
# x86/x86_64 support for -fsplit-stack.
-# Copyright (C) 2009, 2010 Free Software Foundation, Inc.
+# Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc.
# Contributed by Ian Lance Taylor <iant@google.com>.
# This file is part of GCC.
@@ -620,6 +620,82 @@ __stack_split_initialize:
.size __stack_split_initialize, . - __stack_split_initialize
#endif
+# Routines to get and set the guard, for __splitstack_getcontext,
+# __splitstack_setcontext, and __splitstack_makecontext.
+
+# void *__morestack_get_guard (void) returns the current stack guard.
+ .text
+ .global __morestack_get_guard
+ .hidden __morestack_get_guard
+
+#ifdef __ELF__
+ .type __morestack_get_guard,@function
+#endif
+
+__morestack_get_guard:
+
+#ifndef __x86_64__
+ movl %gs:0x30,%eax
+#else
+#ifdef __LP64__
+ movq %fs:0x70,%rax
+#else
+ movl %fs:0x40,%eax
+#endif
+#endif
+ ret
+
+#ifdef __ELF__
+ .size __morestack_get_guard, . - __morestack_get_guard
+#endif
+
+# void __morestack_set_guard (void *) sets the stack guard.
+ .global __morestack_set_guard
+ .hidden __morestack_set_guard
+
+#ifdef __ELF__
+ .type __morestack_set_guard,@function
+#endif
+
+__morestack_set_guard:
+
+#ifndef __x86_64__
+ movl 4(%esp),%eax
+ movl %eax,%gs:0x30
+#else
+ X86_64_SAVE_NEW_STACK_BOUNDARY (di)
+#endif
+ ret
+
+#ifdef __ELF__
+ .size __morestack_set_guard, . - __morestack_set_guard
+#endif
+
+# void *__morestack_make_guard (void *, size_t) returns the stack
+# guard value for a stack.
+ .global __morestack_make_guard
+ .hidden __morestack_make_guard
+
+#ifdef __ELF__
+ .type __morestack_make_guard,@function
+#endif
+
+__morestack_make_guard:
+
+#ifndef __x86_64__
+ movl 4(%esp),%eax
+ subl 8(%esp),%eax
+ addl $BACKOFF,%eax
+#else
+ subq %rsi,%rdi
+ addq $BACKOFF,%rdi
+ movq %rdi,%rax
+#endif
+ ret
+
+#ifdef __ELF__
+ .size __morestack_make_guard, . - __morestack_make_guard
+#endif
# Make __stack_split_initialize a high priority constructor. FIXME:
# This is ELF specific.
diff --git a/libgcc/config/pa/t-stublib b/libgcc/config/pa/t-stublib
index 017998ff689..94380923174 100644
--- a/libgcc/config/pa/t-stublib
+++ b/libgcc/config/pa/t-stublib
@@ -1,8 +1,21 @@
-LIBGCCSTUB_OBJS = pthread_default_stacksize_np-stub.o \
+LIBGCCSTUB_OBJS = rfi-stub.o dfi-stub.o jvrc-stub.o cxaf-stub.o \
+ pthread_default_stacksize_np-stub.o \
pthread_mutex_lock-stub.o \
pthread_mutex_unlock-stub.o \
pthread_once-stub.o
+rfi-stub.o: $(srcdir)/config/pa/stublib.c
+ $(gcc_compile) -c -O2 -DL_register_frame_info $<
+
+dfi-stub.o: $(srcdir)/config/pa/stublib.c
+ $(gcc_compile) -c -O2 -DL_deregister_frame_info $<
+
+cxaf-stub.o: $(srcdir)/config/pa/stublib.c
+ $(gcc_compile) -c -O2 -DL_cxa_finalize $<
+
+jvrc-stub.o: $(srcdir)/config/pa/stublib.c
+ $(gcc_compile) -c -O2 -DL_Jv_RegisterClasses $<
+
pthread_default_stacksize_np-stub.o: $(srcdir)/config/pa/stublib.c
$(gcc_compile) -c -O2 -DL_pthread_default_stacksize_np $<
@@ -17,5 +30,5 @@ pthread_once-stub.o: $(srcdir)/config/pa/stublib.c
libgcc_stub.a: $(LIBGCCSTUB_OBJS)
-rm -rf $@
- $(AR) rc $@ $<
+ $(AR) rc $@ $(LIBGCCSTUB_OBJS)
$(RANLIB) $@
diff --git a/libgcc/config/pa/t-stublib64 b/libgcc/config/pa/t-stublib64
deleted file mode 100644
index 5d0d9682abf..00000000000
--- a/libgcc/config/pa/t-stublib64
+++ /dev/null
@@ -1,13 +0,0 @@
-LIBGCCSTUB_OBJS += rfi-stub.o dfi-stub.o jvrc-stub.o cxaf-stub.o
-
-rfi-stub.o: $(srcdir)/config/pa/stublib.c
- $(gcc_compile) -c -O2 -DL_register_frame_info $<
-
-dfi-stub.o: $(srcdir)/config/pa/stublib.c
- $(gcc_compile) -c -O2 -DL_deregister_frame_info $<
-
-cxaf-stub.o: $(srcdir)/config/pa/stublib.c
- $(gcc_compile) -c -O2 -DL_cxa_finalize $<
-
-jvrc-stub.o: $(srcdir)/config/pa/stublib.c
- $(gcc_compile) -c -O2 -DL_Jv_RegisterClasses $<
diff --git a/libgcc/config/rs6000/linux-unwind.h b/libgcc/config/rs6000/linux-unwind.h
index 20116326c3c..13bf413c7c9 100644
--- a/libgcc/config/rs6000/linux-unwind.h
+++ b/libgcc/config/rs6000/linux-unwind.h
@@ -368,7 +368,7 @@ frob_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs ATT
before the bctrl so this is the first and only place
we need to use the stored R2. */
_Unwind_Word sp = _Unwind_GetGR (context, 1);
- _Unwind_SetGRPtr (context, 2, sp + 40);
+ _Unwind_SetGRPtr (context, 2, (void *)(sp + 40));
}
}
}
diff --git a/libgcc/config/spu/t-elf b/libgcc/config/spu/t-elf
index 83616c1ca7d..29536e88132 100644
--- a/libgcc/config/spu/t-elf
+++ b/libgcc/config/spu/t-elf
@@ -5,7 +5,7 @@ CRTSTUFF_T_CFLAGS =
# We exclude those because the libgcc2.c default versions do not support
# the SPU single-precision format (round towards zero). We provide our
# own versions below and/or via direct expansion.
-LIB2ADD = _floatdisf _floatundisf _floattisf _floatunstisf
+LIB2FUNCS_EXCLUDE = _floatdisf _floatundisf _floattisf _floatunstisf
LIB2ADD_ST = $(srcdir)/config/spu/float_unssidf.c \
$(srcdir)/config/spu/float_unsdidf.c \
diff --git a/libgcc/generic-morestack.c b/libgcc/generic-morestack.c
index 07bc2a66073..00a3b1c3bf0 100644
--- a/libgcc/generic-morestack.c
+++ b/libgcc/generic-morestack.c
@@ -41,12 +41,15 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include <errno.h>
#include <signal.h>
#include <stdlib.h>
+#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/uio.h>
#include "generic-morestack.h"
+typedef unsigned uintptr_type __attribute__ ((mode (pointer)));
+
/* This file contains subroutines that are used by code compiled with
-fsplit-stack. */
@@ -88,14 +91,50 @@ extern void *
__morestack_allocate_stack_space (size_t size)
__attribute__ ((visibility ("hidden")));
-/* This is a function which -fsplit-stack code can call to get a list
- of the stacks. Since it is not called only by the compiler, it is
- not hidden. */
+/* These are functions which -fsplit-stack code can call. These are
+ not called by the compiler, and are not hidden. FIXME: These
+ should be in some header file somewhere, somehow. */
extern void *
__splitstack_find (void *, void *, size_t *, void **, void **, void **)
__attribute__ ((visibility ("default")));
+extern void
+__splitstack_block_signals (int *, int *)
+ __attribute__ ((visibility ("default")));
+
+extern void
+__splitstack_getcontext (void *context[10])
+ __attribute__ ((no_split_stack, visibility ("default")));
+
+extern void
+__splitstack_setcontext (void *context[10])
+ __attribute__ ((no_split_stack, visibility ("default")));
+
+extern void *
+__splitstack_makecontext (size_t, void *context[10], size_t *)
+ __attribute__ ((visibility ("default")));
+
+extern void
+__splitstack_block_signals_context (void *context[10], int *, int *)
+ __attribute__ ((visibility ("default")));
+
+extern void *
+__splitstack_find_context (void *context[10], size_t *, void **, void **,
+ void **)
+ __attribute__ ((visibility ("default")));
+
+/* These functions must be defined by the processor specific code. */
+
+extern void *__morestack_get_guard (void)
+ __attribute__ ((no_split_stack, visibility ("hidden")));
+
+extern void __morestack_set_guard (void *)
+ __attribute__ ((no_split_stack, visibility ("hidden")));
+
+extern void *__morestack_make_guard (void *, size_t)
+ __attribute__ ((no_split_stack, visibility ("hidden")));
+
/* When we allocate a stack segment we put this header at the
start. */
@@ -138,8 +177,13 @@ struct initial_sp
/* A signal mask, put here so that the thread can use it without
needing stack space. */
sigset_t mask;
+ /* Non-zero if we should not block signals. This is a reversed flag
+ so that the default zero value is the safe value. The type is
+ uintptr_type because it replaced one of the void * pointers in
+ extra. */
+ uintptr_type dont_block_signals;
/* Some extra space for later extensibility. */
- void *extra[5];
+ void *extra[4];
};
/* A list of memory blocks allocated by dynamic stack allocation.
@@ -339,18 +383,13 @@ allocate_segment (size_t frame_size)
pss = (struct stack_segment *) space;
- pss->prev = __morestack_current_segment;
+ pss->prev = NULL;
pss->next = NULL;
pss->size = allocate - overhead;
pss->dynamic_allocation = NULL;
pss->free_dynamic_allocation = NULL;
pss->extra = NULL;
- if (__morestack_current_segment != NULL)
- __morestack_current_segment->next = pss;
- else
- __morestack_segments = pss;
-
return pss;
}
@@ -513,7 +552,11 @@ __generic_morestack (size_t *pframe_size, void *old_stack, size_t param_size)
current = *pp;
if (current == NULL)
- current = allocate_segment (frame_size + param_size);
+ {
+ current = allocate_segment (frame_size + param_size);
+ current->prev = __morestack_current_segment;
+ *pp = current;
+ }
current->old_stack = old_stack;
@@ -614,7 +657,9 @@ extern int pthread_sigmask (int, const sigset_t *, sigset_t *)
void
__morestack_block_signals (void)
{
- if (pthread_sigmask)
+ if (__morestack_initial_sp.dont_block_signals)
+ ;
+ else if (pthread_sigmask)
pthread_sigmask (SIG_BLOCK, &__morestack_fullmask,
&__morestack_initial_sp.mask);
else
@@ -627,7 +672,9 @@ __morestack_block_signals (void)
void
__morestack_unblock_signals (void)
{
- if (pthread_sigmask)
+ if (__morestack_initial_sp.dont_block_signals)
+ ;
+ else if (pthread_sigmask)
pthread_sigmask (SIG_SETMASK, &__morestack_initial_sp.mask, NULL);
else
sigprocmask (SIG_SETMASK, &__morestack_initial_sp.mask, NULL);
@@ -727,6 +774,10 @@ __generic_findstack (void *stack)
}
/* We have popped back to the original stack. */
+
+ if (__morestack_initial_sp.sp == NULL)
+ return 0;
+
#ifdef STACK_GROWS_DOWNWARD
if ((char *) stack >= (char *) __morestack_initial_sp.sp)
used = 0;
@@ -796,11 +847,14 @@ __splitstack_find (void *segment_arg, void *sp, size_t *len,
void *ret;
char *nsp;
- if (segment_arg == (void *) 1)
+ if (segment_arg == (void *) (uintptr_type) 1)
{
char *isp = (char *) *initial_sp;
- *next_segment = (void *) 2;
+ if (isp == NULL)
+ return NULL;
+
+ *next_segment = (void *) (uintptr_type) 2;
*next_sp = NULL;
#ifdef STACK_GROWS_DOWNWARD
if ((char *) sp >= isp)
@@ -814,7 +868,7 @@ __splitstack_find (void *segment_arg, void *sp, size_t *len,
return (void *) isp;
#endif
}
- else if (segment_arg == (void *) 2)
+ else if (segment_arg == (void *) (uintptr_type) 2)
return NULL;
else if (segment_arg != NULL)
segment = (struct stack_segment *) segment_arg;
@@ -826,8 +880,8 @@ __splitstack_find (void *segment_arg, void *sp, size_t *len,
while (1)
{
if (segment == NULL)
- return __splitstack_find ((void *) 1, sp, len, next_segment,
- next_sp, initial_sp);
+ return __splitstack_find ((void *) (uintptr_type) 1, sp, len,
+ next_segment, next_sp, initial_sp);
if ((char *) sp >= (char *) (segment + 1)
&& (char *) sp <= (char *) (segment + 1) + segment->size)
break;
@@ -836,7 +890,7 @@ __splitstack_find (void *segment_arg, void *sp, size_t *len,
}
if (segment->prev == NULL)
- *next_segment = (void *) 1;
+ *next_segment = (void *) (uintptr_type) 1;
else
*next_segment = segment->prev;
@@ -878,4 +932,164 @@ __splitstack_find (void *segment_arg, void *sp, size_t *len,
return ret;
}
+/* Tell the split stack code whether it has to block signals while
+ manipulating the stack. This is for programs in which some threads
+ block all signals. If a thread already blocks signals, there is no
+ need for the split stack code to block them as well. If NEW is not
+ NULL, then if *NEW is non-zero signals will be blocked while
+ splitting the stack, otherwise they will not. If OLD is not NULL,
+ *OLD will be set to the old value. */
+
+void
+__splitstack_block_signals (int *new, int *old)
+{
+ if (old != NULL)
+ *old = __morestack_initial_sp.dont_block_signals ? 0 : 1;
+ if (new != NULL)
+ __morestack_initial_sp.dont_block_signals = *new ? 0 : 1;
+}
+
+/* The offsets into the arrays used by __splitstack_getcontext and
+ __splitstack_setcontext. */
+
+enum __splitstack_context_offsets
+{
+ MORESTACK_SEGMENTS = 0,
+ CURRENT_SEGMENT = 1,
+ CURRENT_STACK = 2,
+ STACK_GUARD = 3,
+ INITIAL_SP = 4,
+ INITIAL_SP_LEN = 5,
+ BLOCK_SIGNALS = 6,
+
+ NUMBER_OFFSETS = 10
+};
+
+/* Get the current split stack context. This may be used for
+ coroutine switching, similar to getcontext. The argument should
+ have at least 10 void *pointers for extensibility, although we
+ don't currently use all of them. This would normally be called
+ immediately before a call to getcontext or swapcontext or
+ setjmp. */
+
+void
+__splitstack_getcontext (void *context[NUMBER_OFFSETS])
+{
+ memset (context, 0, NUMBER_OFFSETS * sizeof (void *));
+ context[MORESTACK_SEGMENTS] = (void *) __morestack_segments;
+ context[CURRENT_SEGMENT] = (void *) __morestack_current_segment;
+ context[CURRENT_STACK] = (void *) &context;
+ context[STACK_GUARD] = __morestack_get_guard ();
+ context[INITIAL_SP] = (void *) __morestack_initial_sp.sp;
+ context[INITIAL_SP_LEN] = (void *) (uintptr_type) __morestack_initial_sp.len;
+ context[BLOCK_SIGNALS] = (void *) __morestack_initial_sp.dont_block_signals;
+}
+
+/* Set the current split stack context. The argument should be a
+ context previously passed to __splitstack_getcontext. This would
+ normally be called immediately after a call to getcontext or
+ swapcontext or setjmp if something jumped to it. */
+
+void
+__splitstack_setcontext (void *context[NUMBER_OFFSETS])
+{
+ __morestack_segments = (struct stack_segment *) context[MORESTACK_SEGMENTS];
+ __morestack_current_segment =
+ (struct stack_segment *) context[CURRENT_SEGMENT];
+ __morestack_set_guard (context[STACK_GUARD]);
+ __morestack_initial_sp.sp = context[INITIAL_SP];
+ __morestack_initial_sp.len = (size_t) context[INITIAL_SP_LEN];
+ __morestack_initial_sp.dont_block_signals =
+ (uintptr_type) context[BLOCK_SIGNALS];
+}
+
+/* Create a new split stack context. This will allocate a new stack
+ segment which may be used by a coroutine. STACK_SIZE is the
+ minimum size of the new stack. The caller is responsible for
+ actually setting the stack pointer. This would normally be called
+ before a call to makecontext, and the returned stack pointer and
+ size would be used to set the uc_stack field. A function called
+ via makecontext on a stack created by __splitstack_makecontext may
+ not return. Note that the returned pointer points to the lowest
+ address in the stack space, and thus may not be the value to which
+ to set the stack pointer. */
+
+void *
+__splitstack_makecontext (size_t stack_size, void *context[NUMBER_OFFSETS],
+ size_t *size)
+{
+ struct stack_segment *segment;
+ void *initial_sp;
+
+ memset (context, 0, NUMBER_OFFSETS * sizeof (void *));
+ segment = allocate_segment (stack_size);
+ context[MORESTACK_SEGMENTS] = segment;
+ context[CURRENT_SEGMENT] = segment;
+#ifdef STACK_GROWS_DOWNWARD
+ initial_sp = (void *) ((char *) (segment + 1) + segment->size);
+#else
+ initial_sp = (void *) (segment + 1);
+#endif
+ context[STACK_GUARD] = __morestack_make_guard (initial_sp, segment->size);
+ context[INITIAL_SP] = NULL;
+ context[INITIAL_SP_LEN] = 0;
+ *size = segment->size;
+ return (void *) (segment + 1);
+}
+
+/* Like __splitstack_block_signals, but operating on CONTEXT, rather
+ than on the current state. */
+
+void
+__splitstack_block_signals_context (void *context[NUMBER_OFFSETS], int *new,
+ int *old)
+{
+ if (old != NULL)
+ *old = ((uintptr_type) context[BLOCK_SIGNALS]) != 0 ? 0 : 1;
+ if (new != NULL)
+ context[BLOCK_SIGNALS] = (void *) (uintptr_type) (*new ? 0 : 1);
+}
+
+/* Find the stack segments associated with a split stack context.
+ This will return the address of the first stack segment and set
+ *STACK_SIZE to its size. It will set next_segment, next_sp, and
+ initial_sp which may be passed to __splitstack_find to find the
+ remaining segments. */
+
+void *
+__splitstack_find_context (void *context[NUMBER_OFFSETS], size_t *stack_size,
+ void **next_segment, void **next_sp,
+ void **initial_sp)
+{
+ void *sp;
+ struct stack_segment *segment;
+
+ *initial_sp = context[INITIAL_SP];
+
+ sp = context[CURRENT_STACK];
+ if (sp == NULL)
+ {
+ /* Most likely this context was created but was never used. The
+ value 2 is a code used by __splitstack_find to mean that we
+ have reached the end of the list of stacks. */
+ *next_segment = (void *) (uintptr_type) 2;
+ *next_sp = NULL;
+ *initial_sp = NULL;
+ return NULL;
+ }
+
+ segment = context[CURRENT_SEGMENT];
+ if (segment == NULL)
+ {
+ /* Most likely this context was saved by a thread which was not
+ created using __splistack_makecontext and which has never
+ split the stack. The value 1 is a code used by
+ __splitstack_find to look at the initial stack. */
+ segment = (struct stack_segment *) (uintptr_type) 1;
+ }
+
+ return __splitstack_find (segment, sp, stack_size, next_segment, next_sp,
+ initial_sp);
+}
+
#endif /* !defined (inhibit_libc) */
diff --git a/libgcc/libgcc-std.ver.in b/libgcc/libgcc-std.ver.in
index 2946468fcf5..2d66612d1c5 100644
--- a/libgcc/libgcc-std.ver.in
+++ b/libgcc/libgcc-std.ver.in
@@ -1,5 +1,5 @@
# Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
-# 2008, 2010 Free Software Foundation, Inc.
+# 2008, 2010, 2011 Free Software Foundation, Inc.
#
# This file is part of GCC.
#
@@ -1926,4 +1926,10 @@ GCC_4.7.0 {
__PFX__clrsbsi2
__PFX__clrsbdi2
__PFX__clrsbti2
+ __splitstack_block_signals
+ __splitstack_getcontext
+ __splitstack_setcontext
+ __splitstack_makecontext
+ __splitstack_block_signals_context
+ __splitstack_find_context
}
diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog
index 6d1f1cd868d..6c253b0d0cc 100644
--- a/libgfortran/ChangeLog
+++ b/libgfortran/ChangeLog
@@ -1,3 +1,72 @@
+2011-11-11 Janne Blomqvist <jb@gcc.gnu.org>
+
+ PR libfortran/51090
+ * runtime/main.c (find_addr2line): NULL check before proceeding.
+
+2011-11-10 Janne Blomqvist <jb@gcc.gnu.org>
+
+ * intrinsics/cpu_time.c (__cpu_time_1): Don't force inlining.
+ * intrinsics/random.c (rnumber_4): Remove inline attribute.
+ (rnumber_8, rnumber_10, rnumber_16): Likewise.
+ * intrinsics/system_clock.c (gf_gettime_mono): Likewise.
+ * intrinsics/time_1.h (ATTRIBUTE_ALWAYS_INLINE): Remove macro.
+ (gf_cputime): Add inline attribute for MingW version.
+ * io/format.c (format_hash): Remove inline attribute.
+ * io/io.h (memset4): Inline function from transfer.c and write.c
+ moved here.
+ * io/transfer.c (min_off): Remove inline attribute.
+ (memset4): Move to io.h.
+ * io/write.c (memset4): Likewise.
+ (memcpy4): Remove inline attribute.
+ * io/write_float.def (calculate_exp): Likewise.
+
+2011-11-09 Janne Blomqvist <jb@gcc.gnu.org>
+
+ * intrinsics/time_1.h (gf_gettime): Simplify time() usage.
+
+2011-11-09 Janne Blomqvist <jb@gcc.gnu.org>
+
+ * configure.ac (AC_STDC_HEADERS): Remove.
+ (AC_HEADER_TIME): Remove.
+ (AC_HAVE_HEADERS, AC_CHECK_HEADERS): Move into a single invocation
+ of AC_CHECK_HEADERS_ONCE, don't check for presence of C89 headers.
+ (AC_CHECK_MEMBERS): Use single invocation.
+ (AC_CHECK_FUNCS): Move into single invocation of
+ AC_CHEC_FUNCS_ONCE, don't check for presence of C89 functions.
+ * config.h.in: Regenerate.
+ * configure: Regenerate.
+ * intrinsics/clock.c: Include time.h.
+ (mclock): Assume clock() is present.
+ (mclock8): Likewise.
+ * intrinsics/ctime.c (strctime): Assume strftime is present.
+ (fdate): Assume time() is present.
+ (fdate_sub): Likewise.
+ (ctime): Likewise.
+ * intrinsics/date_and_time.c: Don't provide abs macro.
+ (HAVE_NO_DATE_TIME): Remove code related to macro which is never
+ set.
+ * intrinsics/execute_command_line.c: Assume stdlib.h is present.
+ * intrinsics/exit.c: Likewise.
+ * intrinsics/extends_type_of.c: Likewise.
+ * intrinsics/gerror.c: Assume strerror() is present.
+ * intrinsics/kill.c: Assume signal.h is present.
+ * intrinsics/malloc.c: Assume stdlib.h is present.
+ * intrinsics/move_alloc.c: Likewise.
+ * intrinsics/perror.c: Assume perror() is present.
+ * intrinsics/signal.c: Assume signal.h is present.
+ * intrinsics/stat.c: Assume stdlib.h is present.
+ * intrinsics/system.c: Likewise.
+ * intrinsics/time.c: Include time.h, assume time() is present.
+ * intrinsics/time_1.h: Conditionally include sys/time.h,
+ unconditionally time.h.
+ (gf_cputime): Do division in double, fallback using clock().
+ (gf_gettime): Assume time() is present.
+ * intrinsics/umask.c: Assume stdlib.h is present.
+ * runtime/backtrace.c: Likewise.
+ * runtime/compile_options.c: Assume signal.h is present, assume
+ C89 signals are present.
+ * runtime/error.c: Assume signal.h and stdlib.h are present.
+
2011-11-09 Janne Blomqvist <jb@gcc.gnu.org>
PR fortran/46686
diff --git a/libgfortran/config.h.in b/libgfortran/config.h.in
index 9333f64f8f0..81a4a7fb455 100644
--- a/libgfortran/config.h.in
+++ b/libgfortran/config.h.in
@@ -198,9 +198,6 @@
/* Define to 1 if you have the `chsize' function. */
#undef HAVE_CHSIZE
-/* Define to 1 if you have the `clock' function. */
-#undef HAVE_CLOCK
-
/* Define to 1 if you have the `clock_gettime' function. */
#undef HAVE_CLOCK_GETTIME
@@ -228,7 +225,7 @@
/* Define to 1 if you have the `close' function. */
#undef HAVE_CLOSE
-/* complex.h exists */
+/* Define to 1 if you have the <complex.h> header file. */
#undef HAVE_COMPLEX_H
/* libm includes copysign */
@@ -381,9 +378,6 @@
/* Define to 1 if you have the <floatingpoint.h> header file. */
#undef HAVE_FLOATINGPOINT_H
-/* Define to 1 if you have the <float.h> header file. */
-#undef HAVE_FLOAT_H
-
/* libm includes floor */
#undef HAVE_FLOOR
@@ -435,10 +429,10 @@
/* Define to 1 if you have the `getcwd' function. */
#undef HAVE_GETCWD
-/* libc includes geteuid */
+/* Define to 1 if you have the `geteuid' function. */
#undef HAVE_GETEUID
-/* libc includes getgid */
+/* Define to 1 if you have the `getgid' function. */
#undef HAVE_GETGID
/* Define to 1 if you have the `gethostname' function. */
@@ -450,10 +444,10 @@
/* Define to 1 if you have the `getlogin' function. */
#undef HAVE_GETLOGIN
-/* libc includes getpid */
+/* Define to 1 if you have the `getpid' function. */
#undef HAVE_GETPID
-/* libc includes getppid */
+/* Define to 1 if you have the `getppid' function. */
#undef HAVE_GETPPID
/* Define to 1 if you have the `getpwuid' function. */
@@ -471,7 +465,7 @@
/* Define to 1 if you have the `gettimeofday' function. */
#undef HAVE_GETTIMEOFDAY
-/* libc includes getuid */
+/* Define to 1 if you have the `getuid' function. */
#undef HAVE_GETUID
/* Define to 1 if you have the `gmtime_r' function. */
@@ -606,9 +600,6 @@
/* libm includes nextafterl */
#undef HAVE_NEXTAFTERL
-/* Define to 1 if you have the `perror' function. */
-#undef HAVE_PERROR
-
/* Define to 1 if you have the `pipe' function. */
#undef HAVE_PIPE
@@ -654,12 +645,6 @@
/* Define to 1 if you have the `setmode' function. */
#undef HAVE_SETMODE
-/* Define to 1 if you have the `signal' function. */
-#undef HAVE_SIGNAL
-
-/* Define to 1 if you have the <signal.h> header file. */
-#undef HAVE_SIGNAL_H
-
/* libm includes sin */
#undef HAVE_SIN
@@ -696,30 +681,18 @@
/* Define to 1 if you have the `stat' function. */
#undef HAVE_STAT
-/* Define to 1 if you have the <stdarg.h> header file. */
-#undef HAVE_STDARG_H
-
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
-/* Define to 1 if you have the <stdio.h> header file. */
-#undef HAVE_STDIO_H
-
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the `strcasestr' function. */
#undef HAVE_STRCASESTR
-/* Define to 1 if you have the `strerror' function. */
-#undef HAVE_STRERROR
-
/* Define to 1 if you have the `strerror_r' function. */
#undef HAVE_STRERROR_R
-/* Define to 1 if you have the `strftime' function. */
-#undef HAVE_STRFTIME
-
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
@@ -792,15 +765,9 @@
/* libm includes tgammal */
#undef HAVE_TGAMMAL
-/* Define to 1 if you have the `time' function. */
-#undef HAVE_TIME
-
/* Define to 1 if you have the `times' function. */
#undef HAVE_TIMES
-/* Define to 1 if you have the <time.h> header file. */
-#undef HAVE_TIME_H
-
/* libm includes trunc */
#undef HAVE_TRUNC
@@ -907,9 +874,6 @@
/* Define to 1 if the target supports #pragma weak */
#undef SUPPORTS_WEAK
-/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
-#undef TIME_WITH_SYS_TIME
-
/* Enable extensions on AIX 3, Interix. */
#ifndef _ALL_SOURCE
# undef _ALL_SOURCE
diff --git a/libgfortran/configure b/libgfortran/configure
index a8ac99afa25..c39b003e9e4 100755
--- a/libgfortran/configure
+++ b/libgfortran/configure
@@ -597,6 +597,8 @@ ac_includes_default="\
# include <unistd.h>
#endif"
+ac_header_list=
+ac_func_list=
ac_c_werror_flag=
ac_subst_vars='am__EXEEXT_FALSE
am__EXEEXT_TRUE
@@ -2528,6 +2530,68 @@ $as_echo "$as_me: creating cache $cache_file" >&6;}
>$cache_file
fi
+as_fn_append ac_header_list " unistd.h"
+as_fn_append ac_header_list " sys/time.h"
+as_fn_append ac_header_list " sys/times.h"
+as_fn_append ac_header_list " sys/resource.h"
+as_fn_append ac_header_list " sys/types.h"
+as_fn_append ac_header_list " sys/stat.h"
+as_fn_append ac_header_list " sys/wait.h"
+as_fn_append ac_header_list " floatingpoint.h"
+as_fn_append ac_header_list " ieeefp.h"
+as_fn_append ac_header_list " fenv.h"
+as_fn_append ac_header_list " fptrap.h"
+as_fn_append ac_header_list " pwd.h"
+as_fn_append ac_header_list " complex.h"
+as_fn_append ac_func_list " getrusage"
+as_fn_append ac_func_list " times"
+as_fn_append ac_func_list " mkstemp"
+as_fn_append ac_func_list " strtof"
+as_fn_append ac_func_list " strtold"
+as_fn_append ac_func_list " snprintf"
+as_fn_append ac_func_list " ftruncate"
+as_fn_append ac_func_list " chsize"
+as_fn_append ac_func_list " chdir"
+as_fn_append ac_func_list " getlogin"
+as_fn_append ac_func_list " gethostname"
+as_fn_append ac_func_list " kill"
+as_fn_append ac_func_list " link"
+as_fn_append ac_func_list " symlink"
+as_fn_append ac_func_list " sleep"
+as_fn_append ac_func_list " ttyname"
+as_fn_append ac_func_list " alarm"
+as_fn_append ac_func_list " access"
+as_fn_append ac_func_list " fork"
+as_fn_append ac_func_list " execl"
+as_fn_append ac_func_list " wait"
+as_fn_append ac_func_list " setmode"
+as_fn_append ac_func_list " execve"
+as_fn_append ac_func_list " pipe"
+as_fn_append ac_func_list " dup2"
+as_fn_append ac_func_list " close"
+as_fn_append ac_func_list " fdopen"
+as_fn_append ac_func_list " strcasestr"
+as_fn_append ac_func_list " getrlimit"
+as_fn_append ac_func_list " gettimeofday"
+as_fn_append ac_func_list " stat"
+as_fn_append ac_func_list " fstat"
+as_fn_append ac_func_list " lstat"
+as_fn_append ac_func_list " getpwuid"
+as_fn_append ac_func_list " vsnprintf"
+as_fn_append ac_func_list " dup"
+as_fn_append ac_func_list " getcwd"
+as_fn_append ac_func_list " localtime_r"
+as_fn_append ac_func_list " gmtime_r"
+as_fn_append ac_func_list " strerror_r"
+as_fn_append ac_func_list " getpwuid_r"
+as_fn_append ac_func_list " ttyname_r"
+as_fn_append ac_func_list " clock_gettime"
+as_fn_append ac_func_list " readlink"
+as_fn_append ac_func_list " getgid"
+as_fn_append ac_func_list " getpid"
+as_fn_append ac_func_list " getppid"
+as_fn_append ac_func_list " getuid"
+as_fn_append ac_func_list " geteuid"
# Check that the precious variables saved in the cache have kept the same
# value.
ac_cache_corrupted=false
@@ -12254,7 +12318,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 12257 "configure"
+#line 12321 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -12360,7 +12424,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 12363 "configure"
+#line 12427 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -15871,216 +15935,51 @@ _ACEOF
fi
-# check header files
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
-$as_echo_n "checking for ANSI C header files... " >&6; }
-if test "${ac_cv_header_stdc+set}" = set; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <float.h>
+# check header files (we assume C89 is available, so don't check for that)
-int
-main ()
-{
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_cv_header_stdc=yes
-else
- ac_cv_header_stdc=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-if test $ac_cv_header_stdc = yes; then
- # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <string.h>
+ for ac_header in $ac_header_list
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
+"
+eval as_val=\$$as_ac_Header
+ if test "x$as_val" = x""yes; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "memchr" >/dev/null 2>&1; then :
-else
- ac_cv_header_stdc=no
fi
-rm -f conftest*
-fi
+done
-if test $ac_cv_header_stdc = yes; then
- # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <stdlib.h>
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "free" >/dev/null 2>&1; then :
-else
- ac_cv_header_stdc=no
-fi
-rm -f conftest*
-fi
-if test $ac_cv_header_stdc = yes; then
- # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
- if test "$cross_compiling" = yes; then :
- :
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <ctype.h>
-#include <stdlib.h>
-#if ((' ' & 0x0FF) == 0x020)
-# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
-# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
-#else
-# define ISLOWER(c) \
- (('a' <= (c) && (c) <= 'i') \
- || ('j' <= (c) && (c) <= 'r') \
- || ('s' <= (c) && (c) <= 'z'))
-# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
-#endif
-#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
-int
-main ()
-{
- int i;
- for (i = 0; i < 256; i++)
- if (XOR (islower (i), ISLOWER (i))
- || toupper (i) != TOUPPER (i))
- return 2;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
-else
- ac_cv_header_stdc=no
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
- conftest.$ac_objext conftest.beam conftest.$ac_ext
-fi
-fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
-$as_echo "$ac_cv_header_stdc" >&6; }
-if test $ac_cv_header_stdc = yes; then
-$as_echo "#define STDC_HEADERS 1" >>confdefs.h
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether time.h and sys/time.h may both be included" >&5
-$as_echo_n "checking whether time.h and sys/time.h may both be included... " >&6; }
-if test "${ac_cv_header_time+set}" = set; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <sys/types.h>
-#include <sys/time.h>
-#include <time.h>
-int
-main ()
-{
-if ((struct tm *) 0)
-return 0;
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_cv_header_time=yes
-else
- ac_cv_header_time=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_time" >&5
-$as_echo "$ac_cv_header_time" >&6; }
-if test $ac_cv_header_time = yes; then
-$as_echo "#define TIME_WITH_SYS_TIME 1" >>confdefs.h
-fi
-for ac_header in stdio.h stdlib.h string.h unistd.h signal.h stdarg.h
-do :
- as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
-ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
-eval as_val=\$$as_ac_Header
- if test "x$as_val" = x""yes; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
-fi
-done
-for ac_header in time.h sys/time.h sys/times.h sys/resource.h
-do :
- as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
-ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
-eval as_val=\$$as_ac_Header
- if test "x$as_val" = x""yes; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
-fi
-done
-for ac_header in sys/types.h sys/stat.h sys/wait.h floatingpoint.h ieeefp.h
-do :
- as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
-ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
-eval as_val=\$$as_ac_Header
- if test "x$as_val" = x""yes; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
-fi
-done
-for ac_header in fenv.h fptrap.h float.h pwd.h
-do :
- as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
-ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
-eval as_val=\$$as_ac_Header
- if test "x$as_val" = x""yes; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
-fi
-done
-ac_fn_c_check_header_mongrel "$LINENO" "complex.h" "ac_cv_header_complex_h" "$ac_includes_default"
-if test "x$ac_cv_header_complex_h" = x""yes; then :
-
-$as_echo "#define HAVE_COMPLEX_H 1" >>confdefs.h
-
-fi
@@ -16499,7 +16398,6 @@ _ACEOF
fi
-
ac_fn_c_check_member "$LINENO" "struct stat" "st_blocks" "ac_cv_member_struct_stat_st_blocks" "$ac_includes_default"
if test "x$ac_cv_member_struct_stat_st_blocks" = x""yes; then :
@@ -16509,7 +16407,6 @@ _ACEOF
fi
-
ac_fn_c_check_member "$LINENO" "struct stat" "st_rdev" "ac_cv_member_struct_stat_st_rdev" "$ac_includes_default"
if test "x$ac_cv_member_struct_stat_st_rdev" = x""yes; then :
@@ -16522,20 +16419,10 @@ fi
# Check for library functions.
-for ac_func in getrusage times mkstemp strtof strtold snprintf ftruncate chsize
-do :
- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-eval as_val=\$$as_ac_var
- if test "x$as_val" = x""yes; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-fi
-done
-for ac_func in chdir strerror getlogin gethostname kill link symlink perror
+
+ for ac_func in $ac_func_list
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
@@ -16548,297 +16435,104 @@ _ACEOF
fi
done
-for ac_func in sleep time ttyname signal alarm clock access fork execl
-do :
- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-eval as_val=\$$as_ac_var
- if test "x$as_val" = x""yes; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-fi
-done
-for ac_func in wait setmode execve pipe dup2 close fdopen strcasestr getrlimit
-do :
- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-eval as_val=\$$as_ac_var
- if test "x$as_val" = x""yes; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-fi
-done
-for ac_func in gettimeofday stat fstat lstat getpwuid vsnprintf dup getcwd
-do :
- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-eval as_val=\$$as_ac_var
- if test "x$as_val" = x""yes; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-fi
-done
-for ac_func in localtime_r gmtime_r strerror_r getpwuid_r ttyname_r
-do :
- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-eval as_val=\$$as_ac_var
- if test "x$as_val" = x""yes; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-fi
-done
-for ac_func in clock_gettime strftime readlink
-do :
- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-eval as_val=\$$as_ac_var
- if test "x$as_val" = x""yes; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-fi
-done
-# Check libc for getgid, getpid, getuid
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for getgid in -lc" >&5
-$as_echo_n "checking for getgid in -lc... " >&6; }
-if test "${ac_cv_lib_c_getgid+set}" = set; then :
- $as_echo_n "(cached) " >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lc $LIBS"
-if test x$gcc_no_link = xyes; then
- as_fn_error "Link tests are not allowed after GCC_NO_EXECUTABLES." "$LINENO" 5
-fi
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char getgid ();
-int
-main ()
-{
-return getgid ();
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_lib_c_getgid=yes
-else
- ac_cv_lib_c_getgid=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_getgid" >&5
-$as_echo "$ac_cv_lib_c_getgid" >&6; }
-if test "x$ac_cv_lib_c_getgid" = x""yes; then :
-$as_echo "#define HAVE_GETGID 1" >>confdefs.h
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for getpid in -lc" >&5
-$as_echo_n "checking for getpid in -lc... " >&6; }
-if test "${ac_cv_lib_c_getpid+set}" = set; then :
- $as_echo_n "(cached) " >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lc $LIBS"
-if test x$gcc_no_link = xyes; then
- as_fn_error "Link tests are not allowed after GCC_NO_EXECUTABLES." "$LINENO" 5
-fi
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char getpid ();
-int
-main ()
-{
-return getpid ();
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_lib_c_getpid=yes
-else
- ac_cv_lib_c_getpid=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_getpid" >&5
-$as_echo "$ac_cv_lib_c_getpid" >&6; }
-if test "x$ac_cv_lib_c_getpid" = x""yes; then :
-$as_echo "#define HAVE_GETPID 1" >>confdefs.h
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for getppid in -lc" >&5
-$as_echo_n "checking for getppid in -lc... " >&6; }
-if test "${ac_cv_lib_c_getppid+set}" = set; then :
- $as_echo_n "(cached) " >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lc $LIBS"
-if test x$gcc_no_link = xyes; then
- as_fn_error "Link tests are not allowed after GCC_NO_EXECUTABLES." "$LINENO" 5
-fi
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char getppid ();
-int
-main ()
-{
-return getppid ();
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_lib_c_getppid=yes
-else
- ac_cv_lib_c_getppid=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_getppid" >&5
-$as_echo "$ac_cv_lib_c_getppid" >&6; }
-if test "x$ac_cv_lib_c_getppid" = x""yes; then :
-$as_echo "#define HAVE_GETPPID 1" >>confdefs.h
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for getuid in -lc" >&5
-$as_echo_n "checking for getuid in -lc... " >&6; }
-if test "${ac_cv_lib_c_getuid+set}" = set; then :
- $as_echo_n "(cached) " >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lc $LIBS"
-if test x$gcc_no_link = xyes; then
- as_fn_error "Link tests are not allowed after GCC_NO_EXECUTABLES." "$LINENO" 5
-fi
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char getuid ();
-int
-main ()
-{
-return getuid ();
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_lib_c_getuid=yes
-else
- ac_cv_lib_c_getuid=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_getuid" >&5
-$as_echo "$ac_cv_lib_c_getuid" >&6; }
-if test "x$ac_cv_lib_c_getuid" = x""yes; then :
-$as_echo "#define HAVE_GETUID 1" >>confdefs.h
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for geteuid in -lc" >&5
-$as_echo_n "checking for geteuid in -lc... " >&6; }
-if test "${ac_cv_lib_c_geteuid+set}" = set; then :
- $as_echo_n "(cached) " >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lc $LIBS"
-if test x$gcc_no_link = xyes; then
- as_fn_error "Link tests are not allowed after GCC_NO_EXECUTABLES." "$LINENO" 5
-fi
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char geteuid ();
-int
-main ()
-{
-return geteuid ();
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_lib_c_geteuid=yes
-else
- ac_cv_lib_c_geteuid=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_geteuid" >&5
-$as_echo "$ac_cv_lib_c_geteuid" >&6; }
-if test "x$ac_cv_lib_c_geteuid" = x""yes; then :
-$as_echo "#define HAVE_GETEUID 1" >>confdefs.h
-fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# Check for C99 (and other IEEE) math functions
diff --git a/libgfortran/configure.ac b/libgfortran/configure.ac
index a8b944df064..74fe0c2ed3f 100644
--- a/libgfortran/configure.ac
+++ b/libgfortran/configure.ac
@@ -251,35 +251,22 @@ AC_TYPE_INTPTR_T
AC_TYPE_UINTPTR_T
AC_CHECK_TYPES([ptrdiff_t])
-# check header files
-AC_STDC_HEADERS
-AC_HEADER_TIME
-AC_HAVE_HEADERS(stdio.h stdlib.h string.h unistd.h signal.h stdarg.h)
-AC_CHECK_HEADERS(time.h sys/time.h sys/times.h sys/resource.h)
-AC_CHECK_HEADERS(sys/types.h sys/stat.h sys/wait.h floatingpoint.h ieeefp.h)
-AC_CHECK_HEADERS(fenv.h fptrap.h float.h pwd.h)
-AC_CHECK_HEADER([complex.h],[AC_DEFINE([HAVE_COMPLEX_H], [1], [complex.h exists])])
+# check header files (we assume C89 is available, so don't check for that)
+AC_CHECK_HEADERS_ONCE(unistd.h sys/time.h sys/times.h sys/resource.h \
+sys/types.h sys/stat.h sys/wait.h floatingpoint.h ieeefp.h fenv.h fptrap.h \
+pwd.h complex.h)
+
GCC_HEADER_STDINT(gstdint.h)
-AC_CHECK_MEMBERS([struct stat.st_blksize])
-AC_CHECK_MEMBERS([struct stat.st_blocks])
-AC_CHECK_MEMBERS([struct stat.st_rdev])
+AC_CHECK_MEMBERS([struct stat.st_blksize, struct stat.st_blocks, struct stat.st_rdev])
# Check for library functions.
-AC_CHECK_FUNCS(getrusage times mkstemp strtof strtold snprintf ftruncate chsize)
-AC_CHECK_FUNCS(chdir strerror getlogin gethostname kill link symlink perror)
-AC_CHECK_FUNCS(sleep time ttyname signal alarm clock access fork execl)
-AC_CHECK_FUNCS(wait setmode execve pipe dup2 close fdopen strcasestr getrlimit)
-AC_CHECK_FUNCS(gettimeofday stat fstat lstat getpwuid vsnprintf dup getcwd)
-AC_CHECK_FUNCS(localtime_r gmtime_r strerror_r getpwuid_r ttyname_r)
-AC_CHECK_FUNCS(clock_gettime strftime readlink)
-
-# Check libc for getgid, getpid, getuid
-AC_CHECK_LIB([c],[getgid],[AC_DEFINE([HAVE_GETGID],[1],[libc includes getgid])])
-AC_CHECK_LIB([c],[getpid],[AC_DEFINE([HAVE_GETPID],[1],[libc includes getpid])])
-AC_CHECK_LIB([c],[getppid],[AC_DEFINE([HAVE_GETPPID],[1],[libc includes getppid])])
-AC_CHECK_LIB([c],[getuid],[AC_DEFINE([HAVE_GETUID],[1],[libc includes getuid])])
-AC_CHECK_LIB([c],[geteuid],[AC_DEFINE([HAVE_GETEUID],[1],[libc includes geteuid])])
+AC_CHECK_FUNCS_ONCE(getrusage times mkstemp strtof strtold snprintf \
+ftruncate chsize chdir getlogin gethostname kill link symlink sleep ttyname \
+alarm access fork execl wait setmode execve pipe dup2 close fdopen \
+strcasestr getrlimit gettimeofday stat fstat lstat getpwuid vsnprintf dup \
+getcwd localtime_r gmtime_r strerror_r getpwuid_r ttyname_r clock_gettime \
+readlink getgid getpid getppid getuid geteuid)
# Check for C99 (and other IEEE) math functions
AC_CHECK_LIB([m],[acosf],[AC_DEFINE([HAVE_ACOSF],[1],[libm includes acosf])])
diff --git a/libgfortran/intrinsics/clock.c b/libgfortran/intrinsics/clock.c
index b1d61d8866b..29ccc15cdd6 100644
--- a/libgfortran/intrinsics/clock.c
+++ b/libgfortran/intrinsics/clock.c
@@ -1,8 +1,8 @@
/* Implementation of the MCLOCK and MCLOCK8 g77 intrinsics.
- Copyright (C) 2006, 2007, 2009 Free Software Foundation, Inc.
+ Copyright (C) 2006, 2007, 2009, 2011 Free Software Foundation, Inc.
Contributed by François-Xavier Coudert <coudert@clipper.ens.fr>
-This file is part of the GNU Fortran 95 runtime library (libgfortran).
+This file is part of the GNU Fortran runtime library (libgfortran).
Libgfortran is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public
@@ -24,19 +24,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
#include "libgfortran.h"
-
-#ifdef TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# ifdef HAVE_TIME_H
-# include <time.h>
-# endif
-# endif
-#endif
+#include <time.h>
/* INTEGER(KIND=4) FUNCTION MCLOCK() */
@@ -47,11 +35,7 @@ export_proto(mclock);
GFC_INTEGER_4
mclock (void)
{
-#ifdef HAVE_CLOCK
return (GFC_INTEGER_4) clock ();
-#else
- return (GFC_INTEGER_4) -1;
-#endif
}
@@ -63,10 +47,6 @@ export_proto(mclock8);
GFC_INTEGER_8
mclock8 (void)
{
-#ifdef HAVE_CLOCK
return (GFC_INTEGER_8) clock ();
-#else
- return (GFC_INTEGER_8) -1;
-#endif
}
diff --git a/libgfortran/intrinsics/cpu_time.c b/libgfortran/intrinsics/cpu_time.c
index 619f8d25246..94636c41b0b 100644
--- a/libgfortran/intrinsics/cpu_time.c
+++ b/libgfortran/intrinsics/cpu_time.c
@@ -26,9 +26,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include "time_1.h"
-static inline void __cpu_time_1 (long *, long *) ATTRIBUTE_ALWAYS_INLINE;
-
-static inline void
+static void
__cpu_time_1 (long *sec, long *usec)
{
long user_sec, user_usec, system_sec, system_usec;
diff --git a/libgfortran/intrinsics/ctime.c b/libgfortran/intrinsics/ctime.c
index 1c924a11da4..05bf31fc779 100644
--- a/libgfortran/intrinsics/ctime.c
+++ b/libgfortran/intrinsics/ctime.c
@@ -39,7 +39,6 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
static size_t
strctime (char *s, size_t max, const time_t *timep)
{
-#ifdef HAVE_STRFTIME
struct tm ltm;
int failed;
/* Some targets provide a localtime_r based on a draft of the POSIX
@@ -52,9 +51,6 @@ strctime (char *s, size_t max, const time_t *timep)
if (failed)
return 0;
return strftime (s, max, "%c", &ltm);
-#else
- return 0;
-#endif
}
/* In the default locale, the date and time representation fits in 26
@@ -67,15 +63,9 @@ export_proto(fdate);
void
fdate (char ** date, gfc_charlen_type * date_len)
{
-#if defined(HAVE_TIME)
time_t now = time(NULL);
*date = get_mem (CSZ);
*date_len = strctime (*date, CSZ, &now);
-#else
-
- *date = NULL;
- *date_len = 0;
-#endif
}
@@ -85,15 +75,11 @@ export_proto(fdate_sub);
void
fdate_sub (char * date, gfc_charlen_type date_len)
{
-#if defined(HAVE_TIME)
time_t now = time(NULL);
char *s = get_mem (date_len + 1);
size_t n = strctime (s, date_len + 1, &now);
fstrcpy (date, date_len, s, n);
free (s);
-#else
- memset (date, ' ', date_len);
-#endif
}
@@ -104,15 +90,9 @@ export_proto_np(PREFIX(ctime));
void
PREFIX(ctime) (char ** date, gfc_charlen_type * date_len, GFC_INTEGER_8 t)
{
-#if defined(HAVE_TIME)
time_t now = t;
*date = get_mem (CSZ);
*date_len = strctime (*date, CSZ, &now);
-#else
-
- *date = NULL;
- *date_len = 0;
-#endif
}
diff --git a/libgfortran/intrinsics/date_and_time.c b/libgfortran/intrinsics/date_and_time.c
index fa51d5f5ba2..3c386363df4 100644
--- a/libgfortran/intrinsics/date_and_time.c
+++ b/libgfortran/intrinsics/date_and_time.c
@@ -31,10 +31,6 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include "time_1.h"
-#ifndef abs
-#define abs(x) ((x)>=0 ? (x) : -(x))
-#endif
-
/* If the re-entrant version of gmtime is not available, provide a
fallback implementation. On some targets where the _r version is
@@ -143,7 +139,6 @@ date_and_time (char *__date, char *__time, char *__zone,
char zone[ZONE_LEN + 1];
GFC_INTEGER_4 values[VALUES_SIZE];
-#ifndef HAVE_NO_DATE_TIME
time_t lt;
struct tm local_time;
struct tm UTC_time;
@@ -193,21 +188,6 @@ date_and_time (char *__date, char *__time, char *__zone,
for (i = 0; i < VALUES_SIZE; i++)
values[i] = - GFC_INTEGER_4_HUGE;
}
-#else /* if defined HAVE_NO_DATE_TIME */
- /* We really have *nothing* to return, so return blanks and HUGE(0). */
-
- memset (date, ' ', DATE_LEN);
- date[DATE_LEN] = '\0';
-
- memset (timec, ' ', TIME_LEN);
- timec[TIME_LEN] = '\0';
-
- memset (zone, ' ', ZONE_LEN);
- zone[ZONE_LEN] = '\0';
-
- for (i = 0; i < VALUES_SIZE; i++)
- values[i] = - GFC_INTEGER_4_HUGE;
-#endif /* HAVE_NO_DATE_TIME */
/* Copy the values into the arguments. */
if (__values)
@@ -321,7 +301,6 @@ secnds (GFC_REAL_4 *x)
static void
itime0 (int x[3])
{
-#ifndef HAVE_NO_DATE_TIME
time_t lt;
struct tm local_time;
@@ -335,9 +314,6 @@ itime0 (int x[3])
x[1] = local_time.tm_min;
x[2] = local_time.tm_sec;
}
-#else
- x[0] = x[1] = x[2] = -1;
-#endif
}
extern void itime_i4 (gfc_array_i4 *);
@@ -403,7 +379,6 @@ itime_i8 (gfc_array_i8 *__values)
static void
idate0 (int x[3])
{
-#ifndef HAVE_NO_DATE_TIME
time_t lt;
struct tm local_time;
@@ -417,9 +392,6 @@ idate0 (int x[3])
x[1] = 1 + local_time.tm_mon;
x[2] = 1900 + local_time.tm_year;
}
-#else
- x[0] = x[1] = x[2] = -1;
-#endif
}
extern void idate_i4 (gfc_array_i4 *);
diff --git a/libgfortran/intrinsics/execute_command_line.c b/libgfortran/intrinsics/execute_command_line.c
index d0b79a45a52..25eb4a3e6b8 100644
--- a/libgfortran/intrinsics/execute_command_line.c
+++ b/libgfortran/intrinsics/execute_command_line.c
@@ -1,5 +1,5 @@
/* Implementation of the EXECUTE_COMMAND_LINE intrinsic.
- Copyright (C) 2009 Free Software Foundation, Inc.
+ Copyright (C) 2009, 2011 Free Software Foundation, Inc.
Contributed by François-Xavier Coudert.
This file is part of the GNU Fortran runtime library (libgfortran).
@@ -26,10 +26,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include "libgfortran.h"
#include <string.h>
#include <stdbool.h>
-
-#ifdef HAVE_STDLIB_H
#include <stdlib.h>
-#endif
+
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
diff --git a/libgfortran/intrinsics/exit.c b/libgfortran/intrinsics/exit.c
index 7787581d021..c7da4979970 100644
--- a/libgfortran/intrinsics/exit.c
+++ b/libgfortran/intrinsics/exit.c
@@ -1,8 +1,8 @@
/* Implementation of the EXIT intrinsic.
- Copyright (C) 2004, 2007, 2009 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2007, 2009, 2011 Free Software Foundation, Inc.
Contributed by Steven G. Kargl <kargls@comcast.net>.
-This file is part of the GNU Fortran 95 runtime library (libgfortran).
+This file is part of the GNU Fortran runtime library (libgfortran).
Libgfortran is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public
@@ -25,10 +25,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include "libgfortran.h"
-
-#ifdef HAVE_STDLIB_H
#include <stdlib.h>
-#endif
+
/* SUBROUTINE EXIT(STATUS)
INTEGER, INTENT(IN), OPTIONAL :: STATUS */
diff --git a/libgfortran/intrinsics/extends_type_of.c b/libgfortran/intrinsics/extends_type_of.c
index 2fd149c18a5..223423428d5 100644
--- a/libgfortran/intrinsics/extends_type_of.c
+++ b/libgfortran/intrinsics/extends_type_of.c
@@ -1,8 +1,8 @@
/* Implementation of the EXTENDS_TYPE_OF intrinsic.
- Copyright (C) 2004, 2007, 2009 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2007, 2009, 2011 Free Software Foundation, Inc.
Contributed by Janus Weil <janus@gcc.gnu.org>.
-This file is part of the GNU Fortran 95 runtime library (libgfortran).
+This file is part of the GNU Fortran runtime library (libgfortran).
Libgfortran is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public
@@ -25,10 +25,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include "libgfortran.h"
-
-#ifdef HAVE_STDLIB_H
#include <stdlib.h>
-#endif
typedef struct vtype
diff --git a/libgfortran/intrinsics/gerror.c b/libgfortran/intrinsics/gerror.c
index 6feadc9b7c7..492f7af118f 100644
--- a/libgfortran/intrinsics/gerror.c
+++ b/libgfortran/intrinsics/gerror.c
@@ -1,8 +1,8 @@
/* Implementation of the GERROR g77 intrinsic.
- Copyright (C) 2005, 2007, 2009 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2007, 2009, 2011 Free Software Foundation, Inc.
Contributed by François-Xavier Coudert <coudert@clipper.ens.fr>
-This file is part of the GNU Fortran 95 runtime library (libgfortran).
+This file is part of the GNU Fortran runtime library (libgfortran).
Libgfortran is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public
@@ -33,7 +33,6 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
message corresponding to the last system error (C errno).
CHARACTER(len=*), INTENT(OUT) :: MESSAGE */
-#ifdef HAVE_STRERROR
void PREFIX(gerror) (char *, gfc_charlen_type);
export_proto_np(PREFIX(gerror));
@@ -56,4 +55,3 @@ PREFIX(gerror) (char * msg, gfc_charlen_type msg_len)
if (msg_len > p_len)
memset (&msg[p_len], ' ', msg_len - p_len);
}
-#endif
diff --git a/libgfortran/intrinsics/kill.c b/libgfortran/intrinsics/kill.c
index 83e8b2838ec..be36b00aa1c 100644
--- a/libgfortran/intrinsics/kill.c
+++ b/libgfortran/intrinsics/kill.c
@@ -1,8 +1,8 @@
/* Implementation of the KILL g77 intrinsic.
- Copyright (C) 2005, 2007, 2009 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2007, 2009, 2011 Free Software Foundation, Inc.
Contributed by François-Xavier Coudert <coudert@clipper.ens.fr>
-This file is part of the GNU Fortran 95 runtime library (libgfortran).
+This file is part of the GNU Fortran runtime library (libgfortran).
Libgfortran is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public
@@ -25,10 +25,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include "libgfortran.h"
#include <errno.h>
-
-#ifdef HAVE_SIGNAL_H
#include <signal.h>
-#endif
+
/* SUBROUTINE KILL(PID, SIGNAL, STATUS)
INTEGER, INTENT(IN) :: PID, SIGNAL
diff --git a/libgfortran/intrinsics/malloc.c b/libgfortran/intrinsics/malloc.c
index 19001aef89c..5edc1be8e09 100644
--- a/libgfortran/intrinsics/malloc.c
+++ b/libgfortran/intrinsics/malloc.c
@@ -1,8 +1,8 @@
/* Implementation of the MALLOC and FREE intrinsics
- Copyright (C) 2005, 2007, 2009 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2007, 2009, 2011 Free Software Foundation, Inc.
Contributed by François-Xavier Coudert <coudert@clipper.ens.fr>
-This file is part of the GNU Fortran 95 runtime library (libgfortran).
+This file is part of the GNU Fortran runtime library (libgfortran).
Libgfortran is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public
@@ -24,10 +24,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
#include "libgfortran.h"
-
-#ifdef HAVE_STDLIB_H
#include <stdlib.h>
-#endif
+
extern void PREFIX(free) (void **);
export_proto_np(PREFIX(free));
diff --git a/libgfortran/intrinsics/move_alloc.c b/libgfortran/intrinsics/move_alloc.c
index f76c20c7b6d..7b489ade4c7 100644
--- a/libgfortran/intrinsics/move_alloc.c
+++ b/libgfortran/intrinsics/move_alloc.c
@@ -1,8 +1,8 @@
/* Generic implementation of the MOVE_ALLOC intrinsic
- Copyright (C) 2006, 2007, 2009 Free Software Foundation, Inc.
+ Copyright (C) 2006, 2007, 2009, 2011 Free Software Foundation, Inc.
Contributed by Paul Thomas
-This file is part of the GNU Fortran 95 runtime library (libgfortran).
+This file is part of the GNU Fortran runtime library (libgfortran).
Libgfortran is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public
@@ -24,10 +24,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
#include "libgfortran.h"
-
-#ifdef HAVE_STDLIB_H
#include <stdlib.h>
-#endif
+
extern void move_alloc (gfc_array_char *, gfc_array_char *);
export_proto(move_alloc);
diff --git a/libgfortran/intrinsics/perror.c b/libgfortran/intrinsics/perror.c
index 10348bd0828..bb203c4f7ec 100644
--- a/libgfortran/intrinsics/perror.c
+++ b/libgfortran/intrinsics/perror.c
@@ -1,8 +1,8 @@
/* Implementation of the PERROR intrinsic.
- Copyright (C) 2005, 2007, 2009 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2007, 2009, 2011 Free Software Foundation, Inc.
Contributed by François-Xavier Coudert <coudert@clipper.ens.fr>
-This file is part of the GNU Fortran 95 runtime library (libgfortran).
+This file is part of the GNU Fortran runtime library (libgfortran).
Libgfortran is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public
@@ -31,7 +31,6 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
/* SUBROUTINE PERROR(STRING)
CHARACTER(len=*), INTENT(IN) :: STRING */
-#ifdef HAVE_PERROR
extern void perror_sub (char *, gfc_charlen_type);
iexport_proto(perror_sub);
@@ -52,4 +51,3 @@ perror_sub (char *string, gfc_charlen_type string_len)
perror (str);
}
iexport(perror_sub);
-#endif
diff --git a/libgfortran/intrinsics/random.c b/libgfortran/intrinsics/random.c
index 8c16b855d1c..35576b85bda 100644
--- a/libgfortran/intrinsics/random.c
+++ b/libgfortran/intrinsics/random.c
@@ -74,7 +74,7 @@ static __gthread_mutex_t random_lock;
correct offset. */
-static inline void
+static void
rnumber_4 (GFC_REAL_4 *f, GFC_UINTEGER_4 v)
{
GFC_UINTEGER_4 mask;
@@ -89,7 +89,7 @@ rnumber_4 (GFC_REAL_4 *f, GFC_UINTEGER_4 v)
*f = (GFC_REAL_4) v * GFC_REAL_4_LITERAL(0x1.p-32);
}
-static inline void
+static void
rnumber_8 (GFC_REAL_8 *f, GFC_UINTEGER_8 v)
{
GFC_UINTEGER_8 mask;
@@ -106,7 +106,7 @@ rnumber_8 (GFC_REAL_8 *f, GFC_UINTEGER_8 v)
#ifdef HAVE_GFC_REAL_10
-static inline void
+static void
rnumber_10 (GFC_REAL_10 *f, GFC_UINTEGER_8 v)
{
GFC_UINTEGER_8 mask;
@@ -126,7 +126,7 @@ rnumber_10 (GFC_REAL_10 *f, GFC_UINTEGER_8 v)
/* For REAL(KIND=16), we only need to mask off the lower bits. */
-static inline void
+static void
rnumber_16 (GFC_REAL_16 *f, GFC_UINTEGER_8 v1, GFC_UINTEGER_8 v2)
{
GFC_UINTEGER_8 mask;
diff --git a/libgfortran/intrinsics/signal.c b/libgfortran/intrinsics/signal.c
index 66e54f33af0..85179ee30fa 100644
--- a/libgfortran/intrinsics/signal.c
+++ b/libgfortran/intrinsics/signal.c
@@ -1,8 +1,8 @@
/* Implementation of the SIGNAL and ALARM g77 intrinsics
- Copyright (C) 2005, 2007, 2009 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2007, 2009, 2011 Free Software Foundation, Inc.
Contributed by François-Xavier Coudert <coudert@clipper.ens.fr>
-This file is part of the GNU Fortran 95 runtime library (libgfortran).
+This file is part of the GNU Fortran runtime library (libgfortran).
Libgfortran is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public
@@ -29,9 +29,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include <unistd.h>
#endif
-#ifdef HAVE_SIGNAL_H
#include <signal.h>
-#endif
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
@@ -46,7 +44,6 @@ iexport_proto(signal_sub);
void
signal_sub (int *number, void (*handler)(int), int *status)
{
-#ifdef HAVE_SIGNAL
intptr_t ret;
if (status != NULL)
@@ -56,11 +53,6 @@ signal_sub (int *number, void (*handler)(int), int *status)
}
else
signal (*number, handler);
-#else
- errno = ENOSYS;
- if (status != NULL)
- *status = -1;
-#endif
}
iexport(signal_sub);
@@ -72,7 +64,6 @@ iexport_proto(signal_sub_int);
void
signal_sub_int (int *number, int *handler, int *status)
{
-#ifdef HAVE_SIGNAL
intptr_t ptr = *handler, ret;
if (status != NULL)
@@ -82,11 +73,6 @@ signal_sub_int (int *number, int *handler, int *status)
}
else
signal (*number, (void (*)(int)) ptr);
-#else
- errno = ENOSYS;
- if (status != NULL)
- *status = -1;
-#endif
}
iexport(signal_sub_int);
@@ -129,7 +115,7 @@ alarm_sub_i4 (int * seconds __attribute__ ((unused)),
void (*handler)(int) __attribute__ ((unused)),
GFC_INTEGER_4 *status)
{
-#if defined (SIGALRM) && defined (HAVE_ALARM) && defined (HAVE_SIGNAL)
+#if defined (SIGALRM) && defined (HAVE_ALARM)
if (status != NULL)
{
if (signal (SIGALRM, handler) == SIG_ERR)
@@ -159,7 +145,7 @@ alarm_sub_i8 (int *seconds __attribute__ ((unused)),
void (*handler)(int) __attribute__ ((unused)),
GFC_INTEGER_8 *status)
{
-#if defined (SIGALRM) && defined (HAVE_ALARM) && defined (HAVE_SIGNAL)
+#if defined (SIGALRM) && defined (HAVE_ALARM)
if (status != NULL)
{
if (signal (SIGALRM, handler) == SIG_ERR)
@@ -190,7 +176,7 @@ alarm_sub_int_i4 (int *seconds __attribute__ ((unused)),
int *handler __attribute__ ((unused)),
GFC_INTEGER_4 *status)
{
-#if defined (SIGALRM) && defined (HAVE_ALARM) && defined (HAVE_SIGNAL)
+#if defined (SIGALRM) && defined (HAVE_ALARM)
if (status != NULL)
{
if (signal (SIGALRM, (void (*)(int)) (intptr_t) *handler) == SIG_ERR)
@@ -220,7 +206,7 @@ alarm_sub_int_i8 (int *seconds __attribute__ ((unused)),
int *handler __attribute__ ((unused)),
GFC_INTEGER_8 *status)
{
-#if defined (SIGALRM) && defined (HAVE_ALARM) && defined (HAVE_SIGNAL)
+#if defined (SIGALRM) && defined (HAVE_ALARM)
if (status != NULL)
{
if (signal (SIGALRM, (void (*)(int)) (intptr_t) *handler) == SIG_ERR)
diff --git a/libgfortran/intrinsics/stat.c b/libgfortran/intrinsics/stat.c
index 22d4f79796c..28821f1546d 100644
--- a/libgfortran/intrinsics/stat.c
+++ b/libgfortran/intrinsics/stat.c
@@ -1,8 +1,9 @@
/* Implementation of the STAT and FSTAT intrinsics.
- Copyright (C) 2004, 2005, 2006, 2007, 2009 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2005, 2006, 2007, 2009, 2011
+ Free Software Foundation, Inc.
Contributed by Steven G. Kargl <kargls@comcast.net>.
-This file is part of the GNU Fortran 95 runtime library (libgfortran).
+This file is part of the GNU Fortran runtime library (libgfortran).
Libgfortran is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public
@@ -32,9 +33,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include <sys/stat.h>
#endif
-#ifdef HAVE_STDLIB_H
#include <stdlib.h>
-#endif
#ifdef HAVE_STAT
diff --git a/libgfortran/intrinsics/system.c b/libgfortran/intrinsics/system.c
index 831823ffc4c..5bc083a1ad0 100644
--- a/libgfortran/intrinsics/system.c
+++ b/libgfortran/intrinsics/system.c
@@ -1,8 +1,8 @@
/* Implementation of the SYSTEM intrinsic.
- Copyright (C) 2004, 2007, 2009 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2007, 2009, 2011 Free Software Foundation, Inc.
Contributed by Tobias Schlüter.
-This file is part of the GNU Fortran 95 runtime library (libgfortran).
+This file is part of the GNU Fortran runtime library (libgfortran).
Libgfortran 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
@@ -25,10 +25,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include "libgfortran.h"
#include <string.h>
-
-#ifdef HAVE_STDLIB_H
#include <stdlib.h>
-#endif
extern void system_sub (const char *fcmd, GFC_INTEGER_4 * status,
gfc_charlen_type cmd_len);
diff --git a/libgfortran/intrinsics/system_clock.c b/libgfortran/intrinsics/system_clock.c
index f4bac0777b3..6385c4f0c95 100644
--- a/libgfortran/intrinsics/system_clock.c
+++ b/libgfortran/intrinsics/system_clock.c
@@ -75,7 +75,7 @@ static int weak_gettime (clockid_t, struct timespec *)
Return value: 0 for success, -1 for error. In case of error, errno
is set.
*/
-static inline int
+static int
gf_gettime_mono (time_t * secs, long * nanosecs)
{
int err;
diff --git a/libgfortran/intrinsics/time.c b/libgfortran/intrinsics/time.c
index d046e87ecba..151466a9da0 100644
--- a/libgfortran/intrinsics/time.c
+++ b/libgfortran/intrinsics/time.c
@@ -1,8 +1,8 @@
/* Implementation of the TIME and TIME8 g77 intrinsics.
- Copyright (C) 2005, 2007, 2009 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2007, 2009, 2011 Free Software Foundation, Inc.
Contributed by François-Xavier Coudert <coudert@clipper.ens.fr>
-This file is part of the GNU Fortran 95 runtime library (libgfortran).
+This file is part of the GNU Fortran runtime library (libgfortran).
Libgfortran is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public
@@ -24,24 +24,11 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
#include "libgfortran.h"
-
-#ifdef TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# ifdef HAVE_TIME_H
-# include <time.h>
-# endif
-# endif
-#endif
+#include <time.h>
/* INTEGER(KIND=4) FUNCTION TIME() */
-#ifdef HAVE_TIME
extern GFC_INTEGER_4 time_func (void);
export_proto(time_func);
@@ -61,4 +48,3 @@ time8_func (void)
{
return (GFC_INTEGER_8) time (NULL);
}
-#endif
diff --git a/libgfortran/intrinsics/time_1.h b/libgfortran/intrinsics/time_1.h
index 12d79ebc12f..aaca56ac54a 100644
--- a/libgfortran/intrinsics/time_1.h
+++ b/libgfortran/intrinsics/time_1.h
@@ -40,19 +40,12 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
As usual with UNIX systems, unfortunately no single way is
available for all systems. */
-#ifdef TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# ifdef HAVE_TIME_H
-# include <time.h>
-# endif
-# endif
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
#endif
+#include <time.h>
+
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
@@ -104,14 +97,6 @@ localtime_r (const time_t * timep, struct tm * result)
#endif
-#if defined (__GNUC__) && (__GNUC__ >= 3)
-# define ATTRIBUTE_ALWAYS_INLINE __attribute__ ((__always_inline__))
-#else
-# define ATTRIBUTE_ALWAYS_INLINE
-#endif
-
-static inline int gf_cputime (long *, long *, long *, long *) ATTRIBUTE_ALWAYS_INLINE;
-
/* Helper function for the actual implementation of the DTIME, ETIME and
CPU_TIME intrinsics. Returns 0 for success or -1 if no
CPU time could be computed. */
@@ -121,7 +106,7 @@ static inline int gf_cputime (long *, long *, long *, long *) ATTRIBUTE_ALWAYS_I
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
-static int
+static inline int
gf_cputime (long *user_sec, long *user_usec, long *system_sec, long *system_usec)
{
union {
@@ -174,20 +159,21 @@ gf_cputime (long *user_sec, long *user_usec, long *system_sec, long *system_usec
clock_t err;
err = times (&buf);
*user_sec = buf.tms_utime / HZ;
- *user_usec = buf.tms_utime % HZ * (1000000 / HZ);
+ *user_usec = buf.tms_utime % HZ * (1000000. / HZ);
*system_sec = buf.tms_stime / HZ;
- *system_usec = buf.tms_stime % HZ * (1000000 / HZ);
+ *system_usec = buf.tms_stime % HZ * (1000000. / HZ);
if ((err == (clock_t) -1) && errno != 0)
return -1;
return 0;
#else
-
- /* We have nothing to go on. Return -1. */
- *user_sec = *system_sec = 0;
- *user_usec = *system_usec = 0;
- errno = ENOSYS;
- return -1;
+ clock_t c = clock ();
+ *user_sec = c / CLOCKS_PER_SEC;
+ *user_usec = c % CLOCKS_PER_SEC * (1000000. / CLOCKS_PER_SEC);
+ *system_sec = *system_usec = 0;
+ if (c == (clock_t) -1)
+ return -1;
+ return 0;
#endif
}
@@ -218,19 +204,13 @@ gf_gettime (time_t * secs, long * usecs)
*secs = tv.tv_sec;
*usecs = tv.tv_usec;
return err;
-#elif HAVE_TIME
- time_t t, t2;
- t = time (&t2);
- *secs = t2;
+#else
+ time_t t = time (NULL);
+ *secs = t;
*usecs = 0;
if (t == ((time_t)-1))
return -1;
return 0;
-#else
- *secs = 0;
- *usecs = 0;
- errno = ENOSYS;
- return -1;
#endif
}
diff --git a/libgfortran/intrinsics/umask.c b/libgfortran/intrinsics/umask.c
index 9df684bfc8e..d939e5de318 100644
--- a/libgfortran/intrinsics/umask.c
+++ b/libgfortran/intrinsics/umask.c
@@ -1,8 +1,8 @@
/* Implementation of the UMASK intrinsic.
- Copyright (C) 2004, 2007, 2009 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2007, 2009, 2011 Free Software Foundation, Inc.
Contributed by Steven G. Kargl <kargls@comcast.net>.
-This file is part of the GNU Fortran 95 runtime library (libgfortran).
+This file is part of the GNU Fortran runtime library (libgfortran).
Libgfortran is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public
@@ -25,10 +25,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include "libgfortran.h"
-
-#ifdef HAVE_STDLIB_H
#include <stdlib.h>
-#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
diff --git a/libgfortran/io/format.c b/libgfortran/io/format.c
index 518dc809ecb..1711a75dd0a 100644
--- a/libgfortran/io/format.c
+++ b/libgfortran/io/format.c
@@ -116,8 +116,8 @@ reset_fnode_counters (st_parameter_dt *dtp)
/* A simple hashing function to generate an index into the hash table. */
-static inline
-uint32_t format_hash (st_parameter_dt *dtp)
+static uint32_t
+format_hash (st_parameter_dt *dtp)
{
char *key;
gfc_charlen_type key_len;
diff --git a/libgfortran/io/intrinsics.c b/libgfortran/io/intrinsics.c
index c1287d4bd23..22150e70ce9 100644
--- a/libgfortran/io/intrinsics.c
+++ b/libgfortran/io/intrinsics.c
@@ -27,13 +27,10 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include "io.h"
#include "fbuf.h"
#include "unix.h"
-
-#ifdef HAVE_STDLIB_H
#include <stdlib.h>
-#endif
-
#include <string.h>
+
static const int five = 5;
static const int six = 6;
diff --git a/libgfortran/io/io.h b/libgfortran/io/io.h
index 5270fd7c0b4..06364e17b2c 100644
--- a/libgfortran/io/io.h
+++ b/libgfortran/io/io.h
@@ -801,5 +801,14 @@ dec_waiting_unlocked (gfc_unit *u)
#endif
}
+
+static inline void
+memset4 (gfc_char4_t *p, gfc_char4_t c, int k)
+{
+ int j;
+ for (j = 0; j < k; j++)
+ *p++ = c;
+}
+
#endif
diff --git a/libgfortran/io/transfer.c b/libgfortran/io/transfer.c
index 062f80efec4..976102f3a8e 100644
--- a/libgfortran/io/transfer.c
+++ b/libgfortran/io/transfer.c
@@ -2877,7 +2877,7 @@ next_record_r_unf (st_parameter_dt *dtp, int complete_record)
}
-static inline gfc_offset
+static gfc_offset
min_off (gfc_offset a, gfc_offset b)
{
return (a < b ? a : b);
@@ -3136,13 +3136,6 @@ sset (stream * s, int c, ssize_t nbyte)
return nbyte - bytes_left;
}
-static inline void
-memset4 (gfc_char4_t *p, gfc_char4_t c, int k)
-{
- int j;
- for (j = 0; j < k; j++)
- *p++ = c;
-}
/* Position to the next record in write mode. */
diff --git a/libgfortran/io/write.c b/libgfortran/io/write.c
index 95eec84edcb..8be3a5a72bf 100644
--- a/libgfortran/io/write.c
+++ b/libgfortran/io/write.c
@@ -41,15 +41,7 @@ typedef unsigned char uchar;
/* Helper functions for character(kind=4) internal units. These are needed
by write_float.def. */
-static inline void
-memset4 (gfc_char4_t *p, gfc_char4_t c, int k)
-{
- int j;
- for (j = 0; j < k; j++)
- *p++ = c;
-}
-
-static inline void
+static void
memcpy4 (gfc_char4_t *dest, const char *source, int k)
{
int j;
diff --git a/libgfortran/io/write_float.def b/libgfortran/io/write_float.def
index 7ab70d28200..78f09b29820 100644
--- a/libgfortran/io/write_float.def
+++ b/libgfortran/io/write_float.def
@@ -774,7 +774,7 @@ write_infnan (st_parameter_dt *dtp, const fnode *f, int isnan_flag, int sign_bit
/* Returns the value of 10**d. */
#define CALCULATE_EXP(x) \
-inline static GFC_REAL_ ## x \
+static GFC_REAL_ ## x \
calculate_exp_ ## x (int d)\
{\
int i;\
diff --git a/libgfortran/runtime/backtrace.c b/libgfortran/runtime/backtrace.c
index 606dd34e9d4..e28bdcbc423 100644
--- a/libgfortran/runtime/backtrace.c
+++ b/libgfortran/runtime/backtrace.c
@@ -25,6 +25,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include "libgfortran.h"
#include <string.h>
+#include <stdlib.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
diff --git a/libgfortran/runtime/compile_options.c b/libgfortran/runtime/compile_options.c
index c3e64de33ba..0c139a2d4ef 100644
--- a/libgfortran/runtime/compile_options.c
+++ b/libgfortran/runtime/compile_options.c
@@ -1,5 +1,5 @@
/* Handling of compile-time options that influence the library.
- Copyright (C) 2005, 2007, 2009, 2010 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2007, 2009, 2010, 2011 Free Software Foundation, Inc.
This file is part of the GNU Fortran runtime library (libgfortran).
@@ -23,10 +23,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
#include "libgfortran.h"
-
-#ifdef HAVE_SIGNAL_H
#include <signal.h>
-#endif
/* Useful compile-time options will be stored in here. */
@@ -94,32 +91,17 @@ set_options (int num, int options[])
/* If backtrace is required, we set signal handlers on the POSIX
2001 signals with core action. */
-#if defined(HAVE_SIGNAL) && (defined(SIGQUIT) || defined(SIGILL) \
- || defined(SIGABRT) || defined(SIGFPE) \
- || defined(SIGSEGV) || defined(SIGBUS) \
- || defined(SIGSYS) || defined(SIGTRAP) \
- || defined(SIGXCPU) || defined(SIGXFSZ))
if (compile_options.backtrace)
{
#if defined(SIGQUIT)
signal (SIGQUIT, backtrace_handler);
#endif
-#if defined(SIGILL)
+ /* The following 4 signals are defined by C89. */
signal (SIGILL, backtrace_handler);
-#endif
-
-#if defined(SIGABRT)
signal (SIGABRT, backtrace_handler);
-#endif
-
-#if defined(SIGFPE)
signal (SIGFPE, backtrace_handler);
-#endif
-
-#if defined(SIGSEGV)
signal (SIGSEGV, backtrace_handler);
-#endif
#if defined(SIGBUS)
signal (SIGBUS, backtrace_handler);
@@ -143,8 +125,6 @@ set_options (int num, int options[])
maybe_find_addr2line ();
}
-#endif
-
}
diff --git a/libgfortran/runtime/error.c b/libgfortran/runtime/error.c
index cb064297c96..7e523bc9a57 100644
--- a/libgfortran/runtime/error.c
+++ b/libgfortran/runtime/error.c
@@ -28,18 +28,13 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include <assert.h>
#include <string.h>
#include <errno.h>
-
-#ifdef HAVE_SIGNAL_H
#include <signal.h>
-#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
-#ifdef HAVE_STDLIB_H
#include <stdlib.h>
-#endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
@@ -172,9 +167,7 @@ sys_abort (void)
|| (options.backtrace == -1 && compile_options.backtrace == 1))
{
show_backtrace ();
-#if defined(HAVE_SIGNAL) && defined(SIGABRT)
signal (SIGABRT, SIG_DFL);
-#endif
}
abort();
diff --git a/libgfortran/runtime/main.c b/libgfortran/runtime/main.c
index bc8dab449e8..11b535afa92 100644
--- a/libgfortran/runtime/main.c
+++ b/libgfortran/runtime/main.c
@@ -149,6 +149,8 @@ find_addr2line (void)
#ifdef HAVE_ACCESS
#define A2L_LEN 10
char *path = getenv ("PATH");
+ if (!path)
+ return;
size_t n = strlen (path);
char ap[n + 1 + A2L_LEN];
size_t ai = 0;
diff --git a/libgo/Makefile.am b/libgo/Makefile.am
index eb414906605..00e97d2dc8d 100644
--- a/libgo/Makefile.am
+++ b/libgo/Makefile.am
@@ -434,7 +434,6 @@ runtime_files = \
runtime/go-new.c \
runtime/go-note.c \
runtime/go-panic.c \
- runtime/go-panic-defer.c \
runtime/go-print.c \
runtime/go-rand.c \
runtime/go-rec-big.c \
diff --git a/libgo/Makefile.in b/libgo/Makefile.in
index 4c07233d43d..68b972e16d4 100644
--- a/libgo/Makefile.in
+++ b/libgo/Makefile.in
@@ -198,14 +198,14 @@ am__libgo_la_SOURCES_DIST = runtime/go-append.c runtime/go-assert.c \
runtime/go-map-index.c runtime/go-map-len.c \
runtime/go-map-range.c runtime/go-nanotime.c \
runtime/go-new-channel.c runtime/go-new-map.c runtime/go-new.c \
- runtime/go-note.c runtime/go-panic.c runtime/go-panic-defer.c \
- runtime/go-print.c runtime/go-rand.c runtime/go-rec-big.c \
- runtime/go-rec-nb-big.c runtime/go-rec-nb-small.c \
- runtime/go-rec-small.c runtime/go-recover.c \
- runtime/go-reflect.c runtime/go-reflect-call.c \
- runtime/go-reflect-chan.c runtime/go-reflect-map.c \
- runtime/go-rune.c runtime/go-runtime-error.c \
- runtime/go-sched.c runtime/go-select.c runtime/go-semacquire.c \
+ runtime/go-note.c runtime/go-panic.c runtime/go-print.c \
+ runtime/go-rand.c runtime/go-rec-big.c runtime/go-rec-nb-big.c \
+ runtime/go-rec-nb-small.c runtime/go-rec-small.c \
+ runtime/go-recover.c runtime/go-reflect.c \
+ runtime/go-reflect-call.c runtime/go-reflect-chan.c \
+ runtime/go-reflect-map.c runtime/go-rune.c \
+ runtime/go-runtime-error.c runtime/go-sched.c \
+ runtime/go-select.c runtime/go-semacquire.c \
runtime/go-send-big.c runtime/go-send-nb-big.c \
runtime/go-send-nb-small.c runtime/go-send-small.c \
runtime/go-setenv.c runtime/go-signal.c runtime/go-strcmp.c \
@@ -239,10 +239,9 @@ am__objects_3 = go-append.lo go-assert.lo go-assert-interface.lo \
go-interface-val-compare.lo go-lock-os-thread.lo \
go-make-slice.lo go-map-delete.lo go-map-index.lo \
go-map-len.lo go-map-range.lo go-nanotime.lo go-new-channel.lo \
- go-new-map.lo go-new.lo go-note.lo go-panic.lo \
- go-panic-defer.lo go-print.lo go-rand.lo go-rec-big.lo \
- go-rec-nb-big.lo go-rec-nb-small.lo go-rec-small.lo \
- go-recover.lo go-reflect.lo go-reflect-call.lo \
+ go-new-map.lo go-new.lo go-note.lo go-panic.lo go-print.lo \
+ go-rand.lo go-rec-big.lo go-rec-nb-big.lo go-rec-nb-small.lo \
+ go-rec-small.lo go-recover.lo go-reflect.lo go-reflect-call.lo \
go-reflect-chan.lo go-reflect-map.lo go-rune.lo \
go-runtime-error.lo go-sched.lo go-select.lo go-semacquire.lo \
go-send-big.lo go-send-nb-big.lo go-send-nb-small.lo \
@@ -865,7 +864,6 @@ runtime_files = \
runtime/go-new.c \
runtime/go-note.c \
runtime/go-panic.c \
- runtime/go-panic-defer.c \
runtime/go-print.c \
runtime/go-rand.c \
runtime/go-rec-big.c \
@@ -2492,7 +2490,6 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-new-map.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-new.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-note.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-panic-defer.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-panic.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-print.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-rand.Plo@am__quote@
@@ -2863,13 +2860,6 @@ go-panic.lo: runtime/go-panic.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-panic.lo `test -f 'runtime/go-panic.c' || echo '$(srcdir)/'`runtime/go-panic.c
-go-panic-defer.lo: runtime/go-panic-defer.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-panic-defer.lo -MD -MP -MF $(DEPDIR)/go-panic-defer.Tpo -c -o go-panic-defer.lo `test -f 'runtime/go-panic-defer.c' || echo '$(srcdir)/'`runtime/go-panic-defer.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-panic-defer.Tpo $(DEPDIR)/go-panic-defer.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-panic-defer.c' object='go-panic-defer.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-panic-defer.lo `test -f 'runtime/go-panic-defer.c' || echo '$(srcdir)/'`runtime/go-panic-defer.c
-
go-print.lo: runtime/go-print.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-print.lo -MD -MP -MF $(DEPDIR)/go-print.Tpo -c -o go-print.lo `test -f 'runtime/go-print.c' || echo '$(srcdir)/'`runtime/go-print.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-print.Tpo $(DEPDIR)/go-print.Plo
diff --git a/libgo/runtime/go-defer.c b/libgo/runtime/go-defer.c
index 1f116eb38c9..dda62fb4e1a 100644
--- a/libgo/runtime/go-defer.c
+++ b/libgo/runtime/go-defer.c
@@ -6,6 +6,7 @@
#include <stddef.h>
+#include "runtime.h"
#include "go-alloc.h"
#include "go-panic.h"
#include "go-defer.h"
@@ -17,18 +18,14 @@ __go_defer (_Bool *frame, void (*pfn) (void *), void *arg)
{
struct __go_defer_stack *n;
- if (__go_panic_defer == NULL)
- __go_panic_defer = ((struct __go_panic_defer_struct *)
- __go_alloc (sizeof (struct __go_panic_defer_struct)));
-
n = (struct __go_defer_stack *) __go_alloc (sizeof (struct __go_defer_stack));
- n->__next = __go_panic_defer->__defer;
+ n->__next = g->defer;
n->__frame = frame;
- n->__panic = __go_panic_defer->__panic;
+ n->__panic = g->panic;
n->__pfn = pfn;
n->__arg = arg;
n->__retaddr = NULL;
- __go_panic_defer->__defer = n;
+ g->defer = n;
}
/* This function is called when we want to undefer the stack. */
@@ -36,22 +33,19 @@ __go_defer (_Bool *frame, void (*pfn) (void *), void *arg)
void
__go_undefer (_Bool *frame)
{
- if (__go_panic_defer == NULL)
- return;
- while (__go_panic_defer->__defer != NULL
- && __go_panic_defer->__defer->__frame == frame)
+ while (g->defer != NULL && g->defer->__frame == frame)
{
struct __go_defer_stack *d;
void (*pfn) (void *);
- d = __go_panic_defer->__defer;
+ d = g->defer;
pfn = d->__pfn;
d->__pfn = NULL;
if (pfn != NULL)
(*pfn) (d->__arg);
- __go_panic_defer->__defer = d->__next;
+ g->defer = d->__next;
__go_free (d);
/* Since we are executing a defer function here, we know we are
@@ -69,7 +63,7 @@ __go_undefer (_Bool *frame)
_Bool
__go_set_defer_retaddr (void *retaddr)
{
- if (__go_panic_defer != NULL && __go_panic_defer->__defer != NULL)
- __go_panic_defer->__defer->__retaddr = retaddr;
+ if (g->defer != NULL)
+ g->defer->__retaddr = retaddr;
return 0;
}
diff --git a/libgo/runtime/go-deferred-recover.c b/libgo/runtime/go-deferred-recover.c
index 2d9ca1442fc..d749c2788ab 100644
--- a/libgo/runtime/go-deferred-recover.c
+++ b/libgo/runtime/go-deferred-recover.c
@@ -6,6 +6,7 @@
#include <stddef.h>
+#include "runtime.h"
#include "go-panic.h"
#include "go-defer.h"
@@ -78,9 +79,7 @@
struct __go_empty_interface
__go_deferred_recover ()
{
- if (__go_panic_defer == NULL
- || __go_panic_defer->__defer == NULL
- || __go_panic_defer->__defer->__panic != __go_panic_defer->__panic)
+ if (g->defer == NULL || g->defer->__panic != g->panic)
{
struct __go_empty_interface ret;
diff --git a/libgo/runtime/go-go.c b/libgo/runtime/go-go.c
index d56b8b16397..82b265f964e 100644
--- a/libgo/runtime/go-go.c
+++ b/libgo/runtime/go-go.c
@@ -115,6 +115,7 @@ remove_current_thread (void *dummy __attribute__ ((unused)))
any code from here to thread exit must not assume that m is
valid. */
m = NULL;
+ g = NULL;
i = pthread_mutex_unlock (&__go_thread_ids_lock);
__go_assert (i == 0);
@@ -135,10 +136,11 @@ start_go_thread (void *thread_arg)
#ifdef __rtems__
__wrap_rtems_task_variable_add ((void **) &m);
- __wrap_rtems_task_variable_add ((void **) &__go_panic_defer);
+ __wrap_rtems_task_variable_add ((void **) &g);
#endif
m = newm;
+ g = m->curg;
pthread_cleanup_push (remove_current_thread, NULL);
@@ -230,6 +232,9 @@ __go_go (void (*pfn) (void*), void *arg)
newm->list_entry = list_entry;
+ newm->curg = __go_alloc (sizeof (G));
+ newm->curg->m = newm;
+
newm->id = __sync_fetch_and_add (&mcount, 1);
newm->fastrand = 0x49f6428aUL + newm->id;
@@ -299,9 +304,6 @@ stop_for_gc (void)
}
#endif
- /* FIXME: Perhaps we should just move __go_panic_defer into M. */
- m->gc_panic_defer = __go_panic_defer;
-
/* Tell the garbage collector that we are ready by posting to the
semaphore. */
i = sem_post (&__go_thread_ready_sem);
@@ -433,10 +435,6 @@ runtime_stoptheworld (void)
--c;
}
- /* The gc_panic_defer field should now be set for all M's except the
- one in this thread. Set this one now. */
- m->gc_panic_defer = __go_panic_defer;
-
/* Leave with __go_thread_ids_lock held. */
}
diff --git a/libgo/runtime/go-main.c b/libgo/runtime/go-main.c
index 927a36ce028..15a6a30a93d 100644
--- a/libgo/runtime/go-main.c
+++ b/libgo/runtime/go-main.c
@@ -48,6 +48,10 @@ main (int argc, char **argv)
int i;
struct __go_string *values;
+ m = &runtime_m0;
+ g = &runtime_g0;
+ m->curg = g;
+ g->m = m;
runtime_mallocinit ();
runtime_cpuprofinit ();
__go_gc_goroutine_init (&argc);
diff --git a/libgo/runtime/go-panic-defer.c b/libgo/runtime/go-panic-defer.c
deleted file mode 100644
index 64773bb5eb5..00000000000
--- a/libgo/runtime/go-panic-defer.c
+++ /dev/null
@@ -1,13 +0,0 @@
-/* go-panic-stack.c -- The panic/defer stack.
-
- Copyright 2010 The Go Authors. All rights reserved.
- Use of this source code is governed by a BSD-style
- license that can be found in the LICENSE file. */
-
-#include "go-panic.h"
-
-#ifdef __rtems__
-#define __thread
-#endif
-
-__thread struct __go_panic_defer_struct *__go_panic_defer;
diff --git a/libgo/runtime/go-panic.c b/libgo/runtime/go-panic.c
index f3e182d9bcc..8b95cd4e4d1 100644
--- a/libgo/runtime/go-panic.c
+++ b/libgo/runtime/go-panic.c
@@ -41,14 +41,10 @@ __go_panic (struct __go_empty_interface arg)
{
struct __go_panic_stack *n;
- if (__go_panic_defer == NULL)
- __go_panic_defer = ((struct __go_panic_defer_struct *)
- __go_alloc (sizeof (struct __go_panic_defer_struct)));
-
n = (struct __go_panic_stack *) __go_alloc (sizeof (struct __go_panic_stack));
n->__arg = arg;
- n->__next = __go_panic_defer->__panic;
- __go_panic_defer->__panic = n;
+ n->__next = g->panic;
+ g->panic = n;
/* Run all the defer functions. */
@@ -57,7 +53,7 @@ __go_panic (struct __go_empty_interface arg)
struct __go_defer_stack *d;
void (*pfn) (void *);
- d = __go_panic_defer->__defer;
+ d = g->defer;
if (d == NULL)
break;
@@ -73,7 +69,7 @@ __go_panic (struct __go_empty_interface arg)
/* Some defer function called recover. That means that
we should stop running this panic. */
- __go_panic_defer->__panic = n->__next;
+ g->panic = n->__next;
__go_free (n);
/* Now unwind the stack by throwing an exception. The
@@ -96,13 +92,13 @@ __go_panic (struct __go_empty_interface arg)
*d->__frame = 0;
}
- __go_panic_defer->__defer = d->__next;
+ g->defer = d->__next;
__go_free (d);
}
/* The panic was not recovered. */
- __printpanics (__go_panic_defer->__panic);
+ __printpanics (g->panic);
/* FIXME: We should dump a call stack here. */
abort ();
diff --git a/libgo/runtime/go-panic.h b/libgo/runtime/go-panic.h
index 2836c468159..bd3e238aef4 100644
--- a/libgo/runtime/go-panic.h
+++ b/libgo/runtime/go-panic.h
@@ -31,36 +31,6 @@ struct __go_panic_stack
_Bool __is_foreign;
};
-/* The panic and defer stacks, grouped together into a single thread
- local variable for convenience for systems without TLS. */
-
-struct __go_panic_defer_struct
-{
- /* The list of defers to execute. */
- struct __go_defer_stack *__defer;
-
- /* The list of currently active panics. There will be more than one
- if a deferred function calls panic. */
- struct __go_panic_stack *__panic;
-
- /* The current exception being thrown when unwinding after a call to
- panic . This is really struct _UnwindException *. */
- void *__exception;
-
- /* Whether the current exception is from some other language. */
- _Bool __is_foreign;
-};
-
-#ifdef __rtems__
-#define __thread
-#endif
-
-extern __thread struct __go_panic_defer_struct *__go_panic_defer;
-
-#ifdef __rtems__
-#undef __thread
-#endif
-
extern void __go_panic (struct __go_empty_interface)
__attribute__ ((noreturn));
diff --git a/libgo/runtime/go-recover.c b/libgo/runtime/go-recover.c
index 4de122e3b3e..fe6031c100f 100644
--- a/libgo/runtime/go-recover.c
+++ b/libgo/runtime/go-recover.c
@@ -4,6 +4,7 @@
Use of this source code is governed by a BSD-style
license that can be found in the LICENSE file. */
+#include "runtime.h"
#include "interface.h"
#include "go-panic.h"
#include "go-defer.h"
@@ -21,9 +22,7 @@ __go_can_recover (const void* retaddr)
const char* ret;
const char* dret;
- if (__go_panic_defer == NULL)
- return 0;
- d = __go_panic_defer->__defer;
+ d = g->defer;
if (d == NULL)
return 0;
@@ -31,7 +30,7 @@ __go_can_recover (const void* retaddr)
of the panic stack. We do not want to recover it if that panic
was on the top of the panic stack when this function was
deferred. */
- if (d->__panic == __go_panic_defer->__panic)
+ if (d->__panic == g->panic)
return 0;
/* D->__RETADDR is the address of a label immediately following the
@@ -53,9 +52,7 @@ __go_recover ()
{
struct __go_panic_stack *p;
- if (__go_panic_defer == NULL
- || __go_panic_defer->__panic == NULL
- || __go_panic_defer->__panic->__was_recovered)
+ if (g->panic == NULL || g->panic->__was_recovered)
{
struct __go_empty_interface ret;
@@ -63,7 +60,7 @@ __go_recover ()
ret.__object = NULL;
return ret;
}
- p = __go_panic_defer->__panic;
+ p = g->panic;
p->__was_recovered = 1;
return p->__arg;
}
diff --git a/libgo/runtime/go-unwind.c b/libgo/runtime/go-unwind.c
index e64cf903d9f..58c675a2dc8 100644
--- a/libgo/runtime/go-unwind.c
+++ b/libgo/runtime/go-unwind.c
@@ -13,6 +13,7 @@
#define NO_SIZE_OF_ENCODED_VALUE
#include "unwind-pe.h"
+#include "runtime.h"
#include "go-alloc.h"
#include "go-defer.h"
#include "go-panic.h"
@@ -48,12 +49,12 @@ __go_check_defer (_Bool *frame)
{
struct _Unwind_Exception *hdr;
- if (__go_panic_defer == NULL)
+ if (g == NULL)
{
/* Some other language has thrown an exception. We know there
are no defer handlers, so there is nothing to do. */
}
- else if (__go_panic_defer->__is_foreign)
+ else if (g->is_foreign)
{
struct __go_panic_stack *n;
_Bool was_recovered;
@@ -69,20 +70,20 @@ __go_check_defer (_Bool *frame)
n->__arg.__object = NULL;
n->__was_recovered = 0;
n->__is_foreign = 1;
- n->__next = __go_panic_defer->__panic;
- __go_panic_defer->__panic = n;
+ n->__next = g->panic;
+ g->panic = n;
while (1)
{
struct __go_defer_stack *d;
void (*pfn) (void *);
- d = __go_panic_defer->__defer;
+ d = g->defer;
if (d == NULL || d->__frame != frame || d->__pfn == NULL)
break;
pfn = d->__pfn;
- __go_panic_defer->__defer = d->__next;
+ g->defer = d->__next;
(*pfn) (d->__arg);
@@ -97,7 +98,7 @@ __go_check_defer (_Bool *frame)
}
was_recovered = n->__was_recovered;
- __go_panic_defer->__panic = n->__next;
+ g->panic = n->__next;
__go_free (n);
if (was_recovered)
@@ -110,17 +111,17 @@ __go_check_defer (_Bool *frame)
/* We are panicing through this function. */
*frame = 0;
}
- else if (__go_panic_defer->__defer != NULL
- && __go_panic_defer->__defer->__pfn == NULL
- && __go_panic_defer->__defer->__frame == frame)
+ else if (g->defer != NULL
+ && g->defer->__pfn == NULL
+ && g->defer->__frame == frame)
{
struct __go_defer_stack *d;
/* This is the defer function which called recover. Simply
return to stop the stack unwind, and let the Go code continue
to execute. */
- d = __go_panic_defer->__defer;
- __go_panic_defer->__defer = d->__next;
+ d = g->defer;
+ g->defer = d->__next;
__go_free (d);
/* We are returning from this function. */
@@ -132,7 +133,7 @@ __go_check_defer (_Bool *frame)
/* This is some other defer function. It was already run by the
call to panic, or just above. Rethrow the exception. */
- hdr = (struct _Unwind_Exception *) __go_panic_defer->__exception;
+ hdr = (struct _Unwind_Exception *) g->exception;
#ifdef LIBGO_SJLJ_EXCEPTIONS
_Unwind_SjLj_Resume_or_Rethrow (hdr);
@@ -163,7 +164,7 @@ __go_unwind_stack ()
sizeof hdr->exception_class);
hdr->exception_cleanup = NULL;
- __go_panic_defer->__exception = hdr;
+ g->exception = hdr;
#ifdef __USING_SJLJ_EXCEPTIONS__
_Unwind_SjLj_RaiseException (hdr);
@@ -413,17 +414,17 @@ PERSONALITY_FUNCTION (int version,
return _URC_HANDLER_FOUND;
}
- /* It's possible for __go_panic_defer to be NULL here for an
- exception thrown by a language other than Go. */
- if (__go_panic_defer == NULL)
+ /* It's possible for g to be NULL here for an exception thrown by a
+ language other than Go. */
+ if (g == NULL)
{
if (!is_foreign)
abort ();
}
else
{
- __go_panic_defer->__exception = ue_header;
- __go_panic_defer->__is_foreign = is_foreign;
+ g->exception = ue_header;
+ g->is_foreign = is_foreign;
}
_Unwind_SetGR (context, __builtin_eh_return_data_regno (0),
diff --git a/libgo/runtime/mgc0.c b/libgo/runtime/mgc0.c
index cb585251b53..6d402e55dd6 100644
--- a/libgo/runtime/mgc0.c
+++ b/libgo/runtime/mgc0.c
@@ -652,7 +652,8 @@ mark(void (*scan)(byte*, int64))
}
}
- scan((byte*)&m0, sizeof m0);
+ scan((byte*)&runtime_m0, sizeof runtime_m0);
+ scan((byte*)&runtime_g0, sizeof runtime_g0);
scan((byte*)&finq, sizeof finq);
runtime_MProf_Mark(scan);
diff --git a/libgo/runtime/proc.c b/libgo/runtime/proc.c
index 8af6935b37b..e9b7c9083ca 100644
--- a/libgo/runtime/proc.c
+++ b/libgo/runtime/proc.c
@@ -8,13 +8,15 @@
typedef struct Sched Sched;
-M m0;
+G runtime_g0;
+M runtime_m0;
#ifdef __rtems__
#define __thread
#endif
-__thread M *m = &m0;
+__thread G *g;
+__thread M *m;
static struct {
Lock;
diff --git a/libgo/runtime/runtime.h b/libgo/runtime/runtime.h
index 2767dd8b60b..7f061cbbe31 100644
--- a/libgo/runtime/runtime.h
+++ b/libgo/runtime/runtime.h
@@ -48,11 +48,15 @@ typedef unsigned int uintptr __attribute__ ((mode (pointer)));
typedef uint8 bool;
typedef uint8 byte;
+typedef struct G G;
typedef struct M M;
typedef struct MCache MCache;
typedef struct FixAlloc FixAlloc;
typedef struct Lock Lock;
+typedef struct __go_defer_stack Defer;
+typedef struct __go_panic_stack Panic;
+
/* We use mutexes for locks. 6g uses futexes directly, and perhaps
someday we will do that too. */
@@ -76,9 +80,11 @@ struct Note {
#define __thread
#endif
+extern __thread G* g;
extern __thread M* m;
-extern M m0;
+extern M runtime_m0;
+extern G runtime_g0;
#ifdef __rtems__
#undef __thread
@@ -94,8 +100,34 @@ enum
/* Structures. */
+struct G
+{
+ Defer* defer;
+ Panic* panic;
+ void* exception; // current exception being thrown
+ bool is_foreign; // whether current exception from other language
+ byte* entry; // initial function
+ G* alllink; // on allg
+ void* param; // passed parameter on wakeup
+ int16 status;
+ int32 goid;
+ int8* waitreason; // if status==Gwaiting
+ G* schedlink;
+ bool readyonstop;
+ bool ispanic;
+ M* m; // for debuggers, but offset not hard-coded
+ M* lockedm;
+ M* idlem;
+ // int32 sig;
+ // uintptr sigcode0;
+ // uintptr sigcode1;
+ // uintptr sigpc;
+ // uintptr gopc; // pc of go statement that created this goroutine
+};
+
struct M
{
+ G* curg; // current running goroutine
int32 id;
int32 mallocing;
int32 gcing;
@@ -117,7 +149,6 @@ struct M
void *gc_next_segment;
void *gc_next_sp;
void *gc_initial_sp;
- struct __go_panic_defer_struct *gc_panic_defer;
};
/* Macros. */
diff --git a/libitm/ChangeLog b/libitm/ChangeLog
index e91f91e5497..46c984e8c75 100644
--- a/libitm/ChangeLog
+++ b/libitm/ChangeLog
@@ -1,5 +1,60 @@
+2011-11-10 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * config/alpha/sjlj.S (_ITM_beginTransaction) [!__ELF__]: Don't use
+ .hidden.
+ (.note.GNU-stack): Only use if __linux__.
+ * alloc_cpp.cc [!__osf__] (_ZnaXRKSt9nothrow_t): Dummy function.
+ * testsuite/libitm.c/notx.c: Use dg-options "-pthread".
+ * testsuite/libitm.c/reentrant.c: Likewise.
+ * testsuite/libitm.c/simple-2.c: Likewise.
+ * testsuite/libitm.c/txrelease.c: Likewise.
+ * testsuite/libitm.c++/static_ctor.C: Likewise.
+
+2011-11-10 Richard Henderson <rth@redhat.com>
+
+ * config/x86/x86_avx.cc: Remove #undef __AVX__ hack. Tidy comments.
+ * Makefile.am (x86_avx.lo): Only add -mavx if ARCH_X86_AVX.
+ * configure.ac (ARCH_X86_AVX): New conditional.
+ * Makefile.in, configure: Rebuild.
+
+2011-11-09 Richard Henderson <rth@redhat.com>
+
+ * acinclude.m4 (LIBITM_CHECK_AS_AVX): New.
+ * configure.ac: Use it.
+ * config.h.in, configure: Rebuild.
+ * config/x86/x86_avx.cc: Handle !HAVE_AS_AVX.
+
2011-11-09 Richard Henderson <rth@redhat.com>
+ * barrier.tpl, memcpy.cc, memset.cc, method-wbetl.cc: Remove file.
+ * config/alpha/unaligned.h: Remove file.
+ * config/generic/unaligned.h: Remove file.
+ * config/x86/unaligned.h: Remove file.
+ * config/generic/cachepage.h: Remove file.
+ * config/posix/cachepage.cc: Remove file.
+ * config/generic/cacheline.cc: Remove file.
+ * config/x86/cacheline.cc: Remove file.
+ * config/generic/cacheline.h (gtm_cacheline): Remove the
+ store_mask, copy_mask, copy_mask_wb methods.
+ * config/x86/cacheline.h: Likewise.
+ * config/alpha/cacheline.h: Fall back to generic after setting size.
+ * config/generic/tls.cc (gtm_mask_stack): Remove.
+ * config/x86/x86_avx.cc (GTM_vpperm_shift): Remove.
+ (GTM_vpalignr_table): Remove.
+ * config/x86/x86_sse.cc (GTM_palignr_table): Remove.
+ (GTM_pshift_table): Remove.
+ * config/libitm_i.h: Don't include cachepage.h.
+ * Makefile.am (libitm_la_SOURCES): Remove cacheline.cc, cachepage.cc
+ * Makefile.in, testsuite/Makefile.in: Rebuild.
+
+2011-11-09 Richard Henderson <rth@redhat.com>
+
+ * config/x86/cacheline.h (gtm_cacheline::store_mask): Use .byte
+ to emit branch prediction hint.
+
+ * config/x86/sjlj.S: Protect elf directives with __ELF__.
+ Protect .note.GNU-stack with __linux__.
+
* configure.ac (GCC_AS_CFI_PSEUDO_OP): Test it.
* configure, aclocal.m4, config.h.in: Rebuild.
* config/generic/asmcfi.h: New file.
diff --git a/libitm/Makefile.am b/libitm/Makefile.am
index 69234099b6c..b4674a572fc 100644
--- a/libitm/Makefile.am
+++ b/libitm/Makefile.am
@@ -41,13 +41,15 @@ libitm_la_LDFLAGS = $(libitm_version_info) $(libitm_version_script) \
libitm_la_SOURCES = \
aatree.cc alloc.cc alloc_c.cc alloc_cpp.cc barrier.cc beginend.cc \
- clone.cc cacheline.cc cachepage.cc eh_cpp.cc local.cc \
+ clone.cc eh_cpp.cc local.cc \
query.cc retry.cc rwlock.cc useraction.cc util.cc \
sjlj.S tls.cc method-serial.cc method-gl.cc
if ARCH_X86
libitm_la_SOURCES += x86_sse.cc x86_avx.cc
x86_sse.lo : XCFLAGS += -msse
+endif
+if ARCH_X86_AVX
x86_avx.lo : XCFLAGS += -mavx
endif
diff --git a/libitm/Makefile.in b/libitm/Makefile.in
index 7dc864b3087..74261463ebf 100644
--- a/libitm/Makefile.in
+++ b/libitm/Makefile.in
@@ -48,6 +48,7 @@ DIST_COMMON = $(am__configure_deps) $(srcdir)/../config.guess \
$(top_srcdir)/configure ChangeLog
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \
+ $(top_srcdir)/../config/asmcfi.m4 \
$(top_srcdir)/../config/depstand.m4 \
$(top_srcdir)/../config/enable.m4 \
$(top_srcdir)/../config/futex.m4 \
@@ -94,17 +95,17 @@ am__installdirs = "$(DESTDIR)$(toolexeclibdir)" "$(DESTDIR)$(infodir)" \
LTLIBRARIES = $(toolexeclib_LTLIBRARIES)
libitm_la_LIBADD =
am__libitm_la_SOURCES_DIST = aatree.cc alloc.cc alloc_c.cc \
- alloc_cpp.cc barrier.cc beginend.cc clone.cc cacheline.cc \
- cachepage.cc eh_cpp.cc local.cc query.cc retry.cc rwlock.cc \
- useraction.cc util.cc sjlj.S tls.cc method-serial.cc \
- method-gl.cc x86_sse.cc x86_avx.cc futex.cc
+ alloc_cpp.cc barrier.cc beginend.cc clone.cc eh_cpp.cc \
+ local.cc query.cc retry.cc rwlock.cc useraction.cc util.cc \
+ sjlj.S tls.cc method-serial.cc method-gl.cc x86_sse.cc \
+ x86_avx.cc futex.cc
@ARCH_X86_TRUE@am__objects_1 = x86_sse.lo x86_avx.lo
@ARCH_FUTEX_TRUE@am__objects_2 = futex.lo
am_libitm_la_OBJECTS = aatree.lo alloc.lo alloc_c.lo alloc_cpp.lo \
- barrier.lo beginend.lo clone.lo cacheline.lo cachepage.lo \
- eh_cpp.lo local.lo query.lo retry.lo rwlock.lo useraction.lo \
- util.lo sjlj.lo tls.lo method-serial.lo method-gl.lo \
- $(am__objects_1) $(am__objects_2)
+ barrier.lo beginend.lo clone.lo eh_cpp.lo local.lo query.lo \
+ retry.lo rwlock.lo useraction.lo util.lo sjlj.lo tls.lo \
+ method-serial.lo method-gl.lo $(am__objects_1) \
+ $(am__objects_2)
libitm_la_OBJECTS = $(am_libitm_la_OBJECTS)
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/../depcomp
@@ -234,8 +235,6 @@ ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
-FC = @FC@
-FCFLAGS = @FCFLAGS@
FGREP = @FGREP@
GREP = @GREP@
INSTALL = @INSTALL@
@@ -286,7 +285,6 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_CC = @ac_ct_CC@
ac_ct_CXX = @ac_ct_CXX@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
-ac_ct_FC = @ac_ct_FC@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -371,10 +369,9 @@ libitm_la_LDFLAGS = $(libitm_version_info) $(libitm_version_script) \
-no-undefined
libitm_la_SOURCES = aatree.cc alloc.cc alloc_c.cc alloc_cpp.cc \
- barrier.cc beginend.cc clone.cc cacheline.cc cachepage.cc \
- eh_cpp.cc local.cc query.cc retry.cc rwlock.cc useraction.cc \
- util.cc sjlj.S tls.cc method-serial.cc method-gl.cc \
- $(am__append_1) $(am__append_2)
+ barrier.cc beginend.cc clone.cc eh_cpp.cc local.cc query.cc \
+ retry.cc rwlock.cc useraction.cc util.cc sjlj.S tls.cc \
+ method-serial.cc method-gl.cc $(am__append_1) $(am__append_2)
# Automake Documentation:
# If your package has Texinfo files in many directories, you can use the
@@ -500,8 +497,6 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alloc_cpp.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/barrier.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/beginend.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cacheline.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cachepage.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clone.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eh_cpp.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/futex.Plo@am__quote@
@@ -1264,7 +1259,7 @@ uninstall-am: uninstall-dvi-am uninstall-html-am uninstall-info-am \
vpath % $(strip $(search_path))
@ARCH_X86_TRUE@x86_sse.lo : XCFLAGS += -msse
-@ARCH_X86_TRUE@x86_avx.lo : XCFLAGS += -mavx
+@ARCH_X86_AVX_TRUE@x86_avx.lo : XCFLAGS += -mavx
all-local: $(STAMP_GENINSRC)
diff --git a/libitm/acinclude.m4 b/libitm/acinclude.m4
index 8fcde4b57ad..58fbf424c60 100644
--- a/libitm/acinclude.m4
+++ b/libitm/acinclude.m4
@@ -95,6 +95,20 @@ AC_DEFUN([LIBITM_CHECK_SIZE_T_MANGLING], [
[Define to the letter to which size_t is mangled.])
])
+dnl Check if as supports AVX instructions.
+AC_DEFUN([LIBITM_CHECK_AS_AVX], [
+case "${target_cpu}" in
+i[3456]86 | x86_64)
+ AC_CACHE_CHECK([if the assembler supports AVX], libitm_cv_as_avx, [
+ AC_TRY_COMPILE([], [asm("vzeroupper");],
+ [libitm_cv_as_avx=yes], [libitm_cv_as_avx=no])
+ ])
+ if test x$libitm_cv_as_avx = xyes; then
+ AC_DEFINE(HAVE_AS_AVX, 1, [Define to 1 if the assembler supports AVX.])
+ fi
+ ;;
+esac])
+
sinclude(../libtool.m4)
dnl The lines below arrange for aclocal not to bring an installed
dnl libtool.m4 into aclocal.m4, while still arranging for automake to
diff --git a/libitm/alloc_cpp.cc b/libitm/alloc_cpp.cc
index 59d8b7374eb..4e535513cd5 100644
--- a/libitm/alloc_cpp.cc
+++ b/libitm/alloc_cpp.cc
@@ -60,6 +60,14 @@ extern void _ZdlPvRKSt9nothrow_t (void *, c_nothrow_p) __attribute__((weak));
extern void *_ZnaXRKSt9nothrow_t (size_t, c_nothrow_p) __attribute__((weak));
extern void _ZdaPvRKSt9nothrow_t (void *, c_nothrow_p) __attribute__((weak));
+#ifdef __osf__ /* Really: !HAVE_WEAKDEF */
+void *
+_ZnaXRKSt9nothrow_t (size_t, c_nothrow_p)
+{
+ return NULL;
+}
+#endif /* __osf__ */
+
/* Wrap the delete nothrow symbols for usage with a single argument.
Perhaps should have a configure type check for this, because the
std::nothrow_t reference argument is unused (empty class), and most
diff --git a/libitm/barrier.tpl b/libitm/barrier.tpl
deleted file mode 100644
index dcf101356e6..00000000000
--- a/libitm/barrier.tpl
+++ /dev/null
@@ -1,170 +0,0 @@
-/* -*- c++ -*- */
-/* Copyright (C) 2008, 2009, 2011 Free Software Foundation, Inc.
- Contributed by Richard Henderson <rth@redhat.com>.
-
- This file is part of the GNU Transactional Memory Library (libitm).
-
- Libitm 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.
-
- Libitm 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 "unaligned.h"
-
-namespace {
-
-using namespace GTM;
-
-template<typename T>
-T do_read (const T *ptr, abi_dispatch::lock_type lock)
-{
- //
- // Find the cacheline that holds the current value of *PTR.
- //
- abi_dispatch *disp = abi_disp();
- uintptr_t iptr = reinterpret_cast<uintptr_t>(ptr);
- // Normalize PTR by chopping off the bottom bits so we can search
- // for PTR in the cacheline hash.
- uintptr_t iline = iptr & -CACHELINE_SIZE;
- // The position in the resulting cacheline where *PTR is actually stored.
- uintptr_t iofs = iptr & (CACHELINE_SIZE - 1);
- const gtm_cacheline *pline = reinterpret_cast<const gtm_cacheline *>(iline);
- // Search for the actual cacheline that holds the current value of *PTR.
- const gtm_cacheline *line = disp->read_lock(pline, lock);
-
- // Point to the position in the cacheline where *PTR is stored.
- ptr = reinterpret_cast<const T *>(&line->b[iofs]);
-
- // Straight up loads, because we're either aligned, or we don't care
- // about alignment.
- //
- // If we require alignment on type T, do a straight load if we're
- // aligned. Otherwise do a straight load IFF the load fits entirely
- // in this cacheline. That is, it won't span multiple cachelines.
- if (__builtin_expect (strict_alignment<T>::value
- ? (iofs & (sizeof (T) - 1)) == 0
- : iofs + sizeof(T) <= CACHELINE_SIZE, 1))
- {
- do_normal_load:
- return *ptr;
- }
- // If alignment on T is necessary, but we're unaligned, yet we fit
- // entirely in this cacheline... do the unaligned load dance.
- else if (__builtin_expect (strict_alignment<T>::value
- && iofs + sizeof(T) <= CACHELINE_SIZE, 1))
- {
- do_unaligned_load:
- return unaligned_load<T>(ptr);
- }
- // Otherwise, this load will span multiple cachelines.
- else
- {
- // Get the following cacheline for the rest of the data.
- const gtm_cacheline *line2 = disp->read_lock(pline + 1, lock);
-
- // If the two cachelines are adjacent, just load it all in one
- // swoop.
- if (line2 == line + 1)
- {
- if (!strict_alignment<T>::value)
- goto do_normal_load;
- else
- goto do_unaligned_load;
- }
- else
- {
- // Otherwise, ask the backend to load from two different
- // cachelines.
- return unaligned_load2<T>(line, line2, iofs);
- }
- }
-}
-
-template<typename T>
-void do_write (T *ptr, T val, abi_dispatch::lock_type lock)
-{
- // Note: See comments for do_read() above for hints on this
- // function. Ideally we should abstract out a lot out of these two
- // functions, and avoid all this duplication.
-
- abi_dispatch *disp = abi_disp();
- uintptr_t iptr = reinterpret_cast<uintptr_t>(ptr);
- uintptr_t iline = iptr & -CACHELINE_SIZE;
- uintptr_t iofs = iptr & (CACHELINE_SIZE - 1);
- gtm_cacheline *pline = reinterpret_cast<gtm_cacheline *>(iline);
- gtm_cacheline_mask m = ((gtm_cacheline_mask)2 << (sizeof(T) - 1)) - 1;
- abi_dispatch::mask_pair pair = disp->write_lock(pline, lock);
-
- ptr = reinterpret_cast<T *>(&pair.line->b[iofs]);
-
- if (__builtin_expect (strict_alignment<T>::value
- ? (iofs & (sizeof (val) - 1)) == 0
- : iofs + sizeof(val) <= CACHELINE_SIZE, 1))
- {
- *pair.mask |= m << iofs;
- do_normal_store:
- *ptr = val;
- }
- else if (__builtin_expect (strict_alignment<T>::value
- && iofs + sizeof(val) <= CACHELINE_SIZE, 1))
- {
- *pair.mask |= m << iofs;
- do_unaligned_store:
- unaligned_store<T>(ptr, val);
- }
- else
- {
- *pair.mask |= m << iofs;
- abi_dispatch::mask_pair pair2 = disp->write_lock(pline + 1, lock);
-
- uintptr_t ileft = CACHELINE_SIZE - iofs;
- *pair2.mask |= m >> ileft;
-
- if (pair2.line == pair.line + 1)
- {
- if (!strict_alignment<T>::value)
- goto do_normal_store;
- else
- goto do_unaligned_store;
- }
- else
- unaligned_store2<T>(pair.line, pair2.line, iofs, val);
- }
-}
-
-} /* anonymous namespace */
-
-#define ITM_READ(T, LOCK) \
- _ITM_TYPE_##T ITM_REGPARM _ITM_##LOCK##T (const _ITM_TYPE_##T *ptr) \
- { \
- return do_read (ptr, abi_dispatch::LOCK); \
- }
-
-#define ITM_WRITE(T, LOCK) \
- void ITM_REGPARM _ITM_##LOCK##T (_ITM_TYPE_##T *ptr, _ITM_TYPE_##T val) \
- { \
- do_write (ptr, val, abi_dispatch::LOCK); \
- }
-
-#define ITM_BARRIERS(T) \
- ITM_READ(T, R) \
- ITM_READ(T, RaR) \
- ITM_READ(T, RaW) \
- ITM_READ(T, RfW) \
- ITM_WRITE(T, W) \
- ITM_WRITE(T, WaR) \
- ITM_WRITE(T, WaW)
diff --git a/libitm/config.h.in b/libitm/config.h.in
index 369f6c66caf..52db1a6fdc1 100644
--- a/libitm/config.h.in
+++ b/libitm/config.h.in
@@ -6,6 +6,9 @@
/* Define to 1 if the target supports 64-bit __sync_*_compare_and_swap */
#undef HAVE_64BIT_SYNC_BUILTINS
+/* Define to 1 if the assembler supports AVX. */
+#undef HAVE_AS_AVX
+
/* Define if your assembler supports .cfi_* directives. */
#undef HAVE_AS_CFI_PSEUDO_OP
diff --git a/libitm/config/alpha/cacheline.h b/libitm/config/alpha/cacheline.h
index 5e38486b713..611a1c9a26e 100644
--- a/libitm/config/alpha/cacheline.h
+++ b/libitm/config/alpha/cacheline.h
@@ -33,90 +33,6 @@
// modification mask, below.
#define CACHELINE_SIZE 64
-#ifdef __alpha_bwx__
-# include "config/generic/cacheline.h"
-#else
-// If we don't have byte-word stores, then we'll never be able to
-// adjust *all* of the byte loads/stores to be truely atomic. So
-// only guarantee 4-byte aligned values atomicly stored, exactly
-// like the native system. Use byte zap instructions to accelerate
-// sub-word masked stores.
+#include "config/generic/cacheline.h"
-namespace GTM HIDDEN {
-
-// A gtm_cacheline_mask stores a modified bit for every modified byte
-// in the cacheline with which it is associated.
-typedef sized_integral<CACHELINE_SIZE / 8>::type gtm_cacheline_mask;
-
-union gtm_cacheline
-{
- // Byte access to the cacheline.
- unsigned char b[CACHELINE_SIZE] __attribute__((aligned(CACHELINE_SIZE)));
-
- // Larger sized access to the cacheline.
- uint16_t u16[CACHELINE_SIZE / sizeof(uint16_t)];
- uint32_t u32[CACHELINE_SIZE / sizeof(uint32_t)];
- uint64_t u64[CACHELINE_SIZE / sizeof(uint64_t)];
- gtm_word w[CACHELINE_SIZE / sizeof(gtm_word)];
-
- // Store S into D, but only the bytes specified by M.
- static void store_mask(uint32_t *d, uint32_t s, uint8_t m);
- static void store_mask(uint64_t *d, uint64_t s, uint8_t m);
-
- // Copy S to D, but only the bytes specified by M.
- static void copy_mask (gtm_cacheline * __restrict d,
- const gtm_cacheline * __restrict s,
- gtm_cacheline_mask m);
-
- // A write barrier to emit after (a series of) copy_mask.
- static void copy_mask_wb () { atomic_write_barrier(); }
-};
-
-inline void ALWAYS_INLINE
-gtm_cacheline::store_mask (uint32_t *d, uint32_t s, uint8_t m)
-{
- const uint8_t tm = (1 << sizeof(uint32_t)) - 1;
-
- m &= tm;
- if (__builtin_expect (m, tm))
- {
- if (__builtin_expect (m == tm, 1))
- *d = s;
- else
- *d = __builtin_alpha_zap (*d, m) | __builtin_alpha_zapnot (s, m);
- }
-}
-
-inline void ALWAYS_INLINE
-gtm_cacheline::store_mask (uint64_t *d, uint64_t s, uint8_t m)
-{
- if (__builtin_expect (m, 0xff))
- {
- if (__builtin_expect (m == 0xff, 1))
- *d = s;
- else
- {
- typedef uint32_t *p32 __attribute__((may_alias));
- p32 d32 = reinterpret_cast<p32>(d);
-
- if ((m & 0x0f) == 0x0f)
- {
- d32[0] = s;
- m &= 0xf0;
- }
- else if ((m & 0xf0) == 0xf0)
- {
- d32[1] = s >> 32;
- m &= 0x0f;
- }
-
- if (m)
- *d = __builtin_alpha_zap (*d, m) | __builtin_alpha_zapnot (s, m);
- }
- }
-}
-
-} // namespace GTM
-
-#endif // __alpha_bwx__
#endif // LIBITM_ALPHA_CACHELINE_H
diff --git a/libitm/config/alpha/sjlj.S b/libitm/config/alpha/sjlj.S
index d60a82df62b..3aa5f06e332 100644
--- a/libitm/config/alpha/sjlj.S
+++ b/libitm/config/alpha/sjlj.S
@@ -74,7 +74,9 @@ _ITM_beginTransaction:
.align 4
.globl GTM_longjmp
+#ifdef __ELF__
.hidden GTM_longjmp
+#endif
.ent GTM_longjmp
GTM_longjmp:
@@ -105,4 +107,6 @@ GTM_longjmp:
ret
.end GTM_longjmp
+#ifdef __linux__
.section .note.GNU-stack, "", @progbits
+#endif
diff --git a/libitm/config/alpha/unaligned.h b/libitm/config/alpha/unaligned.h
deleted file mode 100644
index 3d091aee228..00000000000
--- a/libitm/config/alpha/unaligned.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/* Copyright (C) 2009, 2011 Free Software Foundation, Inc.
- Contributed by Richard Henderson <rth@redhat.com>.
-
- This file is part of the GNU Transactional Memory Library (libitm).
-
- Libitm 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.
-
- Libitm 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 LIBITM_ALPHA_UNALIGNED_H
-#define LIBITM_ALPHA_UNALIGNED_H 1
-
-#define HAVE_ARCH_UNALIGNED_LOAD2_U2 1
-#define HAVE_ARCH_UNALIGNED_LOAD2_U4 1
-#define HAVE_ARCH_UNALIGNED_LOAD2_U8 1
-
-#ifndef __alpha_bwx__
-#define HAVE_ARCH_UNALIGNED_STORE2_U2 1
-#endif
-#define HAVE_ARCH_UNALIGNED_STORE2_U4 1
-#define HAVE_ARCH_UNALIGNED_STORE2_U8 1
-
-#include "config/generic/unaligned.h"
-
-namespace GTM HIDDEN {
-
-template<>
-inline uint16_t ALWAYS_INLINE
-unaligned_load2<uint16_t>(const gtm_cacheline *c1,
- const gtm_cacheline *c2, size_t ofs)
-{
- uint64_t v1 = c1->u64[CACHELINE_SIZE / sizeof(uint64_t) - 1];
- uint64_t v2 = c2->u64[0];
-
- return __builtin_alpha_extwl (v1, ofs) | __builtin_alpha_extwh (v2, ofs);
-}
-
-template<>
-inline uint32_t ALWAYS_INLINE
-unaligned_load2<uint32_t>(const gtm_cacheline *c1,
- const gtm_cacheline *c2, size_t ofs)
-{
- uint64_t v1 = c1->u64[CACHELINE_SIZE / sizeof(uint64_t) - 1];
- uint64_t v2 = c2->u64[0];
-
- return __builtin_alpha_extll (v1, ofs) + __builtin_alpha_extlh (v2, ofs);
-}
-
-template<>
-inline uint64_t ALWAYS_INLINE
-unaligned_load2<uint64_t>(const gtm_cacheline *c1,
- const gtm_cacheline *c2, size_t ofs)
-{
- uint64_t v1 = c1->u64[CACHELINE_SIZE / sizeof(uint64_t) - 1];
- uint64_t v2 = c2->u64[0];
-
- return __builtin_alpha_extql (v1, ofs) | __builtin_alpha_extqh (v2, ofs);
-}
-
-#ifndef __alpha_bwx__
-template<>
-inline void
-unaligned_store2<uint16_t>(gtm_cacheline *c1, gtm_cacheline *c2,
- size_t ofs, uint16_t val)
-{
- uint32_t vl = (uint32_t)val << 24, vh = val >> 8;
-
- gtm_cacheline::store_mask (&c1->u32[CACHELINE_SIZE / 4 - 1], vl, 4);
- gtm_cacheline::store_mask (&c2->u32[0], vh, 1);
-}
-#endif
-
-template<>
-inline void
-unaligned_store2<uint32_t>(gtm_cacheline *c1, gtm_cacheline *c2,
- size_t ofs, uint32_t val)
-{
- uint64_t vl = __builtin_alpha_insll (val, ofs);
- uint64_t ml = __builtin_alpha_insll (~0u, ofs);
- uint64_t vh = __builtin_alpha_inslh (val, ofs);
- uint64_t mh = __builtin_alpha_inslh (~0u, ofs);
-
- gtm_cacheline::store_mask (&c1->u64[CACHELINE_SIZE / 8 - 1], vl, ml);
- gtm_cacheline::store_mask (&c2->u64[0], vh, mh);
-}
-
-template<>
-inline void
-unaligned_store2<uint64_t>(gtm_cacheline *c1, gtm_cacheline *c2,
- size_t ofs, uint64_t val)
-{
- uint64_t vl = __builtin_alpha_insql (val, ofs);
- uint64_t ml = __builtin_alpha_insql (~0u, ofs);
- uint64_t vh = __builtin_alpha_insqh (val, ofs);
- uint64_t mh = __builtin_alpha_insqh (~0u, ofs);
-
- gtm_cacheline::store_mask (&c1->u64[CACHELINE_SIZE / 8 - 1], vl, ml);
- gtm_cacheline::store_mask (&c2->u64[0], vh, mh);
-}
-
-} // namespace GTM
-
-#endif // LIBITM_ALPHA_UNALIGNED_H
diff --git a/libitm/config/generic/cacheline.cc b/libitm/config/generic/cacheline.cc
deleted file mode 100644
index 108ffba3037..00000000000
--- a/libitm/config/generic/cacheline.cc
+++ /dev/null
@@ -1,49 +0,0 @@
-/* Copyright (C) 2009, 2011 Free Software Foundation, Inc.
- Contributed by Richard Henderson <rth@redhat.com>.
-
- This file is part of the GNU Transactional Memory Library (libitm).
-
- Libitm 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.
-
- Libitm 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 "libitm_i.h"
-
-
-namespace GTM HIDDEN {
-
-void
-gtm_cacheline::copy_mask (gtm_cacheline * __restrict d,
- const gtm_cacheline * __restrict s,
- gtm_cacheline_mask m)
-{
- const size_t n = sizeof (gtm_word);
-
- if (m == (gtm_cacheline_mask) -1)
- {
- *d = *s;
- return;
- }
- if (__builtin_expect (m == 0, 0))
- return;
-
- for (size_t i = 0; i < CACHELINE_SIZE / n; ++i, m >>= n)
- store_mask (&d->w[i], s->w[i], m);
-}
-
-} // namespace GTM
diff --git a/libitm/config/generic/cacheline.h b/libitm/config/generic/cacheline.h
index 0a5af761d6e..dd7d877d1d1 100644
--- a/libitm/config/generic/cacheline.h
+++ b/libitm/config/generic/cacheline.h
@@ -51,57 +51,8 @@ union gtm_cacheline
uint32_t u32[CACHELINE_SIZE / sizeof(uint32_t)];
uint64_t u64[CACHELINE_SIZE / sizeof(uint64_t)];
gtm_word w[CACHELINE_SIZE / sizeof(gtm_word)];
-
- // Store S into D, but only the bytes specified by M.
- template<typename T> static void store_mask (T *d, T s, uint8_t m);
-
- // Copy S to D, but only the bytes specified by M.
- static void copy_mask (gtm_cacheline * __restrict d,
- const gtm_cacheline * __restrict s,
- gtm_cacheline_mask m);
-
- // A write barrier to emit after (a series of) copy_mask.
- // When we're emitting non-temporal stores, the normal strong
- // ordering of the machine doesn't apply.
- static void copy_mask_wb () { atomic_write_barrier(); }
};
-template<typename T>
-inline void
-gtm_cacheline::store_mask (T *d, T s, uint8_t m)
-{
- const uint8_t tm = (1 << sizeof(T)) - 1;
-
- if (__builtin_expect (m & tm, tm))
- {
- if (__builtin_expect ((m & tm) == tm, 1))
- *d = s;
- else
- {
- const int half = sizeof(T) / 2;
- typedef typename sized_integral<half>::type half_t;
- half_t *dhalf = reinterpret_cast<half_t *>(d);
- half_t s1, s2;
-
- if (WORDS_BIGENDIAN)
- s1 = s >> half*8, s2 = s;
- else
- s1 = s, s2 = s >> half*8;
-
- store_mask (dhalf, s1, m);
- store_mask (dhalf + 1, s2, m >> half);
- }
- }
-}
-
-template<>
-inline void ALWAYS_INLINE
-gtm_cacheline::store_mask<uint8_t> (uint8_t *d, uint8_t s, uint8_t m)
-{
- if (m & 1)
- *d = s;
-}
-
} // namespace GTM
#endif // LIBITM_CACHELINE_H
diff --git a/libitm/config/generic/cachepage.h b/libitm/config/generic/cachepage.h
deleted file mode 100644
index a5472f3831b..00000000000
--- a/libitm/config/generic/cachepage.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/* Copyright (C) 2009, 2011 Free Software Foundation, Inc.
- Contributed by Richard Henderson <rth@redhat.com>.
-
- This file is part of the GNU Transactional Memory Library (libitm).
-
- Libitm 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.
-
- Libitm 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 LIBITM_CACHEPAGE_H
-#define LIBITM_CACHEPAGE_H 1
-
-namespace GTM HIDDEN {
-
-// A "page" worth of saved cachelines plus modification masks. This
-// arrangement is intended to minimize the overhead of alignment. The
-// PAGE_SIZE defined by the target must be a constant for this to work,
-// which means that this definition may not be the same as the real
-// system page size. An additional define of FIXED_PAGE_SIZE by the
-// target indicates that PAGE_SIZE exactly matches the system page size.
-
-#ifndef PAGE_SIZE
-#define PAGE_SIZE 4096
-#endif
-
-struct gtm_cacheline_page
-{
- static const size_t LINES
- = ((PAGE_SIZE - sizeof(gtm_cacheline_page *))
- / (CACHELINE_SIZE + sizeof(gtm_cacheline_mask)));
-
- gtm_cacheline lines[LINES] __attribute__((aligned(PAGE_SIZE)));
- gtm_cacheline_mask masks[LINES];
- gtm_cacheline_page *prev;
-
- static gtm_cacheline_page *
- page_for_line (gtm_cacheline *c)
- {
- return (gtm_cacheline_page *)((uintptr_t)c & -PAGE_SIZE);
- }
-
- gtm_cacheline_mask *
- mask_for_line (gtm_cacheline *c)
- {
- size_t index = c - &this->lines[0];
- return &this->masks[index];
- }
-
- static gtm_cacheline_mask *
- mask_for_page_line (gtm_cacheline *c)
- {
- gtm_cacheline_page *p = page_for_line (c);
- return p->mask_for_line (c);
- }
-
- static void *operator new (size_t);
- static void operator delete (void *);
-};
-
-} // namespace GTM
-
-#endif // LIBITM_CACHEPAGE_H
diff --git a/libitm/config/generic/tls.cc b/libitm/config/generic/tls.cc
index c6421113c86..e502e50869b 100644
--- a/libitm/config/generic/tls.cc
+++ b/libitm/config/generic/tls.cc
@@ -30,51 +30,4 @@ namespace GTM HIDDEN {
__thread gtm_thread_tls _gtm_thr_tls;
#endif
-// Filter out any updates that overlap the libitm stack, as defined by
-// TOP (entry point to library) and BOT (below current function). This
-// definition should be fine for all stack-grows-down architectures.
-
-gtm_cacheline_mask __attribute__((noinline))
-gtm_mask_stack(gtm_cacheline *line, gtm_cacheline_mask mask)
-{
- void *top = gtm_thr()->jb.cfa;
- void *bot = __builtin_dwarf_cfa();
-
- // We must have come through an entry point that set TOP.
- assert (top != NULL);
-
- if (line + 1 < bot)
- {
- // Since we don't have the REAL stack boundaries for this thread,
- // we cannot know if this is a dead write to a stack address below
- // the current function or if it is write to another VMA. In either
- // case allowing the write should not affect correctness.
- }
- else if (line >= top)
- {
- // A valid write to an address in an outer stack frame, or a write
- // to another VMA.
- }
- else
- {
- uintptr_t diff = (uintptr_t)top - (uintptr_t)line;
- if (diff >= CACHELINE_SIZE)
- {
- // The write is either fully within the proscribed area, or the tail
- // of the cacheline overlaps the proscribed area. Assume that all
- // stacks are at least cacheline aligned and declare the head of the
- // cacheline dead.
- mask = 0;
- }
- else
- {
- // The head of the cacheline is within the proscribed area, but the
- // tail of the cacheline is live. Eliminate the dead writes.
- mask &= (gtm_cacheline_mask)-1 << diff;
- }
- }
-
- return mask;
-}
-
} // namespace GTM
diff --git a/libitm/config/generic/unaligned.h b/libitm/config/generic/unaligned.h
deleted file mode 100644
index 50cb13bd277..00000000000
--- a/libitm/config/generic/unaligned.h
+++ /dev/null
@@ -1,228 +0,0 @@
-/* Copyright (C) 2009, 2011 Free Software Foundation, Inc.
- Contributed by Richard Henderson <rth@redhat.com>.
-
- This file is part of the GNU Transactional Memory Library (libitm).
-
- Libitm 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.
-
- Libitm 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 LIBITM_UNALIGNED_H
-#define LIBITM_UNALIGNED_H 1
-
-namespace GTM HIDDEN {
-
-#ifndef STRICT_ALIGNMENT
-#define STRICT_ALIGNMENT 1
-#endif
-
-// A type trait for whether type T requires strict alignment.
-// The generic types are assumed to all be the same; specializations
-// for target-specific types should be done in config/cpu/unaligned.h.
-template<typename T>
- struct strict_alignment
- : public std::integral_constant<bool, STRICT_ALIGNMENT>
- { };
-
-// A helper template for accessing an integral type the same size as T
-template<typename T>
- struct make_integral
- : public sized_integral<sizeof(T)>
- { };
-
-// A helper class for accessing T as an unaligned value.
-template<typename T>
-struct __attribute__((packed)) unaligned_helper
- { T x; };
-
-// A helper class for view-converting T as an integer.
-template<typename T>
-union view_convert_helper
-{
- typedef T type;
- typedef make_integral<T> itype;
-
- type t;
- itype i;
-};
-
-// Generate an unaligned load sequence.
-// The compiler knows how to do this for any specific type.
-template<typename T>
-inline T ALWAYS_INLINE
-unaligned_load(const void *t)
-{
- typedef unaligned_helper<T> UT;
- const UT *ut = reinterpret_cast<const UT *>(t);
- return ut->x;
-}
-
-// Generate an unaligned store sequence.
-template<typename T>
-inline void ALWAYS_INLINE
-unaligned_store(void *t, T val)
-{
- typedef unaligned_helper<T> UT;
- UT *ut = reinterpret_cast<UT *>(t);
- ut->x = val;
-}
-
-// Generate an unaligned load from two different cachelines.
-// It is known that OFS + SIZEOF(T) > CACHELINE_SIZE.
-template<typename T>
-inline T ALWAYS_INLINE
-unaligned_load2(const gtm_cacheline *c1, const gtm_cacheline *c2, size_t ofs)
-{
- size_t left = CACHELINE_SIZE - ofs;
- T ret;
-
- memcpy (&ret, &c1->b[ofs], left);
- memcpy ((char *)&ret + ofs, c2, sizeof(T) - left);
-
- return ret;
-}
-
-// Generate an unaligned store into two different cachelines.
-// It is known that OFS + SIZEOF(T) > CACHELINE_SIZE.
-template<typename T>
-inline void ALWAYS_INLINE
-unaligned_store2(gtm_cacheline *c1, gtm_cacheline *c2, size_t ofs, T val)
-{
- size_t left = CACHELINE_SIZE - ofs;
- memcpy (&c1->b[ofs], &val, left);
- memcpy (c2, (char *)&val + left, sizeof(T) - left);
-}
-
-#ifndef HAVE_ARCH_UNALIGNED_LOAD2_U2
-template<>
-inline uint16_t ALWAYS_INLINE
-unaligned_load2<uint16_t>(const gtm_cacheline *c1,
- const gtm_cacheline *c2, size_t ofs)
-{
- uint16_t v1 = c1->b[CACHELINE_SIZE - 1];
- uint16_t v2 = c2->b[0];
-
- if (WORDS_BIGENDIAN)
- return v1 << 8 | v2;
- else
- return v2 << 8 | v1;
-}
-#endif
-
-#ifndef HAVE_ARCH_UNALIGNED_LOAD2_U4
-template<>
-inline uint32_t ALWAYS_INLINE
-unaligned_load2<uint32_t>(const gtm_cacheline *c1,
- const gtm_cacheline *c2, size_t ofs)
-{
- uint32_t v1 = c1->u32[CACHELINE_SIZE / sizeof(uint32_t) - 1];
- uint32_t v2 = c2->u32[0];
- int s2 = (ofs & (sizeof(uint32_t) - 1)) * 8;
- int s1 = sizeof(uint32_t) * 8 - s2;
-
- if (WORDS_BIGENDIAN)
- return v1 << s2 | v2 >> s1;
- else
- return v2 << s2 | v1 >> s1;
-}
-#endif
-
-#ifndef HAVE_ARCH_UNALIGNED_LOAD2_U8
-template<>
-inline uint64_t ALWAYS_INLINE
-unaligned_load2<uint64_t>(const gtm_cacheline *c1,
- const gtm_cacheline *c2, size_t ofs)
-{
- uint64_t v1 = c1->u64[CACHELINE_SIZE / sizeof(uint64_t) - 1];
- uint64_t v2 = c2->u64[0];
- int s2 = (ofs & (sizeof(uint64_t) - 1)) * 8;
- int s1 = sizeof(uint64_t) * 8 - s2;
-
- if (WORDS_BIGENDIAN)
- return v1 << s2 | v2 >> s1;
- else
- return v2 << s2 | v1 >> s1;
-}
-#endif
-
-template<>
-inline float ALWAYS_INLINE
-unaligned_load2<float>(const gtm_cacheline *c1,
- const gtm_cacheline *c2, size_t ofs)
-{
- typedef view_convert_helper<float> VC; VC vc;
- vc.i = unaligned_load2<VC::itype>(c1, c2, ofs);
- return vc.t;
-}
-
-template<>
-inline double ALWAYS_INLINE
-unaligned_load2<double>(const gtm_cacheline *c1,
- const gtm_cacheline *c2, size_t ofs)
-{
- typedef view_convert_helper<double> VC; VC vc;
- vc.i = unaligned_load2<VC::itype>(c1, c2, ofs);
- return vc.t;
-}
-
-#ifndef HAVE_ARCH_UNALIGNED_STORE2_U2
-template<>
-inline void ALWAYS_INLINE
-unaligned_store2<uint16_t>(gtm_cacheline *c1, gtm_cacheline *c2,
- size_t ofs, uint16_t val)
-{
- uint8_t vl = val, vh = val >> 8;
-
- if (WORDS_BIGENDIAN)
- {
- c1->b[CACHELINE_SIZE - 1] = vh;
- c2->b[0] = vl;
- }
- else
- {
- c1->b[CACHELINE_SIZE - 1] = vl;
- c2->b[0] = vh;
- }
-}
-#endif
-
-#if 0
-#ifndef HAVE_ARCH_UNALIGNED_STORE2_U4
-template<>
-inline void ALWAYS_INLINE
-unaligned_store2<uint32_t>(gtm_cacheline *c1, gtm_cacheline *c2,
- size_t ofs, uint32_t val)
-{
- // ??? We could reuse the store_mask stuff here.
-}
-#endif
-
-template<>
-inline void ALWAYS_INLINE
-unaligned_store2<float>(gtm_cacheline *c1, gtm_cacheline *c2,
- size_t ofs, float val)
-{
- typedef view_convert_helper<float> VC; VC vc;
- vc.t = val;
- unaligned_store2(c1, c2, ofs, vc.i);
-}
-#endif
-
-} // namespace GTM
-
-#endif // LIBITM_UNALIGNED_H
diff --git a/libitm/config/posix/cachepage.cc b/libitm/config/posix/cachepage.cc
deleted file mode 100644
index 128cd5435ae..00000000000
--- a/libitm/config/posix/cachepage.cc
+++ /dev/null
@@ -1,183 +0,0 @@
-/* Copyright (C) 2009, 2011 Free Software Foundation, Inc.
- Contributed by Richard Henderson <rth@redhat.com>.
-
- This file is part of the GNU Transactional Memory Library (libitm).
-
- Libitm 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.
-
- Libitm 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 "libitm_i.h"
-#include <pthread.h>
-
-//
-// We have three possibilities for alloction: mmap, memalign, posix_memalign
-//
-
-#if defined(HAVE_MMAP_ANON) || defined(HAVE_MMAP_DEV_ZERO)
-#include <sys/mman.h>
-#include <fcntl.h>
-#endif
-#ifdef HAVE_MALLOC_H
-#include <malloc.h>
-#endif
-
-namespace GTM HIDDEN {
-
-#if defined(HAVE_MMAP_ANON)
-# if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
-# define MAP_ANONYMOUS MAP_ANON
-# endif
-# define dev_zero -1
-#elif defined(HAVE_MMAP_DEV_ZERO)
-# ifndef MAP_ANONYMOUS
-# define MAP_ANONYMOUS 0
-# endif
-static int dev_zero = -1;
-#endif
-
-#if defined(HAVE_MMAP_ANON) || defined(HAVE_MMAP_DEV_ZERO)
-/* If we get here, we've already opened /dev/zero and verified that
- PAGE_SIZE is valid for the system. */
-static gtm_cacheline_page * alloc_mmap (void) UNUSED;
-static gtm_cacheline_page *
-alloc_mmap (void)
-{
- gtm_cacheline_page *r;
- r = (gtm_cacheline_page *) mmap (NULL, PAGE_SIZE, PROT_READ | PROT_WRITE,
- MAP_PRIVATE | MAP_ANONYMOUS, dev_zero, 0);
- if (r == (gtm_cacheline_page *) MAP_FAILED)
- abort ();
- return r;
-}
-#endif /* MMAP_ANON | MMAP_DEV_ZERO */
-
-#ifdef HAVE_MEMALIGN
-static gtm_cacheline_page * alloc_memalign (void) UNUSED;
-static gtm_cacheline_page *
-alloc_memalign (void)
-{
- gtm_cacheline_page *r;
- r = (gtm_cacheline_page *) memalign (PAGE_SIZE, PAGE_SIZE);
- if (r == NULL)
- abort ();
- return r;
-}
-#endif /* MEMALIGN */
-
-#ifdef HAVE_POSIX_MEMALIGN
-static gtm_cacheline_page *alloc_posix_memalign (void) UNUSED;
-static gtm_cacheline_page *
-alloc_posix_memalign (void)
-{
- void *r;
- if (posix_memalign (&r, PAGE_SIZE, PAGE_SIZE))
- abort ();
- return (gtm_cacheline_page *) r;
-}
-#endif /* POSIX_MEMALIGN */
-
-#if defined(HAVE_MMAP_ANON) && defined(FIXED_PAGE_SIZE)
-# define alloc_page alloc_mmap
-#elif defined(HAVE_MMAP_DEV_ZERO) && defined(FIXED_PAGE_SIZE)
-static gtm_cacheline_page *
-alloc_page (void)
-{
- if (dev_zero < 0)
- {
- dev_zero = open ("/dev/zero", O_RDWR);
- assert (dev_zero >= 0);
- }
- return alloc_mmap ();
-}
-#elif defined(HAVE_MMAP_ANON) || defined(HAVE_MMAP_DEV_ZERO)
-static gtm_cacheline_page * (*alloc_page) (void);
-static void __attribute__((constructor))
-init_alloc_page (void)
-{
- size_t page_size = getpagesize ();
- if (page_size <= PAGE_SIZE && PAGE_SIZE % page_size == 0)
- {
-# ifndef HAVE_MMAP_ANON
- dev_zero = open ("/dev/zero", O_RDWR);
- assert (dev_zero >= 0);
-# endif
- alloc_page = alloc_mmap;
- return;
- }
-# ifdef HAVE_MEMALIGN
- alloc_page = alloc_memalign;
-# elif defined(HAVE_POSIX_MEMALIGN)
- alloc_page = alloc_posix_memalign;
-# else
-# error "No fallback aligned memory allocation method"
-# endif
-}
-#elif defined(HAVE_MEMALIGN)
-# define alloc_page alloc_memalign
-#elif defined(HAVE_POSIX_MEMALIGN)
-# define alloc_page alloc_posix_memalign
-#else
-# error "No aligned memory allocation method"
-#endif
-
-static gtm_cacheline_page *free_pages;
-static pthread_mutex_t free_page_lock = PTHREAD_MUTEX_INITIALIZER;
-
-void *
-gtm_cacheline_page::operator new (size_t size)
-{
- assert (size == sizeof (gtm_cacheline_page));
- assert (size <= PAGE_SIZE);
-
- pthread_mutex_lock(&free_page_lock);
-
- gtm_cacheline_page *r = free_pages;
- free_pages = r ? r->prev : NULL;
-
- pthread_mutex_unlock(&free_page_lock);
-
- if (r == NULL)
- r = alloc_page ();
-
- return r;
-}
-
-void
-gtm_cacheline_page::operator delete (void *xhead)
-{
- gtm_cacheline_page *head = static_cast<gtm_cacheline_page *>(xhead);
- gtm_cacheline_page *tail;
-
- if (head == 0)
- return;
-
- /* ??? We should eventually really free some of these. */
-
- for (tail = head; tail->prev != 0; tail = tail->prev)
- continue;
-
- pthread_mutex_lock(&free_page_lock);
-
- tail->prev = free_pages;
- free_pages = head;
-
- pthread_mutex_unlock(&free_page_lock);
-}
-
-} // namespace GTM
diff --git a/libitm/config/x86/cacheline.cc b/libitm/config/x86/cacheline.cc
deleted file mode 100644
index 2e49a355953..00000000000
--- a/libitm/config/x86/cacheline.cc
+++ /dev/null
@@ -1,73 +0,0 @@
-/* Copyright (C) 2009, 2011 Free Software Foundation, Inc.
- Contributed by Richard Henderson <rth@redhat.com>.
-
- This file is part of the GNU Transactional Memory Library (libitm).
-
- Libitm 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.
-
- Libitm 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 "libitm_i.h"
-
-namespace GTM HIDDEN {
-
-uint32_t const gtm_bit_to_byte_mask[16] =
-{
- 0x00000000,
- 0x000000ff,
- 0x0000ff00,
- 0x0000ffff,
- 0x00ff0000,
- 0x00ff00ff,
- 0x00ffff00,
- 0x00ffffff,
- 0xff000000,
- 0xff0000ff,
- 0xff00ff00,
- 0xff00ffff,
- 0xffff0000,
- 0xffff00ff,
- 0xffffff00,
- 0xffffffff
-};
-
-#ifdef __SSE2__
-# define MEMBER m128i
-#else
-# define MEMBER w
-#endif
-
-void
-gtm_cacheline::copy_mask (gtm_cacheline * __restrict d,
- const gtm_cacheline * __restrict s,
- gtm_cacheline_mask m)
-{
- if (m == (gtm_cacheline_mask)-1)
- {
- *d = *s;
- return;
- }
- if (__builtin_expect (m == 0, 0))
- return;
-
- size_t n = sizeof(d->MEMBER[0]);
- for (size_t i = 0; i < CACHELINE_SIZE / n; ++i, m >>= n)
- store_mask (&d->MEMBER[i], s->MEMBER[i], m);
-}
-
-} // namespace GTM
diff --git a/libitm/config/x86/cacheline.h b/libitm/config/x86/cacheline.h
index 15a95b0be5b..337c9995c17 100644
--- a/libitm/config/x86/cacheline.h
+++ b/libitm/config/x86/cacheline.h
@@ -40,8 +40,6 @@ namespace GTM HIDDEN {
// in the cacheline with which it is associated.
typedef sized_integral<CACHELINE_SIZE / 8>::type gtm_cacheline_mask;
-extern uint32_t const gtm_bit_to_byte_mask[16];
-
union gtm_cacheline
{
// Byte access to the cacheline.
@@ -67,23 +65,6 @@ union gtm_cacheline
__m256i m256i[CACHELINE_SIZE / sizeof(__m256i)];
#endif
- // Store S into D, but only the bytes specified by M.
- static void store_mask (uint32_t *d, uint32_t s, uint8_t m);
- static void store_mask (uint64_t *d, uint64_t s, uint8_t m);
-#ifdef __SSE2__
- static void store_mask (__m128i *d, __m128i s, uint16_t m);
-#endif
-
- // Copy S to D, but only the bytes specified by M.
- static void copy_mask (gtm_cacheline * __restrict d,
- const gtm_cacheline * __restrict s,
- gtm_cacheline_mask m);
-
- // A write barrier to emit after (a series of) copy_mask.
- // When we're emitting non-temporal stores, the normal strong
- // ordering of the machine doesn't apply.
- static void copy_mask_wb ();
-
#if defined(__SSE__) || defined(__AVX__)
// Copy S to D; only bother defining if we can do this more efficiently
// than the compiler-generated default implementation.
@@ -91,14 +72,6 @@ union gtm_cacheline
#endif // SSE, AVX
};
-inline void
-gtm_cacheline::copy_mask_wb ()
-{
-#ifdef __SSE2__
- _mm_sfence ();
-#endif
-}
-
#if defined(__SSE__) || defined(__AVX__)
inline gtm_cacheline& ALWAYS_INLINE
gtm_cacheline::operator= (const gtm_cacheline & __restrict s)
@@ -141,101 +114,11 @@ gtm_cacheline::operator= (const gtm_cacheline & __restrict s)
}
return *this;
-}
-#endif
-// ??? Support masked integer stores more efficiently with an unlocked cmpxchg
-// insn. My reasoning is that while we write to locations that we do not wish
-// to modify, we do it in an uninterruptable insn, and so we either truely
-// write back the original data or the insn fails -- unlike with a
-// load/and/or/write sequence which can be interrupted either by a kernel
-// task switch or an unlucky cacheline steal by another processor. Avoiding
-// the LOCK prefix improves performance by a factor of 10, and we don't need
-// the memory barrier semantics implied by that prefix.
-
-inline void ALWAYS_INLINE
-gtm_cacheline::store_mask (uint32_t *d, uint32_t s, uint8_t m)
-{
- gtm_cacheline_mask tm = (1 << sizeof (s)) - 1;
- if (__builtin_expect (m & tm, tm))
- {
- if (__builtin_expect ((m & tm) == tm, 1))
- *d = s;
- else
- {
- gtm_cacheline_mask bm = gtm_bit_to_byte_mask[m & 15];
- gtm_word n, o = *d;
-
- __asm("\n0:\t"
- "mov %[o], %[n]\n\t"
- "and %[m], %[n]\n\t"
- "or %[s], %[n]\n\t"
- "cmpxchg %[n], %[d]\n\t"
- "jnz,pn 0b"
- : [d] "+m"(*d), [n] "=&r" (n), [o] "+a"(o)
- : [s] "r" (s & bm), [m] "r" (~bm));
- }
- }
+#undef CP
+#undef TYPE
}
-
-inline void ALWAYS_INLINE
-gtm_cacheline::store_mask (uint64_t *d, uint64_t s, uint8_t m)
-{
- gtm_cacheline_mask tm = (1 << sizeof (s)) - 1;
- if (__builtin_expect (m & tm, tm))
- {
- if (__builtin_expect ((m & tm) == tm, 1))
- *d = s;
- else
- {
-#ifdef __x86_64__
- uint32_t bl = gtm_bit_to_byte_mask[m & 15];
- uint32_t bh = gtm_bit_to_byte_mask[(m >> 4) & 15];
- gtm_cacheline_mask bm = bl | ((gtm_cacheline_mask)bh << 31 << 1);
- uint64_t n, o = *d;
- __asm("\n0:\t"
- "mov %[o], %[n]\n\t"
- "and %[m], %[n]\n\t"
- "or %[s], %[n]\n\t"
- "cmpxchg %[n], %[d]\n\t"
- "jnz,pn 0b"
- : [d] "+m"(*d), [n] "=&r" (n), [o] "+a"(o)
- : [s] "r" (s & bm), [m] "r" (~bm));
-#else
- /* ??? While it's possible to perform this operation with
- cmpxchg8b, the sequence requires all 7 general registers
- and thus cannot be performed with -fPIC. Don't even try. */
- uint32_t *d32 = reinterpret_cast<uint32_t *>(d);
- store_mask (d32, s, m);
- store_mask (d32 + 1, s >> 32, m >> 4);
#endif
- }
- }
-}
-
-#ifdef __SSE2__
-inline void ALWAYS_INLINE
-gtm_cacheline::store_mask (__m128i *d, __m128i s, uint16_t m)
-{
- if (__builtin_expect (m == 0, 0))
- return;
- if (__builtin_expect (m == 0xffff, 1))
- *d = s;
- else
- {
- __m128i bm0, bm1, bm2, bm3;
- bm0 = _mm_set_epi32 (0, 0, 0, gtm_bit_to_byte_mask[m & 15]); m >>= 4;
- bm1 = _mm_set_epi32 (0, 0, 0, gtm_bit_to_byte_mask[m & 15]); m >>= 4;
- bm2 = _mm_set_epi32 (0, 0, 0, gtm_bit_to_byte_mask[m & 15]); m >>= 4;
- bm3 = _mm_set_epi32 (0, 0, 0, gtm_bit_to_byte_mask[m & 15]); m >>= 4;
- bm0 = _mm_unpacklo_epi32 (bm0, bm1);
- bm2 = _mm_unpacklo_epi32 (bm2, bm3);
- bm0 = _mm_unpacklo_epi64 (bm0, bm2);
-
- _mm_maskmoveu_si128 (s, bm0, (char *)d);
- }
-}
-#endif // SSE2
} // namespace GTM
diff --git a/libitm/config/x86/sjlj.S b/libitm/config/x86/sjlj.S
index 616949904b0..32572d9db60 100644
--- a/libitm/config/x86/sjlj.S
+++ b/libitm/config/x86/sjlj.S
@@ -26,9 +26,9 @@
#include "asmcfi.h"
.text
- .p2align 4
+
+ .align 4
.globl _ITM_beginTransaction
- .type _ITM_beginTransaction, @function
_ITM_beginTransaction:
cfi_startproc
@@ -66,12 +66,14 @@ _ITM_beginTransaction:
ret
#endif
cfi_endproc
+
+#ifdef __ELF__
+ .type _ITM_beginTransaction, @function
.size _ITM_beginTransaction, .-_ITM_beginTransaction
+#endif
- .p2align 4
+ .align 4
.globl GTM_longjmp
- .type GTM_longjmp, @function
- .hidden GTM_longjmp
GTM_longjmp:
cfi_startproc
@@ -103,6 +105,13 @@ GTM_longjmp:
jmp *%edx
#endif
cfi_endproc
+
+#ifdef __ELF__
+ .type GTM_longjmp, @function
+ .hidden GTM_longjmp
.size GTM_longjmp, .-GTM_longjmp
+#endif
+#ifdef __linux__
.section .note.GNU-stack, "", @progbits
+#endif
diff --git a/libitm/config/x86/unaligned.h b/libitm/config/x86/unaligned.h
deleted file mode 100644
index 01abc47dccb..00000000000
--- a/libitm/config/x86/unaligned.h
+++ /dev/null
@@ -1,237 +0,0 @@
-/* Copyright (C) 2009, 2011 Free Software Foundation, Inc.
- Contributed by Richard Henderson <rth@redhat.com>.
-
- This file is part of the GNU Transactional Memory Library (libitm).
-
- Libitm 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.
-
- Libitm 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 LIBITM_X86_UNALIGNED_H
-#define LIBITM_X86_UNALIGNED_H 1
-
-#define HAVE_ARCH_UNALIGNED_LOAD2_U4 1
-#define HAVE_ARCH_UNALIGNED_LOAD2_U8 1
-
-#include "config/generic/unaligned.h"
-
-namespace GTM HIDDEN {
-
-template<>
-inline uint32_t
-unaligned_load2<uint32_t>(const gtm_cacheline *c1,
- const gtm_cacheline *c2, size_t ofs)
-{
- uint32_t r, lo, hi;
- lo = c1->u32[CACHELINE_SIZE / sizeof(uint32_t) - 1];
- hi = c2->u32[0];
- asm("shrd %b2, %1, %0" : "=r"(r) : "r"(hi), "c"((ofs & 3) * 8), "0"(lo));
- return r;
-}
-
-template<>
-inline uint64_t
-unaligned_load2<uint64_t>(const gtm_cacheline *c1,
- const gtm_cacheline *c2, size_t ofs)
-{
-#ifdef __x86_64__
- uint64_t r, lo, hi;
- lo = c1->u64[CACHELINE_SIZE / sizeof(uint64_t) - 1];
- hi = c2->u64[0];
- asm("shrd %b2, %1, %0" : "=r"(r) : "r"(hi), "c"((ofs & 3) * 8), "0"(lo));
- return r;
-#else
- uint32_t v0, v1, v2;
- uint64_t r;
-
- if (ofs < CACHELINE_SIZE - 4)
- {
- v0 = c1->u32[CACHELINE_SIZE / sizeof(uint32_t) - 2];
- v1 = c1->u32[CACHELINE_SIZE / sizeof(uint32_t) - 1];
- v2 = c2->u32[0];
- }
- else
- {
- v0 = c1->u32[CACHELINE_SIZE / sizeof(uint32_t) - 1];
- v1 = c2->u32[0];
- v2 = c2->u32[1];
- }
- ofs = (ofs & 3) * 8;
- asm("shrd %%cl, %[v1], %[v0]; shrd %%cl, %[v2], %[v1]"
- : "=A"(r) : "c"(ofs), [v0] "a"(v0), [v1] "d"(v1), [v2] "r"(v2));
-
- return r;
-#endif
-}
-
-#if defined(__SSE2__) || defined(__MMX__)
-template<>
-inline _ITM_TYPE_M64
-unaligned_load2<_ITM_TYPE_M64>(const gtm_cacheline *c1,
- const gtm_cacheline *c2, size_t ofs)
-{
-# ifdef __x86_64__
- __m128i lo = _mm_movpi64_epi64 (c1->m64[CACHELINE_SIZE / 8 - 1]);
- __m128i hi = _mm_movpi64_epi64 (c2->m64[0]);
-
- ofs = (ofs & 7) * 8;
- lo = _mm_srli_epi64 (lo, ofs);
- hi = _mm_slli_epi64 (hi, 64 - ofs);
- lo = lo | hi;
- return _mm_movepi64_pi64 (lo);
-# else
- // On 32-bit we're about to return the result in an MMX register, so go
- // ahead and do the computation in that unit, even if SSE2 is available.
- __m64 lo = c1->m64[CACHELINE_SIZE / 8 - 1];
- __m64 hi = c2->m64[0];
-
- ofs = (ofs & 7) * 8;
- lo = _mm_srli_si64 (lo, ofs);
- hi = _mm_slli_si64 (hi, 64 - ofs);
- return lo | hi;
-# endif
-}
-#endif // SSE2 or MMX
-
-// The SSE types are strictly aligned.
-#ifdef __SSE__
-template<>
- struct strict_alignment<_ITM_TYPE_M128>
- : public std::true_type
- { };
-
-// Expand the unaligned SSE move instructions.
-template<>
-inline _ITM_TYPE_M128
-unaligned_load<_ITM_TYPE_M128>(const void *t)
-{
- return _mm_loadu_ps (static_cast<const float *>(t));
-}
-
-template<>
-inline void
-unaligned_store<_ITM_TYPE_M128>(void *t, _ITM_TYPE_M128 val)
-{
- _mm_storeu_ps (static_cast<float *>(t), val);
-}
-#endif // SSE
-
-#ifdef __AVX__
-// The AVX types are strictly aligned when it comes to vmovaps vs vmovups.
-template<>
- struct strict_alignment<_ITM_TYPE_M256>
- : public std::true_type
- { };
-
-template<>
-inline _ITM_TYPE_M256
-unaligned_load<_ITM_TYPE_M256>(const void *t)
-{
- return _mm256_loadu_ps (static_cast<const float *>(t));
-}
-
-template<>
-inline void
-unaligned_store<_ITM_TYPE_M256>(void *t, _ITM_TYPE_M256 val)
-{
- _mm256_storeu_ps (static_cast<float *>(t), val);
-}
-#endif // AVX
-
-#ifdef __XOP__
-# define HAVE_ARCH_REALIGN_M128I 1
-extern const __v16qi GTM_vpperm_shift[16];
-inline __m128i
-realign_m128i (__m128i lo, __m128i hi, unsigned byte_count)
-{
- return _mm_perm_epi8 (lo, hi, GTM_vpperm_shift[byte_count]);
-}
-#elif defined(__AVX__)
-# define HAVE_ARCH_REALIGN_M128I 1
-extern "C" const uint64_t GTM_vpalignr_table[16];
-inline __m128i
-realign_m128i (__m128i lo, __m128i hi, unsigned byte_count)
-{
- register __m128i xmm0 __asm__("xmm0") = hi;
- register __m128i xmm1 __asm__("xmm1") = lo;
- __asm("call *%2" : "+x"(xmm0) : "x"(xmm1),
- "r"(&GTM_vpalignr_table[byte_count]));
- return xmm0;
-}
-#elif defined(__SSSE3__)
-# define HAVE_ARCH_REALIGN_M128I 1
-extern "C" const uint64_t GTM_palignr_table[16];
-inline __m128i
-realign_m128i (__m128i lo, __m128i hi, unsigned byte_count)
-{
- register __m128i xmm0 __asm__("xmm0") = hi;
- register __m128i xmm1 __asm__("xmm1") = lo;
- __asm("call *%2" : "+x"(xmm0) : "x"(xmm1),
- "r"(&GTM_palignr_table[byte_count]));
- return xmm0;
-}
-#elif defined(__SSE2__)
-# define HAVE_ARCH_REALIGN_M128I 1
-extern "C" const char GTM_pshift_table[16 * 16];
-inline __m128i
-realign_m128i (__m128i lo, __m128i hi, unsigned byte_count)
-{
- register __m128i xmm0 __asm__("xmm0") = lo;
- register __m128i xmm1 __asm__("xmm1") = hi;
- __asm("call *%2" : "+x"(xmm0), "+x"(xmm1)
- : "r"(GTM_pshift_table + byte_count*16));
- return xmm0;
-}
-#endif // XOP, AVX, SSSE3, SSE2
-
-#ifdef HAVE_ARCH_REALIGN_M128I
-template<>
-inline _ITM_TYPE_M128
-unaligned_load2<_ITM_TYPE_M128>(const gtm_cacheline *c1,
- const gtm_cacheline *c2, size_t ofs)
-{
- return (_ITM_TYPE_M128)
- realign_m128i (c1->m128i[CACHELINE_SIZE / 16 - 1],
- c2->m128i[0], ofs & 15);
-}
-#endif // HAVE_ARCH_REALIGN_M128I
-
-#ifdef __AVX__
-template<>
-inline _ITM_TYPE_M256
-unaligned_load2<_ITM_TYPE_M256>(const gtm_cacheline *c1,
- const gtm_cacheline *c2, size_t ofs)
-{
- __m128i v0, v1;
- __m256i r;
-
- v0 = (__m128i) unaligned_load2<_ITM_TYPE_M128>(c1, c2, ofs);
- if (ofs < CACHELINE_SIZE - 16)
- v1 = v0, v0 = _mm_loadu_si128 ((const __m128i *) &c1->b[ofs]);
- else
- v1 = _mm_loadu_si128((const __m128i *)&c2->b[ofs + 16 - CACHELINE_SIZE]);
-
- r = _mm256_castsi128_si256 ((__m128i)v0);
- r = _mm256_insertf128_si256 (r, (__m128i)v1, 1);
- return (_ITM_TYPE_M256) r;
-}
-#endif // AVX
-
-} // namespace GTM
-
-#endif // LIBITM_X86_UNALIGNED_H
diff --git a/libitm/config/x86/x86_avx.cc b/libitm/config/x86/x86_avx.cc
index 9d1ddfb3ee8..6a5e297116b 100644
--- a/libitm/config/x86/x86_avx.cc
+++ b/libitm/config/x86/x86_avx.cc
@@ -22,9 +22,62 @@
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
+#include "config.h"
+
#include "libitm_i.h"
#include "dispatch.h"
+extern "C" {
+
+#ifndef HAVE_AS_AVX
+// If we don't have an AVX capable assembler, we didn't set -mavx on the
+// command-line either, which means that libitm.h defined neither this type
+// nor the functions in this file. Define the type and unconditionally
+// wrap the file in extern "C" to make up for the lack of pre-declaration.
+typedef float _ITM_TYPE_M256 __attribute__((vector_size(32), may_alias));
+#endif
+
+// Re-define the memcpy implementations so that we can frob the
+// interface to deal with possibly missing AVX instruction set support.
+
+#ifdef HAVE_AS_AVX
+#define RETURN(X) return X
+#define STORE(X,Y) X = Y
+#define OUTPUT(T) _ITM_TYPE_##T
+#define INPUT(T,X) , _ITM_TYPE_##T X
+#else
+/* Emit vmovaps (%rax),%ymm0. */
+#define RETURN(X) \
+ asm volatile(".byte 0xc5,0xfc,0x28,0x00" : "=m"(X) : "a"(&X))
+/* Emit vmovaps %ymm0,(%rax); vzeroupper. */
+#define STORE(X,Y) \
+ asm volatile(".byte 0xc5,0xfc,0x29,0x00,0xc5,0xf8,0x77" : "=m"(X) : "a"(&X))
+#define OUTPUT(T) void
+#define INPUT(T,X)
+#endif
+
+#undef ITM_READ_MEMCPY
+#define ITM_READ_MEMCPY(T, LSMOD, TARGET, M2) \
+OUTPUT(T) ITM_REGPARM _ITM_##LSMOD##T (const _ITM_TYPE_##T *ptr) \
+{ \
+ _ITM_TYPE_##T v; \
+ TARGET memtransfer##M2(&v, ptr, sizeof(_ITM_TYPE_##T), false, \
+ GTM::abi_dispatch::NONTXNAL, \
+ GTM::abi_dispatch::LSMOD); \
+ RETURN(v); \
+}
+
+#undef ITM_WRITE_MEMCPY
+#define ITM_WRITE_MEMCPY(T, LSMOD, TARGET, M2) \
+void ITM_REGPARM _ITM_##LSMOD##T (_ITM_TYPE_##T *ptr INPUT(T,in)) \
+{ \
+ _ITM_TYPE_##T v; \
+ STORE(v, in); \
+ TARGET memtransfer##M2(ptr, &v, sizeof(_ITM_TYPE_##T), false, \
+ GTM::abi_dispatch::LSMOD, \
+ GTM::abi_dispatch::NONTXNAL); \
+}
+
// ??? Use memcpy for now, until we have figured out how to best instantiate
// these loads/stores.
CREATE_DISPATCH_FUNCTIONS_T_MEMCPY(M256, GTM::abi_disp()->, )
@@ -35,61 +88,4 @@ _ITM_LM256 (const _ITM_TYPE_M256 *ptr)
GTM::GTM_LB (ptr, sizeof (*ptr));
}
-// Helpers for re-aligning two 128-bit values.
-#ifdef __XOP__
-const __v16qi GTM::GTM_vpperm_shift[16] =
-{
- { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
- { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 },
- { 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 },
- { 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18 },
- { 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 },
- { 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 },
- { 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21 },
- { 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22 },
- { 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23 },
- { 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 },
- { 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 },
- { 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 },
- { 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27 },
- { 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28 },
- { 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29 },
- { 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 },
-};
-#else
-# define INSN0 "movdqa %xmm1, %xmm0"
-# define INSN(N) "vpalignr $" #N ", %xmm0, %xmm1, %xmm0"
-# define TABLE_ENT_0 INSN0 "\n\tret\n\t"
-# define TABLE_ENT(N) ".balign 8\n\t" INSN(N) "\n\tret\n\t"
-
-asm(".pushsection .text\n\
- .balign 16\n\
- .globl GTM_vpalignr_table\n\
- .hidden GTM_vpalignr_table\n\
- .type GTM_vpalignr_table, @function\n\
-GTM_vpalignr_table:\n\t"
- TABLE_ENT_0
- TABLE_ENT(1)
- TABLE_ENT(2)
- TABLE_ENT(3)
- TABLE_ENT(4)
- TABLE_ENT(5)
- TABLE_ENT(6)
- TABLE_ENT(7)
- TABLE_ENT(8)
- TABLE_ENT(9)
- TABLE_ENT(10)
- TABLE_ENT(11)
- TABLE_ENT(12)
- TABLE_ENT(13)
- TABLE_ENT(14)
- TABLE_ENT(15)
- ".balign 8\n\
- .size GTM_vpalignr_table, .-GTM_vpalignr_table\n\
- .popsection");
-
-# undef INSN0
-# undef INSN
-# undef TABLE_ENT_0
-# undef TABLE_ENT
-#endif
+} // extern "C"
diff --git a/libitm/config/x86/x86_sse.cc b/libitm/config/x86/x86_sse.cc
index 7440c949cb7..5a1c67ac8b1 100644
--- a/libitm/config/x86/x86_sse.cc
+++ b/libitm/config/x86/x86_sse.cc
@@ -41,82 +41,3 @@ _ITM_LM128 (const _ITM_TYPE_M128 *ptr)
{
GTM::GTM_LB (ptr, sizeof (*ptr));
}
-
-// Helpers for re-aligning two 128-bit values.
-#ifdef __SSSE3__
-# define INSN0 "movdqa %xmm1, %xmm0"
-# define INSN(N) "palignr $" #N ", %xmm1, %xmm0"
-# define TABLE_ENT_0 INSN0 "\n\tret\n\t"
-# define TABLE_ENT(N) ".balign 8\n\t" INSN(N) "\n\tret\n\t"
-
-asm(".pushsection .text\n\
- .balign 16\n\
- .globl GTM_palignr_table\n\
- .hidden GTM_palignr_table\n\
- .type GTM_palignr_table, @function\n\
-GTM_palignr_table:\n\t"
- TABLE_ENT_0
- TABLE_ENT(1)
- TABLE_ENT(2)
- TABLE_ENT(3)
- TABLE_ENT(4)
- TABLE_ENT(5)
- TABLE_ENT(6)
- TABLE_ENT(7)
- TABLE_ENT(8)
- TABLE_ENT(9)
- TABLE_ENT(10)
- TABLE_ENT(11)
- TABLE_ENT(12)
- TABLE_ENT(13)
- TABLE_ENT(14)
- TABLE_ENT(15)
- ".balign 8\n\
- .size GTM_palignr_table, .-GTM_palignr_table\n\
- .popsection");
-
-# undef INSN0
-# undef INSN
-# undef TABLE_ENT_0
-# undef TABLE_ENT
-#elif defined(__SSE2__)
-# define INSNS_8 "punpcklqdq %xmm1, %xmm0"
-# define INSNS(N) "psrldq $"#N", %xmm0\n\t" \
- "pslldq $(16-"#N"), %xmm1\n\t" \
- "por %xmm1, %xmm0"
-# define TABLE_ENT_0 "ret\n\t"
-# define TABLE_ENT_8 ".balign 16\n\t" INSNS_8 "\n\tret\n\t"
-# define TABLE_ENT(N) ".balign 16\n\t" INSNS(N) "\n\tret\n\t"
-
-asm(".pushsection .text\n\
- .balign 16\n\
- .globl GTM_pshift_table\n\
- .hidden GTM_pshift_table\n\
- .type GTM_pshift_table, @function\n\
-GTM_pshift_table:\n\t"
- TABLE_ENT_0
- TABLE_ENT(1)
- TABLE_ENT(2)
- TABLE_ENT(3)
- TABLE_ENT(4)
- TABLE_ENT(5)
- TABLE_ENT(6)
- TABLE_ENT(7)
- TABLE_ENT_8
- TABLE_ENT(9)
- TABLE_ENT(10)
- TABLE_ENT(11)
- TABLE_ENT(12)
- TABLE_ENT(13)
- TABLE_ENT(14)
- TABLE_ENT(15)
- ".balign 8\n\
- .size GTM_pshift_table, .-GTM_pshift_table\n\
- .popsection");
-
-# undef INSNS_8
-# undef INSNS
-# undef TABLE_ENT_0
-# undef TABLE_ENT_8
-# undef TABLE_ENT
-#endif
diff --git a/libitm/configure b/libitm/configure
index 0f0ec1fc77a..c0317ccfc4d 100644
--- a/libitm/configure
+++ b/libitm/configure
@@ -603,6 +603,8 @@ LTLIBOBJS
LIBOBJS
ARCH_FUTEX_FALSE
ARCH_FUTEX_TRUE
+ARCH_X86_AVX_FALSE
+ARCH_X86_AVX_TRUE
ARCH_X86_FALSE
ARCH_X86_TRUE
link_itm
@@ -11714,7 +11716,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11717 "configure"
+#line 11719 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -11820,7 +11822,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11823 "configure"
+#line 11825 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -17115,6 +17117,43 @@ $as_echo "#define HAVE_64BIT_SYNC_BUILTINS 1" >>confdefs.h
fi
+case "${target_cpu}" in
+i345686 | x86_64)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the assembler supports AVX" >&5
+$as_echo_n "checking if the assembler supports AVX... " >&6; }
+if test "${libitm_cv_as_avx+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+asm("vzeroupper");
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ libitm_cv_as_avx=yes
+else
+ libitm_cv_as_avx=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libitm_cv_as_avx" >&5
+$as_echo "$libitm_cv_as_avx" >&6; }
+ if test x$libitm_cv_as_avx = xyes; then
+
+$as_echo "#define HAVE_AS_AVX 1" >>confdefs.h
+
+ fi
+ ;;
+esac
+
# Cleanup and exit.
CFLAGS="$save_CFLAGS"
cat >confcache <<\_ACEOF
@@ -17228,6 +17267,14 @@ else
ARCH_X86_FALSE=
fi
+ if test "$libitm_cv_as_avx" = yes; then
+ ARCH_X86_AVX_TRUE=
+ ARCH_X86_AVX_FALSE='#'
+else
+ ARCH_X86_AVX_TRUE='#'
+ ARCH_X86_AVX_FALSE=
+fi
+
if test $enable_linux_futex = yes; then
ARCH_FUTEX_TRUE=
ARCH_FUTEX_FALSE='#'
@@ -17381,6 +17428,10 @@ if test -z "${ARCH_X86_TRUE}" && test -z "${ARCH_X86_FALSE}"; then
as_fn_error "conditional \"ARCH_X86\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
+if test -z "${ARCH_X86_AVX_TRUE}" && test -z "${ARCH_X86_AVX_FALSE}"; then
+ as_fn_error "conditional \"ARCH_X86_AVX\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
if test -z "${ARCH_FUTEX_TRUE}" && test -z "${ARCH_FUTEX_FALSE}"; then
as_fn_error "conditional \"ARCH_FUTEX\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
diff --git a/libitm/configure.ac b/libitm/configure.ac
index c40ecb5bf3c..672b71279e3 100644
--- a/libitm/configure.ac
+++ b/libitm/configure.ac
@@ -237,6 +237,7 @@ CFLAGS="$save_CFLAGS $XCFLAGS"
# had a chance to set XCFLAGS.
LIBITM_CHECK_SYNC_BUILTINS
LIBITM_CHECK_64BIT_SYNC_BUILTINS
+LIBITM_CHECK_AS_AVX
# Cleanup and exit.
CFLAGS="$save_CFLAGS"
@@ -271,6 +272,7 @@ fi
AC_SUBST(link_itm)
AM_CONDITIONAL([ARCH_X86], [test "$ARCH" = x86])
+AM_CONDITIONAL([ARCH_X86_AVX], [test "$libitm_cv_as_avx" = yes])
AM_CONDITIONAL([ARCH_FUTEX], [test $enable_linux_futex = yes])
AC_CONFIG_FILES(Makefile testsuite/Makefile libitm.spec)
diff --git a/libitm/libitm_i.h b/libitm/libitm_i.h
index c188fa5f43f..58e43b01281 100644
--- a/libitm/libitm_i.h
+++ b/libitm/libitm_i.h
@@ -78,7 +78,6 @@ enum gtm_restart_reason
#include "rwlock.h"
#include "aatree.h"
#include "cacheline.h"
-#include "cachepage.h"
#include "stmlock.h"
#include "dispatch.h"
#include "containers.h"
diff --git a/libitm/memcpy.cc b/libitm/memcpy.cc
deleted file mode 100644
index 9919e6a9afa..00000000000
--- a/libitm/memcpy.cc
+++ /dev/null
@@ -1,365 +0,0 @@
-/* Copyright (C) 2008, 2009, 2011 Free Software Foundation, Inc.
- Contributed by Richard Henderson <rth@redhat.com>.
-
- This file is part of the GNU Transactional Memory Library (libitm).
-
- Libitm 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.
-
- Libitm 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 "libitm_i.h"
-
-using namespace GTM;
-
-static void
-do_memcpy (uintptr_t idst, uintptr_t isrc, size_t size,
- abi_dispatch::lock_type W, abi_dispatch::lock_type R)
-{
- abi_dispatch *disp = abi_disp();
- // The position in the destination cacheline where *IDST starts.
- uintptr_t dofs = idst & (CACHELINE_SIZE - 1);
- // The position in the source cacheline where *ISRC starts.
- uintptr_t sofs = isrc & (CACHELINE_SIZE - 1);
- const gtm_cacheline *src
- = reinterpret_cast<const gtm_cacheline *>(isrc & -CACHELINE_SIZE);
- gtm_cacheline *dst
- = reinterpret_cast<gtm_cacheline *>(idst & -CACHELINE_SIZE);
- const gtm_cacheline *sline;
- abi_dispatch::mask_pair dpair;
-
- if (size == 0)
- return;
-
- // If both SRC and DST data start at the same position in the cachelines,
- // we can easily copy the data in tandem, cacheline by cacheline...
- if (dofs == sofs)
- {
- // We copy the data in three stages:
-
- // (a) Copy stray bytes at the beginning that are smaller than a
- // cacheline.
- if (sofs != 0)
- {
- size_t sleft = CACHELINE_SIZE - sofs;
- size_t min = (size <= sleft ? size : sleft);
-
- dpair = disp->write_lock(dst, W);
- sline = disp->read_lock(src, R);
- *dpair.mask |= (((gtm_cacheline_mask)1 << min) - 1) << sofs;
- memcpy (&dpair.line->b[sofs], &sline->b[sofs], min);
- dst++;
- src++;
- size -= min;
- }
-
- // (b) Copy subsequent cacheline sized chunks.
- while (size >= CACHELINE_SIZE)
- {
- dpair = disp->write_lock(dst, W);
- sline = disp->read_lock(src, R);
- *dpair.mask = -1;
- *dpair.line = *sline;
- dst++;
- src++;
- size -= CACHELINE_SIZE;
- }
-
- // (c) Copy anything left over.
- if (size != 0)
- {
- dpair = disp->write_lock(dst, W);
- sline = disp->read_lock(src, R);
- *dpair.mask |= ((gtm_cacheline_mask)1 << size) - 1;
- memcpy (dpair.line, sline, size);
- }
- }
- // ... otherwise, we must copy the data in disparate hunks using
- // temporary storage.
- else
- {
- gtm_cacheline c;
- size_t sleft = CACHELINE_SIZE - sofs;
-
- sline = disp->read_lock(src, R);
-
- // As above, we copy the data in three stages:
-
- // (a) Copy stray bytes at the beginning that are smaller than a
- // cacheline.
- if (dofs != 0)
- {
- size_t dleft = CACHELINE_SIZE - dofs;
- size_t min = (size <= dleft ? size : dleft);
-
- dpair = disp->write_lock(dst, W);
- *dpair.mask |= (((gtm_cacheline_mask)1 << min) - 1) << dofs;
-
- // If what's left in the source cacheline will fit in the
- // rest of the destination cacheline, straight up copy it.
- if (min <= sleft)
- {
- memcpy (&dpair.line->b[dofs], &sline->b[sofs], min);
- sofs += min;
- }
- // Otherwise, we need more bits from the source cacheline
- // that are available. Piece together what we need from
- // contiguous (source) cachelines, into temp space, and copy
- // it over.
- else
- {
- memcpy (&c, &sline->b[sofs], sleft);
- sline = disp->read_lock(++src, R);
- sofs = min - sleft;
- memcpy (&c.b[sleft], sline, sofs);
- memcpy (&dpair.line->b[dofs], &c, min);
- }
- sleft = CACHELINE_SIZE - sofs;
-
- dst++;
- size -= min;
- }
-
- // (b) Copy subsequent cacheline sized chunks.
- while (size >= CACHELINE_SIZE)
- {
- // We have a full (destination) cacheline where to put the
- // data, but to get to the corresponding cacheline sized
- // chunk in the source, we have to piece together two
- // contiguous source cachelines.
-
- memcpy (&c, &sline->b[sofs], sleft);
- sline = disp->read_lock(++src, R);
- memcpy (&c.b[sleft], sline, sofs);
-
- dpair = disp->write_lock(dst, W);
- *dpair.mask = -1;
- *dpair.line = c;
-
- dst++;
- size -= CACHELINE_SIZE;
- }
-
- // (c) Copy anything left over.
- if (size != 0)
- {
- dpair = disp->write_lock(dst, W);
- *dpair.mask |= ((gtm_cacheline_mask)1 << size) - 1;
- // If what's left to copy is entirely in the remaining
- // source cacheline, do it.
- if (size <= sleft)
- memcpy (dpair.line, &sline->b[sofs], size);
- // Otherwise, piece together the remaining bits, and copy.
- else
- {
- memcpy (&c, &sline->b[sofs], sleft);
- sline = disp->read_lock(++src, R);
- memcpy (&c.b[sleft], sline, size - sleft);
- memcpy (dpair.line, &c, size);
- }
- }
- }
-}
-
-static void
-do_memmove (uintptr_t idst, uintptr_t isrc, size_t size,
- abi_dispatch::lock_type W, abi_dispatch::lock_type R)
-{
- abi_dispatch *disp = abi_disp();
- uintptr_t dleft, sleft, sofs, dofs;
- const gtm_cacheline *sline;
- abi_dispatch::mask_pair dpair;
-
- if (size == 0)
- return;
-
- /* The co-aligned memmove below doesn't work for DST == SRC, so filter
- that out. It's tempting to just return here, as this is a no-op move.
- However, our caller has the right to expect the locks to be acquired
- as advertized. */
- if (__builtin_expect (idst == isrc, 0))
- {
- /* If the write lock is already acquired, nothing to do. */
- if (W == abi_dispatch::WaW)
- return;
- /* If the destination is protected, acquire a write lock. */
- if (W != abi_dispatch::NOLOCK)
- R = abi_dispatch::RfW;
- /* Notice serial mode, where we don't acquire locks at all. */
- if (R == abi_dispatch::NOLOCK)
- return;
-
- idst = isrc + size;
- for (isrc &= -CACHELINE_SIZE; isrc < idst; isrc += CACHELINE_SIZE)
- disp->read_lock(reinterpret_cast<const gtm_cacheline *>(isrc), R);
- return;
- }
-
- /* Fall back to memcpy if the implementation above can handle it. */
- if (idst < isrc || isrc + size <= idst)
- {
- do_memcpy (idst, isrc, size, W, R);
- return;
- }
-
- /* What remains requires a backward copy from the end of the blocks. */
- idst += size;
- isrc += size;
- dofs = idst & (CACHELINE_SIZE - 1);
- sofs = isrc & (CACHELINE_SIZE - 1);
- dleft = CACHELINE_SIZE - dofs;
- sleft = CACHELINE_SIZE - sofs;
-
- gtm_cacheline *dst
- = reinterpret_cast<gtm_cacheline *>(idst & -CACHELINE_SIZE);
- const gtm_cacheline *src
- = reinterpret_cast<const gtm_cacheline *>(isrc & -CACHELINE_SIZE);
- if (dofs == 0)
- dst--;
- if (sofs == 0)
- src--;
-
- if (dofs == sofs)
- {
- /* Since DST and SRC are co-aligned, and we didn't use the memcpy
- optimization above, that implies that SIZE > CACHELINE_SIZE. */
- if (sofs != 0)
- {
- dpair = disp->write_lock(dst, W);
- sline = disp->read_lock(src, R);
- *dpair.mask |= ((gtm_cacheline_mask)1 << sleft) - 1;
- memcpy (dpair.line, sline, sleft);
- dst--;
- src--;
- size -= sleft;
- }
-
- while (size >= CACHELINE_SIZE)
- {
- dpair = disp->write_lock(dst, W);
- sline = disp->read_lock(src, R);
- *dpair.mask = -1;
- *dpair.line = *sline;
- dst--;
- src--;
- size -= CACHELINE_SIZE;
- }
-
- if (size != 0)
- {
- size_t ofs = CACHELINE_SIZE - size;
- dpair = disp->write_lock(dst, W);
- sline = disp->read_lock(src, R);
- *dpair.mask |= (((gtm_cacheline_mask)1 << size) - 1) << ofs;
- memcpy (&dpair.line->b[ofs], &sline->b[ofs], size);
- }
- }
- else
- {
- gtm_cacheline c;
-
- sline = disp->read_lock(src, R);
- if (dofs != 0)
- {
- size_t min = (size <= dofs ? size : dofs);
-
- if (min <= sofs)
- {
- sofs -= min;
- memcpy (&c, &sline->b[sofs], min);
- }
- else
- {
- size_t min_ofs = min - sofs;
- memcpy (&c.b[min_ofs], sline, sofs);
- sline = disp->read_lock(--src, R);
- sofs = CACHELINE_SIZE - min_ofs;
- memcpy (&c, &sline->b[sofs], min_ofs);
- }
-
- dofs = dleft - min;
- dpair = disp->write_lock(dst, W);
- *dpair.mask |= (((gtm_cacheline_mask)1 << min) - 1) << dofs;
- memcpy (&dpair.line->b[dofs], &c, min);
-
- sleft = CACHELINE_SIZE - sofs;
- dst--;
- size -= min;
- }
-
- while (size >= CACHELINE_SIZE)
- {
- memcpy (&c.b[sleft], sline, sofs);
- sline = disp->read_lock(--src, R);
- memcpy (&c, &sline->b[sofs], sleft);
-
- dpair = disp->write_lock(dst, W);
- *dpair.mask = -1;
- *dpair.line = c;
-
- dst--;
- size -= CACHELINE_SIZE;
- }
-
- if (size != 0)
- {
- dofs = CACHELINE_SIZE - size;
-
- memcpy (&c.b[sleft], sline, sofs);
- if (sleft > dofs)
- {
- sline = disp->read_lock(--src, R);
- memcpy (&c, &sline->b[sofs], sleft);
- }
-
- dpair = disp->write_lock(dst, W);
- *dpair.mask |= (gtm_cacheline_mask)-1 << dofs;
- memcpy (&dpair.line->b[dofs], &c.b[dofs], size);
- }
- }
-}
-
-#define ITM_MEM_DEF(NAME, READ, WRITE) \
-void ITM_REGPARM _ITM_memcpy##NAME(void *dst, const void *src, size_t size) \
-{ \
- do_memcpy ((uintptr_t)dst, (uintptr_t)src, size, \
- abi_dispatch::WRITE, abi_dispatch::READ); \
-} \
-void ITM_REGPARM _ITM_memmove##NAME(void *dst, const void *src, size_t size) \
-{ \
- do_memmove ((uintptr_t)dst, (uintptr_t)src, size, \
- abi_dispatch::WRITE, abi_dispatch::READ); \
-}
-
-ITM_MEM_DEF(RnWt, NOLOCK, W)
-ITM_MEM_DEF(RnWtaR, NOLOCK, WaR)
-ITM_MEM_DEF(RnWtaW, NOLOCK, WaW)
-
-ITM_MEM_DEF(RtWn, R, NOLOCK)
-ITM_MEM_DEF(RtWt, R, W)
-ITM_MEM_DEF(RtWtaR, R, WaR)
-ITM_MEM_DEF(RtWtaW, R, WaW)
-
-ITM_MEM_DEF(RtaRWn, RaR, NOLOCK)
-ITM_MEM_DEF(RtaRWt, RaR, W)
-ITM_MEM_DEF(RtaRWtaR, RaR, WaR)
-ITM_MEM_DEF(RtaRWtaW, RaR, WaW)
-
-ITM_MEM_DEF(RtaWWn, RaW, NOLOCK)
-ITM_MEM_DEF(RtaWWt, RaW, W)
-ITM_MEM_DEF(RtaWWtaR, RaW, WaR)
-ITM_MEM_DEF(RtaWWtaW, RaW, WaW)
diff --git a/libitm/memset.cc b/libitm/memset.cc
deleted file mode 100644
index 3a627dd6c7d..00000000000
--- a/libitm/memset.cc
+++ /dev/null
@@ -1,78 +0,0 @@
-/* Copyright (C) 2008, 2009, 2011 Free Software Foundation, Inc.
- Contributed by Richard Henderson <rth@redhat.com>.
-
- This file is part of the GNU Transactional Memory Library (libitm).
-
- Libitm 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.
-
- Libitm 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 "libitm_i.h"
-
-using namespace GTM;
-
-static void
-do_memset(uintptr_t idst, int c, size_t size, abi_dispatch::lock_type W)
-{
- abi_dispatch *disp = abi_disp();
- uintptr_t dofs = idst & (CACHELINE_SIZE - 1);
- abi_dispatch::mask_pair dpair;
- gtm_cacheline *dst
- = reinterpret_cast<gtm_cacheline *>(idst & -CACHELINE_SIZE);
-
- if (size == 0)
- return;
-
- if (dofs != 0)
- {
- size_t dleft = CACHELINE_SIZE - dofs;
- size_t min = (size <= dleft ? size : dleft);
-
- dpair = disp->write_lock(dst, W);
- *dpair.mask |= (((gtm_cacheline_mask)1 << min) - 1) << dofs;
- memset (&dpair.line->b[dofs], c, min);
- dst++;
- size -= min;
- }
-
- while (size >= CACHELINE_SIZE)
- {
- dpair = disp->write_lock(dst, W);
- *dpair.mask = -1;
- memset (dpair.line, c, CACHELINE_SIZE);
- dst++;
- size -= CACHELINE_SIZE;
- }
-
- if (size != 0)
- {
- dpair = disp->write_lock(dst, W);
- *dpair.mask |= ((gtm_cacheline_mask)1 << size) - 1;
- memset (dpair.line, c, size);
- }
-}
-
-#define ITM_MEM_DEF(WRITE) \
-void ITM_REGPARM _ITM_memset##WRITE(void *dst, int c, size_t size) \
-{ \
- do_memset ((uintptr_t)dst, c, size, abi_dispatch::WRITE); \
-}
-
-ITM_MEM_DEF(W)
-ITM_MEM_DEF(WaR)
-ITM_MEM_DEF(WaW)
diff --git a/libitm/method-wbetl.cc b/libitm/method-wbetl.cc
deleted file mode 100644
index 093d1c769f1..00000000000
--- a/libitm/method-wbetl.cc
+++ /dev/null
@@ -1,628 +0,0 @@
-/* Copyright (C) 2009, 2011 Free Software Foundation, Inc.
- Contributed by Richard Henderson <rth@redhat.com>.
-
- This file is part of the GNU Transactional Memory Library (libitm).
-
- Libitm 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.
-
- Libitm 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 "libitm_i.h"
-
-namespace {
-
-using namespace GTM;
-
-class wbetl_dispatch : public abi_dispatch
-{
- private:
- static const size_t RW_SET_SIZE = 4096;
-
- struct r_entry
- {
- gtm_version version;
- gtm_stmlock *lock;
- };
-
- r_entry *m_rset_entries;
- size_t m_rset_nb_entries;
- size_t m_rset_size;
-
- struct w_entry
- {
- /* There's a hashtable where the locks are held, so multiple
- cachelines can hash to a given bucket. This link points to the
- possible next cacheline that also hashes to this bucket. */
- struct w_entry *next;
-
- /* Every entry in this bucket (accessed by NEXT) has the same LOCK
- address below. */
- gtm_stmlock *lock;
-
- gtm_cacheline *addr;
- gtm_cacheline *value;
- gtm_version version;
- };
-
- w_entry *m_wset_entries;
- size_t m_wset_nb_entries;
- size_t m_wset_size;
- bool m_wset_reallocate;
-
- gtm_version m_start;
- gtm_version m_end;
-
- gtm_cacheline_page *m_cache_page;
- unsigned m_n_cache_page;
-
- private:
- bool local_w_entry_p (w_entry *w);
- bool has_read (gtm_stmlock *lock);
- bool validate();
- bool extend();
-
- gtm_cacheline *do_write_lock(gtm_cacheline *);
- gtm_cacheline *do_after_write_lock(gtm_cacheline *);
- const gtm_cacheline *do_read_lock(const gtm_cacheline *, bool);
-
- public:
- wbetl_dispatch();
-
- virtual const gtm_cacheline *read_lock(const gtm_cacheline *, ls_modifier);
- virtual mask_pair write_lock(gtm_cacheline *, ls_modifier);
-
- virtual bool trycommit();
- virtual void rollback();
- virtual void reinit();
- virtual void fini();
- virtual bool trydropreference (void *, size_t);
-};
-
-/* Check if W is one of our write locks. */
-
-inline bool
-wbetl_dispatch::local_w_entry_p (w_entry *w)
-{
- return (m_wset_entries <= w && w < m_wset_entries + m_wset_nb_entries);
-}
-
-/* Check if stripe has been read previously. */
-
-inline bool
-wbetl_dispatch::has_read (gtm_stmlock *lock)
-{
- // ??? Consider using an AA tree to lookup the r_set entries.
- size_t n = m_rset_nb_entries;
- for (size_t i = 0; i < n; ++i)
- if (m_rset_entries[i].lock == lock)
- return true;
-
- return false;
-}
-
-/* Validate read set, i.e. check if all read addresses are still valid now. */
-
-bool
-wbetl_dispatch::validate ()
-{
- __sync_synchronize ();
-
- size_t n = m_rset_nb_entries;
- for (size_t i = 0; i < n; ++i)
- {
- r_entry *r = &m_rset_entries[i];
- gtm_stmlock l = *r->lock;
-
- if (gtm_stmlock_owned_p (l))
- {
- w_entry *w = (w_entry *) gtm_stmlock_get_addr (l);
-
- // If someone has locked us, it better be by someone in the
- // current thread.
- if (!local_w_entry_p (w))
- return false;
- }
- else if (gtm_stmlock_get_version (l) != r->version)
- return false;
- }
-
- return true;
-}
-
-/* Extend the snapshot range. */
-
-bool
-wbetl_dispatch::extend ()
-{
- gtm_version now = gtm_get_clock ();
-
- if (validate ())
- {
- m_end = now;
- return true;
- }
- return false;
-}
-
-/* Acquire a write lock on ADDR. */
-
-gtm_cacheline *
-wbetl_dispatch::do_write_lock(gtm_cacheline *addr)
-{
- gtm_stmlock *lock;
- gtm_stmlock l, l2;
- gtm_version version;
- w_entry *w, *prev = NULL;
-
- lock = gtm_get_stmlock (addr);
- l = *lock;
-
- restart_no_load:
- if (gtm_stmlock_owned_p (l))
- {
- w = (w_entry *) gtm_stmlock_get_addr (l);
-
- /* Did we previously write the same address? */
- if (local_w_entry_p (w))
- {
- prev = w;
- while (1)
- {
- if (addr == prev->addr)
- return prev->value;
- if (prev->next == NULL)
- break;
- prev = prev->next;
- }
-
- /* Get version from previous entry write set. */
- version = prev->version;
-
- /* If there's not enough entries, we must reallocate the array,
- which invalidates all pointers to write set entries, which
- means we have to restart the transaction. */
- if (m_wset_nb_entries == m_wset_size)
- {
- m_wset_size *= 2;
- m_wset_reallocate = true;
- gtm_tx()->restart (RESTART_REALLOCATE);
- }
-
- w = &m_wset_entries[m_wset_nb_entries];
- goto do_write;
- }
-
- gtm_tx()->restart (RESTART_LOCKED_WRITE);
- }
- else
- {
- version = gtm_stmlock_get_version (l);
-
- /* We might have read an older version previously. */
- if (version > m_end)
- {
- if (has_read (lock))
- gtm_tx()->restart (RESTART_VALIDATE_WRITE);
- }
-
- /* Extend write set, aborting to reallocate write set entries. */
- if (m_wset_nb_entries == m_wset_size)
- {
- m_wset_size *= 2;
- m_wset_reallocate = true;
- gtm_tx()->restart (RESTART_REALLOCATE);
- }
-
- /* Acquire the lock. */
- w = &m_wset_entries[m_wset_nb_entries];
- l2 = gtm_stmlock_set_owned (w);
- l = __sync_val_compare_and_swap (lock, l, l2);
- if (l != l2)
- goto restart_no_load;
- }
-
- do_write:
- m_wset_nb_entries++;
- if (prev != NULL)
- prev->next = w;
- w->next = 0;
- w->lock = lock;
- w->addr = addr;
- w->version = version;
-
- gtm_cacheline_page *page = m_cache_page;
- unsigned index = m_n_cache_page;
-
- if (page == NULL || index == gtm_cacheline_page::LINES)
- {
- gtm_cacheline_page *npage = new gtm_cacheline_page;
- npage->prev = page;
- m_cache_page = page = npage;
- m_n_cache_page = 1;
- index = 0;
- }
- else
- m_n_cache_page = index + 1;
-
- gtm_cacheline *line = &page->lines[index];
- w->value = line;
- page->masks[index] = 0;
- *line = *addr;
-
- return line;
-}
-
-gtm_cacheline *
-wbetl_dispatch::do_after_write_lock (gtm_cacheline *addr)
-{
- gtm_stmlock *lock;
- gtm_stmlock l;
- w_entry *w;
-
- lock = gtm_get_stmlock (addr);
- l = *lock;
- assert (gtm_stmlock_owned_p (l));
-
- w = (w_entry *) gtm_stmlock_get_addr (l);
- assert (local_w_entry_p (w));
-
- while (1)
- {
- if (addr == w->addr)
- return w->value;
- w = w->next;
- }
-}
-
-/* Acquire a read lock on ADDR. */
-
-const gtm_cacheline *
-wbetl_dispatch::do_read_lock (const gtm_cacheline *addr, bool after_read)
-{
- gtm_stmlock *lock;
- gtm_stmlock l, l2;
- gtm_version version;
- w_entry *w;
-
- lock = gtm_get_stmlock (addr);
- l = *lock;
-
- restart_no_load:
- if (gtm_stmlock_owned_p (l))
- {
- w = (w_entry *) gtm_stmlock_get_addr (l);
-
- /* Did we previously write the same address? */
- if (local_w_entry_p (w))
- {
- while (1)
- {
- if (addr == w->addr)
- return w->value;
- if (w->next == NULL)
- return addr;
- w = w->next;
- }
- }
-
- gtm_tx()->restart (RESTART_LOCKED_READ);
- }
-
- version = gtm_stmlock_get_version (l);
-
- /* If version is no longer valid, re-validate the read set. */
- if (version > m_end)
- {
- if (!extend ())
- gtm_tx()->restart (RESTART_VALIDATE_READ);
-
- if (!after_read)
- {
- // Verify that the version has not yet been overwritten. The read
- // value has not yet been added to read set and may not have been
- // checked during the extend.
- //
- // ??? This only makes sense if we're actually reading the value
- // and returning it now -- which I believe the original TinySTM
- // did. This doesn't make a whole lot of sense when we're
- // manipulating cachelines as we are now. Do we need some other
- // form of lock verification here, or is the validate call in
- // trycommit sufficient?
-
- __sync_synchronize ();
- l2 = *lock;
- if (l != l2)
- {
- l = l2;
- goto restart_no_load;
- }
- }
- }
-
- if (!after_read)
- {
- r_entry *r;
-
- /* Add the address and version to the read set. */
- if (m_rset_nb_entries == m_rset_size)
- {
- m_rset_size *= 2;
-
- m_rset_entries = (r_entry *)
- xrealloc (m_rset_entries, m_rset_size * sizeof(r_entry));
- }
- r = &m_rset_entries[m_rset_nb_entries++];
- r->version = version;
- r->lock = lock;
- }
-
- return addr;
-}
-
-const gtm_cacheline *
-wbetl_dispatch::read_lock (const gtm_cacheline *addr, ls_modifier ltype)
-{
- switch (ltype)
- {
- case NONTXNAL:
- return addr;
- case R:
- return do_read_lock (addr, false);
- case RaR:
- return do_read_lock (addr, true);
- case RaW:
- return do_after_write_lock (const_cast<gtm_cacheline *>(addr));
- case RfW:
- return do_write_lock (const_cast<gtm_cacheline *>(addr));
- default:
- abort ();
- }
-}
-
-abi_dispatch::mask_pair
-wbetl_dispatch::write_lock (gtm_cacheline *addr, ls_modifier ltype)
-{
- gtm_cacheline *line;
-
- switch (ltype)
- {
- case NONTXNAL:
- return mask_pair (addr, &mask_sink);
- case W:
- case WaR:
- line = do_write_lock (addr);
- break;
- case WaW:
- line = do_after_write_lock (addr);
- break;
- default:
- abort ();
- }
-
- return mask_pair (line, gtm_cacheline_page::mask_for_page_line (line));
-}
-
-/* Commit the transaction. */
-
-bool
-wbetl_dispatch::trycommit ()
-{
- const size_t n = m_wset_nb_entries;
- if (n != 0)
- {
- /* Get commit timestamp. */
- gtm_version t = gtm_inc_clock ();
-
- /* Validate only if a concurrent transaction has started since. */
- if (m_start != t - 1 && !validate ())
- return false;
-
- /* Install new versions. */
- for (size_t i = 0; i < n; ++i)
- {
- w_entry *w = &m_wset_entries[i];
- gtm_cacheline_mask mask
- = *gtm_cacheline_page::mask_for_page_line (w->value);
-
- /* Filter out any updates that overlap the libitm stack. */
- mask = gtm_mask_stack (w->addr, mask);
-
- gtm_cacheline::copy_mask (w->addr, w->value, mask);
- }
-
- /* Only emit barrier after all cachelines are copied. */
- gtm_cacheline::copy_mask_wb ();
-
- /* Drop locks. */
- for (size_t i = 0; i < n; ++i)
- {
- w_entry *w = &m_wset_entries[i];
-
- /* Every link along the chain has the same lock, but only
- bother dropping the lock once per bucket (at the end). */
- if (w->next == NULL)
- *w->lock = gtm_stmlock_set_version (t);
- }
- }
-
- __sync_synchronize ();
- return true;
-}
-
-void
-wbetl_dispatch::rollback ()
-{
- /* Drop locks. */
- const size_t n = m_wset_nb_entries;
- for (size_t i = 0; i < n; ++i)
- {
- w_entry *w = &m_wset_entries[i];
-
- /* Every link along the chain has the same lock, but only
- bother dropping the lock once per bucket (at the end). */
- if (w->next == NULL)
- *w->lock = gtm_stmlock_set_version (w->version);
- }
-
- __sync_synchronize ();
-}
-
-void
-wbetl_dispatch::reinit ()
-{
- gtm_cacheline_page *page;
-
- m_rset_nb_entries = 0;
- m_wset_nb_entries = 0;
-
- if (m_wset_reallocate)
- {
- m_wset_reallocate = 0;
- m_wset_entries = (w_entry *)
- xrealloc (m_wset_entries, m_wset_size * sizeof(w_entry));
- }
-
- page = m_cache_page;
- if (page)
- {
- /* Release all but one of the pages of cachelines. */
- gtm_cacheline_page *prev = page->prev;
- if (prev)
- {
- page->prev = 0;
- delete prev;
- }
-
- /* Start the next cacheline allocation from the beginning. */
- m_n_cache_page = 0;
- }
-
- m_start = m_end = gtm_get_clock ();
-}
-
-void
-wbetl_dispatch::fini ()
-{
- delete m_cache_page;
- free (m_rset_entries);
- free (m_wset_entries);
- delete this;
-}
-
-/* Attempt to drop any internal references to PTR. Return TRUE if successful.
-
- This is an adaptation of the transactional memcpy function.
-
- What we do here is flush out the current transactional content of
- PTR to real memory, and remove the write mask bits associated with
- it so future commits will ignore this piece of memory. */
-
-bool
-wbetl_dispatch::trydropreference (void *ptr, size_t size)
-{
- if (size == 0)
- return true;
-
- if (!validate ())
- return false;
-
- uintptr_t isrc = (uintptr_t)ptr;
- // The position in the source cacheline where *PTR starts.
- uintptr_t sofs = isrc & (CACHELINE_SIZE - 1);
- gtm_cacheline *src
- = reinterpret_cast<gtm_cacheline *>(isrc & -CACHELINE_SIZE);
- unsigned char *dst = (unsigned char *)ptr;
- abi_dispatch::mask_pair pair;
-
- // If we're trying to drop a reference, we should already have a
- // write lock on it. If we don't have one, there's no work to do.
- if (!gtm_stmlock_owned_p (*gtm_get_stmlock (src)))
- return true;
-
- // We copy the data in three stages:
-
- // (a) Copy stray bytes at the beginning that are smaller than a
- // cacheline.
- if (sofs != 0)
- {
- size_t sleft = CACHELINE_SIZE - sofs;
- size_t min = (size <= sleft ? size : sleft);
-
- // WaW will give us the current locked entry.
- pair = this->write_lock (src, WaW);
-
- // *jedi mind wave*...these aren't the droids you're looking for.
- *pair.mask &= ~((((gtm_cacheline_mask)1 << min) - 1) << sofs);
-
- memcpy (dst, &pair.line->b[sofs], min);
- dst += min;
- src++;
- size -= min;
- }
-
- // (b) Copy subsequent cacheline sized chunks.
- while (size >= CACHELINE_SIZE)
- {
- pair = this->write_lock(src, WaW);
- *pair.mask = 0;
- memcpy (dst, pair.line, CACHELINE_SIZE);
- dst += CACHELINE_SIZE;
- src++;
- size -= CACHELINE_SIZE;
- }
-
- // (c) Copy anything left over.
- if (size != 0)
- {
- pair = this->write_lock(src, WaW);
- *pair.mask &= ~(((gtm_cacheline_mask)1 << size) - 1);
- memcpy (dst, pair.line, size);
- }
-
- // No need to drop locks, since we're going to abort the transaction
- // anyhow.
-
- return true;
-}
-
-
-wbetl_dispatch::wbetl_dispatch ()
- : abi_dispatch (false, false)
-{
- m_rset_entries = (r_entry *) xmalloc (RW_SET_SIZE * sizeof(r_entry));
- m_rset_nb_entries = 0;
- m_rset_size = RW_SET_SIZE;
-
- m_wset_entries = (w_entry *) xmalloc (RW_SET_SIZE * sizeof(w_entry));
- m_wset_nb_entries = 0;
- m_wset_size = RW_SET_SIZE;
- m_wset_reallocate = false;
-
- m_start = m_end = gtm_get_clock ();
-
- m_cache_page = 0;
- m_n_cache_page = 0;
-}
-
-} // anon namespace
-
-abi_dispatch *
-GTM::dispatch_wbetl ()
-{
- return new wbetl_dispatch ();
-}
diff --git a/libitm/testsuite/Makefile.in b/libitm/testsuite/Makefile.in
index ed1f314e0d6..6990cfeb681 100644
--- a/libitm/testsuite/Makefile.in
+++ b/libitm/testsuite/Makefile.in
@@ -38,6 +38,7 @@ subdir = testsuite
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \
+ $(top_srcdir)/../config/asmcfi.m4 \
$(top_srcdir)/../config/depstand.m4 \
$(top_srcdir)/../config/enable.m4 \
$(top_srcdir)/../config/futex.m4 \
@@ -90,8 +91,6 @@ ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
-FC = @FC@
-FCFLAGS = @FCFLAGS@
FGREP = @FGREP@
GREP = @GREP@
INSTALL = @INSTALL@
@@ -142,7 +141,6 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_CC = @ac_ct_CC@
ac_ct_CXX = @ac_ct_CXX@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
-ac_ct_FC = @ac_ct_FC@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
diff --git a/libitm/testsuite/libitm.c++/static_ctor.C b/libitm/testsuite/libitm.c++/static_ctor.C
index 1ba751687ba..18f95fc01e5 100644
--- a/libitm/testsuite/libitm.c++/static_ctor.C
+++ b/libitm/testsuite/libitm.c++/static_ctor.C
@@ -1,4 +1,5 @@
/* { dg-do run } */
+/* { dg-options "-pthread" } */
/* { dg-xfail-if "" { *-*-* } { "*" } { "" } } */
/* Tests static constructors inside of transactional code. */
diff --git a/libitm/testsuite/libitm.c/notx.c b/libitm/testsuite/libitm.c/notx.c
index 999da025a82..7ca6580452b 100644
--- a/libitm/testsuite/libitm.c/notx.c
+++ b/libitm/testsuite/libitm.c/notx.c
@@ -1,5 +1,8 @@
/* These tests all check whether initialization happens properly even if no
transaction has been used in the current thread yet. */
+
+/* { dg-options "-pthread" } */
+
#include <stdlib.h>
#include <pthread.h>
#include <libitm.h>
diff --git a/libitm/testsuite/libitm.c/reentrant.c b/libitm/testsuite/libitm.c/reentrant.c
index 007bbaab741..451530a55ab 100644
--- a/libitm/testsuite/libitm.c/reentrant.c
+++ b/libitm/testsuite/libitm.c/reentrant.c
@@ -1,4 +1,5 @@
/* { dg-do run { xfail *-*-* } }
+/* { dg-options "-pthread" } */
/* Tests that new transactions can be started from both transaction_pure and
transaction_unsafe code. This also requires proper handling of reentrant
diff --git a/libitm/testsuite/libitm.c/simple-2.c b/libitm/testsuite/libitm.c/simple-2.c
index e92c917340d..c77d75dcf51 100644
--- a/libitm/testsuite/libitm.c/simple-2.c
+++ b/libitm/testsuite/libitm.c/simple-2.c
@@ -1,5 +1,7 @@
/* Simplest test involving real threads. Verify we get the correct answer. */
+/* { dg-options "-pthread" } */
+
#include <stdlib.h>
#include <pthread.h>
diff --git a/libitm/testsuite/libitm.c/txrelease.c b/libitm/testsuite/libitm.c/txrelease.c
index 7bf04343d57..37d6b2c9d00 100644
--- a/libitm/testsuite/libitm.c/txrelease.c
+++ b/libitm/testsuite/libitm.c/txrelease.c
@@ -2,6 +2,8 @@
transaction data when a thread exists, potentially repeatedly. However,
we currently cannot check whether the data has indeed been released. */
+/* { dg-options "-pthread" } */
+
#include <stddef.h>
#include <stdlib.h>
#include <pthread.h>
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index f18d7ee511b..5eb3f8d4376 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,54 @@
+2011-11-14 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * include/c_global/cmath (frexp, modf, remquo): Do not mark constexpr,
+ not viable anyway due to the pointer parameter.
+
+2011-11-13 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * include/c_global/cmath (atan2, fmod, pow, copysign, fdim,
+ fma, fmax, fmin, hypot, nextafter, remainder, remquo): Simplify
+ constraining on the return type.
+ * include/tr1/cmath (copysign, fdim, fma, fmax, fmin, hypot,
+ nextafter, remainder, remquo): Likewise.
+
+2011-11-13 Gerald Pfeifer <gerald@pfeifer.com>
+
+ * using.xml: Use GNU/Linux.
+
+2011-11-12 Jason Merrill <jason@redhat.com>
+
+ PR c++/51060
+ * testsuite/25_algorithms/max/1.cc (test01): Drop references.
+ * testsuite/25_algorithms/min/1.cc (test01): Drop references.
+ * testsuite/25_algorithms/minmax/1.cc (test01): Drop references.
+
+2011-11-12 Jonathan Wakely <jwakely.gcc@gmail.com>
+
+ PR libstdc++/51083
+ * include/ext/type_traits.h (__promote): Only define __type member
+ for integral and floating point types, to prevent math functions
+ participating in overload resolution for other types.
+ (__promote_2, __promote_3, __promote_4): Use __promote in default
+ template argument values, so deduction only succeeds for integral and
+ floating point types.
+ * testsuite/26_numerics/cmath/51083.cc: New.
+ * testsuite/26_numerics/complex/51083.cc: New.
+ * testsuite/tr1/8_c_compatibility/cmath/51083.cc: New.
+ * testsuite/tr1/8_c_compatibility/complex/51083.cc: New.
+
+2011-11-10 Andrew MacLeod <amacleod@redhat.com>
+
+ PR middle-end/51038
+ * include/bits/atomic_base.h (atomic_thread_fence): Call built-in.
+ (atomic_signal_fence): Call built-in.
+ (test_and_set, clear): Call new atomic built-ins.
+
+2011-11-09 Jonathan Wakely <jwakely.gcc@gmail.com>
+
+ * include/bits/allocator.h (__shrink_to_fit_aux::_S_do_it): Create
+ the new object with the same allocator.
+ * testsuite/23_containers/vector/capacity/shrink_to_fit2.cc: New.
+
2011-11-09 Jonathan Wakely <jwakely.gcc@gmail.com>
* include/profile/unordered_map: Add missing copy constructors.
diff --git a/libstdc++-v3/doc/xml/manual/using.xml b/libstdc++-v3/doc/xml/manual/using.xml
index f081ed4bc44..601ca20d1eb 100644
--- a/libstdc++-v3/doc/xml/manual/using.xml
+++ b/libstdc++-v3/doc/xml/manual/using.xml
@@ -1177,7 +1177,7 @@ A quick read of the relevant part of the GCC
<itemizedlist>
<listitem>
<para>
- GNU ld (default on Linux):
+ GNU ld (default on GNU/Linux):
<literal>-Wl,-rpath,</literal><filename class="directory">destdir/lib</filename>
</para>
</listitem>
@@ -1207,7 +1207,7 @@ A quick read of the relevant part of the GCC
On some platforms the system administrator can configure the
dynamic linker to always look for libraries in
<filename class="directory">destdir/lib</filename>, for example
- by using the <command>ldconfig</command> utility on Linux
+ by using the <command>ldconfig</command> utility on GNU/Linux
or the <command>crle</command> utility on Solaris. This is a
system-wide change which can make the system unusable so if you
are unsure then use one of the other methods described above.
@@ -1269,7 +1269,7 @@ A quick read of the relevant part of the GCC
to display how ad hoc this is: On Solaris, both -pthreads and
-threads (with subtly different meanings) are honored. On OSF,
-pthread and -threads (with subtly different meanings) are
- honored. On Linux/i386, -pthread is honored. On FreeBSD,
+ honored. On GNU/Linux i386, -pthread is honored. On FreeBSD,
-pthread is honored. Some other ports use other switches.
AFAIK, none of this is properly documented anywhere other than
in ``gcc -dumpspecs'' (look at lib and cpp entries).
diff --git a/libstdc++-v3/include/bits/allocator.h b/libstdc++-v3/include/bits/allocator.h
index 76329b377ea..b985d3f5e6f 100644
--- a/libstdc++-v3/include/bits/allocator.h
+++ b/libstdc++-v3/include/bits/allocator.h
@@ -198,7 +198,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__try
{
_Tp(__make_move_if_noexcept_iterator(__c.begin()),
- __make_move_if_noexcept_iterator(__c.end())).swap(__c);
+ __make_move_if_noexcept_iterator(__c.end()),
+ __c.get_allocator()).swap(__c);
return true;
}
__catch(...)
diff --git a/libstdc++-v3/include/bits/atomic_base.h b/libstdc++-v3/include/bits/atomic_base.h
index 5327c1bfa21..f0336611d3f 100644
--- a/libstdc++-v3/include/bits/atomic_base.h
+++ b/libstdc++-v3/include/bits/atomic_base.h
@@ -68,11 +68,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return __mo2;
}
- void
- atomic_thread_fence(memory_order __m) noexcept;
+ inline void
+ atomic_thread_fence(memory_order __m) noexcept
+ {
+ __atomic_thread_fence (__m);
+ }
- void
- atomic_signal_fence(memory_order __m) noexcept;
+ inline void
+ atomic_signal_fence(memory_order __m) noexcept
+ {
+ __atomic_thread_fence (__m);
+ }
/// kill_dependency
template<typename _Tp>
@@ -261,35 +267,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
bool
test_and_set(memory_order __m = memory_order_seq_cst) noexcept
{
- /* The standard *requires* this to be lock free. If exchange is not
- always lock free, the resort to the old test_and_set. */
- if (__atomic_always_lock_free (sizeof (_M_i), 0))
- return __atomic_exchange_n(&_M_i, 1, __m);
- else
- {
- /* Sync test and set is only guaranteed to be acquire. */
- if (__m == memory_order_seq_cst || __m == memory_order_release
- || __m == memory_order_acq_rel)
- atomic_thread_fence (__m);
- return __sync_lock_test_and_set (&_M_i, 1);
- }
+ return __atomic_test_and_set (&_M_i, __m);
}
bool
test_and_set(memory_order __m = memory_order_seq_cst) volatile noexcept
{
- /* The standard *requires* this to be lock free. If exchange is not
- always lock free, the resort to the old test_and_set. */
- if (__atomic_always_lock_free (sizeof (_M_i), 0))
- return __atomic_exchange_n(&_M_i, 1, __m);
- else
- {
- /* Sync test and set is only guaranteed to be acquire. */
- if (__m == memory_order_seq_cst || __m == memory_order_release
- || __m == memory_order_acq_rel)
- atomic_thread_fence (__m);
- return __sync_lock_test_and_set (&_M_i, 1);
- }
+ return __atomic_test_and_set (&_M_i, __m);
}
void
@@ -299,17 +283,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__glibcxx_assert(__m != memory_order_acquire);
__glibcxx_assert(__m != memory_order_acq_rel);
- /* The standard *requires* this to be lock free. If store is not always
- lock free, the resort to the old style __sync_lock_release. */
- if (__atomic_always_lock_free (sizeof (_M_i), 0))
- __atomic_store_n(&_M_i, 0, __m);
- else
- {
- __sync_lock_release (&_M_i, 0);
- /* __sync_lock_release is only guaranteed to be a release barrier. */
- if (__m == memory_order_seq_cst)
- atomic_thread_fence (__m);
- }
+ __atomic_clear (&_M_i, __m);
}
void
@@ -319,17 +293,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__glibcxx_assert(__m != memory_order_acquire);
__glibcxx_assert(__m != memory_order_acq_rel);
- /* The standard *requires* this to be lock free. If store is not always
- lock free, the resort to the old style __sync_lock_release. */
- if (__atomic_always_lock_free (sizeof (_M_i), 0))
- __atomic_store_n(&_M_i, 0, __m);
- else
- {
- __sync_lock_release (&_M_i, 0);
- /* __sync_lock_release is only guaranteed to be a release barrier. */
- if (__m == memory_order_seq_cst)
- atomic_thread_fence (__m);
- }
+ __atomic_clear (&_M_i, __m);
}
};
diff --git a/libstdc++-v3/include/c_global/cmath b/libstdc++-v3/include/c_global/cmath
index 016bdba0408..75d1a02e1ed 100644
--- a/libstdc++-v3/include/c_global/cmath
+++ b/libstdc++-v3/include/c_global/cmath
@@ -173,10 +173,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Tp, typename _Up>
inline _GLIBCXX_CONSTEXPR
- typename __gnu_cxx::__promote_2<
- typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value
- && __is_arithmetic<_Up>::__value,
- _Tp>::__type, _Up>::__type
+ typename __gnu_cxx::__promote_2<_Tp, _Up>::__type
atan2(_Tp __y, _Up __x)
{
typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
@@ -311,10 +308,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Tp, typename _Up>
inline _GLIBCXX_CONSTEXPR
- typename __gnu_cxx::__promote_2<
- typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value
- && __is_arithmetic<_Up>::__value,
- _Tp>::__type, _Up>::__type
+ typename __gnu_cxx::__promote_2<_Tp, _Up>::__type
fmod(_Tp __x, _Up __y)
{
typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
@@ -324,11 +318,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
using ::frexp;
#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO1
- inline _GLIBCXX_CONSTEXPR float
+ inline float
frexp(float __x, int* __exp)
{ return __builtin_frexpf(__x, __exp); }
- inline _GLIBCXX_CONSTEXPR long double
+ inline long double
frexp(long double __x, int* __exp)
{ return __builtin_frexpl(__x, __exp); }
#endif
@@ -400,11 +394,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
using ::modf;
#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO1
- inline _GLIBCXX_CONSTEXPR float
+ inline float
modf(float __x, float* __iptr)
{ return __builtin_modff(__x, __iptr); }
- inline _GLIBCXX_CONSTEXPR long double
+ inline long double
modf(long double __x, long double* __iptr)
{ return __builtin_modfl(__x, __iptr); }
#endif
@@ -439,10 +433,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Tp, typename _Up>
inline _GLIBCXX_CONSTEXPR
- typename __gnu_cxx::__promote_2<
- typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value
- && __is_arithmetic<_Up>::__value,
- _Tp>::__type, _Up>::__type
+ typename __gnu_cxx::__promote_2<_Tp, _Up>::__type
pow(_Tp __x, _Up __y)
{
typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
@@ -1256,11 +1247,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return __builtin_copysignl(__x, __y); }
template<typename _Tp, typename _Up>
- constexpr
- typename __gnu_cxx::__promote_2<
- typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value
- && __is_arithmetic<_Up>::__value,
- _Tp>::__type, _Up>::__type
+ constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type
copysign(_Tp __x, _Up __y)
{
typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
@@ -1332,11 +1319,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return __builtin_fdiml(__x, __y); }
template<typename _Tp, typename _Up>
- constexpr
- typename __gnu_cxx::__promote_2<
- typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value
- && __is_arithmetic<_Up>::__value,
- _Tp>::__type, _Up>::__type
+ constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type
fdim(_Tp __x, _Up __y)
{
typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
@@ -1352,12 +1335,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return __builtin_fmal(__x, __y, __z); }
template<typename _Tp, typename _Up, typename _Vp>
- constexpr
- typename __gnu_cxx::__promote_3<
- typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value
- && __is_arithmetic<_Up>::__value
- && __is_arithmetic<_Vp>::__value,
- _Tp>::__type, _Up, _Vp>::__type
+ constexpr typename __gnu_cxx::__promote_3<_Tp, _Up, _Vp>::__type
fma(_Tp __x, _Up __y, _Vp __z)
{
typedef typename __gnu_cxx::__promote_3<_Tp, _Up, _Vp>::__type __type;
@@ -1373,11 +1351,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return __builtin_fmaxl(__x, __y); }
template<typename _Tp, typename _Up>
- constexpr
- typename __gnu_cxx::__promote_2<
- typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value
- && __is_arithmetic<_Up>::__value,
- _Tp>::__type, _Up>::__type
+ constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type
fmax(_Tp __x, _Up __y)
{
typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
@@ -1393,11 +1367,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return __builtin_fminl(__x, __y); }
template<typename _Tp, typename _Up>
- constexpr
- typename __gnu_cxx::__promote_2<
- typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value
- && __is_arithmetic<_Up>::__value,
- _Tp>::__type, _Up>::__type
+ constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type
fmin(_Tp __x, _Up __y)
{
typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
@@ -1413,12 +1383,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return __builtin_hypotl(__x, __y); }
template<typename _Tp, typename _Up>
- constexpr
- typename __gnu_cxx::__promote_2<
- typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value
- && __is_arithmetic<_Up>::__value,
- _Tp>::__type, _Up>::__type
- hypot(_Tp __x, _Up __y)
+ constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type
+ hypot(_Tp __x, _Up __y)
{
typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
return hypot(__type(__x), __type(__y));
@@ -1575,11 +1541,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return __builtin_nextafterl(__x, __y); }
template<typename _Tp, typename _Up>
- constexpr
- typename __gnu_cxx::__promote_2<
- typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value
- && __is_arithmetic<_Up>::__value,
- _Tp>::__type, _Up>::__type
+ constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type
nextafter(_Tp __x, _Up __y)
{
typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
@@ -1609,31 +1571,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return __builtin_remainderl(__x, __y); }
template<typename _Tp, typename _Up>
- constexpr
- typename __gnu_cxx::__promote_2<
- typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value
- && __is_arithmetic<_Up>::__value,
- _Tp>::__type, _Up>::__type
+ constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type
remainder(_Tp __x, _Up __y)
{
typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
return remainder(__type(__x), __type(__y));
}
- constexpr float
+ inline float
remquo(float __x, float __y, int* __pquo)
{ return __builtin_remquof(__x, __y, __pquo); }
- constexpr long double
+ inline long double
remquo(long double __x, long double __y, int* __pquo)
{ return __builtin_remquol(__x, __y, __pquo); }
template<typename _Tp, typename _Up>
- constexpr
- typename __gnu_cxx::__promote_2<
- typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value
- && __is_arithmetic<_Up>::__value,
- _Tp>::__type, _Up>::__type
+ inline typename __gnu_cxx::__promote_2<_Tp, _Up>::__type
remquo(_Tp __x, _Up __y, int* __pquo)
{
typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
diff --git a/libstdc++-v3/include/ext/type_traits.h b/libstdc++-v3/include/ext/type_traits.h
index 92747268a06..b0fa36bcec8 100644
--- a/libstdc++-v3/include/ext/type_traits.h
+++ b/libstdc++-v3/include/ext/type_traits.h
@@ -161,44 +161,50 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
struct __promote
{ typedef double __type; };
+ // No nested __type member for non-integer non-floating point types,
+ // allows this type to be used for SFINAE to constrain overloads in
+ // <cmath> and <complex> to only the intended types.
template<typename _Tp>
struct __promote<_Tp, false>
- { typedef _Tp __type; };
+ { };
+
+ template<>
+ struct __promote<long double>
+ { typedef long double __type; };
+
+ template<>
+ struct __promote<double>
+ { typedef double __type; };
+
+ template<>
+ struct __promote<float>
+ { typedef float __type; };
- template<typename _Tp, typename _Up>
+ template<typename _Tp, typename _Up,
+ typename _Tp2 = typename __promote<_Tp>::__type,
+ typename _Up2 = typename __promote<_Up>::__type>
struct __promote_2
{
- private:
- typedef typename __promote<_Tp>::__type __type1;
- typedef typename __promote<_Up>::__type __type2;
-
- public:
- typedef __typeof__(__type1() + __type2()) __type;
+ typedef __typeof__(_Tp2() + _Up2()) __type;
};
- template<typename _Tp, typename _Up, typename _Vp>
+ template<typename _Tp, typename _Up, typename _Vp,
+ typename _Tp2 = typename __promote<_Tp>::__type,
+ typename _Up2 = typename __promote<_Up>::__type,
+ typename _Vp2 = typename __promote<_Vp>::__type>
struct __promote_3
{
- private:
- typedef typename __promote<_Tp>::__type __type1;
- typedef typename __promote<_Up>::__type __type2;
- typedef typename __promote<_Vp>::__type __type3;
-
- public:
- typedef __typeof__(__type1() + __type2() + __type3()) __type;
+ typedef __typeof__(_Tp2() + _Up2() + _Vp2()) __type;
};
- template<typename _Tp, typename _Up, typename _Vp, typename _Wp>
+ template<typename _Tp, typename _Up, typename _Vp, typename _Wp,
+ typename _Tp2 = typename __promote<_Tp>::__type,
+ typename _Up2 = typename __promote<_Up>::__type,
+ typename _Vp2 = typename __promote<_Vp>::__type,
+ typename _Wp2 = typename __promote<_Wp>::__type>
struct __promote_4
{
- private:
- typedef typename __promote<_Tp>::__type __type1;
- typedef typename __promote<_Up>::__type __type2;
- typedef typename __promote<_Vp>::__type __type3;
- typedef typename __promote<_Wp>::__type __type4;
-
- public:
- typedef __typeof__(__type1() + __type2() + __type3() + __type4()) __type;
+ typedef __typeof__(_Tp2() + _Up2() + _Vp2() + _Wp2()) __type;
};
_GLIBCXX_END_NAMESPACE_VERSION
diff --git a/libstdc++-v3/include/tr1/cmath b/libstdc++-v3/include/tr1/cmath
index 06631e51e97..e702bee16fa 100644
--- a/libstdc++-v3/include/tr1/cmath
+++ b/libstdc++-v3/include/tr1/cmath
@@ -492,11 +492,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return __builtin_copysignl(__x, __y); }
template<typename _Tp, typename _Up>
- inline
- typename __gnu_cxx::__promote_2<
- typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value
- && __is_arithmetic<_Up>::__value,
- _Tp>::__type, _Up>::__type
+ inline typename __gnu_cxx::__promote_2<_Tp, _Up>::__type
copysign(_Tp __x, _Up __y)
{
typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
@@ -597,11 +593,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return __builtin_fdiml(__x, __y); }
template<typename _Tp, typename _Up>
- inline
- typename __gnu_cxx::__promote_2<
- typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value
- && __is_arithmetic<_Up>::__value,
- _Tp>::__type, _Up>::__type
+ inline typename __gnu_cxx::__promote_2<_Tp, _Up>::__type
fdim(_Tp __x, _Up __y)
{
typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
@@ -619,12 +611,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return __builtin_fmal(__x, __y, __z); }
template<typename _Tp, typename _Up, typename _Vp>
- inline
- typename __gnu_cxx::__promote_3<
- typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value
- && __is_arithmetic<_Up>::__value
- && __is_arithmetic<_Vp>::__value,
- _Tp>::__type, _Up, _Vp>::__type
+ inline typename __gnu_cxx::__promote_3<_Tp, _Up, _Vp>::__type
fma(_Tp __x, _Up __y, _Vp __z)
{
typedef typename __gnu_cxx::__promote_3<_Tp, _Up, _Vp>::__type __type;
@@ -640,11 +627,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return __builtin_fmaxl(__x, __y); }
template<typename _Tp, typename _Up>
- inline
- typename __gnu_cxx::__promote_2<
- typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value
- && __is_arithmetic<_Up>::__value,
- _Tp>::__type, _Up>::__type
+ inline typename __gnu_cxx::__promote_2<_Tp, _Up>::__type
fmax(_Tp __x, _Up __y)
{
typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
@@ -660,11 +643,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return __builtin_fminl(__x, __y); }
template<typename _Tp, typename _Up>
- inline
- typename __gnu_cxx::__promote_2<
- typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value
- && __is_arithmetic<_Up>::__value,
- _Tp>::__type, _Up>::__type
+ inline typename __gnu_cxx::__promote_2<_Tp, _Up>::__type
fmin(_Tp __x, _Up __y)
{
typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
@@ -683,11 +662,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return __builtin_hypotl(__x, __y); }
template<typename _Tp, typename _Up>
- inline
- typename __gnu_cxx::__promote_2<
- typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value
- && __is_arithmetic<_Up>::__value,
- _Tp>::__type, _Up>::__type
+ inline typename __gnu_cxx::__promote_2<_Tp, _Up>::__type
hypot(_Tp __y, _Up __x)
{
typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
@@ -851,11 +826,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return __builtin_nextafterl(__x, __y); }
template<typename _Tp, typename _Up>
- inline
- typename __gnu_cxx::__promote_2<
- typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value
- && __is_arithmetic<_Up>::__value,
- _Tp>::__type, _Up>::__type
+ inline typename __gnu_cxx::__promote_2<_Tp, _Up>::__type
nextafter(_Tp __x, _Up __y)
{
typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
@@ -889,11 +860,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return __builtin_remainderl(__x, __y); }
template<typename _Tp, typename _Up>
- inline
- typename __gnu_cxx::__promote_2<
- typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value
- && __is_arithmetic<_Up>::__value,
- _Tp>::__type, _Up>::__type
+ inline typename __gnu_cxx::__promote_2<_Tp, _Up>::__type
remainder(_Tp __x, _Up __y)
{
typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
@@ -909,11 +876,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return __builtin_remquol(__x, __y, __pquo); }
template<typename _Tp, typename _Up>
- inline
- typename __gnu_cxx::__promote_2<
- typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value
- && __is_arithmetic<_Up>::__value,
- _Tp>::__type, _Up>::__type
+ inline typename __gnu_cxx::__promote_2<_Tp, _Up>::__type
remquo(_Tp __x, _Up __y, int* __pquo)
{
typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
diff --git a/libstdc++-v3/testsuite/23_containers/vector/capacity/shrink_to_fit2.cc b/libstdc++-v3/testsuite/23_containers/vector/capacity/shrink_to_fit2.cc
new file mode 100644
index 00000000000..81cd55a8f27
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/vector/capacity/shrink_to_fit2.cc
@@ -0,0 +1,61 @@
+// { dg-options "-std=gnu++0x" }
+
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without Pred the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <vector>
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+using __gnu_test::propagating_allocator;
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef propagating_allocator<int, true> alloc_type;
+ alloc_type alloc(5);
+
+ std::vector<int, alloc_type> v(10u, 1, alloc);
+ v.reserve(100);
+ VERIFY( v.size() < v.capacity() );
+ v.shrink_to_fit();
+ VERIFY( v.size() == v.capacity() );
+ VERIFY( v.get_allocator().get_personality() == alloc.get_personality() );
+}
+
+void test02()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef propagating_allocator<int, false> alloc_type;
+ alloc_type alloc(5);
+
+ std::vector<int, alloc_type> v(10u, 1, alloc);
+ v.reserve(100);
+ VERIFY( v.size() < v.capacity() );
+ v.shrink_to_fit();
+ VERIFY( v.size() == v.capacity() );
+ VERIFY( v.get_allocator().get_personality() == alloc.get_personality() );
+}
+
+int main()
+{
+ test01();
+ test02();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/25_algorithms/max/1.cc b/libstdc++-v3/testsuite/25_algorithms/max/1.cc
index 978466f1b07..1757b6a49f6 100644
--- a/libstdc++-v3/testsuite/25_algorithms/max/1.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/max/1.cc
@@ -25,13 +25,13 @@ void test01()
{
bool test __attribute__((unused)) = true;
- const int& x = std::max(1, 2);
- const int& y = std::max(4, 3);
+ const int x = std::max(1, 2);
+ const int y = std::max(4, 3);
VERIFY( x == 2 );
VERIFY( y == 4 );
- const int& xc = std::max(1, 2, std::greater<int>());
- const int& yc = std::max(4, 3, std::greater<int>());
+ const int xc = std::max(1, 2, std::greater<int>());
+ const int yc = std::max(4, 3, std::greater<int>());
VERIFY( xc == 1 );
VERIFY( yc == 3 );
}
diff --git a/libstdc++-v3/testsuite/25_algorithms/min/1.cc b/libstdc++-v3/testsuite/25_algorithms/min/1.cc
index 23bc7216173..ca52e497245 100644
--- a/libstdc++-v3/testsuite/25_algorithms/min/1.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/min/1.cc
@@ -25,13 +25,13 @@ void test01()
{
bool test __attribute__((unused)) = true;
- const int& z = std::min(1, 2);
- const int& w = std::min(4, 3);
+ const int z = std::min(1, 2);
+ const int w = std::min(4, 3);
VERIFY( z == 1 );
VERIFY( w == 3 );
- const int& zc = std::min(1, 2, std::greater<int>());
- const int& wc = std::min(4, 3, std::greater<int>());
+ const int zc = std::min(1, 2, std::greater<int>());
+ const int wc = std::min(4, 3, std::greater<int>());
VERIFY( zc == 2 );
VERIFY( wc == 4 );
}
diff --git a/libstdc++-v3/testsuite/25_algorithms/minmax/1.cc b/libstdc++-v3/testsuite/25_algorithms/minmax/1.cc
index 52122415e70..5e581927d69 100644
--- a/libstdc++-v3/testsuite/25_algorithms/minmax/1.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/minmax/1.cc
@@ -27,15 +27,15 @@ void test01()
{
bool test __attribute__((unused)) = true;
- std::pair<const int&, const int&> z = std::minmax(1, 2);
- std::pair<const int&, const int&> w = std::minmax(4, 3);
+ std::pair<const int, const int> z = std::minmax(1, 2);
+ std::pair<const int, const int> w = std::minmax(4, 3);
VERIFY( z.first == 1 );
VERIFY( z.second == 2 );
VERIFY( w.first == 3 );
VERIFY( w.second == 4 );
- std::pair<const int&, const int&> zc = std::minmax(1, 2, std::greater<int>());
- std::pair<const int&, const int&> wc = std::minmax(4, 3, std::greater<int>());
+ std::pair<const int, const int> zc = std::minmax(1, 2, std::greater<int>());
+ std::pair<const int, const int> wc = std::minmax(4, 3, std::greater<int>());
VERIFY( zc.first == 2 );
VERIFY( zc.second == 1 );
VERIFY( wc.first == 4 );
diff --git a/libstdc++-v3/testsuite/26_numerics/cmath/51083.cc b/libstdc++-v3/testsuite/26_numerics/cmath/51083.cc
new file mode 100644
index 00000000000..8ba9b10e5d8
--- /dev/null
+++ b/libstdc++-v3/testsuite/26_numerics/cmath/51083.cc
@@ -0,0 +1,62 @@
+// { dg-options "-std=gnu++0x" }
+//
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <cmath>
+
+namespace a
+{
+ template<typename> class Mat { };
+
+ template<typename T> struct Mat2 : Mat<T> { };
+
+ template<typename T>
+ int fdim(Mat<T>) { return 1; }
+
+ template<typename T, typename U>
+ int floor(Mat<T>, U) { return 1; }
+ template<typename T, typename U>
+ int floor(T, Mat<U>) { return 1; }
+
+ template<typename T, typename U, typename V>
+ int fma(Mat<T>, U, V) { return 1; }
+ template<typename T, typename U, typename V>
+ int fma(T, Mat<U>, V) { return 1; }
+ template<typename T, typename U, typename V>
+ int fma(T, U, Mat<V>) { return 1; }
+}
+
+int main()
+{
+ int __attribute__((unused)) i;
+
+ using namespace std;
+
+ a::Mat2<double> c;
+ i = fdim(c);
+ i = floor(c, 0.);
+ i = floor(0., c);
+ i = floor(c, 1);
+ i = floor(1, c);
+ i = fma(c, 0., 1.);
+ i = fma(0., c, 1.);
+ i = fma(0., 1., c);
+ i = fma(c, 0., 1);
+ i = fma(0., c, 1);
+ i = fma(0., 1, c);
+}
diff --git a/libstdc++-v3/testsuite/26_numerics/complex/51083.cc b/libstdc++-v3/testsuite/26_numerics/complex/51083.cc
new file mode 100644
index 00000000000..54e781ba1a0
--- /dev/null
+++ b/libstdc++-v3/testsuite/26_numerics/complex/51083.cc
@@ -0,0 +1,54 @@
+// { dg-options "-std=gnu++0x" }
+//
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <complex>
+
+namespace a
+{
+ template<typename> class Mat { };
+
+ template<typename T> struct Mat2 : Mat<T> { };
+
+ template<typename T> int arg(Mat<T>) { return 1; }
+ template<typename T> int conj(Mat<T>) { return 1; }
+ template<typename T> int imag(Mat<T>) { return 1; }
+ template<typename T> int norm(Mat<T>) { return 1; }
+ template<typename T> int proj(Mat<T>) { return 1; }
+ template<typename T> int real(Mat<T>) { return 1; }
+
+ template<typename T, typename U> int pow(Mat<T>, U) { return 1; }
+ template<typename T, typename U> int pow(T, Mat<U>) { return 1; }
+}
+
+int main()
+{
+ int __attribute__((unused)) i;
+
+ using namespace std;
+
+ a::Mat2< std::complex<double> > c;
+ i = arg(c);
+ i = conj(c);
+ i = imag(c);
+ i = norm(c);
+ i = proj(c);
+ i = real(c);
+ i = pow(std::complex<float>(), c);
+ i = pow(c, std::complex<float>());
+}
diff --git a/libstdc++-v3/testsuite/tr1/8_c_compatibility/cmath/51083.cc b/libstdc++-v3/testsuite/tr1/8_c_compatibility/cmath/51083.cc
new file mode 100644
index 00000000000..504305a3043
--- /dev/null
+++ b/libstdc++-v3/testsuite/tr1/8_c_compatibility/cmath/51083.cc
@@ -0,0 +1,62 @@
+// { dg-options "-std=gnu++0x" }
+//
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <tr1/cmath>
+
+namespace a
+{
+ template<typename> class Mat { };
+
+ template<typename T> struct Mat2 : Mat<T> { };
+
+ template<typename T>
+ int fdim(Mat<T>) { return 1; }
+
+ template<typename T, typename U>
+ int floor(Mat<T>, U) { return 1; }
+ template<typename T, typename U>
+ int floor(T, Mat<U>) { return 1; }
+
+ template<typename T, typename U, typename V>
+ int fma(Mat<T>, U, V) { return 1; }
+ template<typename T, typename U, typename V>
+ int fma(T, Mat<U>, V) { return 1; }
+ template<typename T, typename U, typename V>
+ int fma(T, U, Mat<V>) { return 1; }
+}
+
+int main()
+{
+ int __attribute__((unused)) i;
+
+ using namespace std::tr1;
+
+ a::Mat2<double> c;
+ i = fdim(c);
+ i = floor(c, 0.);
+ i = floor(0., c);
+ i = floor(c, 1);
+ i = floor(1, c);
+ i = fma(c, 0., 1.);
+ i = fma(0., c, 1.);
+ i = fma(0., 1., c);
+ i = fma(c, 0., 1);
+ i = fma(0., c, 1);
+ i = fma(0., 1, c);
+}
diff --git a/libstdc++-v3/testsuite/tr1/8_c_compatibility/complex/51083.cc b/libstdc++-v3/testsuite/tr1/8_c_compatibility/complex/51083.cc
new file mode 100644
index 00000000000..f41914ee91e
--- /dev/null
+++ b/libstdc++-v3/testsuite/tr1/8_c_compatibility/complex/51083.cc
@@ -0,0 +1,54 @@
+// { dg-options "-std=gnu++0x" }
+//
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <tr1/complex>
+
+namespace a
+{
+ template<typename> class Mat { };
+
+ template<typename T> struct Mat2 : Mat<T> { };
+
+ template<typename T> int arg(Mat<T>) { return 1; }
+ template<typename T> int conj(Mat<T>) { return 1; }
+ template<typename T> int imag(Mat<T>) { return 1; }
+ template<typename T> int norm(Mat<T>) { return 1; }
+ template<typename T> int proj(Mat<T>) { return 1; }
+ template<typename T> int real(Mat<T>) { return 1; }
+
+ template<typename T, typename U> int pow(Mat<T>, U) { return 1; }
+ template<typename T, typename U> int pow(T, Mat<U>) { return 1; }
+}
+
+int main()
+{
+ int __attribute__((unused)) i;
+
+ using namespace std::tr1;
+
+ a::Mat2< std::complex<double> > c;
+ i = arg(c);
+ i = conj(c);
+ i = imag(c);
+ i = norm(c);
+ i = proj(c);
+ i = real(c);
+ i = pow(std::complex<float>(), c);
+ i = pow(c, std::complex<float>());
+}