gcc 4.5: sync with both OE and yocto

Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
This commit is contained in:
Koen Kooi 2010-12-23 14:02:13 +01:00
parent 8bb6722b13
commit 7eb7dce48b
27 changed files with 14213 additions and 7692 deletions

View File

@ -1,10 +1,18 @@
require gcc-common.inc
LICENSE = "GPLv3"
DEPENDS =+ "mpfr gmp libmpc elfutils"
NATIVEDEPS = "mpfr-native gmp-native gettext-native libmpc-native elfutils-native"
SRCREV = "165931"
LICENSE="GCC RUNTIME LIBRARY EXCEPTION & GPLv2 & GPLv3 & LGPLv2.1 & LGPLv3"
LIC_FILES_CHKSUM = "file://COPYING;md5=59530bdf33659b29e73d4adb9f9f6552 \
file://COPYING3;md5=d32239bcb673463ab874e80d47fae504 \
file://COPYING3.LIB;md5=6a6a8e020838b23406c81b19c1d46df6 \
file://COPYING.LIB;md5=2d5025d4aa3495befef8f17206a5b0a1 \
file://COPYING.RUNTIME;md5=fe60d87048567d4fe8c8a0ed2448bcc8"
SRCREV = "167948"
PV = "4.5"
# BINV should be incremented after updating to a revision
# after a minor gcc release (e.g. 4.5.1 or 4.5.2) has been made
@ -12,121 +20,144 @@ PV = "4.5"
# 4.5.1 then the value below will be 2 which will mean 4.5.2
# which will be next minor release and so on.
BINV = "${PV}.2"
BINV = "${PV}.3"
BRANCH = "gcc-4_5-branch"
PR_append = "+svnr${SRCPV}"
SRC_URI = "svn://gcc.gnu.org/svn/gcc/branches;module=${BRANCH} \
file://gcc-4.3.1-ARCH_FLAGS_FOR_TARGET.patch \
file://100-uclibc-conf.patch \
file://gcc-uclibc-locale-ctype_touplow_t.patch \
file://cache-amnesia.patch \
file://gcc-flags-for-build.patch \
file://libstdc++-emit-__cxa_end_cleanup-in-text.patch \
file://arm-bswapsi2.patch \
file://Makefile.in.patch \
file://linaro/gcc-4.5-linaro-r99297.patch \
file://linaro/gcc-4.5-linaro-r99298.patch \
file://linaro/gcc-4.5-linaro-r99299.patch \
file://linaro/gcc-4.5-linaro-r99300.patch \
file://linaro/gcc-4.5-linaro-r99301.patch \
file://linaro/gcc-4.5-linaro-r99302.patch \
file://linaro/gcc-4.5-linaro-r99303.patch \
file://linaro/gcc-4.5-linaro-r99304.patch \
file://linaro/gcc-4.5-linaro-r99305.patch \
file://linaro/gcc-4.5-linaro-r99306.patch \
file://linaro/gcc-4.5-linaro-r99307.patch \
file://linaro/gcc-4.5-linaro-r99308.patch \
file://linaro/gcc-4.5-linaro-r99310.patch \
file://linaro/gcc-4.5-linaro-r99312.patch \
file://linaro/gcc-4.5-linaro-r99313.patch \
file://linaro/gcc-4.5-linaro-r99314.patch \
file://linaro/gcc-4.5-linaro-r99315.patch \
file://linaro/gcc-4.5-linaro-r99316.patch \
file://linaro/gcc-4.5-linaro-r99318.patch \
file://linaro/gcc-4.5-linaro-r99319.patch \
file://linaro/gcc-4.5-linaro-r99320.patch \
file://linaro/gcc-4.5-linaro-r99321.patch \
file://linaro/gcc-4.5-linaro-r99322.patch \
file://linaro/gcc-4.5-linaro-r99323.patch \
file://linaro/gcc-4.5-linaro-r99324.patch \
file://linaro/gcc-4.5-linaro-r99325.patch \
file://linaro/gcc-4.5-linaro-r99326.patch \
file://linaro/gcc-4.5-linaro-r99327.patch \
file://linaro/gcc-4.5-linaro-r99332.patch \
file://linaro/gcc-4.5-linaro-r99335.patch \
file://linaro/gcc-4.5-linaro-r99336.patch \
file://linaro/gcc-4.5-linaro-r99337.patch \
file://linaro/gcc-4.5-linaro-r99338.patch \
file://linaro/gcc-4.5-linaro-r99339.patch \
file://linaro/gcc-4.5-linaro-r99340.patch \
file://linaro/gcc-4.5-linaro-r99341.patch \
file://linaro/gcc-4.5-linaro-r99342.patch \
file://linaro/gcc-4.5-linaro-r99343.patch \
file://linaro/gcc-4.5-linaro-r99344.patch \
file://linaro/gcc-4.5-linaro-r99345.patch \
file://linaro/gcc-4.5-linaro-r99346.patch \
file://linaro/gcc-4.5-linaro-r99347.patch \
file://linaro/gcc-4.5-linaro-r99348.patch \
file://linaro/gcc-4.5-linaro-r99349.patch \
# file://linaro/gcc-4.5-linaro-r99350.patch \
file://linaro/gcc-4.5-linaro-r99351.patch \
file://linaro/gcc-4.5-linaro-r99352.patch \
file://linaro/gcc-4.5-linaro-r99353.patch \
file://linaro/gcc-4.5-linaro-r99354.patch \
file://linaro/gcc-4.5-linaro-r99355.patch \
file://linaro/gcc-4.5-linaro-r99356.patch \
file://linaro/gcc-4.5-linaro-r99357.patch \
file://linaro/gcc-4.5-linaro-r99358.patch \
file://linaro/gcc-4.5-linaro-r99359.patch \
file://linaro/gcc-4.5-linaro-r99360.patch \
file://linaro/gcc-4.5-linaro-r99361.patch \
file://linaro/gcc-4.5-linaro-r99363.patch \
file://linaro/gcc-4.5-linaro-r99364.patch \
file://linaro/gcc-4.5-linaro-r99365.patch \
file://linaro/gcc-4.5-linaro-r99366.patch \
file://linaro/gcc-4.5-linaro-r99367.patch \
file://linaro/gcc-4.5-linaro-r99368.patch \
file://linaro/gcc-4.5-linaro-r99369.patch \
file://linaro/gcc-4.5-linaro-r99371.patch \
file://linaro/gcc-4.5-linaro-r99372.patch \
file://linaro/gcc-4.5-linaro-r99373.patch \
file://linaro/gcc-4.5-linaro-r99374.patch \
file://linaro/gcc-4.5-linaro-r99375.patch \
file://linaro/gcc-4.5-linaro-r99376.patch \
file://linaro/gcc-4.5-linaro-r99377.patch \
file://linaro/gcc-4.5-linaro-r99378.patch \
file://linaro/gcc-4.5-linaro-r99379.patch \
file://linaro/gcc-4.5-linaro-r99380.patch \
file://linaro/gcc-4.5-linaro-r99381.patch \
file://linaro/gcc-4.5-linaro-r99383.patch \
file://linaro/gcc-4.5-linaro-r99384.patch \
file://linaro/gcc-4.5-linaro-r99385.patch \
file://linaro/gcc-4.5-linaro-r99388.patch \
file://linaro/gcc-4.5-linaro-r99391.patch \
file://linaro/gcc-4.5-linaro-r99392.patch \
file://linaro/gcc-4.5-linaro-r99393.patch \
file://linaro/gcc-4.5-linaro-r99395.patch \
file://linaro/gcc-4.5-linaro-r99396.patch \
file://linaro/gcc-4.5-linaro-r99397.patch \
file://linaro/gcc-4.5-linaro-r99398.patch \
file://linaro/gcc-4.5-linaro-r99402.patch \
file://linaro/gcc-4.5-linaro-r99403.patch \
file://linaro/gcc-4.5-linaro-r99404.patch \
file://linaro/gcc-4.5-linaro-r99405.patch \
file://linaro/gcc-4.5-linaro-r99406.patch \
file://linaro/gcc-4.5-linaro-r99407.patch \
file://linaro/gcc-4.5-linaro-r99408.patch \
file://linaro/gcc-4.5-linaro-r99409.patch \
file://linaro/gcc-4.5-linaro-r99410.patch \
file://linaro/gcc-4.5-linaro-r99411.patch \
file://linaro/gcc-4.5-linaro-r99412.patch \
file://linaro/gcc-4.5-linaro-r99413.patch \
file://linaro/gcc-4.5-linaro-r99414.patch \
file://linaro/gcc-4.5-linaro-r99415.patch \
file://gcc-vmovl-PR45805.patch \
file://gcc-scalar-widening-pr45847.patch \
file://gcc-linaro-fix-lp-653316.patch \
file://gcc-4.3.1-ARCH_FLAGS_FOR_TARGET.patch \
file://100-uclibc-conf.patch \
file://gcc-uclibc-locale-ctype_touplow_t.patch \
file://cache-amnesia.patch \
file://gcc-flags-for-build.patch \
file://libstdc++-emit-__cxa_end_cleanup-in-text.patch \
file://arm-bswapsi2.patch \
file://Makefile.in.patch \
file://gcc-armv4-pass-fix-v4bx-to-ld.patch \
file://linaro/gcc-4.5-linaro-r99297.patch \
file://linaro/gcc-4.5-linaro-r99298.patch \
file://linaro/gcc-4.5-linaro-r99299.patch \
file://linaro/gcc-4.5-linaro-r99300.patch \
file://linaro/gcc-4.5-linaro-r99301.patch \
file://linaro/gcc-4.5-linaro-r99302.patch \
file://linaro/gcc-4.5-linaro-r99303.patch \
file://linaro/gcc-4.5-linaro-r99304.patch \
file://linaro/gcc-4.5-linaro-r99305.patch \
file://linaro/gcc-4.5-linaro-r99306.patch \
file://linaro/gcc-4.5-linaro-r99307.patch \
file://linaro/gcc-4.5-linaro-r99308.patch \
file://linaro/gcc-4.5-linaro-r99310.patch \
file://linaro/gcc-4.5-linaro-r99312.patch \
file://linaro/gcc-4.5-linaro-r99313.patch \
file://linaro/gcc-4.5-linaro-r99314.patch \
file://linaro/gcc-4.5-linaro-r99315.patch \
file://linaro/gcc-4.5-linaro-r99316.patch \
file://linaro/gcc-4.5-linaro-r99318.patch \
file://linaro/gcc-4.5-linaro-r99319.patch \
file://linaro/gcc-4.5-linaro-r99320.patch \
file://linaro/gcc-4.5-linaro-r99321.patch \
file://linaro/gcc-4.5-linaro-r99322.patch \
file://linaro/gcc-4.5-linaro-r99323.patch \
file://linaro/gcc-4.5-linaro-r99324.patch \
file://linaro/gcc-4.5-linaro-r99325.patch \
file://linaro/gcc-4.5-linaro-r99326.patch \
file://linaro/gcc-4.5-linaro-r99327.patch \
file://linaro/gcc-4.5-linaro-r99332.patch \
file://linaro/gcc-4.5-linaro-r99335.patch \
file://linaro/gcc-4.5-linaro-r99336.patch \
file://linaro/gcc-4.5-linaro-r99337.patch \
file://linaro/gcc-4.5-linaro-r99338.patch \
file://linaro/gcc-4.5-linaro-r99339.patch \
file://linaro/gcc-4.5-linaro-r99340.patch \
file://linaro/gcc-4.5-linaro-r99341.patch \
file://linaro/gcc-4.5-linaro-r99342.patch \
file://linaro/gcc-4.5-linaro-r99343.patch \
file://linaro/gcc-4.5-linaro-r99344.patch \
file://linaro/gcc-4.5-linaro-r99345.patch \
file://linaro/gcc-4.5-linaro-r99346.patch \
file://linaro/gcc-4.5-linaro-r99347.patch \
file://linaro/gcc-4.5-linaro-r99348.patch \
file://linaro/gcc-4.5-linaro-r99349.patch \
# file://linaro/gcc-4.5-linaro-r99350.patch \
file://linaro/gcc-4.5-linaro-r99351.patch \
file://linaro/gcc-4.5-linaro-r99352.patch \
file://linaro/gcc-4.5-linaro-r99353.patch \
file://linaro/gcc-4.5-linaro-r99354.patch \
file://linaro/gcc-4.5-linaro-r99355.patch \
file://linaro/gcc-4.5-linaro-r99356.patch \
file://linaro/gcc-4.5-linaro-r99357.patch \
file://linaro/gcc-4.5-linaro-r99358.patch \
file://linaro/gcc-4.5-linaro-r99359.patch \
file://linaro/gcc-4.5-linaro-r99360.patch \
file://linaro/gcc-4.5-linaro-r99361.patch \
file://linaro/gcc-4.5-linaro-r99363.patch \
file://linaro/gcc-4.5-linaro-r99364.patch \
file://linaro/gcc-4.5-linaro-r99365.patch \
file://linaro/gcc-4.5-linaro-r99366.patch \
file://linaro/gcc-4.5-linaro-r99367.patch \
file://linaro/gcc-4.5-linaro-r99368.patch \
file://linaro/gcc-4.5-linaro-r99369.patch \
file://linaro/gcc-4.5-linaro-r99371.patch \
file://linaro/gcc-4.5-linaro-r99372.patch \
file://linaro/gcc-4.5-linaro-r99373.patch \
file://linaro/gcc-4.5-linaro-r99374.patch \
file://linaro/gcc-4.5-linaro-r99375.patch \
file://linaro/gcc-4.5-linaro-r99376.patch \
file://linaro/gcc-4.5-linaro-r99377.patch \
file://linaro/gcc-4.5-linaro-r99378.patch \
file://linaro/gcc-4.5-linaro-r99379.patch \
file://linaro/gcc-4.5-linaro-r99380.patch \
file://linaro/gcc-4.5-linaro-r99381.patch \
file://linaro/gcc-4.5-linaro-r99383.patch \
file://linaro/gcc-4.5-linaro-r99384.patch \
file://linaro/gcc-4.5-linaro-r99385.patch \
file://linaro/gcc-4.5-linaro-r99388.patch \
file://linaro/gcc-4.5-linaro-r99391.patch \
file://linaro/gcc-4.5-linaro-r99392.patch \
file://linaro/gcc-4.5-linaro-r99393.patch \
file://linaro/gcc-4.5-linaro-r99395.patch \
file://linaro/gcc-4.5-linaro-r99396.patch \
file://linaro/gcc-4.5-linaro-r99397.patch \
file://linaro/gcc-4.5-linaro-r99398.patch \
file://linaro/gcc-4.5-linaro-r99402.patch \
file://linaro/gcc-4.5-linaro-r99403.patch \
file://linaro/gcc-4.5-linaro-r99404.patch \
file://linaro/gcc-4.5-linaro-r99405.patch \
file://linaro/gcc-4.5-linaro-r99406.patch \
file://linaro/gcc-4.5-linaro-r99407.patch \
file://linaro/gcc-4.5-linaro-r99408.patch \
file://linaro/gcc-4.5-linaro-r99409.patch \
file://linaro/gcc-4.5-linaro-r99410.patch \
file://linaro/gcc-4.5-linaro-r99411.patch \
file://linaro/gcc-4.5-linaro-r99412.patch \
file://linaro/gcc-4.5-linaro-r99413.patch \
file://linaro/gcc-4.5-linaro-r99414.patch \
file://linaro/gcc-4.5-linaro-r99415.patch \
file://linaro/gcc-4.5-linaro-r99416.patch \
file://linaro/gcc-4.5-linaro-r99417.patch \
file://linaro/gcc-4.5-linaro-r99418.patch \
file://linaro/gcc-4.5-linaro-r99419.patch \
file://linaro/gcc-4.5-linaro-r99420.patch \
file://linaro/gcc-4.5-linaro-r99421.patch \
file://linaro/gcc-4.5-linaro-r99423.patch \
file://linaro/gcc-4.5-linaro-r99424.patch \
file://linaro/gcc-4.5-linaro-r99425.patch \
file://linaro/gcc-4.5-linaro-r99426.patch \
file://linaro/gcc-4.5-linaro-r99429.patch \
file://linaro/gcc-4.5-linaro-r99432.patch \
file://linaro/gcc-4.5-linaro-r99433.patch \
file://linaro/gcc-4.5-linaro-r99434.patch \
file://linaro/gcc-4.5-linaro-r99435.patch \
file://linaro/gcc-4.5-linaro-r99436.patch \
file://linaro/gcc-4.5-linaro-r99437.patch \
file://linaro/gcc-4.5-linaro-r99439.patch \
file://linaro/gcc-4.5-linaro-r99440.patch \
file://linaro/gcc-4.5-linaro-r99441.patch \
file://linaro/gcc-4.5-linaro-r99442.patch \
file://linaro/gcc-4.5-linaro-r99443.patch \
file://linaro/gcc-4.5-linaro-r99444.patch \
file://gcc-scalar-widening-pr45847.patch \
file://gcc-arm-qihi-split-PR46883.patch \
\
file://optional_libstdc.patch \
file://64bithack.patch \

View File

@ -0,0 +1,52 @@
Backport of http://gcc.gnu.org/ml/gcc-patches/2010-12/msg01096.html
This should fix the ICE found in samba
-Khem
Index: a/gcc/config/arm/arm.md
===================================================================
--- a/gcc/config/arm/arm.md (revision 167797)
+++ b/gcc/config/arm/arm.md (working copy)
@@ -4137,8 +4137,8 @@
})
(define_split
- [(set (match_operand:SI 0 "register_operand" "")
- (zero_extend:SI (match_operand:HI 1 "register_operand" "")))]
+ [(set (match_operand:SI 0 "s_register_operand" "")
+ (zero_extend:SI (match_operand:HI 1 "s_register_operand" "")))]
"!TARGET_THUMB2 && !arm_arch6"
[(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
(set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
@@ -4244,8 +4244,8 @@
})
(define_split
- [(set (match_operand:SI 0 "register_operand" "")
- (zero_extend:SI (match_operand:QI 1 "register_operand" "")))]
+ [(set (match_operand:SI 0 "s_register_operand" "")
+ (zero_extend:SI (match_operand:QI 1 "s_register_operand" "")))]
"!arm_arch6"
[(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
(set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 24)))]
Index: a/gcc/testsuite/gcc.target/arm/pr46883.c
===================================================================
--- a/gcc/testsuite/gcc.target/arm/pr46883.c (revision 0)
+++ b/gcc/testsuite/gcc.target/arm/pr46883.c (revision 0)
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -march=armv5te" } */
+
+void bar (unsigned char *q, unsigned short *data16s, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ {
+ q[2 * i] =
+ (((data16s[i] & 0xFF) << 8) | ((data16s[i] >> 8) & 0xFF)) & 0xFF;
+ q[2 * i + 1] =
+ ((unsigned short)
+ (((data16s[i] & 0xFF) << 8) | ((data16s[i] >> 8) & 0xFF))) >> 8;
+ }
+}

View File

@ -0,0 +1,29 @@
The LINK_SPEC for linux gets overwritten by linux-eabi.h which
means the value of TARGET_FIX_V4BX_SPEC gets lost and as a result
the option is not passed to linker when chosing march=armv4
This patch redefines this in linux-eabi.h and reinserts it
for eabi defaulting toolchains.
We might want to send it upstream
-Khem
Index: gcc-4.5/gcc/config/arm/linux-eabi.h
===================================================================
--- gcc-4.5.orig/gcc/config/arm/linux-eabi.h
+++ gcc-4.5/gcc/config/arm/linux-eabi.h
@@ -63,10 +63,14 @@
#undef GLIBC_DYNAMIC_LINKER
#define GLIBC_DYNAMIC_LINKER "/lib/ld-linux.so.3"
+/* For armv4 we pass --fix-v4bx to linker to support EABI */
+#undef TARGET_FIX_V4BX_SPEC
+#define TARGET_FIX_V4BX_SPEC " %{mcpu=arm8|mcpu=arm810|mcpu=strongarm*|march=armv4:--fix-v4bx}"
+
/* At this point, bpabi.h will have clobbered LINK_SPEC. We want to
use the GNU/Linux version, not the generic BPABI version. */
#undef LINK_SPEC
-#define LINK_SPEC LINUX_TARGET_LINK_SPEC BE8_LINK_SPEC
+#define LINK_SPEC LINUX_TARGET_LINK_SPEC BE8_LINK_SPEC TARGET_FIX_V4BX_SPEC
/* Use the default LIBGCC_SPEC, not the version in linux-elf.h, as we
do not use -lfloat. */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,130 @@
2010-10-15 Chung-Lin Tang <cltang@codesourcery.com>
Backport from mainline:
2010-10-15 Chung-Lin Tang <cltang@codesourcery.com>
gcc/
* ifcvt.c (find_active_insn_before): New function.
(find_active_insn_after): New function.
(cond_exec_process_if_block): Use new functions to replace
prev_active_insn() and next_active_insn().
gcc/testsuite/
* gcc.dg/20101010-1.c: New testcase.
=== modified file 'gcc/ifcvt.c'
Index: gcc-4.5/gcc/ifcvt.c
===================================================================
--- gcc-4.5.orig/gcc/ifcvt.c
+++ gcc-4.5/gcc/ifcvt.c
@@ -88,6 +88,8 @@ static int count_bb_insns (const_basic_b
static bool cheap_bb_rtx_cost_p (const_basic_block, int);
static rtx first_active_insn (basic_block);
static rtx last_active_insn (basic_block, int);
+static rtx find_active_insn_before (basic_block, rtx);
+static rtx find_active_insn_after (basic_block, rtx);
static basic_block block_fallthru (basic_block);
static int cond_exec_process_insns (ce_if_block_t *, rtx, rtx, rtx, rtx, int);
static rtx cond_exec_get_condition (rtx);
@@ -230,6 +232,48 @@ last_active_insn (basic_block bb, int sk
return insn;
}
+/* Return the active insn before INSN inside basic block CURR_BB. */
+
+static rtx
+find_active_insn_before (basic_block curr_bb, rtx insn)
+{
+ if (!insn || insn == BB_HEAD (curr_bb))
+ return NULL_RTX;
+
+ while ((insn = PREV_INSN (insn)) != NULL_RTX)
+ {
+ if (NONJUMP_INSN_P (insn) || JUMP_P (insn) || CALL_P (insn))
+ break;
+
+ /* No other active insn all the way to the start of the basic block. */
+ if (insn == BB_HEAD (curr_bb))
+ return NULL_RTX;
+ }
+
+ return insn;
+}
+
+/* Return the active insn after INSN inside basic block CURR_BB. */
+
+static rtx
+find_active_insn_after (basic_block curr_bb, rtx insn)
+{
+ if (!insn || insn == BB_END (curr_bb))
+ return NULL_RTX;
+
+ while ((insn = NEXT_INSN (insn)) != NULL_RTX)
+ {
+ if (NONJUMP_INSN_P (insn) || JUMP_P (insn) || CALL_P (insn))
+ break;
+
+ /* No other active insn all the way to the end of the basic block. */
+ if (insn == BB_END (curr_bb))
+ return NULL_RTX;
+ }
+
+ return insn;
+}
+
/* Return the basic block reached by falling though the basic block BB. */
static basic_block
@@ -448,9 +492,9 @@ cond_exec_process_if_block (ce_if_block_
if (n_matching > 0)
{
if (then_end)
- then_end = prev_active_insn (then_first_tail);
+ then_end = find_active_insn_before (then_bb, then_first_tail);
if (else_end)
- else_end = prev_active_insn (else_first_tail);
+ else_end = find_active_insn_before (else_bb, else_first_tail);
n_insns -= 2 * n_matching;
}
@@ -488,9 +532,9 @@ cond_exec_process_if_block (ce_if_block_
if (n_matching > 0)
{
if (then_start)
- then_start = next_active_insn (then_last_head);
+ then_start = find_active_insn_after (then_bb, then_last_head);
if (else_start)
- else_start = next_active_insn (else_last_head);
+ else_start = find_active_insn_after (else_bb, else_last_head);
n_insns -= 2 * n_matching;
}
}
@@ -646,7 +690,7 @@ cond_exec_process_if_block (ce_if_block_
{
rtx from = then_first_tail;
if (!INSN_P (from))
- from = next_active_insn (from);
+ from = find_active_insn_after (then_bb, from);
delete_insn_chain (from, BB_END (then_bb), false);
}
if (else_last_head)
Index: gcc-4.5/gcc/testsuite/gcc.dg/20101010-1.c
===================================================================
--- /dev/null
+++ gcc-4.5/gcc/testsuite/gcc.dg/20101010-1.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-crossjumping" } */
+
+int foo (void)
+{
+ int len;
+ if (bar1 (&len))
+ {
+ char devpath [len];
+ if (bar2 (devpath) == len)
+ return len;
+ }
+ return -1;
+}

View File

@ -0,0 +1,53 @@
2010-10-15 Jie Zhang <jie@codesourcery.com>
Backport from mainline:
gcc/testsuite/
2010-10-15 Jie Zhang <jie@codesourcery.com>
* lib/lto.exp (lto-link-and-maybe-run): Use the default linker
script when relocatable linking.
=== modified file 'gcc/testsuite/lib/lto.exp'
Index: gcc-4.5/gcc/testsuite/lib/lto.exp
===================================================================
--- gcc-4.5.orig/gcc/testsuite/lib/lto.exp
+++ gcc-4.5/gcc/testsuite/lib/lto.exp
@@ -156,6 +156,7 @@ proc lto-link-and-maybe-run { testname o
global testcase
global tool
global compile_type
+ global board_info
# Check that all of the objects were built successfully.
foreach obj [split $objlist] {
@@ -170,10 +171,29 @@ proc lto-link-and-maybe-run { testname o
set options ""
lappend options "additional_flags=$optall $optfile"
+ set target_board [target_info name]
+ set relocatable 0
+
+ # Some LTO tests do relocatable linking. Some target boards set
+ # a linker script which can't be used for relocatable linking.
+ # Use the default linker script instead.
+ if { [lsearch -exact [split "$optall $optfile"] "-r"] >= 0 } {
+ set relocatable 1
+ }
+
+ if { $relocatable } {
+ set saved_ldscript [board_info $target_board ldscript]
+ set board_info($target_board,ldscript) ""
+ }
+
# Link the objects into an executable.
set comp_output [${tool}_target_compile "$objlist" $dest executable \
"$options"]
+ if { $relocatable } {
+ set board_info($target_board,ldscript) $saved_ldscript
+ }
+
# Prune unimportant visibility warnings before checking output.
set comp_output [lto_prune_warns $comp_output]

View File

@ -0,0 +1,25 @@
2010-10-20 Yao Qi <yao@codesourcery.com>
Merge from Sourcery G++ to fix LP:660021
2010-10-18 Paul Brook <paul@codesourcery.com>
* tree-vect-stmts.c (supportable_widening_operation): Check if wide
vector type exists.
=== modified file 'gcc/tree-vect-stmts.c'
Index: gcc-4.5/gcc/tree-vect-stmts.c
===================================================================
--- gcc-4.5.orig/gcc/tree-vect-stmts.c
+++ gcc-4.5/gcc/tree-vect-stmts.c
@@ -4867,6 +4867,11 @@ supportable_widening_operation (enum tre
tree wide_vectype = get_vectype_for_scalar_type (type);
enum tree_code c1, c2;
+ /* Check we have a valid vector type for the result. */
+ if (!wide_vectype)
+ return false;
+
+
/* The result of a vectorized widening operation usually requires two vectors
(because the widened results do not fit int one vector). The generated
vector results would normally be expected to be generated in the same

View File

@ -0,0 +1,734 @@
2010-10-22 Julian Brown <julian@codesourcery.com>
Backport from mainline:
2010-10-18 Marcus Shawcroft <marcus.shawcroft@arm.com>
gcc/testsuite/
* gcc.target/arm/synchronize.c: Permit dmb or mcr in assembler scan.
2010-10-14 Julian Brown <julian@codesourcery.com>
Backport from mainline:
2010-08-18 Marcus Shawcroft <marcus.shawcroft@arm.com>
gcc/
* config/arm/arm-protos.h (arm_expand_sync): New.
(arm_output_memory_barrier, arm_output_sync_insn): New.
(arm_sync_loop_insns): New.
* config/arm/arm.c (FL_ARCH7): New.
(FL_FOR_ARCH7): Include FL_ARCH7.
(arm_arch7): New.
(arm_print_operand): Support %C markup.
(arm_legitimize_sync_memory): New.
(arm_emit, arm_insn_count, arm_count, arm_output_asm_insn): New.
(arm_process_output_memory_barrier, arm_output_memory_barrier): New.
(arm_ldrex_suffix, arm_output_ldrex, arm_output_strex): New.
(arm_output_op2, arm_output_op3, arm_output_sync_loop): New.
(arm_get_sync_operand, FETCH_SYNC_OPERAND): New.
(arm_process_output_sync_insn, arm_output_sync_insn): New.
(arm_sync_loop_insns,arm_call_generator, arm_expand_sync): New.
* config/arm/arm.h (struct arm_sync_generator): New.
(TARGET_HAVE_DMB, TARGET_HAVE_DMB_MCR): New.
(TARGET_HAVE_MEMORY_BARRIER): New.
(TARGET_HAVE_LDREX, TARGET_HAVE_LDREXBHD): New.
* config/arm/arm.md: Include sync.md.
(UNSPEC_MEMORY_BARRIER): New.
(VUNSPEC_SYNC_COMPARE_AND_SWAP, VUNSPEC_SYNC_LOCK): New.
(VUNSPEC_SYNC_OP):New.
(VUNSPEC_SYNC_NEW_OP, VUNSPEC_SYNC_OLD_OP): New.
(sync_result, sync_memory, sync_required_value): New attributes.
(sync_new_value, sync_t1, sync_t2): Likewise.
(sync_release_barrier, sync_op): Likewise.
(length): Add logic to length attribute defintion to call
arm_sync_loop_insns when appropriate.
* config/arm/sync.md: New file.
2010-09-02 Marcus Shawcroft <marcus.shawcroft@arm.com>
gcc/
* config/arm/predicates.md (arm_sync_memory_operand): New.
* config/arm/sync.md (arm_sync_compare_and_swapsi): Change predicate
to arm_sync_memory_operand and constraint to Q.
(arm_sync_compare_and_swap<mode>): Likewise.
(arm_sync_compare_and_swap<mode>): Likewise.
(arm_sync_lock_test_and_setsi): Likewise.
(arm_sync_lock_test_and_set<mode>): Likewise.
(arm_sync_new_<sync_optab>si): Likewise.
(arm_sync_new_nandsi): Likewise.
(arm_sync_new_<sync_optab><mode>): Likewise.
(arm_sync_new_nand<mode>): Likewise.
(arm_sync_old_<sync_optab>si): Likewise.
(arm_sync_old_nandsi): Likewise.
(arm_sync_old_<sync_optab><mode>): Likewise.
(arm_sync_old_nand<mode>): Likewise.
2010-09-13 Marcus Shawcroft <marcus.shawcroft@arm.com>
gcc/
* config/arm/arm.md: (define_attr "conds"): Update comment.
* config/arm/sync.md (arm_sync_compare_and_swapsi): Change
conds attribute to clob.
(arm_sync_compare_and_swapsi): Likewise.
(arm_sync_compare_and_swap<mode>): Likewise.
(arm_sync_lock_test_and_setsi): Likewise.
(arm_sync_lock_test_and_set<mode>): Likewise.
(arm_sync_new_<sync_optab>si): Likewise.
(arm_sync_new_nandsi): Likewise.
(arm_sync_new_<sync_optab><mode>): Likewise.
(arm_sync_new_nand<mode>): Likewise.
(arm_sync_old_<sync_optab>si): Likewise.
(arm_sync_old_nandsi): Likewise.
(arm_sync_old_<sync_optab><mode>): Likewise.
(arm_sync_old_nand<mode>): Likewise.
2010-09-13 Marcus Shawcroft <marcus.shawcroft@arm.com>
gcc/testsuite/
* gcc.target/arm/sync-1.c: New.
Backport from FSF:
gcc/
2010-08-18 Marcus Shawcroft <marcus.shawcroft@arm.com>
* config/arm/arm-protos.h (arm_expand_sync): New.
(arm_output_memory_barrier, arm_output_sync_insn): New.
(arm_sync_loop_insns): New.
* config/arm/arm.c (FL_ARCH7): New.
(FL_FOR_ARCH7): Include FL_ARCH7.
(arm_arch7): New.
(arm_print_operand): Support %C markup.
(arm_legitimize_sync_memory): New.
(arm_emit, arm_insn_count, arm_count, arm_output_asm_insn): New.
(arm_process_output_memory_barrier, arm_output_memory_barrier): New.
(arm_ldrex_suffix, arm_output_ldrex, arm_output_strex): New.
(arm_output_op2, arm_output_op3, arm_output_sync_loop): New.
(arm_get_sync_operand, FETCH_SYNC_OPERAND): New.
(arm_process_output_sync_insn, arm_output_sync_insn): New.
(arm_sync_loop_insns,arm_call_generator, arm_expand_sync): New.
* config/arm/arm.h (struct arm_sync_generator): New.
(TARGET_HAVE_DMB, TARGET_HAVE_DMB_MCR): New.
(TARGET_HAVE_MEMORY_BARRIER): New.
(TARGET_HAVE_LDREX, TARGET_HAVE_LDREXBHD): New.
* config/arm/arm.md: Include sync.md.
(UNSPEC_MEMORY_BARRIER): New.
(VUNSPEC_SYNC_COMPARE_AND_SWAP, VUNSPEC_SYNC_LOCK): New.
(VUNSPEC_SYNC_OP):New.
(VUNSPEC_SYNC_NEW_OP, VUNSPEC_SYNC_OLD_OP): New.
(sync_result, sync_memory, sync_required_value): New attributes.
(sync_new_value, sync_t1, sync_t2): Likewise.
(sync_release_barrier, sync_op): Likewise.
(length): Add logic to length attribute defintion to call
arm_sync_loop_insns when appropriate.
* config/arm/sync.md: New file.
gcc/
2010-09-02 Marcus Shawcroft <marcus.shawcroft@arm.com>
* config/arm/predicates.md (arm_sync_memory_operand): New.
* config/arm/sync.md (arm_sync_compare_and_swapsi): Change predicate
to arm_sync_memory_operand and constraint to Q.
(arm_sync_compare_and_swap<mode>): Likewise.
(arm_sync_compare_and_swap<mode>): Likewise.
(arm_sync_lock_test_and_setsi): Likewise.
(arm_sync_lock_test_and_set<mode>): Likewise.
(arm_sync_new_<sync_optab>si): Likewise.
(arm_sync_new_nandsi): Likewise.
(arm_sync_new_<sync_optab><mode>): Likewise.
(arm_sync_new_nand<mode>): Likewise.
(arm_sync_old_<sync_optab>si): Likewise.
(arm_sync_old_nandsi): Likewise.
(arm_sync_old_<sync_optab><mode>): Likewise.
(arm_sync_old_nand<mode>): Likewise.
=== modified file 'gcc/config/arm/arm-protos.h'
Index: gcc-4.5/gcc/config/arm/arm-protos.h
===================================================================
--- gcc-4.5.orig/gcc/config/arm/arm-protos.h
+++ gcc-4.5/gcc/config/arm/arm-protos.h
@@ -151,6 +151,11 @@ extern const char *vfp_output_fstmd (rtx
extern void arm_set_return_address (rtx, rtx);
extern int arm_eliminable_register (rtx);
extern const char *arm_output_shift(rtx *, int);
+extern void arm_expand_sync (enum machine_mode, struct arm_sync_generator *,
+ rtx, rtx, rtx, rtx);
+extern const char *arm_output_memory_barrier (rtx *);
+extern const char *arm_output_sync_insn (rtx, rtx *);
+extern unsigned int arm_sync_loop_insns (rtx , rtx *);
extern bool arm_output_addr_const_extra (FILE *, rtx);
Index: gcc-4.5/gcc/config/arm/arm.c
===================================================================
--- gcc-4.5.orig/gcc/config/arm/arm.c
+++ gcc-4.5/gcc/config/arm/arm.c
@@ -602,6 +602,7 @@ static int thumb_call_reg_needed;
#define FL_NEON (1 << 20) /* Neon instructions. */
#define FL_ARCH7EM (1 << 21) /* Instructions present in the ARMv7E-M
architecture. */
+#define FL_ARCH7 (1 << 22) /* Architecture 7. */
#define FL_IWMMXT (1 << 29) /* XScale v2 or "Intel Wireless MMX technology". */
@@ -626,7 +627,7 @@ static int thumb_call_reg_needed;
#define FL_FOR_ARCH6ZK FL_FOR_ARCH6K
#define FL_FOR_ARCH6T2 (FL_FOR_ARCH6 | FL_THUMB2)
#define FL_FOR_ARCH6M (FL_FOR_ARCH6 & ~FL_NOTM)
-#define FL_FOR_ARCH7 (FL_FOR_ARCH6T2 &~ FL_NOTM)
+#define FL_FOR_ARCH7 ((FL_FOR_ARCH6T2 & ~FL_NOTM) | FL_ARCH7)
#define FL_FOR_ARCH7A (FL_FOR_ARCH7 | FL_NOTM | FL_ARCH6K)
#define FL_FOR_ARCH7R (FL_FOR_ARCH7A | FL_DIV)
#define FL_FOR_ARCH7M (FL_FOR_ARCH7 | FL_DIV)
@@ -664,6 +665,9 @@ int arm_arch6 = 0;
/* Nonzero if this chip supports the ARM 6K extensions. */
int arm_arch6k = 0;
+/* Nonzero if this chip supports the ARM 7 extensions. */
+int arm_arch7 = 0;
+
/* Nonzero if instructions not present in the 'M' profile can be used. */
int arm_arch_notm = 0;
@@ -1602,6 +1606,7 @@ arm_override_options (void)
arm_arch6 = (insn_flags & FL_ARCH6) != 0;
arm_arch6k = (insn_flags & FL_ARCH6K) != 0;
arm_arch_notm = (insn_flags & FL_NOTM) != 0;
+ arm_arch7 = (insn_flags & FL_ARCH7) != 0;
arm_arch7em = (insn_flags & FL_ARCH7EM) != 0;
arm_arch_thumb2 = (insn_flags & FL_THUMB2) != 0;
arm_arch_xscale = (insn_flags & FL_XSCALE) != 0;
@@ -16562,6 +16567,17 @@ arm_print_operand (FILE *stream, rtx x,
}
return;
+ case 'C':
+ {
+ rtx addr;
+
+ gcc_assert (GET_CODE (x) == MEM);
+ addr = XEXP (x, 0);
+ gcc_assert (GET_CODE (addr) == REG);
+ asm_fprintf (stream, "[%r]", REGNO (addr));
+ }
+ return;
+
/* Translate an S register number into a D register number and element index. */
case 'y':
{
@@ -22793,4 +22809,372 @@ arm_builtin_support_vector_misalignment
is_packed);
}
+/* Legitimize a memory reference for sync primitive implemented using
+ ldrex / strex. We currently force the form of the reference to be
+ indirect without offset. We do not yet support the indirect offset
+ addressing supported by some ARM targets for these
+ instructions. */
+static rtx
+arm_legitimize_sync_memory (rtx memory)
+{
+ rtx addr = force_reg (Pmode, XEXP (memory, 0));
+ rtx legitimate_memory = gen_rtx_MEM (GET_MODE (memory), addr);
+
+ set_mem_alias_set (legitimate_memory, ALIAS_SET_MEMORY_BARRIER);
+ MEM_VOLATILE_P (legitimate_memory) = MEM_VOLATILE_P (memory);
+ return legitimate_memory;
+}
+
+/* An instruction emitter. */
+typedef void (* emit_f) (int label, const char *, rtx *);
+
+/* An instruction emitter that emits via the conventional
+ output_asm_insn. */
+static void
+arm_emit (int label ATTRIBUTE_UNUSED, const char *pattern, rtx *operands)
+{
+ output_asm_insn (pattern, operands);
+}
+
+/* Count the number of emitted synchronization instructions. */
+static unsigned arm_insn_count;
+
+/* An emitter that counts emitted instructions but does not actually
+ emit instruction into the the instruction stream. */
+static void
+arm_count (int label,
+ const char *pattern ATTRIBUTE_UNUSED,
+ rtx *operands ATTRIBUTE_UNUSED)
+{
+ if (! label)
+ ++ arm_insn_count;
+}
+
+/* Construct a pattern using conventional output formatting and feed
+ it to output_asm_insn. Provides a mechanism to construct the
+ output pattern on the fly. Note the hard limit on the pattern
+ buffer size. */
+static void
+arm_output_asm_insn (emit_f emit, int label, rtx *operands,
+ const char *pattern, ...)
+{
+ va_list ap;
+ char buffer[256];
+
+ va_start (ap, pattern);
+ vsprintf (buffer, pattern, ap);
+ va_end (ap);
+ emit (label, buffer, operands);
+}
+
+/* Emit the memory barrier instruction, if any, provided by this
+ target to a specified emitter. */
+static void
+arm_process_output_memory_barrier (emit_f emit, rtx *operands)
+{
+ if (TARGET_HAVE_DMB)
+ {
+ /* Note we issue a system level barrier. We should consider
+ issuing a inner shareabilty zone barrier here instead, ie.
+ "DMB ISH". */
+ emit (0, "dmb\tsy", operands);
+ return;
+ }
+
+ if (TARGET_HAVE_DMB_MCR)
+ {
+ emit (0, "mcr\tp15, 0, r0, c7, c10, 5", operands);
+ return;
+ }
+
+ gcc_unreachable ();
+}
+
+/* Emit the memory barrier instruction, if any, provided by this
+ target. */
+const char *
+arm_output_memory_barrier (rtx *operands)
+{
+ arm_process_output_memory_barrier (arm_emit, operands);
+ return "";
+}
+
+/* Helper to figure out the instruction suffix required on ldrex/strex
+ for operations on an object of the specified mode. */
+static const char *
+arm_ldrex_suffix (enum machine_mode mode)
+{
+ switch (mode)
+ {
+ case QImode: return "b";
+ case HImode: return "h";
+ case SImode: return "";
+ case DImode: return "d";
+ default:
+ gcc_unreachable ();
+ }
+ return "";
+}
+
+/* Emit an ldrex{b,h,d, } instruction appropriate for the specified
+ mode. */
+static void
+arm_output_ldrex (emit_f emit,
+ enum machine_mode mode,
+ rtx target,
+ rtx memory)
+{
+ const char *suffix = arm_ldrex_suffix (mode);
+ rtx operands[2];
+
+ operands[0] = target;
+ operands[1] = memory;
+ arm_output_asm_insn (emit, 0, operands, "ldrex%s\t%%0, %%C1", suffix);
+}
+
+/* Emit a strex{b,h,d, } instruction appropriate for the specified
+ mode. */
+static void
+arm_output_strex (emit_f emit,
+ enum machine_mode mode,
+ const char *cc,
+ rtx result,
+ rtx value,
+ rtx memory)
+{
+ const char *suffix = arm_ldrex_suffix (mode);
+ rtx operands[3];
+
+ operands[0] = result;
+ operands[1] = value;
+ operands[2] = memory;
+ arm_output_asm_insn (emit, 0, operands, "strex%s%s\t%%0, %%1, %%C2", suffix,
+ cc);
+}
+
+/* Helper to emit a two operand instruction. */
+static void
+arm_output_op2 (emit_f emit, const char *mnemonic, rtx d, rtx s)
+{
+ rtx operands[2];
+
+ operands[0] = d;
+ operands[1] = s;
+ arm_output_asm_insn (emit, 0, operands, "%s\t%%0, %%1", mnemonic);
+}
+
+/* Helper to emit a three operand instruction. */
+static void
+arm_output_op3 (emit_f emit, const char *mnemonic, rtx d, rtx a, rtx b)
+{
+ rtx operands[3];
+
+ operands[0] = d;
+ operands[1] = a;
+ operands[2] = b;
+ arm_output_asm_insn (emit, 0, operands, "%s\t%%0, %%1, %%2", mnemonic);
+}
+
+/* Emit a load store exclusive synchronization loop.
+
+ do
+ old_value = [mem]
+ if old_value != required_value
+ break;
+ t1 = sync_op (old_value, new_value)
+ [mem] = t1, t2 = [0|1]
+ while ! t2
+
+ Note:
+ t1 == t2 is not permitted
+ t1 == old_value is permitted
+
+ required_value:
+
+ RTX register or const_int representing the required old_value for
+ the modify to continue, if NULL no comparsion is performed. */
+static void
+arm_output_sync_loop (emit_f emit,
+ enum machine_mode mode,
+ rtx old_value,
+ rtx memory,
+ rtx required_value,
+ rtx new_value,
+ rtx t1,
+ rtx t2,
+ enum attr_sync_op sync_op,
+ int early_barrier_required)
+{
+ rtx operands[1];
+
+ gcc_assert (t1 != t2);
+
+ if (early_barrier_required)
+ arm_process_output_memory_barrier (emit, NULL);
+
+ arm_output_asm_insn (emit, 1, operands, "%sLSYT%%=:", LOCAL_LABEL_PREFIX);
+
+ arm_output_ldrex (emit, mode, old_value, memory);
+
+ if (required_value)
+ {
+ rtx operands[2];
+
+ operands[0] = old_value;
+ operands[1] = required_value;
+ arm_output_asm_insn (emit, 0, operands, "cmp\t%%0, %%1");
+ arm_output_asm_insn (emit, 0, operands, "bne\t%sLSYB%%=", LOCAL_LABEL_PREFIX);
+ }
+
+ switch (sync_op)
+ {
+ case SYNC_OP_ADD:
+ arm_output_op3 (emit, "add", t1, old_value, new_value);
+ break;
+
+ case SYNC_OP_SUB:
+ arm_output_op3 (emit, "sub", t1, old_value, new_value);
+ break;
+
+ case SYNC_OP_IOR:
+ arm_output_op3 (emit, "orr", t1, old_value, new_value);
+ break;
+
+ case SYNC_OP_XOR:
+ arm_output_op3 (emit, "eor", t1, old_value, new_value);
+ break;
+
+ case SYNC_OP_AND:
+ arm_output_op3 (emit,"and", t1, old_value, new_value);
+ break;
+
+ case SYNC_OP_NAND:
+ arm_output_op3 (emit, "and", t1, old_value, new_value);
+ arm_output_op2 (emit, "mvn", t1, t1);
+ break;
+
+ case SYNC_OP_NONE:
+ t1 = new_value;
+ break;
+ }
+
+ arm_output_strex (emit, mode, "", t2, t1, memory);
+ operands[0] = t2;
+ arm_output_asm_insn (emit, 0, operands, "teq\t%%0, #0");
+ arm_output_asm_insn (emit, 0, operands, "bne\t%sLSYT%%=", LOCAL_LABEL_PREFIX);
+
+ arm_process_output_memory_barrier (emit, NULL);
+ arm_output_asm_insn (emit, 1, operands, "%sLSYB%%=:", LOCAL_LABEL_PREFIX);
+}
+
+static rtx
+arm_get_sync_operand (rtx *operands, int index, rtx default_value)
+{
+ if (index > 0)
+ default_value = operands[index - 1];
+
+ return default_value;
+}
+
+#define FETCH_SYNC_OPERAND(NAME, DEFAULT) \
+ arm_get_sync_operand (operands, (int) get_attr_sync_##NAME (insn), DEFAULT);
+
+/* Extract the operands for a synchroniztion instruction from the
+ instructions attributes and emit the instruction. */
+static void
+arm_process_output_sync_insn (emit_f emit, rtx insn, rtx *operands)
+{
+ rtx result, memory, required_value, new_value, t1, t2;
+ int early_barrier;
+ enum machine_mode mode;
+ enum attr_sync_op sync_op;
+
+ result = FETCH_SYNC_OPERAND(result, 0);
+ memory = FETCH_SYNC_OPERAND(memory, 0);
+ required_value = FETCH_SYNC_OPERAND(required_value, 0);
+ new_value = FETCH_SYNC_OPERAND(new_value, 0);
+ t1 = FETCH_SYNC_OPERAND(t1, 0);
+ t2 = FETCH_SYNC_OPERAND(t2, 0);
+ early_barrier =
+ get_attr_sync_release_barrier (insn) == SYNC_RELEASE_BARRIER_YES;
+ sync_op = get_attr_sync_op (insn);
+ mode = GET_MODE (memory);
+
+ arm_output_sync_loop (emit, mode, result, memory, required_value,
+ new_value, t1, t2, sync_op, early_barrier);
+}
+
+/* Emit a synchronization instruction loop. */
+const char *
+arm_output_sync_insn (rtx insn, rtx *operands)
+{
+ arm_process_output_sync_insn (arm_emit, insn, operands);
+ return "";
+}
+
+/* Count the number of machine instruction that will be emitted for a
+ synchronization instruction. Note that the emitter used does not
+ emit instructions, it just counts instructions being carefull not
+ to count labels. */
+unsigned int
+arm_sync_loop_insns (rtx insn, rtx *operands)
+{
+ arm_insn_count = 0;
+ arm_process_output_sync_insn (arm_count, insn, operands);
+ return arm_insn_count;
+}
+
+/* Helper to call a target sync instruction generator, dealing with
+ the variation in operands required by the different generators. */
+static rtx
+arm_call_generator (struct arm_sync_generator *generator, rtx old_value,
+ rtx memory, rtx required_value, rtx new_value)
+{
+ switch (generator->op)
+ {
+ case arm_sync_generator_omn:
+ gcc_assert (! required_value);
+ return generator->u.omn (old_value, memory, new_value);
+
+ case arm_sync_generator_omrn:
+ gcc_assert (required_value);
+ return generator->u.omrn (old_value, memory, required_value, new_value);
+ }
+
+ return NULL;
+}
+
+/* Expand a synchronization loop. The synchronization loop is expanded
+ as an opaque block of instructions in order to ensure that we do
+ not subsequently get extraneous memory accesses inserted within the
+ critical region. The exclusive access property of ldrex/strex is
+ only guaranteed in there are no intervening memory accesses. */
+void
+arm_expand_sync (enum machine_mode mode,
+ struct arm_sync_generator *generator,
+ rtx target, rtx memory, rtx required_value, rtx new_value)
+{
+ if (target == NULL)
+ target = gen_reg_rtx (mode);
+
+ memory = arm_legitimize_sync_memory (memory);
+ if (mode != SImode)
+ {
+ rtx load_temp = gen_reg_rtx (SImode);
+
+ if (required_value)
+ required_value = convert_modes (SImode, mode, required_value, true);
+
+ new_value = convert_modes (SImode, mode, new_value, true);
+ emit_insn (arm_call_generator (generator, load_temp, memory,
+ required_value, new_value));
+ emit_move_insn (target, gen_lowpart (mode, load_temp));
+ }
+ else
+ {
+ emit_insn (arm_call_generator (generator, target, memory, required_value,
+ new_value));
+ }
+}
+
#include "gt-arm.h"
Index: gcc-4.5/gcc/config/arm/arm.h
===================================================================
--- gcc-4.5.orig/gcc/config/arm/arm.h
+++ gcc-4.5/gcc/config/arm/arm.h
@@ -128,6 +128,24 @@ enum target_cpus
/* The processor for which instructions should be scheduled. */
extern enum processor_type arm_tune;
+enum arm_sync_generator_tag
+ {
+ arm_sync_generator_omn,
+ arm_sync_generator_omrn
+ };
+
+/* Wrapper to pass around a polymorphic pointer to a sync instruction
+ generator and. */
+struct arm_sync_generator
+{
+ enum arm_sync_generator_tag op;
+ union
+ {
+ rtx (* omn) (rtx, rtx, rtx);
+ rtx (* omrn) (rtx, rtx, rtx, rtx);
+ } u;
+};
+
typedef enum arm_cond_code
{
ARM_EQ = 0, ARM_NE, ARM_CS, ARM_CC, ARM_MI, ARM_PL, ARM_VS, ARM_VC,
@@ -272,6 +290,20 @@ extern void (*arm_lang_output_object_att
for Thumb-2. */
#define TARGET_UNIFIED_ASM TARGET_THUMB2
+/* Nonzero if this chip provides the DMB instruction. */
+#define TARGET_HAVE_DMB (arm_arch7)
+
+/* Nonzero if this chip implements a memory barrier via CP15. */
+#define TARGET_HAVE_DMB_MCR (arm_arch6k && ! TARGET_HAVE_DMB)
+
+/* Nonzero if this chip implements a memory barrier instruction. */
+#define TARGET_HAVE_MEMORY_BARRIER (TARGET_HAVE_DMB || TARGET_HAVE_DMB_MCR)
+
+/* Nonzero if this chip supports ldrex and strex */
+#define TARGET_HAVE_LDREX ((arm_arch6 && TARGET_ARM) || arm_arch7)
+
+/* Nonzero if this chip supports ldrex{bhd} and strex{bhd}. */
+#define TARGET_HAVE_LDREXBHD ((arm_arch6k && TARGET_ARM) || arm_arch7)
/* True iff the full BPABI is being used. If TARGET_BPABI is true,
then TARGET_AAPCS_BASED must be true -- but the converse does not
@@ -405,6 +437,12 @@ extern int arm_arch5e;
/* Nonzero if this chip supports the ARM Architecture 6 extensions. */
extern int arm_arch6;
+/* Nonzero if this chip supports the ARM Architecture 6k extensions. */
+extern int arm_arch6k;
+
+/* Nonzero if this chip supports the ARM Architecture 7 extensions. */
+extern int arm_arch7;
+
/* Nonzero if instructions not present in the 'M' profile can be used. */
extern int arm_arch_notm;
Index: gcc-4.5/gcc/config/arm/arm.md
===================================================================
--- gcc-4.5.orig/gcc/config/arm/arm.md
+++ gcc-4.5/gcc/config/arm/arm.md
@@ -103,6 +103,7 @@
(UNSPEC_RBIT 26) ; rbit operation.
(UNSPEC_SYMBOL_OFFSET 27) ; The offset of the start of the symbol from
; another symbolic address.
+ (UNSPEC_MEMORY_BARRIER 28) ; Represent a memory barrier.
]
)
@@ -139,6 +140,11 @@
(VUNSPEC_ALIGN32 16) ; Used to force 32-byte alignment.
(VUNSPEC_EH_RETURN 20); Use to override the return address for exception
; handling.
+ (VUNSPEC_SYNC_COMPARE_AND_SWAP 21) ; Represent an atomic compare swap.
+ (VUNSPEC_SYNC_LOCK 22) ; Represent a sync_lock_test_and_set.
+ (VUNSPEC_SYNC_OP 23) ; Represent a sync_<op>
+ (VUNSPEC_SYNC_NEW_OP 24) ; Represent a sync_new_<op>
+ (VUNSPEC_SYNC_OLD_OP 25) ; Represent a sync_old_<op>
]
)
@@ -163,8 +169,21 @@
(define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
(const (symbol_ref "arm_fpu_attr")))
+(define_attr "sync_result" "none,0,1,2,3,4,5" (const_string "none"))
+(define_attr "sync_memory" "none,0,1,2,3,4,5" (const_string "none"))
+(define_attr "sync_required_value" "none,0,1,2,3,4,5" (const_string "none"))
+(define_attr "sync_new_value" "none,0,1,2,3,4,5" (const_string "none"))
+(define_attr "sync_t1" "none,0,1,2,3,4,5" (const_string "none"))
+(define_attr "sync_t2" "none,0,1,2,3,4,5" (const_string "none"))
+(define_attr "sync_release_barrier" "yes,no" (const_string "yes"))
+(define_attr "sync_op" "none,add,sub,ior,xor,and,nand"
+ (const_string "none"))
+
; LENGTH of an instruction (in bytes)
-(define_attr "length" "" (const_int 4))
+(define_attr "length" ""
+ (cond [(not (eq_attr "sync_memory" "none"))
+ (symbol_ref "arm_sync_loop_insns (insn, operands) * 4")
+ ] (const_int 4)))
; POOL_RANGE is how far away from a constant pool entry that this insn
; can be placed. If the distance is zero, then this insn will never
@@ -11549,4 +11568,5 @@
(include "thumb2.md")
;; Neon patterns
(include "neon.md")
-
+;; Synchronization Primitives
+(include "sync.md")
Index: gcc-4.5/gcc/config/arm/predicates.md
===================================================================
--- gcc-4.5.orig/gcc/config/arm/predicates.md
+++ gcc-4.5/gcc/config/arm/predicates.md
@@ -573,6 +573,11 @@
(and (match_test "TARGET_32BIT")
(match_operand 0 "arm_di_operand"))))
+;; True if the operand is memory reference suitable for a ldrex/strex.
+(define_predicate "arm_sync_memory_operand"
+ (and (match_operand 0 "memory_operand")
+ (match_code "reg" "0")))
+
;; Predicates for parallel expanders based on mode.
(define_special_predicate "vect_par_constant_high"
(match_code "parallel")
Index: gcc-4.5/gcc/testsuite/gcc.target/arm/synchronize.c
===================================================================
--- gcc-4.5.orig/gcc/testsuite/gcc.target/arm/synchronize.c
+++ gcc-4.5/gcc/testsuite/gcc.target/arm/synchronize.c
@@ -1,4 +1,4 @@
-/* { dg-final { scan-assembler "__sync_synchronize" { target arm*-*-linux-*eabi } } } */
+/* { dg-final { scan-assembler "__sync_synchronize|dmb|mcr" { target arm*-*-linux-*eabi } } } */
void *foo (void)
{

View File

@ -0,0 +1,38 @@
2010-10-18 Kazu Hirata <kazu@codesourcery.com>
Issue #9720
Backport from mainline:
gcc/
2010-10-07 Tejas Belagod <tejas.belagod@arm.com>
* config/arm/neon.md (neon_unpack<US>_<mode>): Add 'w' to
constraint, add register specifier in instruction template.
(neon_vec_pack_trunc_<mode>): Likewise.
(neon_vec_<US>mult_<mode>): Add register specifier to
instruction template.
=== modified file 'gcc/config/arm/neon.md'
Index: gcc-4.5/gcc/config/arm/neon.md
===================================================================
--- gcc-4.5.orig/gcc/config/arm/neon.md
+++ gcc-4.5/gcc/config/arm/neon.md
@@ -5682,9 +5682,9 @@
;; Vectorize for non-neon-quad case
(define_insn "neon_unpack<US>_<mode>"
[(set (match_operand:<V_widen> 0 "register_operand" "=w")
- (SE:<V_widen> (match_operand:VDI 1 "register_operand" "")))]
+ (SE:<V_widen> (match_operand:VDI 1 "register_operand" "w")))]
"TARGET_NEON"
- "vmovl.<US><V_sz_elem> %q0, %1"
+ "vmovl.<US><V_sz_elem> %q0, %P1"
[(set_attr "neon_type" "neon_shift_1")]
)
@@ -5721,7 +5721,7 @@
(SE:<V_widen>
(match_operand:VDI 2 "register_operand" "w"))))]
"TARGET_NEON"
- "vmull.<US><V_sz_elem> %q0, %1, %2"
+ "vmull.<US><V_sz_elem> %q0, %P1, %P2"
[(set_attr "neon_type" "neon_shift_1")]
)

View File

@ -0,0 +1,94 @@
2010-10-20 Nathan Froyd <froydnj@codesourcery.com>
Issue #9781
Backport from mainline:
gcc/
2010-10-20 Nathan Froyd <froydnj@codesourcery.com>
* ifcvt.c (noce_emit_cmove): If both of the values are SUBREGs, try
emitting the conditional move in the inner mode of the SUBREG.
=== modified file 'gcc/ifcvt.c'
--- old/gcc/ifcvt.c 2010-10-15 10:01:07 +0000
+++ new/gcc/ifcvt.c 2010-11-04 12:11:15 +0000
@@ -1338,6 +1338,9 @@
noce_emit_cmove (struct noce_if_info *if_info, rtx x, enum rtx_code code,
rtx cmp_a, rtx cmp_b, rtx vfalse, rtx vtrue)
{
+ rtx target;
+ int unsignedp;
+
/* If earliest == jump, try to build the cmove insn directly.
This is helpful when combine has created some complex condition
(like for alpha's cmovlbs) that we can't hope to regenerate
@@ -1372,10 +1375,62 @@
return NULL_RTX;
#if HAVE_conditional_move
- return emit_conditional_move (x, code, cmp_a, cmp_b, VOIDmode,
- vtrue, vfalse, GET_MODE (x),
- (code == LTU || code == GEU
- || code == LEU || code == GTU));
+ unsignedp = (code == LTU || code == GEU
+ || code == LEU || code == GTU);
+
+ target = emit_conditional_move (x, code, cmp_a, cmp_b, VOIDmode,
+ vtrue, vfalse, GET_MODE (x),
+ unsignedp);
+ if (target)
+ return target;
+
+ /* We might be faced with a situation like:
+
+ x = (reg:M TARGET)
+ vtrue = (subreg:M (reg:N VTRUE) BYTE)
+ vfalse = (subreg:M (reg:N VFALSE) BYTE)
+
+ We can't do a conditional move in mode M, but it's possible that we
+ could do a conditional move in mode N instead and take a subreg of
+ the result.
+
+ If we can't create new pseudos, though, don't bother. */
+ if (reload_completed)
+ return NULL_RTX;
+
+ if (GET_CODE (vtrue) == SUBREG && GET_CODE (vfalse) == SUBREG)
+ {
+ rtx reg_vtrue = SUBREG_REG (vtrue);
+ rtx reg_vfalse = SUBREG_REG (vfalse);
+ unsigned int byte_vtrue = SUBREG_BYTE (vtrue);
+ unsigned int byte_vfalse = SUBREG_BYTE (vfalse);
+ rtx promoted_target;
+
+ if (GET_MODE (reg_vtrue) != GET_MODE (reg_vfalse)
+ || byte_vtrue != byte_vfalse
+ || (SUBREG_PROMOTED_VAR_P (vtrue)
+ != SUBREG_PROMOTED_VAR_P (vfalse))
+ || (SUBREG_PROMOTED_UNSIGNED_P (vtrue)
+ != SUBREG_PROMOTED_UNSIGNED_P (vfalse)))
+ return NULL_RTX;
+
+ promoted_target = gen_reg_rtx (GET_MODE (reg_vtrue));
+
+ target = emit_conditional_move (promoted_target, code, cmp_a, cmp_b,
+ VOIDmode, reg_vtrue, reg_vfalse,
+ GET_MODE (reg_vtrue), unsignedp);
+ /* Nope, couldn't do it in that mode either. */
+ if (!target)
+ return NULL_RTX;
+
+ target = gen_rtx_SUBREG (GET_MODE (vtrue), promoted_target, byte_vtrue);
+ SUBREG_PROMOTED_VAR_P (target) = SUBREG_PROMOTED_VAR_P (vtrue);
+ SUBREG_PROMOTED_UNSIGNED_SET (target, SUBREG_PROMOTED_UNSIGNED_P (vtrue));
+ emit_move_insn (x, target);
+ return x;
+ }
+ else
+ return NULL_RTX;
#else
/* We'll never get here, as noce_process_if_block doesn't call the
functions involved. Ifdef code, however, should be discouraged

View File

@ -0,0 +1,114 @@
2010-10-25 Jie Zhang <jie@codesourcery.com>
Issue #9812
Backport from mainline:
gcc/
2010-10-25 Jie Zhang <jie@codesourcery.com>
* combine.c (try_combine): If insns need to be kept around,
check that they can be copied in the merged instruction.
gcc/testsuite/
2010-10-25 Jie Zhang <jie@codesourcery.com>
* g++.dg/opt/combine.c: New test.
=== modified file 'gcc/combine.c'
--- old/gcc/combine.c 2010-09-20 22:37:32 +0000
+++ new/gcc/combine.c 2010-11-04 12:39:28 +0000
@@ -2809,6 +2809,17 @@
= i1 && ! (i1_feeds_i3 ? dead_or_set_p (i3, i1dest)
: (dead_or_set_p (i3, i1dest) || dead_or_set_p (i2, i1dest)));
+ /* We are about to copy insns for the case where they need to be kept
+ around. Check that they can be copied in the merged instruction. */
+
+ if (targetm.cannot_copy_insn_p
+ && ((added_sets_2 && targetm.cannot_copy_insn_p (i2))
+ || (i1 && added_sets_1 && targetm.cannot_copy_insn_p (i1))))
+ {
+ undo_all ();
+ return 0;
+ }
+
/* If the set in I2 needs to be kept around, we must make a copy of
PATTERN (I2), so that when we substitute I1SRC for I1DEST in
PATTERN (I2), we are only substituting for the original I1DEST, not into
=== added file 'gcc/testsuite/g++.dg/opt/combine.C'
--- old/gcc/testsuite/g++.dg/opt/combine.C 1970-01-01 00:00:00 +0000
+++ new/gcc/testsuite/g++.dg/opt/combine.C 2010-11-04 12:39:28 +0000
@@ -0,0 +1,72 @@
+// { dg-do assemble { target fpic } }
+// { dg-options "-O2 -fweb -fPIC -fvisibility=hidden" }
+
+class QBasicAtomicInt
+{
+public:
+ volatile int _q_value;
+ inline operator int () const {return _q_value;}
+};
+class QVariant;
+class QScriptContext;
+class QScriptEngine;
+class QScriptValue
+{
+public:
+ QVariant toVariant () const;
+};
+class QScriptDebuggerBackendPrivate
+{
+ static QScriptValue trace (QScriptContext *context);
+};
+template <typename T> struct QMetaTypeId { };
+template <typename T> struct QMetaTypeId2
+{
+ static inline int qt_metatype_id ()
+ {
+ return QMetaTypeId<T>::qt_metatype_id () ;
+ }
+};
+template <typename T> inline int qMetaTypeId (T * = 0)
+{
+ return QMetaTypeId2<T>::qt_metatype_id () ;
+}
+class QVariant { };
+template<typename T> inline T qvariant_cast (const QVariant &v)
+{
+ const int vid = qMetaTypeId<T> ((0)) ;
+};
+class QScriptContext
+{
+public:
+ QScriptValue callee () const;
+};
+class QScriptEngine
+{
+public:
+ static bool convertV2 (const QScriptValue &value , int type , void *ptr) ;
+};
+inline bool qscriptvalue_cast_helper (const QScriptValue &value , int type , void *ptr)
+{
+ return QScriptEngine::convertV2 (value, type, ptr) ;
+}
+template<typename T> T qscriptvalue_cast (const QScriptValue &value)
+{
+ T t;
+ const int id = qMetaTypeId<T> () ;
+ if ( qscriptvalue_cast_helper (value, id, &t))
+ return qvariant_cast<T> (value.toVariant ()) ;
+}
+template <> struct QMetaTypeId< QScriptDebuggerBackendPrivate* >
+{
+ static int qt_metatype_id ()
+ {
+ static QBasicAtomicInt metatype_id = { (0) };
+ return metatype_id;
+ }
+};
+QScriptValue QScriptDebuggerBackendPrivate::trace (QScriptContext *context)
+{
+ QScriptValue data = context->callee () ;
+ QScriptDebuggerBackendPrivate *self = qscriptvalue_cast<QScriptDebuggerBackendPrivate*> (data) ;
+}

View File

@ -0,0 +1,687 @@
Issue #1259
Backport from mainline:
gcc/
2010-10-22 Jie Zhang <jie@codesourcery.com>
* expr.c (emit_group_load_1): Update calls to extract_bit_field.
(copy_blkmode_from_reg): Likewise.
(read_complex_part): Likewise.
(expand_expr_real_1): Calculate packedp and pass it to
extract_bit_field.
* expr.h (extract_bit_field): Update declaration.
* calls.c (store_unaligned_arguments_into_pseudos): Update call
to extract_bit_field.
* expmed.c (extract_fixed_bit_field): Update calls to
extract_fixed_bit_field.
(store_split_bit_field): Likewise.
(extract_bit_field_1): Add new argument packedp.
(extract_bit_field): Add new argument packedp.
(extract_fixed_bit_field): Add new argument packedp and let
packed attribute override volatile.
* stmt.c (expand_return): Update call to extract_bit_field.
2010-10-15 Jie Zhang <jie@codesourcery.com>
* doc/invoke.texi: Add -fstrict-volatile-bitfields to
Option Summary and Index.
2010-07-13 DJ Delorie <dj@redhat.com>
* config/h8300/h8300.c (h8300_init_once): Default to
-fstrict_volatile_bitfields.
* config/sh/sh.c (sh_override_options): Default to
-fstrict_volatile_bitfields.
* config/rx/rx.c (rx_option_override): New.
* config/m32c/m32c.c (m32c_override_options): Default to
-fstrict_volatile_bitfields.
2010-06-16 DJ Delorie <dj@redhat.com>
* common.opt (-fstrict-volatile-bitfields): new.
* doc/invoke.texi: Document it.
* fold-const.c (optimize_bit_field_compare): For volatile
bitfields, use the field's type to determine the mode, not the
field's size.
* expr.c (expand_assignment): Likewise.
(get_inner_reference): Likewise.
(expand_expr_real_1): Likewise.
* expmed.c (store_fixed_bit_field): Likewise.
(extract_bit_field_1): Likewise.
(extract_fixed_bit_field): Likewise.
gcc/testsuite/
2010-08-19 Uros Bizjak <ubizjak@gmail.com>
PR testsuite/45324
* gcc.target/i386/volatile-bitfields-1.c: Also scan movb.
2010-06-16 DJ Delorie <dj@redhat.com>
* gcc.target/i386/volatile-bitfields-1.c: New.
* gcc.target/i386/volatile-bitfields-2.c: New.
=== modified file 'gcc/calls.c'
--- old/gcc/calls.c 2010-10-04 00:50:43 +0000
+++ new/gcc/calls.c 2010-11-04 12:43:52 +0000
@@ -878,7 +878,7 @@
int bitsize = MIN (bytes * BITS_PER_UNIT, BITS_PER_WORD);
args[i].aligned_regs[j] = reg;
- word = extract_bit_field (word, bitsize, 0, 1, NULL_RTX,
+ word = extract_bit_field (word, bitsize, 0, 1, false, NULL_RTX,
word_mode, word_mode);
/* There is no need to restrict this code to loading items
=== modified file 'gcc/common.opt'
--- old/gcc/common.opt 2010-07-29 14:59:35 +0000
+++ new/gcc/common.opt 2010-11-04 12:43:52 +0000
@@ -613,6 +613,10 @@
Common Report Var(flag_loop_block) Optimization
Enable Loop Blocking transformation
+fstrict-volatile-bitfields
+Common Report Var(flag_strict_volatile_bitfields) Init(-1)
+Force bitfield accesses to match their type width
+
fguess-branch-probability
Common Report Var(flag_guess_branch_prob) Optimization
Enable guessing of branch probabilities
=== modified file 'gcc/config/h8300/h8300.c'
--- old/gcc/config/h8300/h8300.c 2010-04-02 18:54:46 +0000
+++ new/gcc/config/h8300/h8300.c 2010-11-04 12:43:52 +0000
@@ -403,6 +403,10 @@
restore er6 though, so bump up the cost. */
h8300_move_ratio = 6;
}
+
+ /* This target defaults to strict volatile bitfields. */
+ if (flag_strict_volatile_bitfields < 0)
+ flag_strict_volatile_bitfields = 1;
}
/* Implement REG_CLASS_FROM_LETTER.
=== modified file 'gcc/config/m32c/m32c.c'
--- old/gcc/config/m32c/m32c.c 2009-10-22 18:46:26 +0000
+++ new/gcc/config/m32c/m32c.c 2010-11-04 12:43:52 +0000
@@ -428,6 +428,10 @@
if (TARGET_A24)
flag_ivopts = 0;
+
+ /* This target defaults to strict volatile bitfields. */
+ if (flag_strict_volatile_bitfields < 0)
+ flag_strict_volatile_bitfields = 1;
}
/* Defining data structures for per-function information */
=== modified file 'gcc/config/rx/rx.c'
--- old/gcc/config/rx/rx.c 2010-07-27 14:39:53 +0000
+++ new/gcc/config/rx/rx.c 2010-11-04 12:43:52 +0000
@@ -2187,6 +2187,14 @@
}
}
+static void
+rx_option_override (void)
+{
+ /* This target defaults to strict volatile bitfields. */
+ if (flag_strict_volatile_bitfields < 0)
+ flag_strict_volatile_bitfields = 1;
+}
+
static bool
rx_allocate_stack_slots_for_args (void)
@@ -2759,6 +2767,9 @@
#undef TARGET_CC_MODES_COMPATIBLE
#define TARGET_CC_MODES_COMPATIBLE rx_cc_modes_compatible
+#undef TARGET_OPTION_OVERRIDE
+#define TARGET_OPTION_OVERRIDE rx_option_override
+
struct gcc_target targetm = TARGET_INITIALIZER;
/* #include "gt-rx.h" */
=== modified file 'gcc/config/sh/sh.c'
--- old/gcc/config/sh/sh.c 2010-05-05 21:12:17 +0000
+++ new/gcc/config/sh/sh.c 2010-11-04 12:43:52 +0000
@@ -950,6 +950,10 @@
if (sh_fixed_range_str)
sh_fix_range (sh_fixed_range_str);
+
+ /* This target defaults to strict volatile bitfields. */
+ if (flag_strict_volatile_bitfields < 0)
+ flag_strict_volatile_bitfields = 1;
}
/* Print the operand address in x to the stream. */
=== modified file 'gcc/doc/invoke.texi'
--- old/gcc/doc/invoke.texi 2010-10-04 00:50:43 +0000
+++ new/gcc/doc/invoke.texi 2010-11-04 12:43:52 +0000
@@ -922,7 +922,7 @@
-fargument-noalias-global -fargument-noalias-anything @gol
-fleading-underscore -ftls-model=@var{model} @gol
-ftrapv -fwrapv -fbounds-check @gol
--fvisibility}
+-fvisibility -fstrict-volatile-bitfields}
@end table
@menu
@@ -17629,6 +17629,33 @@
An overview of these techniques, their benefits and how to use them
is at @w{@uref{http://gcc.gnu.org/wiki/Visibility}}.
+@item -fstrict-volatile-bitfields
+@opindex fstrict-volatile-bitfields
+This option should be used if accesses to volatile bitfields (or other
+structure fields, although the compiler usually honors those types
+anyway) should use a single access in a mode of the same size as the
+container's type, aligned to a natural alignment if possible. For
+example, targets with memory-mapped peripheral registers might require
+all such accesses to be 16 bits wide; with this flag the user could
+declare all peripheral bitfields as ``unsigned short'' (assuming short
+is 16 bits on these targets) to force GCC to use 16 bit accesses
+instead of, perhaps, a more efficient 32 bit access.
+
+If this option is disabled, the compiler will use the most efficient
+instruction. In the previous example, that might be a 32-bit load
+instruction, even though that will access bytes that do not contain
+any portion of the bitfield, or memory-mapped registers unrelated to
+the one being updated.
+
+If the target requires strict alignment, and honoring the container
+type would require violating this alignment, a warning is issued.
+However, the access happens as the user requested, under the
+assumption that the user knows something about the target hardware
+that GCC is unaware of.
+
+The default value of this option is determined by the application binary
+interface for the target processor.
+
@end table
@c man end
=== modified file 'gcc/expmed.c'
--- old/gcc/expmed.c 2010-10-04 00:50:43 +0000
+++ new/gcc/expmed.c 2010-11-04 12:43:52 +0000
@@ -47,7 +47,7 @@
static rtx extract_fixed_bit_field (enum machine_mode, rtx,
unsigned HOST_WIDE_INT,
unsigned HOST_WIDE_INT,
- unsigned HOST_WIDE_INT, rtx, int);
+ unsigned HOST_WIDE_INT, rtx, int, bool);
static rtx mask_rtx (enum machine_mode, int, int, int);
static rtx lshift_value (enum machine_mode, rtx, int, int);
static rtx extract_split_bit_field (rtx, unsigned HOST_WIDE_INT,
@@ -904,8 +904,14 @@
if (GET_MODE_BITSIZE (mode) == 0
|| GET_MODE_BITSIZE (mode) > GET_MODE_BITSIZE (word_mode))
mode = word_mode;
- mode = get_best_mode (bitsize, bitpos + offset * BITS_PER_UNIT,
- MEM_ALIGN (op0), mode, MEM_VOLATILE_P (op0));
+
+ if (MEM_VOLATILE_P (op0)
+ && GET_MODE_BITSIZE (GET_MODE (op0)) > 0
+ && flag_strict_volatile_bitfields > 0)
+ mode = GET_MODE (op0);
+ else
+ mode = get_best_mode (bitsize, bitpos + offset * BITS_PER_UNIT,
+ MEM_ALIGN (op0), mode, MEM_VOLATILE_P (op0));
if (mode == VOIDmode)
{
@@ -1099,7 +1105,7 @@
endianness compensation) to fetch the piece we want. */
part = extract_fixed_bit_field (word_mode, value, 0, thissize,
total_bits - bitsize + bitsdone,
- NULL_RTX, 1);
+ NULL_RTX, 1, false);
}
else
{
@@ -1110,7 +1116,7 @@
& (((HOST_WIDE_INT) 1 << thissize) - 1));
else
part = extract_fixed_bit_field (word_mode, value, 0, thissize,
- bitsdone, NULL_RTX, 1);
+ bitsdone, NULL_RTX, 1, false);
}
/* If OP0 is a register, then handle OFFSET here.
@@ -1176,7 +1182,8 @@
static rtx
extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
- unsigned HOST_WIDE_INT bitnum, int unsignedp, rtx target,
+ unsigned HOST_WIDE_INT bitnum,
+ int unsignedp, bool packedp, rtx target,
enum machine_mode mode, enum machine_mode tmode,
bool fallback_p)
{
@@ -1378,6 +1385,14 @@
? mode_for_size (bitsize, GET_MODE_CLASS (tmode), 0)
: mode);
+ /* If the bitfield is volatile, we need to make sure the access
+ remains on a type-aligned boundary. */
+ if (GET_CODE (op0) == MEM
+ && MEM_VOLATILE_P (op0)
+ && GET_MODE_BITSIZE (GET_MODE (op0)) > 0
+ && flag_strict_volatile_bitfields > 0)
+ goto no_subreg_mode_swap;
+
if (((bitsize >= BITS_PER_WORD && bitsize == GET_MODE_BITSIZE (mode)
&& bitpos % BITS_PER_WORD == 0)
|| (mode1 != BLKmode
@@ -1450,7 +1465,7 @@
rtx result_part
= extract_bit_field (op0, MIN (BITS_PER_WORD,
bitsize - i * BITS_PER_WORD),
- bitnum + bit_offset, 1, target_part, mode,
+ bitnum + bit_offset, 1, false, target_part, mode,
word_mode);
gcc_assert (target_part);
@@ -1649,7 +1664,7 @@
xop0 = adjust_address (op0, bestmode, xoffset);
xop0 = force_reg (bestmode, xop0);
result = extract_bit_field_1 (xop0, bitsize, xbitpos,
- unsignedp, target,
+ unsignedp, packedp, target,
mode, tmode, false);
if (result)
return result;
@@ -1663,7 +1678,7 @@
return NULL;
target = extract_fixed_bit_field (int_mode, op0, offset, bitsize,
- bitpos, target, unsignedp);
+ bitpos, target, unsignedp, packedp);
return convert_extracted_bit_field (target, mode, tmode, unsignedp);
}
@@ -1674,6 +1689,7 @@
STR_RTX is the structure containing the byte (a REG or MEM).
UNSIGNEDP is nonzero if this is an unsigned bit field.
+ PACKEDP is nonzero if the field has the packed attribute.
MODE is the natural mode of the field value once extracted.
TMODE is the mode the caller would like the value to have;
but the value may be returned with type MODE instead.
@@ -1685,10 +1701,10 @@
rtx
extract_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
- unsigned HOST_WIDE_INT bitnum, int unsignedp, rtx target,
- enum machine_mode mode, enum machine_mode tmode)
+ unsigned HOST_WIDE_INT bitnum, int unsignedp, bool packedp,
+ rtx target, enum machine_mode mode, enum machine_mode tmode)
{
- return extract_bit_field_1 (str_rtx, bitsize, bitnum, unsignedp,
+ return extract_bit_field_1 (str_rtx, bitsize, bitnum, unsignedp, packedp,
target, mode, tmode, true);
}
@@ -1704,6 +1720,8 @@
which is significant on bigendian machines.)
UNSIGNEDP is nonzero for an unsigned bit field (don't sign-extend value).
+ PACKEDP is true if the field has the packed attribute.
+
If TARGET is nonzero, attempts to store the value there
and return TARGET, but this is not guaranteed.
If TARGET is not used, create a pseudo-reg of mode TMODE for the value. */
@@ -1713,7 +1731,7 @@
unsigned HOST_WIDE_INT offset,
unsigned HOST_WIDE_INT bitsize,
unsigned HOST_WIDE_INT bitpos, rtx target,
- int unsignedp)
+ int unsignedp, bool packedp)
{
unsigned int total_bits = BITS_PER_WORD;
enum machine_mode mode;
@@ -1730,8 +1748,19 @@
includes the entire field. If such a mode would be larger than
a word, we won't be doing the extraction the normal way. */
- mode = get_best_mode (bitsize, bitpos + offset * BITS_PER_UNIT,
- MEM_ALIGN (op0), word_mode, MEM_VOLATILE_P (op0));
+ if (MEM_VOLATILE_P (op0)
+ && flag_strict_volatile_bitfields > 0)
+ {
+ if (GET_MODE_BITSIZE (GET_MODE (op0)) > 0)
+ mode = GET_MODE (op0);
+ else if (target && GET_MODE_BITSIZE (GET_MODE (target)) > 0)
+ mode = GET_MODE (target);
+ else
+ mode = tmode;
+ }
+ else
+ mode = get_best_mode (bitsize, bitpos + offset * BITS_PER_UNIT,
+ MEM_ALIGN (op0), word_mode, MEM_VOLATILE_P (op0));
if (mode == VOIDmode)
/* The only way this should occur is if the field spans word
@@ -1752,12 +1781,67 @@
* BITS_PER_UNIT);
}
- /* Get ref to an aligned byte, halfword, or word containing the field.
- Adjust BITPOS to be position within a word,
- and OFFSET to be the offset of that word.
- Then alter OP0 to refer to that word. */
- bitpos += (offset % (total_bits / BITS_PER_UNIT)) * BITS_PER_UNIT;
- offset -= (offset % (total_bits / BITS_PER_UNIT));
+ /* If we're accessing a volatile MEM, we can't do the next
+ alignment step if it results in a multi-word access where we
+ otherwise wouldn't have one. So, check for that case
+ here. */
+ if (MEM_P (op0)
+ && MEM_VOLATILE_P (op0)
+ && flag_strict_volatile_bitfields > 0
+ && bitpos + bitsize <= total_bits
+ && bitpos + bitsize + (offset % (total_bits / BITS_PER_UNIT)) * BITS_PER_UNIT > total_bits)
+ {
+ if (STRICT_ALIGNMENT)
+ {
+ static bool informed_about_misalignment = false;
+ bool warned;
+
+ if (packedp)
+ {
+ if (bitsize == total_bits)
+ warned = warning_at (input_location, OPT_fstrict_volatile_bitfields,
+ "multiple accesses to volatile structure member"
+ " because of packed attribute");
+ else
+ warned = warning_at (input_location, OPT_fstrict_volatile_bitfields,
+ "multiple accesses to volatile structure bitfield"
+ " because of packed attribute");
+
+ return extract_split_bit_field (op0, bitsize,
+ bitpos + offset * BITS_PER_UNIT,
+ unsignedp);
+ }
+
+ if (bitsize == total_bits)
+ warned = warning_at (input_location, OPT_fstrict_volatile_bitfields,
+ "mis-aligned access used for structure member");
+ else
+ warned = warning_at (input_location, OPT_fstrict_volatile_bitfields,
+ "mis-aligned access used for structure bitfield");
+
+ if (! informed_about_misalignment && warned)
+ {
+ informed_about_misalignment = true;
+ inform (input_location,
+ "When a volatile object spans multiple type-sized locations,"
+ " the compiler must choose between using a single mis-aligned access to"
+ " preserve the volatility, or using multiple aligned accesses to avoid"
+ " runtime faults. This code may fail at runtime if the hardware does"
+ " not allow this access.");
+ }
+ }
+ }
+ else
+ {
+
+ /* Get ref to an aligned byte, halfword, or word containing the field.
+ Adjust BITPOS to be position within a word,
+ and OFFSET to be the offset of that word.
+ Then alter OP0 to refer to that word. */
+ bitpos += (offset % (total_bits / BITS_PER_UNIT)) * BITS_PER_UNIT;
+ offset -= (offset % (total_bits / BITS_PER_UNIT));
+ }
+
op0 = adjust_address (op0, mode, offset);
}
@@ -1966,7 +2050,7 @@
extract_fixed_bit_field wants offset in bytes. */
part = extract_fixed_bit_field (word_mode, word,
offset * unit / BITS_PER_UNIT,
- thissize, thispos, 0, 1);
+ thissize, thispos, 0, 1, false);
bitsdone += thissize;
/* Shift this part into place for the result. */
=== modified file 'gcc/expr.c'
--- old/gcc/expr.c 2010-10-04 00:50:43 +0000
+++ new/gcc/expr.c 2010-11-04 12:43:52 +0000
@@ -1749,7 +1749,7 @@
&& (!REG_P (tmps[i]) || GET_MODE (tmps[i]) != mode))
tmps[i] = extract_bit_field (tmps[i], bytelen * BITS_PER_UNIT,
(bytepos % slen0) * BITS_PER_UNIT,
- 1, NULL_RTX, mode, mode);
+ 1, false, NULL_RTX, mode, mode);
}
else
{
@@ -1759,7 +1759,7 @@
mem = assign_stack_temp (GET_MODE (src), slen, 0);
emit_move_insn (mem, src);
tmps[i] = extract_bit_field (mem, bytelen * BITS_PER_UNIT,
- 0, 1, NULL_RTX, mode, mode);
+ 0, 1, false, NULL_RTX, mode, mode);
}
}
/* FIXME: A SIMD parallel will eventually lead to a subreg of a
@@ -1800,7 +1800,7 @@
tmps[i] = src;
else
tmps[i] = extract_bit_field (src, bytelen * BITS_PER_UNIT,
- bytepos * BITS_PER_UNIT, 1, NULL_RTX,
+ bytepos * BITS_PER_UNIT, 1, false, NULL_RTX,
mode, mode);
if (shift)
@@ -2213,7 +2213,7 @@
bitpos for the destination store (left justified). */
store_bit_field (dst, bitsize, bitpos % BITS_PER_WORD, copy_mode,
extract_bit_field (src, bitsize,
- xbitpos % BITS_PER_WORD, 1,
+ xbitpos % BITS_PER_WORD, 1, false,
NULL_RTX, copy_mode, copy_mode));
}
@@ -2970,7 +2970,7 @@
}
return extract_bit_field (cplx, ibitsize, imag_p ? ibitsize : 0,
- true, NULL_RTX, imode, imode);
+ true, false, NULL_RTX, imode, imode);
}
/* A subroutine of emit_move_insn_1. Yet another lowpart generator.
@@ -4233,6 +4233,13 @@
to_rtx = expand_normal (tem);
+ /* If the bitfield is volatile, we want to access it in the
+ field's mode, not the computed mode. */
+ if (volatilep
+ && GET_CODE (to_rtx) == MEM
+ && flag_strict_volatile_bitfields > 0)
+ to_rtx = adjust_address (to_rtx, mode1, 0);
+
if (offset != 0)
{
enum machine_mode address_mode;
@@ -5993,6 +6000,12 @@
mode = DECL_MODE (field);
else if (DECL_MODE (field) == BLKmode)
blkmode_bitfield = true;
+ else if (TREE_THIS_VOLATILE (exp)
+ && flag_strict_volatile_bitfields > 0)
+ /* Volatile bitfields should be accessed in the mode of the
+ field's type, not the mode computed based on the bit
+ size. */
+ mode = TYPE_MODE (DECL_BIT_FIELD_TYPE (field));
*punsignedp = DECL_UNSIGNED (field);
}
@@ -8848,6 +8861,7 @@
HOST_WIDE_INT bitsize, bitpos;
tree offset;
int volatilep = 0, must_force_mem;
+ bool packedp = false;
tree tem = get_inner_reference (exp, &bitsize, &bitpos, &offset,
&mode1, &unsignedp, &volatilep, true);
rtx orig_op0, memloc;
@@ -8857,6 +8871,11 @@
infinitely recurse. */
gcc_assert (tem != exp);
+ if (TYPE_PACKED (TREE_TYPE (TREE_OPERAND (exp, 0)))
+ || (TREE_CODE (TREE_OPERAND (exp, 1)) == FIELD_DECL
+ && DECL_PACKED (TREE_OPERAND (exp, 1))))
+ packedp = true;
+
/* If TEM's type is a union of variable size, pass TARGET to the inner
computation, since it will need a temporary and TARGET is known
to have to do. This occurs in unchecked conversion in Ada. */
@@ -8873,6 +8892,14 @@
|| modifier == EXPAND_STACK_PARM)
? modifier : EXPAND_NORMAL);
+
+ /* If the bitfield is volatile, we want to access it in the
+ field's mode, not the computed mode. */
+ if (volatilep
+ && GET_CODE (op0) == MEM
+ && flag_strict_volatile_bitfields > 0)
+ op0 = adjust_address (op0, mode1, 0);
+
mode2
= CONSTANT_P (op0) ? TYPE_MODE (TREE_TYPE (tem)) : GET_MODE (op0);
@@ -8998,6 +9025,9 @@
&& GET_MODE_CLASS (mode) != MODE_COMPLEX_FLOAT
&& modifier != EXPAND_CONST_ADDRESS
&& modifier != EXPAND_INITIALIZER)
+ /* If the field is volatile, we always want an aligned
+ access. */
+ || (volatilep && flag_strict_volatile_bitfields > 0)
/* If the field isn't aligned enough to fetch as a memref,
fetch it as a bit field. */
|| (mode1 != BLKmode
@@ -9058,7 +9088,7 @@
if (MEM_P (op0) && REG_P (XEXP (op0, 0)))
mark_reg_pointer (XEXP (op0, 0), MEM_ALIGN (op0));
- op0 = extract_bit_field (op0, bitsize, bitpos, unsignedp,
+ op0 = extract_bit_field (op0, bitsize, bitpos, unsignedp, packedp,
(modifier == EXPAND_STACK_PARM
? NULL_RTX : target),
ext_mode, ext_mode);
=== modified file 'gcc/expr.h'
--- old/gcc/expr.h 2010-02-19 09:53:51 +0000
+++ new/gcc/expr.h 2010-11-04 12:43:52 +0000
@@ -802,7 +802,7 @@
extern void store_bit_field (rtx, unsigned HOST_WIDE_INT,
unsigned HOST_WIDE_INT, enum machine_mode, rtx);
extern rtx extract_bit_field (rtx, unsigned HOST_WIDE_INT,
- unsigned HOST_WIDE_INT, int, rtx,
+ unsigned HOST_WIDE_INT, int, bool, rtx,
enum machine_mode, enum machine_mode);
extern rtx extract_low_bits (enum machine_mode, enum machine_mode, rtx);
extern rtx expand_mult (enum machine_mode, rtx, rtx, rtx, int);
=== modified file 'gcc/fold-const.c'
--- old/gcc/fold-const.c 2010-10-04 00:50:43 +0000
+++ new/gcc/fold-const.c 2010-11-04 12:43:52 +0000
@@ -4208,11 +4208,16 @@
/* See if we can find a mode to refer to this field. We should be able to,
but fail if we can't. */
- nmode = get_best_mode (lbitsize, lbitpos,
- const_p ? TYPE_ALIGN (TREE_TYPE (linner))
- : MIN (TYPE_ALIGN (TREE_TYPE (linner)),
- TYPE_ALIGN (TREE_TYPE (rinner))),
- word_mode, lvolatilep || rvolatilep);
+ if (lvolatilep
+ && GET_MODE_BITSIZE (lmode) > 0
+ && flag_strict_volatile_bitfields > 0)
+ nmode = lmode;
+ else
+ nmode = get_best_mode (lbitsize, lbitpos,
+ const_p ? TYPE_ALIGN (TREE_TYPE (linner))
+ : MIN (TYPE_ALIGN (TREE_TYPE (linner)),
+ TYPE_ALIGN (TREE_TYPE (rinner))),
+ word_mode, lvolatilep || rvolatilep);
if (nmode == VOIDmode)
return 0;
=== modified file 'gcc/stmt.c'
--- old/gcc/stmt.c 2010-08-13 11:53:46 +0000
+++ new/gcc/stmt.c 2010-11-04 12:43:52 +0000
@@ -1751,7 +1751,7 @@
xbitpos for the destination store (right justified). */
store_bit_field (dst, bitsize, xbitpos % BITS_PER_WORD, word_mode,
extract_bit_field (src, bitsize,
- bitpos % BITS_PER_WORD, 1,
+ bitpos % BITS_PER_WORD, 1, false,
NULL_RTX, word_mode, word_mode));
}
=== added file 'gcc/testsuite/gcc.target/i386/volatile-bitfields-1.c'
--- old/gcc/testsuite/gcc.target/i386/volatile-bitfields-1.c 1970-01-01 00:00:00 +0000
+++ new/gcc/testsuite/gcc.target/i386/volatile-bitfields-1.c 2010-11-04 12:43:52 +0000
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fstrict-volatile-bitfields" } */
+
+typedef struct {
+ char a:1;
+ char b:7;
+ int c;
+} BitStruct;
+
+volatile BitStruct bits;
+
+int foo ()
+{
+ return bits.b;
+}
+
+/* { dg-final { scan-assembler "mov(b|zbl).*bits" } } */
=== added file 'gcc/testsuite/gcc.target/i386/volatile-bitfields-2.c'
--- old/gcc/testsuite/gcc.target/i386/volatile-bitfields-2.c 1970-01-01 00:00:00 +0000
+++ new/gcc/testsuite/gcc.target/i386/volatile-bitfields-2.c 2010-11-04 12:43:52 +0000
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-strict-volatile-bitfields" } */
+
+typedef struct {
+ char a:1;
+ char b:7;
+ int c;
+} BitStruct;
+
+volatile BitStruct bits;
+
+int foo ()
+{
+ return bits.b;
+}
+
+/* { dg-final { scan-assembler "movl.*bits" } } */

View File

@ -0,0 +1,128 @@
2010-10-26 Jie Zhang <jie@codesourcery.com>
Issue #1259
Backport from mainline:
gcc/
2010-10-26 Jie Zhang <jie@codesourcery.com>
* stor-layout.c (layout_decl): Use the field's type to
determine the mode and keep DECL_BIT_FIELD for a volatile
bit-field.
* config/arm/arm.c (arm_override_options): Default to
-fstrict-volatile-bitfields.
gcc/testsuite/
2010-10-26 Jie Zhang <jie@codesourcery.com>
* gcc.target/arm/volatile-bitfields-1.c: New test.
* gcc.target/arm/volatile-bitfields-2.c: New test.
* gcc.target/arm/volatile-bitfields-3.c: New test.
=== modified file 'gcc/config/arm/arm.c'
--- old/gcc/config/arm/arm.c 2010-11-04 10:45:05 +0000
+++ new/gcc/config/arm/arm.c 2010-11-04 12:49:37 +0000
@@ -1933,6 +1933,10 @@
calculation, which is 2 instructions. */
set_param_value ("gcse-unrestricted-cost", 2);
+ /* ARM EABI defaults to strict volatile bitfields. */
+ if (TARGET_AAPCS_BASED && flag_strict_volatile_bitfields < 0)
+ flag_strict_volatile_bitfields = 1;
+
/* Register global variables with the garbage collector. */
arm_add_gc_roots ();
=== modified file 'gcc/stor-layout.c'
--- old/gcc/stor-layout.c 2010-04-02 18:54:46 +0000
+++ new/gcc/stor-layout.c 2010-11-04 12:49:37 +0000
@@ -593,11 +593,14 @@
}
/* See if we can use an ordinary integer mode for a bit-field.
- Conditions are: a fixed size that is correct for another mode
- and occupying a complete byte or bytes on proper boundary. */
+ Conditions are: a fixed size that is correct for another mode,
+ occupying a complete byte or bytes on proper boundary,
+ and not volatile or not -fstrict-volatile-bitfields. */
if (TYPE_SIZE (type) != 0
&& TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
- && GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT)
+ && GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
+ && !(TREE_THIS_VOLATILE (decl)
+ && flag_strict_volatile_bitfields > 0))
{
enum machine_mode xmode
= mode_for_size_tree (DECL_SIZE (decl), MODE_INT, 1);
=== added file 'gcc/testsuite/gcc.target/arm/volatile-bitfields-1.c'
--- old/gcc/testsuite/gcc.target/arm/volatile-bitfields-1.c 1970-01-01 00:00:00 +0000
+++ new/gcc/testsuite/gcc.target/arm/volatile-bitfields-1.c 2010-11-04 12:49:37 +0000
@@ -0,0 +1,18 @@
+/* { dg-require-effective-target arm_eabi } */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+typedef struct {
+ char a:1;
+ char b:7;
+ int c;
+} BitStruct;
+
+volatile BitStruct bits;
+
+int foo ()
+{
+ return bits.b;
+}
+
+/* { dg-final { scan-assembler "ldrb\[\\t \]+\[^\n\]*,\[\\t \]*\\\[\[^\n\]*\\\]" } } */
=== added file 'gcc/testsuite/gcc.target/arm/volatile-bitfields-2.c'
--- old/gcc/testsuite/gcc.target/arm/volatile-bitfields-2.c 1970-01-01 00:00:00 +0000
+++ new/gcc/testsuite/gcc.target/arm/volatile-bitfields-2.c 2010-11-04 12:49:37 +0000
@@ -0,0 +1,18 @@
+/* { dg-require-effective-target arm_eabi } */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+typedef struct {
+ volatile unsigned long a:8;
+ volatile unsigned long b:8;
+ volatile unsigned long c:16;
+} BitStruct;
+
+BitStruct bits;
+
+unsigned long foo ()
+{
+ return bits.b;
+}
+
+/* { dg-final { scan-assembler "ldr\[\\t \]+\[^\n\]*,\[\\t \]*\\\[\[^\n\]*\\\]" } } */
=== added file 'gcc/testsuite/gcc.target/arm/volatile-bitfields-3.c'
--- old/gcc/testsuite/gcc.target/arm/volatile-bitfields-3.c 1970-01-01 00:00:00 +0000
+++ new/gcc/testsuite/gcc.target/arm/volatile-bitfields-3.c 2010-11-04 12:49:37 +0000
@@ -0,0 +1,18 @@
+/* { dg-require-effective-target arm_eabi } */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+typedef struct {
+ volatile unsigned long a:8;
+ volatile unsigned long b:8;
+ volatile unsigned long c:16;
+} BitStruct;
+
+BitStruct bits;
+
+unsigned long foo ()
+{
+ return bits.c;
+}
+
+/* { dg-final { scan-assembler "ldr\[\\t \]+\[^\n\]*,\[\\t \]*\\\[\[^\n\]*\\\]" } } */

View File

@ -0,0 +1,41 @@
Backport from mainline:
gcc/
2010-10-26 Jie Zhang <jie@codesourcery.com>
* doc/invoke.texi: Improve documentation of
-fstrict-volatile-bitfields.
=== modified file 'gcc/doc/invoke.texi'
--- old/gcc/doc/invoke.texi 2010-11-04 12:43:52 +0000
+++ new/gcc/doc/invoke.texi 2010-11-04 14:29:09 +0000
@@ -17633,8 +17633,8 @@
@opindex fstrict-volatile-bitfields
This option should be used if accesses to volatile bitfields (or other
structure fields, although the compiler usually honors those types
-anyway) should use a single access in a mode of the same size as the
-container's type, aligned to a natural alignment if possible. For
+anyway) should use a single access of the width of the
+field's type, aligned to a natural alignment if possible. For
example, targets with memory-mapped peripheral registers might require
all such accesses to be 16 bits wide; with this flag the user could
declare all peripheral bitfields as ``unsigned short'' (assuming short
@@ -17647,11 +17647,13 @@
any portion of the bitfield, or memory-mapped registers unrelated to
the one being updated.
-If the target requires strict alignment, and honoring the container
+If the target requires strict alignment, and honoring the field
type would require violating this alignment, a warning is issued.
-However, the access happens as the user requested, under the
-assumption that the user knows something about the target hardware
-that GCC is unaware of.
+If the field has @code{packed} attribute, the access is done without
+honoring the field type. If the field doesn't have @code{packed}
+attribute, the access is done honoring the field type. In both cases,
+GCC assumes that the user knows something about the target hardware
+that it is unaware of.
The default value of this option is determined by the application binary
interface for the target processor.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,70 @@
2010-11-03 Nathan Froyd <froydnj@codesourcery.com>
Issue #10002
gcc/
* config/arm/arm.c (arm_legitimate_index_p): Split
VALID_NEON_QREG_MODE and VALID_NEON_DREG_MODE cases. Permit
slightly larger constants in the latter case.
(thumb2_legitimate_index_p): Likewise.
=== modified file 'gcc/config/arm/arm.c'
--- old/gcc/config/arm/arm.c 2010-11-04 12:49:37 +0000
+++ new/gcc/config/arm/arm.c 2010-11-11 11:00:53 +0000
@@ -5611,13 +5611,25 @@
&& INTVAL (index) > -1024
&& (INTVAL (index) & 3) == 0);
- if (TARGET_NEON
- && (VALID_NEON_DREG_MODE (mode) || VALID_NEON_QREG_MODE (mode)))
+ /* For quad modes, we restrict the constant offset to be slightly less
+ than what the instruction format permits. We do this because for
+ quad mode moves, we will actually decompose them into two separate
+ double-mode reads or writes. INDEX must therefore be a valid
+ (double-mode) offset and so should INDEX+8. */
+ if (TARGET_NEON && VALID_NEON_QREG_MODE (mode))
return (code == CONST_INT
&& INTVAL (index) < 1016
&& INTVAL (index) > -1024
&& (INTVAL (index) & 3) == 0);
+ /* We have no such constraint on double mode offsets, so we permit the
+ full range of the instruction format. */
+ if (TARGET_NEON && VALID_NEON_DREG_MODE (mode))
+ return (code == CONST_INT
+ && INTVAL (index) < 1024
+ && INTVAL (index) > -1024
+ && (INTVAL (index) & 3) == 0);
+
if (TARGET_REALLY_IWMMXT && VALID_IWMMXT_REG_MODE (mode))
return (code == CONST_INT
&& INTVAL (index) < 1024
@@ -5731,13 +5743,25 @@
&& (INTVAL (index) & 3) == 0);
}
- if (TARGET_NEON
- && (VALID_NEON_DREG_MODE (mode) || VALID_NEON_QREG_MODE (mode)))
+ /* For quad modes, we restrict the constant offset to be slightly less
+ than what the instruction format permits. We do this because for
+ quad mode moves, we will actually decompose them into two separate
+ double-mode reads or writes. INDEX must therefore be a valid
+ (double-mode) offset and so should INDEX+8. */
+ if (TARGET_NEON && VALID_NEON_QREG_MODE (mode))
return (code == CONST_INT
&& INTVAL (index) < 1016
&& INTVAL (index) > -1024
&& (INTVAL (index) & 3) == 0);
+ /* We have no such constraint on double mode offsets, so we permit the
+ full range of the instruction format. */
+ if (TARGET_NEON && VALID_NEON_DREG_MODE (mode))
+ return (code == CONST_INT
+ && INTVAL (index) < 1024
+ && INTVAL (index) > -1024
+ && (INTVAL (index) & 3) == 0);
+
if (arm_address_register_rtx_p (index, strict_p)
&& (GET_MODE_SIZE (mode) <= 4))
return 1;

View File

@ -0,0 +1,40 @@
2010-10-29 Julian Brown <julian@codesourcery.com>
Launchpad #629671
gcc/
* config/arm/arm.h (REG_CLASS_CONTENTS): Remove soft frame pointer
from CORE_REGS and GENERAL_REGS classes.
* config/arm/arm.md (*thumb1_movsi_insn): Ignore all parts of final
constraint for register preferencing.
=== modified file 'gcc/config/arm/arm.h'
--- old/gcc/config/arm/arm.h 2010-11-04 10:45:05 +0000
+++ new/gcc/config/arm/arm.h 2010-11-11 11:12:14 +0000
@@ -1262,8 +1262,8 @@
{ 0x0000DF00, 0x00000000, 0x00000000, 0x00000000 }, /* HI_REGS */ \
{ 0x01000000, 0x00000000, 0x00000000, 0x00000000 }, /* CC_REG */ \
{ 0x00000000, 0x00000000, 0x00000000, 0x80000000 }, /* VFPCC_REG */ \
- { 0x0200DFFF, 0x00000000, 0x00000000, 0x00000000 }, /* GENERAL_REGS */ \
- { 0x0200FFFF, 0x00000000, 0x00000000, 0x00000000 }, /* CORE_REGS */ \
+ { 0x0000DFFF, 0x00000000, 0x00000000, 0x00000000 }, /* GENERAL_REGS */ \
+ { 0x0000FFFF, 0x00000000, 0x00000000, 0x00000000 }, /* CORE_REGS */ \
{ 0xFAFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x7FFFFFFF } /* ALL_REGS */ \
}
=== modified file 'gcc/config/arm/arm.md'
--- old/gcc/config/arm/arm.md 2010-11-04 10:45:05 +0000
+++ new/gcc/config/arm/arm.md 2010-11-11 11:12:14 +0000
@@ -5160,8 +5160,8 @@
})
(define_insn "*thumb1_movsi_insn"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lhk")
- (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lhk"))]
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*l*h*k")
+ (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*l*h*k"))]
"TARGET_THUMB1
&& ( register_operand (operands[0], SImode)
|| register_operand (operands[1], SImode))"

View File

@ -0,0 +1,30 @@
2010-11-3 Chung-Lin Tang <cltang@codesourcery.com>
Backport from mainline:
2010-11-02 Chung-Lin Tang <cltang@codesourcery.com>
gcc/
* Makefile.in (LIBGCC2_CFLAGS): Add -fno-stack-protector, to
explicitly disable stack protection when building libgcc.
(CRTSTUFF_CFLAGS): Same, for crtbegin/end.
--- old/gcc/Makefile.in 2010-11-08 22:08:43 +0000
+++ new/gcc/Makefile.in 2010-11-11 11:34:59 +0000
@@ -646,6 +646,7 @@
LIBGCC2_CFLAGS = -O2 $(LIBGCC2_INCLUDES) $(GCC_CFLAGS) $(TARGET_LIBGCC2_CFLAGS) \
$(LIBGCC2_DEBUG_CFLAGS) $(GTHREAD_FLAGS) \
-DIN_LIBGCC2 -D__GCC_FLOAT_NOT_NEEDED \
+ -fno-stack-protector \
$(INHIBIT_LIBC_CFLAGS)
# Additional options to use when compiling libgcc2.a.
@@ -659,6 +660,7 @@
CRTSTUFF_CFLAGS = -O2 $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -g0 \
-finhibit-size-directive -fno-inline -fno-exceptions \
-fno-zero-initialized-in-bss -fno-toplevel-reorder -fno-tree-vectorize \
+ -fno-stack-protector \
$(INHIBIT_LIBC_CFLAGS)
# Additional sources to handle exceptions; overridden by targets as needed.

View File

@ -0,0 +1,32 @@
2010-11-08 Yao Qi <yao@codesourcery.com>
Backport from mainline:
gcc/
2010-08-02 Bernd Schmidt <bernds@codesourcery.com>
* config/arm/arm.c (arm_rtx_costs_1): Remove second clause from the
if statement which adds extra costs to frame-related
expressions.
=== modified file 'gcc/config/arm/arm.c'
--- old/gcc/config/arm/arm.c 2010-11-11 11:00:53 +0000
+++ new/gcc/config/arm/arm.c 2010-11-11 11:50:33 +0000
@@ -6805,12 +6805,10 @@
since then they might not be moved outside of loops. As a compromise
we allow integration with ops that have a constant as their second
operand. */
- if ((REG_OR_SUBREG_REG (XEXP (x, 0))
- && ARM_FRAME_RTX (REG_OR_SUBREG_RTX (XEXP (x, 0)))
- && GET_CODE (XEXP (x, 1)) != CONST_INT)
- || (REG_OR_SUBREG_REG (XEXP (x, 0))
- && ARM_FRAME_RTX (REG_OR_SUBREG_RTX (XEXP (x, 0)))))
- *total = 4;
+ if (REG_OR_SUBREG_REG (XEXP (x, 0))
+ && ARM_FRAME_RTX (REG_OR_SUBREG_RTX (XEXP (x, 0)))
+ && GET_CODE (XEXP (x, 1)) != CONST_INT)
+ *total = COSTS_N_INSNS (1);
if (mode == DImode)
{

View File

@ -0,0 +1,209 @@
2010-11-24 Maxim Kuvyrkov <maxim@codesourcery.com>
gcc/
* combine.c (subst, combine_simlify_rtx): Add new argument, use it
to track processing of conditionals. Update all callers.
(try_combine, simplify_if_then_else): Update.
=== modified file 'gcc/combine.c'
--- old/gcc/combine.c 2010-11-04 12:39:28 +0000
+++ new/gcc/combine.c 2010-11-25 11:11:45 +0000
@@ -392,8 +392,8 @@
static void undo_all (void);
static void undo_commit (void);
static rtx *find_split_point (rtx *, rtx);
-static rtx subst (rtx, rtx, rtx, int, int);
-static rtx combine_simplify_rtx (rtx, enum machine_mode, int);
+static rtx subst (rtx, rtx, rtx, int, int, int);
+static rtx combine_simplify_rtx (rtx, enum machine_mode, int, int);
static rtx simplify_if_then_else (rtx);
static rtx simplify_set (rtx);
static rtx simplify_logical (rtx);
@@ -2944,12 +2944,12 @@
if (i1)
{
subst_low_luid = DF_INSN_LUID (i1);
- i1src = subst (i1src, pc_rtx, pc_rtx, 0, 0);
+ i1src = subst (i1src, pc_rtx, pc_rtx, 0, 0, 0);
}
else
{
subst_low_luid = DF_INSN_LUID (i2);
- i2src = subst (i2src, pc_rtx, pc_rtx, 0, 0);
+ i2src = subst (i2src, pc_rtx, pc_rtx, 0, 0, 0);
}
}
@@ -2960,7 +2960,7 @@
to avoid self-referential rtl. */
subst_low_luid = DF_INSN_LUID (i2);
- newpat = subst (PATTERN (i3), i2dest, i2src, 0,
+ newpat = subst (PATTERN (i3), i2dest, i2src, 0, 0,
! i1_feeds_i3 && i1dest_in_i1src);
substed_i2 = 1;
@@ -2991,7 +2991,7 @@
n_occurrences = 0;
subst_low_luid = DF_INSN_LUID (i1);
- newpat = subst (newpat, i1dest, i1src, 0, 0);
+ newpat = subst (newpat, i1dest, i1src, 0, 0, 0);
substed_i1 = 1;
}
@@ -3053,7 +3053,7 @@
else
/* See comment where i2pat is assigned. */
XVECEXP (newpat, 0, --total_sets)
- = subst (i2pat, i1dest, i1src, 0, 0);
+ = subst (i2pat, i1dest, i1src, 0, 0, 0);
}
}
@@ -4605,11 +4605,13 @@
IN_DEST is nonzero if we are processing the SET_DEST of a SET.
+ IN_COND is nonzero if we are on top level of the condition.
+
UNIQUE_COPY is nonzero if each substitution must be unique. We do this
by copying if `n_occurrences' is nonzero. */
static rtx
-subst (rtx x, rtx from, rtx to, int in_dest, int unique_copy)
+subst (rtx x, rtx from, rtx to, int in_dest, int in_cond, int unique_copy)
{
enum rtx_code code = GET_CODE (x);
enum machine_mode op0_mode = VOIDmode;
@@ -4670,7 +4672,7 @@
&& GET_CODE (XVECEXP (x, 0, 0)) == SET
&& GET_CODE (SET_SRC (XVECEXP (x, 0, 0))) == ASM_OPERANDS)
{
- new_rtx = subst (XVECEXP (x, 0, 0), from, to, 0, unique_copy);
+ new_rtx = subst (XVECEXP (x, 0, 0), from, to, 0, 0, unique_copy);
/* If this substitution failed, this whole thing fails. */
if (GET_CODE (new_rtx) == CLOBBER
@@ -4687,7 +4689,7 @@
&& GET_CODE (dest) != CC0
&& GET_CODE (dest) != PC)
{
- new_rtx = subst (dest, from, to, 0, unique_copy);
+ new_rtx = subst (dest, from, to, 0, 0, unique_copy);
/* If this substitution failed, this whole thing fails. */
if (GET_CODE (new_rtx) == CLOBBER
@@ -4733,8 +4735,8 @@
}
else
{
- new_rtx = subst (XVECEXP (x, i, j), from, to, 0,
- unique_copy);
+ new_rtx = subst (XVECEXP (x, i, j), from, to, 0, 0,
+ unique_copy);
/* If this substitution failed, this whole thing
fails. */
@@ -4811,7 +4813,9 @@
&& (code == SUBREG || code == STRICT_LOW_PART
|| code == ZERO_EXTRACT))
|| code == SET)
- && i == 0), unique_copy);
+ && i == 0),
+ code == IF_THEN_ELSE && i == 0,
+ unique_copy);
/* If we found that we will have to reject this combination,
indicate that by returning the CLOBBER ourselves, rather than
@@ -4868,7 +4872,7 @@
/* If X is sufficiently simple, don't bother trying to do anything
with it. */
if (code != CONST_INT && code != REG && code != CLOBBER)
- x = combine_simplify_rtx (x, op0_mode, in_dest);
+ x = combine_simplify_rtx (x, op0_mode, in_dest, in_cond);
if (GET_CODE (x) == code)
break;
@@ -4888,10 +4892,12 @@
expression.
OP0_MODE is the original mode of XEXP (x, 0). IN_DEST is nonzero
- if we are inside a SET_DEST. */
+ if we are inside a SET_DEST. IN_COND is nonzero if we are on the top level
+ of a condition. */
static rtx
-combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest)
+combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest,
+ int in_cond)
{
enum rtx_code code = GET_CODE (x);
enum machine_mode mode = GET_MODE (x);
@@ -4946,8 +4952,8 @@
false arms to store-flag values. Be careful to use copy_rtx
here since true_rtx or false_rtx might share RTL with x as a
result of the if_then_else_cond call above. */
- true_rtx = subst (copy_rtx (true_rtx), pc_rtx, pc_rtx, 0, 0);
- false_rtx = subst (copy_rtx (false_rtx), pc_rtx, pc_rtx, 0, 0);
+ true_rtx = subst (copy_rtx (true_rtx), pc_rtx, pc_rtx, 0, 0, 0);
+ false_rtx = subst (copy_rtx (false_rtx), pc_rtx, pc_rtx, 0, 0, 0);
/* If true_rtx and false_rtx are not general_operands, an if_then_else
is unlikely to be simpler. */
@@ -5291,7 +5297,7 @@
{
/* Try to simplify the expression further. */
rtx tor = simplify_gen_binary (IOR, mode, XEXP (x, 0), XEXP (x, 1));
- temp = combine_simplify_rtx (tor, mode, in_dest);
+ temp = combine_simplify_rtx (tor, mode, in_dest, 0);
/* If we could, great. If not, do not go ahead with the IOR
replacement, since PLUS appears in many special purpose
@@ -5384,7 +5390,16 @@
ZERO_EXTRACT is indeed appropriate, it will be placed back by
the call to make_compound_operation in the SET case. */
- if (STORE_FLAG_VALUE == 1
+ if (in_cond)
+ /* Don't apply below optimizations if the caller would
+ prefer a comparison rather than a value.
+ E.g., for the condition in an IF_THEN_ELSE most targets need
+ an explicit comparison. */
+ {
+ ;
+ }
+
+ else if (STORE_FLAG_VALUE == 1
&& new_code == NE && GET_MODE_CLASS (mode) == MODE_INT
&& op1 == const0_rtx
&& mode == GET_MODE (op0)
@@ -5628,11 +5643,11 @@
if (reg_mentioned_p (from, true_rtx))
true_rtx = subst (known_cond (copy_rtx (true_rtx), true_code,
from, true_val),
- pc_rtx, pc_rtx, 0, 0);
+ pc_rtx, pc_rtx, 0, 0, 0);
if (reg_mentioned_p (from, false_rtx))
false_rtx = subst (known_cond (copy_rtx (false_rtx), false_code,
from, false_val),
- pc_rtx, pc_rtx, 0, 0);
+ pc_rtx, pc_rtx, 0, 0, 0);
SUBST (XEXP (x, 1), swapped ? false_rtx : true_rtx);
SUBST (XEXP (x, 2), swapped ? true_rtx : false_rtx);
@@ -5849,11 +5864,11 @@
{
temp = subst (simplify_gen_relational (true_code, m, VOIDmode,
cond_op0, cond_op1),
- pc_rtx, pc_rtx, 0, 0);
+ pc_rtx, pc_rtx, 0, 0, 0);
temp = simplify_gen_binary (MULT, m, temp,
simplify_gen_binary (MULT, m, c1,
const_true_rtx));
- temp = subst (temp, pc_rtx, pc_rtx, 0, 0);
+ temp = subst (temp, pc_rtx, pc_rtx, 0, 0, 0);
temp = simplify_gen_binary (op, m, gen_lowpart (m, z), temp);
if (extend_op != UNKNOWN)

View File

@ -0,0 +1,27 @@
2010-11-24 Richard Sandiford <richard.sandiford@linaro.org>
Launchpad #618684
Backport from mainline:
2010-04-10 Bernd Schmidt <bernds@codesourcery.com>
* reload1.c (eliminate_regs_in_insn): Don't restore an operand
if doing so would replace the entire pattern.
=== modified file 'gcc/reload1.c'
--- old/gcc/reload1.c 2010-10-04 00:50:43 +0000
+++ new/gcc/reload1.c 2010-11-24 13:40:23 +0000
@@ -3567,7 +3567,10 @@
{
/* Restore the old body. */
for (i = 0; i < recog_data.n_operands; i++)
- *recog_data.operand_loc[i] = orig_operand[i];
+ /* Restoring a top-level match_parallel would clobber the new_body
+ we installed in the insn. */
+ if (recog_data.operand_loc[i] != &PATTERN (insn))
+ *recog_data.operand_loc[i] = orig_operand[i];
for (i = 0; i < recog_data.n_dups; i++)
*recog_data.dup_loc[i] = orig_operand[(int) recog_data.dup_num[i]];
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,78 @@
2010-11-24 Chung-Lin Tang <cltang@codesourcery.com>
2010-07-08 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>
PR bootstrap/44768
* cfgexpand.c (estimated_stack_frame_size): Make self-contained
with respect to current_function_decl. Pass decl of the function.
* tree-inline.h (estimated_stack_frame_size): Adjust prototype.
* ipa-inline.c (compute_inline_parameters): Pass decl to
estimated_stack_frame_size.
=== modified file 'gcc/cfgexpand.c'
--- old/gcc/cfgexpand.c 2010-10-04 00:50:43 +0000
+++ new/gcc/cfgexpand.c 2010-11-24 08:43:48 +0000
@@ -1248,8 +1248,8 @@
stack_vars_alloc = stack_vars_num = 0;
}
-/* Make a fair guess for the size of the stack frame of the current
- function. This doesn't have to be exact, the result is only used
+/* Make a fair guess for the size of the stack frame of the decl
+ passed. This doesn't have to be exact, the result is only used
in the inline heuristics. So we don't want to run the full stack
var packing algorithm (which is quadratic in the number of stack
vars). Instead, we calculate the total size of all stack vars.
@@ -1257,11 +1257,14 @@
vars doesn't happen very often. */
HOST_WIDE_INT
-estimated_stack_frame_size (void)
+estimated_stack_frame_size (tree decl)
{
HOST_WIDE_INT size = 0;
size_t i;
tree t, outer_block = DECL_INITIAL (current_function_decl);
+ tree old_cur_fun_decl = current_function_decl;
+ current_function_decl = decl;
+ push_cfun (DECL_STRUCT_FUNCTION (decl));
init_vars_expansion ();
@@ -1284,7 +1287,8 @@
size += account_stack_vars ();
fini_vars_expansion ();
}
-
+ pop_cfun ();
+ current_function_decl = old_cur_fun_decl;
return size;
}
=== modified file 'gcc/ipa-inline.c'
--- old/gcc/ipa-inline.c 2010-06-30 21:30:12 +0000
+++ new/gcc/ipa-inline.c 2010-11-24 08:43:48 +0000
@@ -1967,7 +1967,7 @@
/* Estimate the stack size for the function. But not at -O0
because estimated_stack_frame_size is a quadratic problem. */
- self_stack_size = optimize ? estimated_stack_frame_size () : 0;
+ self_stack_size = optimize ? estimated_stack_frame_size (node->decl) : 0;
inline_summary (node)->estimated_self_stack_size = self_stack_size;
node->global.estimated_stack_size = self_stack_size;
node->global.stack_frame_offset = 0;
=== modified file 'gcc/tree-inline.h'
--- old/gcc/tree-inline.h 2009-09-14 18:18:58 +0000
+++ new/gcc/tree-inline.h 2010-11-24 08:43:48 +0000
@@ -187,6 +187,6 @@
extern tree remap_type (tree type, copy_body_data *id);
extern gimple_seq copy_gimple_seq_and_replace_locals (gimple_seq seq);
-extern HOST_WIDE_INT estimated_stack_frame_size (void);
+extern HOST_WIDE_INT estimated_stack_frame_size (tree);
#endif /* GCC_TREE_INLINE_H */

View File

@ -0,0 +1,33 @@
2010-11-25 Andrew Stubbs <ams@codesourcery.com>
Backport from mainline:
2010-10-28 Andrew Stubbs <ams@codesourcery.com>
gcc/
* config/arm/arm.c (const_ok_for_arm): Support 0xXY00XY00 pattern
constants in thumb2.
=== modified file 'gcc/config/arm/arm.c'
--- old/gcc/config/arm/arm.c 2010-11-11 11:50:33 +0000
+++ new/gcc/config/arm/arm.c 2010-12-10 15:30:47 +0000
@@ -2340,11 +2340,17 @@
{
HOST_WIDE_INT v;
- /* Allow repeated pattern. */
+ /* Allow repeated patterns 0x00XY00XY or 0xXYXYXYXY. */
v = i & 0xff;
v |= v << 16;
if (i == v || i == (v | (v << 8)))
return TRUE;
+
+ /* Allow repeated pattern 0xXY00XY00. */
+ v = i & 0xff00;
+ v |= v << 16;
+ if (i == v)
+ return TRUE;
}
return FALSE;

View File

@ -0,0 +1,23 @@
2010-11-24 Maxim Kuvyrkov <maxim@codesourcery.com>
gcc/
* loop-iv.c (get_biv_step): Workaround loop analysis ICE.
=== modified file 'gcc/loop-iv.c'
--- old/gcc/loop-iv.c 2009-11-25 10:55:54 +0000
+++ new/gcc/loop-iv.c 2010-12-10 15:32:04 +0000
@@ -796,6 +796,13 @@
outer_step))
return false;
+ /* CSL local: workaround get_biv_step_1() inability to handle DU
+ chains originating at sets of subregs. Such subregs are introduced
+ by Tom's extension elimination pass. For upstream duscussion see
+ http://gcc.gnu.org/ml/gcc/2010-11/msg00552.html . */
+ if (!((*inner_mode == *outer_mode) != (*extend != UNKNOWN)))
+ return false;
+
gcc_assert ((*inner_mode == *outer_mode) != (*extend != UNKNOWN));
gcc_assert (*inner_mode != *outer_mode || *outer_step == const0_rtx);

View File

@ -0,0 +1,873 @@
2010-11-26 Tom de Vries <tom@codesourcery.com>
gcc/
* gcc/ee.c: New file.
* gcc/tree-pass.h (pass_ee): Declare.
* gcc/opts.c (decode_options): Set flag_ee at -O2.
* gcc/timevar.def (TV_EE): New timevar.
* gcc/common.opt (fextension-elimination): New option.
* gcc/Makefile.in (ee.o): New rule.
* gcc/passes.c (pass_ee): Add it.
* gcc/testsuite/gcc.dg/extend-4.c: New test.
* gcc/testsuite/gcc.dg/extend-1.c: New test.
* gcc/testsuite/gcc.dg/extend-2.c: New test.
* gcc/testsuite/gcc.dg/extend-2-64.c: New test.
* gcc/testsuite/gcc.dg/extend-3.c: New test.
=== modified file 'gcc/Makefile.in'
--- old/gcc/Makefile.in 2010-11-16 18:05:53 +0000
+++ new/gcc/Makefile.in 2010-12-10 15:33:37 +0000
@@ -1194,6 +1194,7 @@
dse.o \
dwarf2asm.o \
dwarf2out.o \
+ ee.o \
ebitmap.o \
emit-rtl.o \
et-forest.o \
@@ -2965,6 +2966,11 @@
web.o : web.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
hard-reg-set.h $(FLAGS_H) $(BASIC_BLOCK_H) $(FUNCTION_H) output.h $(TOPLEV_H) \
$(DF_H) $(OBSTACK_H) $(TIMEVAR_H) $(TREE_PASS_H)
+ee.o : ee.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
+ hard-reg-set.h $(FLAGS_H) $(BASIC_BLOCK_H) $(FUNCTION_H) output.h \
+ $(DF_H) $(TIMEVAR_H) tree-pass.h $(RECOG_H) $(EXPR_H) \
+ $(REGS_H) $(TREE_H) $(TM_P_H) insn-config.h $(INSN_ATTR_H) $(TOPLEV_H) $(DIAGNOSTIC_CORE_H) \
+ $(TARGET_H) $(OPTABS_H) insn-codes.h rtlhooks-def.h $(PARAMS_H) $(CGRAPH_H)
gcse.o : gcse.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
$(REGS_H) hard-reg-set.h $(FLAGS_H) $(REAL_H) insn-config.h $(GGC_H) \
$(RECOG_H) $(EXPR_H) $(BASIC_BLOCK_H) $(FUNCTION_H) output.h $(TOPLEV_H) \
=== modified file 'gcc/common.opt'
--- old/gcc/common.opt 2010-11-04 12:43:52 +0000
+++ new/gcc/common.opt 2010-12-10 15:33:37 +0000
@@ -496,6 +496,10 @@
Common Report Var(flag_early_inlining) Init(1) Optimization
Perform early inlining
+fextension-elimination
+Common Report Var(flag_ee) Init(0) Optimization
+Perform extension elimination
+
feliminate-dwarf2-dups
Common Report Var(flag_eliminate_dwarf2_dups)
Perform DWARF2 duplicate elimination
=== added file 'gcc/ee.c'
--- old/gcc/ee.c 1970-01-01 00:00:00 +0000
+++ new/gcc/ee.c 2010-12-10 15:33:37 +0000
@@ -0,0 +1,662 @@
+/* Redundant extension elimination
+ Copyright (C) 2010 Free Software Foundation, Inc.
+ Contributed by Tom de Vries (tom@codesourcery.com)
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+/*
+
+ MOTIVATING EXAMPLE
+
+ The motivating example for this pass is:
+
+ void f(unsigned char *p, short s, int c, int *z)
+ {
+ if (c)
+ *z = 0;
+ *p ^= (unsigned char)s;
+ }
+
+ For MIPS, compilation results in the following insns.
+
+ (set (reg/v:SI 199)
+ (sign_extend:SI (subreg:HI (reg:SI 200) 2)))
+
+ ...
+
+ (set (reg:QI 203)
+ (subreg:QI (reg/v:SI 199) 3))
+
+ These insns are the only def and the only use of reg 199, each located in a
+ different bb.
+
+ The sign-extension preserves the lower half of reg 200 and copies them to
+ reg 199, and the subreg use of reg 199 only reads the least significant byte.
+ The sign extension is therefore redundant (the extension part, not the copy
+ part), and can safely be replaced with a regcopy from reg 200 to reg 199.
+
+
+ OTHER SIGN/ZERO EXTENSION ELIMINATION PASSES
+
+ There are other passes which eliminate sign/zero-extension: combine and
+ implicit_zee. Both attempt to eliminate extensions by combining them with
+ other instructions. The combine pass does this at bb level,
+ implicit_zee works at inter-bb level.
+
+ The combine pass combine an extension with either:
+ - all uses of the extension, or
+ - all defs of the operand of the extension.
+ The implicit_zee pass only implements the latter.
+
+ For our motivating example, combine doesn't work since the def and the use of
+ reg 199 are in a different bb.
+
+ Implicit_zee does not work since it only combines an extension with the defs
+ of its operand.
+
+
+ INTENDED EFFECT
+
+ This pass works by removing sign/zero-extensions, or replacing them with
+ regcopies. The idea there is that the regcopy might be eliminated by a later
+ pass. In case the regcopy cannot be eliminated, it might at least be cheaper
+ than the extension.
+
+
+ IMPLEMENTATION
+
+ The pass scans twice over all instructions.
+
+ The first scan registers all uses of a reg in the biggest_use array. After
+ that first scan, the biggest_use array contains the size in bits of the
+ biggest use of each reg.
+
+ The second scan finds extensions, determines whether they are redundant based
+ on the biggest use, and deletes or replaces them.
+
+ In case that the src and dest reg of the replacement are not of the same size,
+ we do not replace with a normal regcopy, but with a truncate or with the copy
+ of a paradoxical subreg instead.
+
+
+ LIMITATIONS
+
+ The scope of the analysis is limited to an extension and its uses. The other
+ type of analysis (related to the defs of the operand of an extension) is not
+ done.
+
+ Furthermore, we do the analysis of biggest use per reg. So when determining
+ whether an extension is redundant, we take all uses of a the dest reg into
+ account, also the ones that are not uses of the extension. This could be
+ overcome by calculating the def-use chains and using those for analysis
+ instead.
+
+ Finally, during the analysis each insn is looked at in isolation. There is no
+ propagation of information during the analysis. To overcome this limitation,
+ a backward iterative bit-level liveness analysis is needed. */
+
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "rtl.h"
+#include "tree.h"
+#include "tm_p.h"
+#include "flags.h"
+#include "regs.h"
+#include "hard-reg-set.h"
+#include "basic-block.h"
+#include "insn-config.h"
+#include "function.h"
+#include "expr.h"
+#include "insn-attr.h"
+#include "recog.h"
+#include "toplev.h"
+#include "target.h"
+#include "timevar.h"
+#include "optabs.h"
+#include "insn-codes.h"
+#include "rtlhooks-def.h"
+#include "output.h"
+#include "params.h"
+#include "timevar.h"
+#include "tree-pass.h"
+#include "cgraph.h"
+
+#define SKIP_REG (-1)
+
+/* Array to register the biggest use of a reg, in bits. */
+
+static int *biggest_use;
+
+/* Forward declaration. */
+
+static void note_use (rtx *x, void *data);
+
+/* The following two functions are borrowed from trunk/gcc/toplev.c. They can be
+ removed for a check-in into gcc trunk. */
+
+/* Given X, an unsigned number, return the number of least significant bits
+ that are zero. When X == 0, the result is the word size. */
+
+static int
+ctz_hwi (unsigned HOST_WIDE_INT x)
+{
+ return x ? floor_log2 (x & -x) : HOST_BITS_PER_WIDE_INT;
+}
+
+/* Similarly for most significant bits. */
+
+static int
+clz_hwi (unsigned HOST_WIDE_INT x)
+{
+ return HOST_BITS_PER_WIDE_INT - 1 - floor_log2(x);
+}
+
+/* Check whether this is a paradoxical subreg. */
+
+static bool
+paradoxical_subreg_p (rtx subreg)
+{
+ enum machine_mode subreg_mode, reg_mode;
+
+ if (GET_CODE (subreg) != SUBREG)
+ return false;
+
+ subreg_mode = GET_MODE (subreg);
+ reg_mode = GET_MODE (SUBREG_REG (subreg));
+
+ if (GET_MODE_SIZE (subreg_mode) > GET_MODE_SIZE (reg_mode))
+ return true;
+
+ return false;
+}
+
+/* Get the size and reg number of a REG or SUBREG use. */
+
+static bool
+reg_use_p (rtx use, int *size, unsigned int *regno)
+{
+ rtx reg;
+
+ if (REG_P (use))
+ {
+ *regno = REGNO (use);
+ *size = GET_MODE_BITSIZE (GET_MODE (use));
+ return true;
+ }
+ else if (GET_CODE (use) == SUBREG)
+ {
+ reg = SUBREG_REG (use);
+
+ if (!REG_P (reg))
+ return false;
+
+ *regno = REGNO (reg);
+
+ if (paradoxical_subreg_p (use))
+ *size = GET_MODE_BITSIZE (GET_MODE (reg));
+ else
+ *size = subreg_lsb (use) + GET_MODE_BITSIZE (GET_MODE (use));
+
+ return true;
+ }
+
+ return false;
+}
+
+/* Register the use of a reg. */
+
+static void
+register_use (int size, unsigned int regno)
+{
+ int *current = &biggest_use[regno];
+
+ if (*current == SKIP_REG)
+ return;
+
+ *current = MAX (*current, size);
+}
+
+/* Handle embedded uses. */
+
+static void
+note_embedded_uses (rtx use, rtx pattern)
+{
+ const char *format_ptr;
+ int i, j;
+
+ format_ptr = GET_RTX_FORMAT (GET_CODE (use));
+ for (i = 0; i < GET_RTX_LENGTH (GET_CODE (use)); i++)
+ if (format_ptr[i] == 'e')
+ note_use (&XEXP (use, i), pattern);
+ else if (format_ptr[i] == 'E')
+ for (j = 0; j < XVECLEN (use, i); j++)
+ note_use (&XVECEXP (use, i, j), pattern);
+}
+
+/* Get the set that has use as its SRC operand. */
+
+static rtx
+get_set (rtx use, rtx pattern)
+{
+ rtx sub;
+ int i;
+
+ if (GET_CODE (pattern) == SET && SET_SRC (pattern) == use)
+ return pattern;
+
+ if (GET_CODE (pattern) == PARALLEL)
+ for (i = 0; i < XVECLEN (pattern, 0); ++i)
+ {
+ sub = XVECEXP (pattern, 0, i);
+ if (GET_CODE (sub) == SET && SET_SRC (sub) == use)
+ return sub;
+ }
+
+ return NULL_RTX;
+}
+
+/* Handle a restricted op use. In this context restricted means that a bit in an
+ operand influences only the same bit or more significant bits in the result.
+ The bitwise ops are a subclass, but PLUS is one as well. */
+
+static void
+note_restricted_op_use (rtx use, unsigned int nr_operands, rtx pattern)
+{
+ unsigned int i, smallest;
+ int operand_size[2];
+ int used_size;
+ unsigned int operand_regno[2];
+ bool operand_reg[2];
+ bool operand_ignore[2];
+ rtx set;
+
+ /* Init operand_reg, operand_size, operand_regno and operand_ignore. */
+ for (i = 0; i < nr_operands; ++i)
+ {
+ operand_reg[i] = reg_use_p (XEXP (use, i), &operand_size[i],
+ &operand_regno[i]);
+ operand_ignore[i] = false;
+ }
+
+ /* Handle case of reg and-masked with const. */
+ if (GET_CODE (use) == AND && CONST_INT_P (XEXP (use, 1)) && operand_reg[0])
+ {
+ used_size =
+ HOST_BITS_PER_WIDE_INT - clz_hwi (UINTVAL (XEXP (use, 1)));
+ operand_size[0] = MIN (operand_size[0], used_size);
+ }
+
+ /* Handle case of reg or-masked with const. */
+ if (GET_CODE (use) == IOR && CONST_INT_P (XEXP (use, 1)) && operand_reg[0])
+ {
+ used_size =
+ HOST_BITS_PER_WIDE_INT - clz_hwi (~UINTVAL (XEXP (use, 1)));
+ operand_size[0] = MIN (operand_size[0], used_size);
+ }
+
+ /* Ignore the use of a in 'a = a + b'. */
+ set = get_set (use, pattern);
+ if (set != NULL_RTX && REG_P (SET_DEST (set)))
+ for (i = 0; i < nr_operands; ++i)
+ operand_ignore[i] = (operand_reg[i]
+ && (REGNO (SET_DEST (set)) == operand_regno[i]));
+
+ /* Handle the case a reg is combined with don't care bits. */
+ if (nr_operands == 2 && operand_reg[0] && operand_reg[1]
+ && operand_size[0] != operand_size[1])
+ {
+ smallest = operand_size[0] > operand_size[1];
+
+ if (paradoxical_subreg_p (XEXP (use, smallest))
+ && !SUBREG_PROMOTED_VAR_P (XEXP (use, smallest)))
+ operand_size[1 - smallest] = operand_size[smallest];
+ }
+
+ /* Register the operand use, if necessary. */
+ for (i = 0; i < nr_operands; ++i)
+ if (!operand_reg[i])
+ note_use (&XEXP (use, i), pattern);
+ else if (!operand_ignore[i])
+ register_use (operand_size[i], operand_regno[i]);
+}
+
+/* Handle all uses noted by note_uses. */
+
+static void
+note_use (rtx *x, void *data)
+{
+ rtx use = *x;
+ rtx pattern = (rtx)data;
+ int use_size;
+ unsigned int use_regno;
+
+ switch (GET_CODE (use))
+ {
+ case REG:
+ case SUBREG:
+ if (!reg_use_p (use, &use_size, &use_regno))
+ {
+ note_embedded_uses (use, pattern);
+ return;
+ }
+ register_use (use_size, use_regno);
+ return;
+ case IOR:
+ case AND:
+ case XOR:
+ case PLUS:
+ case MINUS:
+ note_restricted_op_use (use, 2, pattern);
+ return;
+ case NOT:
+ case NEG:
+ note_restricted_op_use (use, 1, pattern);
+ return;
+ case ASHIFT:
+ if (!reg_use_p (XEXP (use, 0), &use_size, &use_regno)
+ || !CONST_INT_P (XEXP (use, 1))
+ || INTVAL (XEXP (use, 1)) <= 0
+ || paradoxical_subreg_p (XEXP (use, 0)))
+ {
+ note_embedded_uses (use, pattern);
+ return;
+ }
+ register_use (use_size - INTVAL (XEXP (use, 1)), use_regno);
+ return;
+ default:
+ note_embedded_uses (use, pattern);
+ return;
+ }
+}
+
+/* Check whether reg is implicitly used. */
+
+static bool
+implicit_use_p (int regno)
+{
+#ifdef EPILOGUE_USES
+ if (EPILOGUE_USES (regno))
+ return true;
+#endif
+
+#ifdef EH_USES
+ if (EH_USES (regno))
+ return true;
+#endif
+
+ return false;
+}
+
+/* Note the uses of argument registers in a call. */
+
+static void
+note_call_uses (rtx insn)
+{
+ rtx link, link_expr;
+
+ if (!CALL_P (insn))
+ return;
+
+ for (link = CALL_INSN_FUNCTION_USAGE (insn); link; link = XEXP (link, 1))
+ {
+ link_expr = XEXP (link, 0);
+
+ if (GET_CODE (link_expr) == USE)
+ note_use (&XEXP (link_expr, 0), link);
+ }
+}
+
+/* Calculate the biggest use mode for all regs. */
+
+static void
+calculate_biggest_use (void)
+{
+ int i;
+ basic_block bb;
+ rtx insn;
+
+ /* Initialize biggest_use for all regs to 0. If a reg is used implicitly, we
+ handle that reg conservatively and set it to SKIP_REG instead. */
+ for (i = 0; i < max_reg_num (); i++)
+ biggest_use[i] = ((implicit_use_p (i) || HARD_REGISTER_NUM_P (i))
+ ? SKIP_REG : 0);
+
+ /* For all insns, call note_use for each use in insn. */
+ FOR_EACH_BB (bb)
+ FOR_BB_INSNS (bb, insn)
+ {
+ if (!NONDEBUG_INSN_P (insn))
+ continue;
+
+ note_uses (&PATTERN (insn), note_use, PATTERN (insn));
+
+ if (CALL_P (insn))
+ note_call_uses (insn);
+ }
+
+ /* Dump the biggest uses found. */
+ if (dump_file)
+ for (i = 0; i < max_reg_num (); i++)
+ if (biggest_use[i] > 0)
+ fprintf (dump_file, "reg %d: size %d\n", i, biggest_use[i]);
+}
+
+/* Check whether this is a sign/zero extension. */
+
+static bool
+extension_p (rtx insn, rtx *dest, rtx *inner, int *preserved_size)
+{
+ rtx src, op0;
+
+ /* Detect set of reg. */
+ if (GET_CODE (PATTERN (insn)) != SET)
+ return false;
+
+ src = SET_SRC (PATTERN (insn));
+ *dest = SET_DEST (PATTERN (insn));
+
+ if (!REG_P (*dest))
+ return false;
+
+ /* Detect sign or zero extension. */
+ if (GET_CODE (src) == ZERO_EXTEND || GET_CODE (src) == SIGN_EXTEND
+ || (GET_CODE (src) == AND && CONST_INT_P (XEXP (src, 1))))
+ {
+ op0 = XEXP (src, 0);
+
+ /* Determine amount of least significant bits preserved by operation. */
+ if (GET_CODE (src) == AND)
+ *preserved_size = ctz_hwi (~UINTVAL (XEXP (src, 1)));
+ else
+ *preserved_size = GET_MODE_BITSIZE (GET_MODE (op0));
+
+ if (GET_CODE (op0) == SUBREG)
+ {
+ if (subreg_lsb (op0) != 0)
+ return false;
+
+ *inner = SUBREG_REG (op0);
+ return true;
+ }
+ else if (REG_P (op0))
+ {
+ *inner = op0;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/* Check whether this is a redundant sign/zero extension. */
+
+static bool
+redundant_extension_p (rtx insn, rtx *dest, rtx *inner)
+{
+ int biggest_dest_use;
+ int preserved_size;
+
+ if (!extension_p (insn, dest, inner, &preserved_size))
+ return false;
+
+ if (dump_file)
+ fprintf (dump_file, "considering extension %u with preserved size %d\n",
+ INSN_UID (insn), preserved_size);
+
+ biggest_dest_use = biggest_use[REGNO (*dest)];
+
+ if (biggest_dest_use == SKIP_REG)
+ return false;
+
+ if (preserved_size < biggest_dest_use)
+ return false;
+
+ if (dump_file)
+ fprintf (dump_file, "found superfluous extension %u\n", INSN_UID (insn));
+
+ return true;
+}
+
+/* Try to remove or replace the redundant extension. */
+
+static void
+try_remove_or_replace_extension (rtx insn, rtx dest, rtx inner)
+{
+ rtx cp_src, cp_dest, seq, one;
+
+ if (GET_MODE_CLASS (GET_MODE (dest)) != GET_MODE_CLASS (GET_MODE (inner)))
+ return;
+
+ /* Check whether replacement is needed. */
+ if (dest != inner)
+ {
+ start_sequence ();
+
+ /* Determine the proper replacement operation. */
+ if (GET_MODE (dest) == GET_MODE (inner))
+ {
+ cp_src = inner;
+ cp_dest = dest;
+ }
+ else if (GET_MODE_SIZE (GET_MODE (dest))
+ > GET_MODE_SIZE (GET_MODE (inner)))
+ {
+ emit_clobber (dest);
+ cp_src = inner;
+ cp_dest = gen_lowpart_SUBREG (GET_MODE (inner), dest);
+ }
+ else
+ {
+ cp_src = gen_rtx_TRUNCATE (GET_MODE (dest), inner);
+ cp_dest = dest;
+ }
+
+ emit_move_insn (cp_dest, cp_src);
+
+ seq = get_insns ();
+ end_sequence ();
+
+ /* If the replacement is not supported, bail out. */
+ for (one = seq; one != NULL_RTX; one = NEXT_INSN (one))
+ if (recog_memoized (one) < 0 && GET_CODE (PATTERN (one)) != CLOBBER)
+ return;
+
+ /* Insert the replacement. */
+ emit_insn_before (seq, insn);
+ }
+
+ /* Note replacement/removal in the dump. */
+ if (dump_file)
+ {
+ fprintf (dump_file, "superfluous extension %u ", INSN_UID (insn));
+ if (dest != inner)
+ fprintf (dump_file, "replaced by %u\n", INSN_UID (seq));
+ else
+ fprintf (dump_file, "removed\n");
+ }
+
+ /* Remove the extension. */
+ delete_insn (insn);
+}
+
+/* Find redundant extensions and remove or replace them if possible. */
+
+static void
+remove_redundant_extensions (void)
+{
+ basic_block bb;
+ rtx insn, next, dest, inner;
+
+ biggest_use = XNEWVEC (int, max_reg_num ());
+ calculate_biggest_use ();
+
+ /* Remove redundant extensions. */
+ FOR_EACH_BB (bb)
+ FOR_BB_INSNS_SAFE (bb, insn, next)
+ {
+ if (!NONDEBUG_INSN_P (insn))
+ continue;
+
+ if (!redundant_extension_p (insn, &dest, &inner))
+ continue;
+
+ try_remove_or_replace_extension (insn, dest, inner);
+ }
+
+ free (biggest_use);
+}
+
+/* Remove redundant extensions. */
+
+static unsigned int
+rest_of_handle_ee (void)
+{
+ remove_redundant_extensions ();
+ return 0;
+}
+
+/* Run ee pass when flag_ee is set at optimization level > 0. */
+
+static bool
+gate_handle_ee (void)
+{
+ return (optimize > 0 && flag_ee);
+}
+
+struct rtl_opt_pass pass_ee =
+{
+ {
+ RTL_PASS,
+ "ee", /* name */
+ gate_handle_ee, /* gate */
+ rest_of_handle_ee, /* execute */
+ NULL, /* sub */
+ NULL, /* next */
+ 0, /* static_pass_number */
+ TV_EE, /* tv_id */
+ 0, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ TODO_ggc_collect |
+ TODO_dump_func |
+ TODO_verify_rtl_sharing, /* todo_flags_finish */
+ }
+};
=== modified file 'gcc/opts.c'
--- old/gcc/opts.c 2010-05-17 09:13:28 +0000
+++ new/gcc/opts.c 2010-12-10 15:33:37 +0000
@@ -907,6 +907,7 @@
flag_tree_switch_conversion = opt2;
flag_ipa_cp = opt2;
flag_ipa_sra = opt2;
+ flag_ee = opt2;
/* Track fields in field-sensitive alias analysis. */
set_param_value ("max-fields-for-field-sensitive",
=== modified file 'gcc/passes.c'
--- old/gcc/passes.c 2010-09-01 13:29:58 +0000
+++ new/gcc/passes.c 2010-12-10 15:33:37 +0000
@@ -974,6 +974,7 @@
NEXT_PASS (pass_lower_subreg);
NEXT_PASS (pass_df_initialize_opt);
NEXT_PASS (pass_cse);
+ NEXT_PASS (pass_ee);
NEXT_PASS (pass_rtl_fwprop);
NEXT_PASS (pass_rtl_cprop);
NEXT_PASS (pass_rtl_pre);
=== added file 'gcc/testsuite/gcc.dg/extend-1.c'
--- old/gcc/testsuite/gcc.dg/extend-1.c 1970-01-01 00:00:00 +0000
+++ new/gcc/testsuite/gcc.dg/extend-1.c 2010-12-10 15:33:37 +0000
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-rtl-ee" } */
+
+void f(unsigned char * p, short s, int c, int *z)
+{
+ if (c)
+ *z = 0;
+ *p ^= (unsigned char)s;
+}
+
+/* { dg-final { scan-rtl-dump-times "sign_extend:" 0 "ee" { target mips*-*-* } } } */
+/* { dg-final { scan-rtl-dump-times "superfluous extension \[0-9\]+ replaced" 1 "ee" { target mips*-*-* } } } */
+/* { dg-final { cleanup-rtl-dump "ee" } } */
=== added file 'gcc/testsuite/gcc.dg/extend-2-64.c'
--- old/gcc/testsuite/gcc.dg/extend-2-64.c 1970-01-01 00:00:00 +0000
+++ new/gcc/testsuite/gcc.dg/extend-2-64.c 2010-12-10 15:33:37 +0000
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-rtl-ee" } */
+/* { dg-require-effective-target mips64 } */
+
+void f(unsigned char * p, short *s, int c)
+{
+ short or = 0;
+ while (c)
+ {
+ or = or | s[c];
+ c --;
+ }
+ *p = (unsigned char)or;
+}
+
+/* { dg-final { scan-rtl-dump-times "zero_extend:" 1 "ee" { target mips*-*-* } } } */
+/* { dg-final { scan-rtl-dump-times "sign_extend:" 0 "ee" { target mips*-*-* } } } */
+/* { dg-final { scan-rtl-dump-times "superfluous extension \[0-9\]+ replaced" 3 "ee" { target mips*-*-* } } } */
+/* { dg-final { cleanup-rtl-dump "ee" } } */
+
=== added file 'gcc/testsuite/gcc.dg/extend-2.c'
--- old/gcc/testsuite/gcc.dg/extend-2.c 1970-01-01 00:00:00 +0000
+++ new/gcc/testsuite/gcc.dg/extend-2.c 2010-12-10 15:33:37 +0000
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-rtl-ee" } */
+/* { dg-require-effective-target ilp32 } */
+
+void f(unsigned char * p, short *s, int c)
+{
+ short or = 0;
+ while (c)
+ {
+ or = or | s[c];
+ c --;
+ }
+ *p = (unsigned char)or;
+}
+
+/* { dg-final { scan-rtl-dump-times "zero_extend" 0 "ee" { target mips*-*-* } } } */
+/* { dg-final { scan-rtl-dump-times "sign_extend" 0 "ee" { target mips*-*-* } } } */
+/* { dg-final { scan-rtl-dump-times "superfluous extension \[0-9\]+ replaced" 2 "ee" { target mips*-*-* } } } */
+/* { dg-final { cleanup-rtl-dump "ee" } } */
+
=== added file 'gcc/testsuite/gcc.dg/extend-3.c'
--- old/gcc/testsuite/gcc.dg/extend-3.c 1970-01-01 00:00:00 +0000
+++ new/gcc/testsuite/gcc.dg/extend-3.c 2010-12-10 15:33:37 +0000
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-rtl-ee" } */
+
+unsigned int f(unsigned char byte)
+{
+ return byte << 25;
+}
+
+/* { dg-final { scan-rtl-dump-times "zero_extend:" 0 "ee" { target mips*-*-* } } } */
+/* { dg-final { scan-rtl-dump "superfluous extension \[0-9\]+ replaced" "ee" { target mips*-*-* } } } */
+/* { dg-final { cleanup-rtl-dump "ee" } } */
+
=== added file 'gcc/testsuite/gcc.dg/extend-4.c'
--- old/gcc/testsuite/gcc.dg/extend-4.c 1970-01-01 00:00:00 +0000
+++ new/gcc/testsuite/gcc.dg/extend-4.c 2010-12-10 15:33:37 +0000
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-rtl-ee" } */
+
+unsigned char f(unsigned int a)
+{
+ unsigned int b = a & 0x10ff;
+ return b;
+}
+
+/* { dg-final { scan-rtl-dump-times "and:" 0 "ee" { target mips*-*-* } } } */
+/* { dg-final { scan-rtl-dump-times "superfluous extension \[0-9\]+ replaced" 1 "ee" { target mips*-*-* } } } */
+/* { dg-final { cleanup-rtl-dump "ee" } } */
+
=== modified file 'gcc/timevar.def'
--- old/gcc/timevar.def 2009-11-27 12:43:08 +0000
+++ new/gcc/timevar.def 2010-12-10 15:33:37 +0000
@@ -162,6 +162,7 @@
DEFTIMEVAR (TV_VARCONST , "varconst")
DEFTIMEVAR (TV_LOWER_SUBREG , "lower subreg")
DEFTIMEVAR (TV_JUMP , "jump")
+DEFTIMEVAR (TV_EE , "extension elimination")
DEFTIMEVAR (TV_FWPROP , "forward prop")
DEFTIMEVAR (TV_CSE , "CSE")
DEFTIMEVAR (TV_DCE , "dead code elimination")
=== modified file 'gcc/tree-pass.h'
--- old/gcc/tree-pass.h 2010-09-01 13:29:58 +0000
+++ new/gcc/tree-pass.h 2010-12-10 15:33:37 +0000
@@ -468,6 +468,7 @@
extern struct rtl_opt_pass pass_initial_value_sets;
extern struct rtl_opt_pass pass_unshare_all_rtl;
extern struct rtl_opt_pass pass_instantiate_virtual_regs;
+extern struct rtl_opt_pass pass_ee;
extern struct rtl_opt_pass pass_rtl_fwprop;
extern struct rtl_opt_pass pass_rtl_fwprop_addr;
extern struct rtl_opt_pass pass_jump2;

View File

@ -0,0 +1,183 @@
2010-12-02 Bernd Schmidt <bernds@codesourcery.com>
Issue #10089
gcc/
* expr.c (store_field): Avoid a direct store if the mode is larger
than the size of the bit field.
* stor-layout.c (layout_decl): If flag_strict_volatile_bitfields,
treat non-volatile bit fields like volatile ones.
* toplev.c (process_options): Disallow combination of
-fstrict-volatile-bitfields and ABI versions less than 2.
* config/arm/arm.c (arm_option_override): Don't enable
flag_strict_volatile_bitfields if the ABI version is less than 2.
* config/h8300/h8300.c (h8300_option_override): Likewise.
* config/rx/rx.c (rx_option_override): Likewise.
* config/m32c/m32c.c (m32c_option_override): Likewise.
* config/sh/sh.c (sh_option_override): Likewise.
gcc/testsuite/
* gcc.target/arm/volatile-bitfields-4.c: New test.
* c-c++-common/abi-bf.c: New test.
=== modified file 'gcc/config/arm/arm.c'
--- old/gcc/config/arm/arm.c 2010-12-10 15:30:47 +0000
+++ new/gcc/config/arm/arm.c 2010-12-10 15:34:19 +0000
@@ -1934,7 +1934,8 @@
set_param_value ("gcse-unrestricted-cost", 2);
/* ARM EABI defaults to strict volatile bitfields. */
- if (TARGET_AAPCS_BASED && flag_strict_volatile_bitfields < 0)
+ if (TARGET_AAPCS_BASED && flag_strict_volatile_bitfields < 0
+ && abi_version_at_least(2))
flag_strict_volatile_bitfields = 1;
/* Register global variables with the garbage collector. */
=== modified file 'gcc/config/h8300/h8300.c'
--- old/gcc/config/h8300/h8300.c 2010-11-04 12:43:52 +0000
+++ new/gcc/config/h8300/h8300.c 2010-12-10 15:34:19 +0000
@@ -405,7 +405,7 @@
}
/* This target defaults to strict volatile bitfields. */
- if (flag_strict_volatile_bitfields < 0)
+ if (flag_strict_volatile_bitfields < 0 && abi_version_at_least(2))
flag_strict_volatile_bitfields = 1;
}
=== modified file 'gcc/config/m32c/m32c.c'
--- old/gcc/config/m32c/m32c.c 2010-11-04 12:43:52 +0000
+++ new/gcc/config/m32c/m32c.c 2010-12-10 15:34:19 +0000
@@ -430,7 +430,7 @@
flag_ivopts = 0;
/* This target defaults to strict volatile bitfields. */
- if (flag_strict_volatile_bitfields < 0)
+ if (flag_strict_volatile_bitfields < 0 && abi_version_at_least(2))
flag_strict_volatile_bitfields = 1;
}
=== modified file 'gcc/config/rx/rx.c'
--- old/gcc/config/rx/rx.c 2010-11-04 12:43:52 +0000
+++ new/gcc/config/rx/rx.c 2010-12-10 15:34:19 +0000
@@ -2191,7 +2191,7 @@
rx_option_override (void)
{
/* This target defaults to strict volatile bitfields. */
- if (flag_strict_volatile_bitfields < 0)
+ if (flag_strict_volatile_bitfields < 0 && abi_version_at_least(2))
flag_strict_volatile_bitfields = 1;
}
=== modified file 'gcc/config/sh/sh.c'
--- old/gcc/config/sh/sh.c 2010-11-04 12:43:52 +0000
+++ new/gcc/config/sh/sh.c 2010-12-10 15:34:19 +0000
@@ -952,7 +952,7 @@
sh_fix_range (sh_fixed_range_str);
/* This target defaults to strict volatile bitfields. */
- if (flag_strict_volatile_bitfields < 0)
+ if (flag_strict_volatile_bitfields < 0 && abi_version_at_least(2))
flag_strict_volatile_bitfields = 1;
}
=== modified file 'gcc/expr.c'
--- old/gcc/expr.c 2010-11-04 12:43:52 +0000
+++ new/gcc/expr.c 2010-12-10 15:34:19 +0000
@@ -5848,6 +5848,8 @@
|| bitpos % GET_MODE_ALIGNMENT (mode))
&& SLOW_UNALIGNED_ACCESS (mode, MEM_ALIGN (target)))
|| (bitpos % BITS_PER_UNIT != 0)))
+ || (bitsize >= 0 && mode != BLKmode
+ && GET_MODE_BITSIZE (mode) > bitsize)
/* If the RHS and field are a constant size and the size of the
RHS isn't the same size as the bitfield, we must use bitfield
operations. */
=== modified file 'gcc/stor-layout.c'
--- old/gcc/stor-layout.c 2010-11-26 12:03:32 +0000
+++ new/gcc/stor-layout.c 2010-12-10 15:34:19 +0000
@@ -621,12 +621,13 @@
/* See if we can use an ordinary integer mode for a bit-field.
Conditions are: a fixed size that is correct for another mode,
occupying a complete byte or bytes on proper boundary,
- and not volatile or not -fstrict-volatile-bitfields. */
+ and not -fstrict-volatile-bitfields. If the latter is set,
+ we unfortunately can't check TREE_THIS_VOLATILE, as a cast
+ may make a volatile object later. */
if (TYPE_SIZE (type) != 0
&& TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
&& GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
- && !(TREE_THIS_VOLATILE (decl)
- && flag_strict_volatile_bitfields > 0))
+ && flag_strict_volatile_bitfields <= 0)
{
enum machine_mode xmode
= mode_for_size_tree (DECL_SIZE (decl), MODE_INT, 1);
=== added file 'gcc/testsuite/c-c++-common/abi-bf.c'
--- old/gcc/testsuite/c-c++-common/abi-bf.c 1970-01-01 00:00:00 +0000
+++ new/gcc/testsuite/c-c++-common/abi-bf.c 2010-12-10 15:34:19 +0000
@@ -0,0 +1,3 @@
+/* { dg-warning "incompatible" } */
+/* { dg-do compile } */
+/* { dg-options "-fstrict-volatile-bitfields -fabi-version=1" } */
=== added file 'gcc/testsuite/gcc.target/arm/volatile-bitfields-4.c'
--- old/gcc/testsuite/gcc.target/arm/volatile-bitfields-4.c 1970-01-01 00:00:00 +0000
+++ new/gcc/testsuite/gcc.target/arm/volatile-bitfields-4.c 2010-12-10 15:34:19 +0000
@@ -0,0 +1,30 @@
+/* { dg-require-effective-target arm_eabi } */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { scan-assembler-times "ldr\[\\t \]+\[^\n\]*,\[\\t \]*\\\[\[^\n\]*\\\]" 2 } } */
+/* { dg-final { scan-assembler-times "str\[\\t \]+\[^\n\]*,\[\\t \]*\\\[\[^\n\]*\\\]" 2 } } */
+/* { dg-final { scan-assembler-not "strb" } } */
+
+struct thing {
+ unsigned a: 8;
+ unsigned b: 8;
+ unsigned c: 8;
+ unsigned d: 8;
+};
+
+struct thing2 {
+ volatile unsigned a: 8;
+ volatile unsigned b: 8;
+ volatile unsigned c: 8;
+ volatile unsigned d: 8;
+};
+
+void test1(volatile struct thing *t)
+{
+ t->a = 5;
+}
+
+void test2(struct thing2 *t)
+{
+ t->a = 5;
+}
=== modified file 'gcc/toplev.c'
--- old/gcc/toplev.c 2010-03-31 01:44:10 +0000
+++ new/gcc/toplev.c 2010-12-10 15:34:19 +0000
@@ -1851,6 +1851,13 @@
sorry ("Graphite loop optimizations cannot be used");
#endif
+ if (flag_strict_volatile_bitfields > 0 && !abi_version_at_least (2))
+ {
+ warning (0, "-fstrict-volatile-bitfield disabled; "
+ "it is incompatible with ABI versions < 2");
+ flag_strict_volatile_bitfields = 0;
+ }
+
/* Unrolling all loops implies that standard loop unrolling must also
be done. */
if (flag_unroll_all_loops)