| Submitter | Khem Raj |
|---|---|
| Date | Dec. 14, 2010, 12:01 a.m. |
| Message ID | <1292284879-11158-1-git-send-email-raj.khem@gmail.com> |
| Download | mbox | patch |
| Permalink | /patch/66/ |
| State | Accepted |
| Headers | show |
Comments
On 14/12/2010 01:01, Khem Raj wrote: > * This fixes the gcc ICE as seen compiling samba > > Signed-off-by: Khem Raj<raj.khem@gmail.com> Acked-by: Eric Bénard <eric@eukrea.com> > --- > recipes/gcc/gcc-4.5.inc | 3 +- > recipes/gcc/gcc-4.5/gcc-revert-pr42172.patch | 989 ++++++++++++++++++++++++++ > 2 files changed, 991 insertions(+), 1 deletions(-) > create mode 100644 recipes/gcc/gcc-4.5/gcc-revert-pr42172.patch > > diff --git a/recipes/gcc/gcc-4.5.inc b/recipes/gcc/gcc-4.5.inc > index df462e0..1116331 100644 > --- a/recipes/gcc/gcc-4.5.inc > +++ b/recipes/gcc/gcc-4.5.inc > @@ -8,7 +8,7 @@ DEPENDS = "mpfr gmp libmpc libelf" > NATIVEDEPS = "mpfr-native gmp-native libmpc-native" > > > -INC_PR = "r24" > +INC_PR = "r25" > > SRCREV = "167449" > PV = "4.5" > @@ -137,6 +137,7 @@ SRC_URI = "svn://gcc.gnu.org/svn/gcc/branches;module=${BRANCH} \ > file://linaro/gcc-4.5-linaro-r99419.patch \ > file://linaro/gcc-4.5-linaro-r99420.patch \ > file://gcc-scalar-widening-pr45847.patch \ > + file://gcc-revert-pr42172.patch \ > " > > SRC_URI_append_mips64 = " file://mips64-nomultilib.patch " > diff --git a/recipes/gcc/gcc-4.5/gcc-revert-pr42172.patch b/recipes/gcc/gcc-4.5/gcc-revert-pr42172.patch > new file mode 100644 > index 0000000..c49cdf1 > --- /dev/null > +++ b/recipes/gcc/gcc-4.5/gcc-revert-pr42172.patch > @@ -0,0 +1,989 @@ > +This reverts the fix for pr 42172 > +http://gcc.gnu.org/bugzilla/show_bug.cgi?id=42172 > +It causes regression in samba compilation for arches below armv7 > +-Khem > + > +Index: gcc-4_5-branch/gcc/config/arm/arm.c > +=================================================================== > +--- gcc-4_5-branch.orig/gcc/config/arm/arm.c > ++++ gcc-4_5-branch/gcc/config/arm/arm.c > +@@ -6420,7 +6420,6 @@ static inline int > + thumb1_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer) > + { > + enum machine_mode mode = GET_MODE (x); > +- int total; > + > + switch (code) > + { > +@@ -6523,20 +6522,24 @@ thumb1_rtx_costs (rtx x, enum rtx_code c > + return 14; > + return 2; > + > +- case SIGN_EXTEND: > + case ZERO_EXTEND: > +- total = mode == DImode ? COSTS_N_INSNS (1) : 0; > +- total += thumb1_rtx_costs (XEXP (x, 0), GET_CODE (XEXP (x, 0)), code); > +- > +- if (mode == SImode) > +- return total; > ++ /* XXX still guessing. */ > ++ switch (GET_MODE (XEXP (x, 0))) > ++ { > ++ case QImode: > ++ return (1 + (mode == DImode ? 4 : 0) > ++ + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0)); > ++ > ++ case HImode: > ++ return (4 + (mode == DImode ? 4 : 0) > ++ + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0)); > + > +- if (arm_arch6) > +- return total + COSTS_N_INSNS (1); > ++ case SImode: > ++ return (1 + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0)); > + > +- /* Assume a two-shift sequence. Increase the cost slightly so > +- we prefer actual shifts over an extend operation. */ > +- return total + 1 + COSTS_N_INSNS (2); > ++ default: > ++ return 99; > ++ } > + > + default: > + return 99; > +@@ -7020,39 +7023,44 @@ arm_rtx_costs_1 (rtx x, enum rtx_code ou > + return false; > + > + case SIGN_EXTEND: > ++ if (GET_MODE_CLASS (mode) == MODE_INT) > ++ { > ++ *total = 0; > ++ if (mode == DImode) > ++ *total += COSTS_N_INSNS (1); > ++ > ++ if (GET_MODE (XEXP (x, 0)) != SImode) > ++ { > ++ if (arm_arch6) > ++ { > ++ if (GET_CODE (XEXP (x, 0)) != MEM) > ++ *total += COSTS_N_INSNS (1); > ++ } > ++ else if (!arm_arch4 || GET_CODE (XEXP (x, 0)) != MEM) > ++ *total += COSTS_N_INSNS (2); > ++ } > ++ > ++ return false; > ++ } > ++ > ++ /* Fall through */ > + case ZERO_EXTEND: > + *total = 0; > + if (GET_MODE_CLASS (mode) == MODE_INT) > + { > +- rtx op = XEXP (x, 0); > +- enum machine_mode opmode = GET_MODE (op); > +- > + if (mode == DImode) > + *total += COSTS_N_INSNS (1); > + > +- if (opmode != SImode) > ++ if (GET_MODE (XEXP (x, 0)) != SImode) > + { > +- if (MEM_P (op)) > ++ if (arm_arch6) > + { > +- /* If !arm_arch4, we use one of the extendhisi2_mem > +- or movhi_bytes patterns for HImode. For a QImode > +- sign extension, we first zero-extend from memory > +- and then perform a shift sequence. */ > +- if (!arm_arch4&& (opmode != QImode || code == SIGN_EXTEND)) > +- *total += COSTS_N_INSNS (2); > ++ if (GET_CODE (XEXP (x, 0)) != MEM) > ++ *total += COSTS_N_INSNS (1); > + } > +- else if (arm_arch6) > +- *total += COSTS_N_INSNS (1); > +- > +- /* We don't have the necessary insn, so we need to perform some > +- other operation. */ > +- else if (TARGET_ARM&& code == ZERO_EXTEND&& mode == QImode) > +- /* An and with constant 255. */ > +- *total += COSTS_N_INSNS (1); > +- else > +- /* A shift sequence. Increase costs slightly to avoid > +- combining two shifts into an extend operation. */ > +- *total += COSTS_N_INSNS (2) + 1; > ++ else if (!arm_arch4 || GET_CODE (XEXP (x, 0)) != MEM) > ++ *total += COSTS_N_INSNS (GET_MODE (XEXP (x, 0)) == QImode ? > ++ 1 : 2); > + } > + > + return false; > +@@ -7302,8 +7310,41 @@ arm_size_rtx_costs (rtx x, enum rtx_code > + return false; > + > + case SIGN_EXTEND: > ++ *total = 0; > ++ if (GET_MODE_SIZE (GET_MODE (XEXP (x, 0)))< 4) > ++ { > ++ if (!(arm_arch4&& MEM_P (XEXP (x, 0)))) > ++ *total += COSTS_N_INSNS (arm_arch6 ? 1 : 2); > ++ } > ++ if (mode == DImode) > ++ *total += COSTS_N_INSNS (1); > ++ return false; > ++ > + case ZERO_EXTEND: > +- return arm_rtx_costs_1 (x, outer_code, total, 0); > ++ *total = 0; > ++ if (!(arm_arch4&& MEM_P (XEXP (x, 0)))) > ++ { > ++ switch (GET_MODE (XEXP (x, 0))) > ++ { > ++ case QImode: > ++ *total += COSTS_N_INSNS (1); > ++ break; > ++ > ++ case HImode: > ++ *total += COSTS_N_INSNS (arm_arch6 ? 1 : 2); > ++ > ++ case SImode: > ++ break; > ++ > ++ default: > ++ *total += COSTS_N_INSNS (2); > ++ } > ++ } > ++ > ++ if (mode == DImode) > ++ *total += COSTS_N_INSNS (1); > ++ > ++ return false; > + > + case CONST_INT: > + if (const_ok_for_arm (INTVAL (x))) > +Index: gcc-4_5-branch/gcc/config/arm/arm.md > +=================================================================== > +--- gcc-4_5-branch.orig/gcc/config/arm/arm.md > ++++ gcc-4_5-branch/gcc/config/arm/arm.md > +@@ -156,9 +156,6 @@ > + ; patterns that share the same RTL in both ARM and Thumb code. > + (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code"))) > + > +-; IS_ARCH6 is set to 'yes' when we are generating code form ARMv6. > +-(define_attr "is_arch6" "no,yes" (const (symbol_ref "arm_arch6"))) > +- > + ;; Operand number of an input operand that is shifted. Zero if the > + ;; given instruction does not shift one of its input operands. > + (define_attr "shift" "" (const_int 0)) > +@@ -4094,46 +4091,92 @@ > + ) > + > + (define_expand "zero_extendhisi2" > +- [(set (match_operand:SI 0 "s_register_operand" "") > +- (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))] > ++ [(set (match_dup 2) > ++ (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "") > ++ (const_int 16))) > ++ (set (match_operand:SI 0 "s_register_operand" "") > ++ (lshiftrt:SI (match_dup 2) (const_int 16)))] > + "TARGET_EITHER" > +-{ > +- if (TARGET_ARM&& !arm_arch4&& MEM_P (operands[1])) > +- { > +- emit_insn (gen_movhi_bytes (operands[0], operands[1])); > +- DONE; > +- } > +- if (!arm_arch6&& !MEM_P (operands[1])) > ++ " > ++ { > ++ if ((TARGET_THUMB1 || arm_arch4)&& GET_CODE (operands[1]) == MEM) > ++ { > ++ emit_insn (gen_rtx_SET (VOIDmode, operands[0], > ++ gen_rtx_ZERO_EXTEND (SImode, operands[1]))); > ++ DONE; > ++ } > ++ if (TARGET_ARM&& GET_CODE (operands[1]) == MEM) > ++ { > ++ emit_insn (gen_movhi_bytes (operands[0], operands[1])); > ++ DONE; > ++ } > ++ > ++ if (!s_register_operand (operands[1], HImode)) > ++ operands[1] = copy_to_mode_reg (HImode, operands[1]); > ++ > ++ if (arm_arch6) > ++ { > ++ emit_insn (gen_rtx_SET (VOIDmode, operands[0], > ++ gen_rtx_ZERO_EXTEND (SImode, operands[1]))); > ++ DONE; > ++ } > ++ > ++ operands[1] = gen_lowpart (SImode, operands[1]); > ++ operands[2] = gen_reg_rtx (SImode); > ++ }" > ++) > ++ > ++(define_insn "*thumb1_zero_extendhisi2" > ++ [(set (match_operand:SI 0 "register_operand" "=l") > ++ (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))] > ++ "TARGET_THUMB1&& !arm_arch6" > ++ "* > ++ rtx mem = XEXP (operands[1], 0); > ++ > ++ if (GET_CODE (mem) == CONST) > ++ mem = XEXP (mem, 0); > ++ > ++ if (GET_CODE (mem) == LABEL_REF) > ++ return \"ldr\\t%0, %1\"; > ++ > ++ if (GET_CODE (mem) == PLUS) > + { > +- rtx t = gen_lowpart (SImode, operands[1]); > +- rtx tmp = gen_reg_rtx (SImode); > +- emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16))); > +- emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (16))); > +- DONE; > ++ rtx a = XEXP (mem, 0); > ++ rtx b = XEXP (mem, 1); > ++ > ++ /* This can happen due to bugs in reload. */ > ++ if (GET_CODE (a) == REG&& REGNO (a) == SP_REGNUM) > ++ { > ++ rtx ops[2]; > ++ ops[0] = operands[0]; > ++ ops[1] = a; > ++ > ++ output_asm_insn (\"mov %0, %1\", ops); > ++ > ++ XEXP (mem, 0) = operands[0]; > ++ } > ++ > ++ else if ( GET_CODE (a) == LABEL_REF > ++ && GET_CODE (b) == CONST_INT) > ++ return \"ldr\\t%0, %1\"; > + } > +-}) > + > +-(define_split > +- [(set (match_operand:SI 0 "register_operand" "") > +- (zero_extend:SI (match_operand:HI 1 "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)))] > +-{ > +- operands[2] = gen_lowpart (SImode, operands[1]); > +-}) > ++ return \"ldrh\\t%0, %1\"; > ++ " > ++ [(set_attr "length" "4") > ++ (set_attr "type" "load_byte") > ++ (set_attr "pool_range" "60")] > ++) > + > +-(define_insn "*thumb1_zero_extendhisi2" > ++(define_insn "*thumb1_zero_extendhisi2_v6" > + [(set (match_operand:SI 0 "register_operand" "=l,l") > + (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))] > +- "TARGET_THUMB1" > ++ "TARGET_THUMB1&& arm_arch6" > + "* > + rtx mem; > + > +- if (which_alternative == 0&& arm_arch6) > +- return \"uxth\\t%0, %1\"; > + if (which_alternative == 0) > +- return \"#\"; > ++ return \"uxth\\t%0, %1\"; > + > + mem = XEXP (operands[1], 0); > + > +@@ -4167,25 +4210,20 @@ > + > + return \"ldrh\\t%0, %1\"; > + " > +- [(set_attr_alternative "length" > +- [(if_then_else (eq_attr "is_arch6" "yes") > +- (const_int 2) (const_int 4)) > +- (const_int 4)]) > ++ [(set_attr "length" "2,4") > + (set_attr "type" "alu_shift,load_byte") > + (set_attr "pool_range" "*,60")] > + ) > + > + (define_insn "*arm_zero_extendhisi2" > +- [(set (match_operand:SI 0 "s_register_operand" "=r,r") > +- (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))] > ++ [(set (match_operand:SI 0 "s_register_operand" "=r") > ++ (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))] > + "TARGET_ARM&& arm_arch4&& !arm_arch6" > +- "@ > +- # > +- ldr%(h%)\\t%0, %1" > +- [(set_attr "type" "alu_shift,load_byte") > ++ "ldr%(h%)\\t%0, %1" > ++ [(set_attr "type" "load_byte") > + (set_attr "predicable" "yes") > +- (set_attr "pool_range" "*,256") > +- (set_attr "neg_pool_range" "*,244")] > ++ (set_attr "pool_range" "256") > ++ (set_attr "neg_pool_range" "244")] > + ) > + > + (define_insn "*arm_zero_extendhisi2_v6" > +@@ -4215,49 +4253,50 @@ > + [(set (match_operand:SI 0 "s_register_operand" "") > + (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))] > + "TARGET_EITHER" > +-{ > +- if (TARGET_ARM&& !arm_arch6&& GET_CODE (operands[1]) != MEM) > +- { > +- emit_insn (gen_andsi3 (operands[0], > +- gen_lowpart (SImode, operands[1]), > +- GEN_INT (255))); > +- DONE; > +- } > +- if (!arm_arch6&& !MEM_P (operands[1])) > ++ " > ++ if (!arm_arch6&& GET_CODE (operands[1]) != MEM) > + { > +- rtx t = gen_lowpart (SImode, operands[1]); > +- rtx tmp = gen_reg_rtx (SImode); > +- emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24))); > +- emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (24))); > +- DONE; > +- } > +-}) > ++ if (TARGET_ARM) > ++ { > ++ emit_insn (gen_andsi3 (operands[0], > ++ gen_lowpart (SImode, operands[1]), > ++ GEN_INT (255))); > ++ } > ++ else /* TARGET_THUMB */ > ++ { > ++ rtx temp = gen_reg_rtx (SImode); > ++ rtx ops[3]; > + > +-(define_split > +- [(set (match_operand:SI 0 "register_operand" "") > +- (zero_extend:SI (match_operand:QI 1 "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)))] > +-{ > +- operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0); > +- if (TARGET_ARM) > +- { > +- emit_insn (gen_andsi3 (operands[0], operands[2], GEN_INT (255))); > ++ operands[1] = copy_to_mode_reg (QImode, operands[1]); > ++ operands[1] = gen_lowpart (SImode, operands[1]); > ++ > ++ ops[0] = temp; > ++ ops[1] = operands[1]; > ++ ops[2] = GEN_INT (24); > ++ > ++ emit_insn (gen_rtx_SET (VOIDmode, ops[0], > ++ gen_rtx_ASHIFT (SImode, ops[1], ops[2]))); > ++ > ++ ops[0] = operands[0]; > ++ ops[1] = temp; > ++ ops[2] = GEN_INT (24); > ++ > ++ emit_insn (gen_rtx_SET (VOIDmode, ops[0], > ++ gen_rtx_LSHIFTRT (SImode, ops[1], ops[2]))); > ++ } > + DONE; > + } > +-}) > ++ " > ++) > + > + (define_insn "*thumb1_zero_extendqisi2" > +- [(set (match_operand:SI 0 "register_operand" "=l,l") > +- (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))] > ++ [(set (match_operand:SI 0 "register_operand" "=l") > ++ (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))] > + "TARGET_THUMB1&& !arm_arch6" > +- "@ > +- # > +- ldrb\\t%0, %1" > +- [(set_attr "length" "4,2") > +- (set_attr "type" "alu_shift,load_byte") > +- (set_attr "pool_range" "*,32")] > ++ "ldrb\\t%0, %1" > ++ [(set_attr "length" "2") > ++ (set_attr "type" "load_byte") > ++ (set_attr "pool_range" "32")] > + ) > + > + (define_insn "*thumb1_zero_extendqisi2_v6" > +@@ -4273,17 +4312,14 @@ > + ) > + > + (define_insn "*arm_zero_extendqisi2" > +- [(set (match_operand:SI 0 "s_register_operand" "=r,r") > +- (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))] > ++ [(set (match_operand:SI 0 "s_register_operand" "=r") > ++ (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))] > + "TARGET_ARM&& !arm_arch6" > +- "@ > +- # > +- ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2" > +- [(set_attr "length" "8,4") > +- (set_attr "type" "alu_shift,load_byte") > ++ "ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2" > ++ [(set_attr "type" "load_byte") > + (set_attr "predicable" "yes") > +- (set_attr "pool_range" "*,4096") > +- (set_attr "neg_pool_range" "*,4084")] > ++ (set_attr "pool_range" "4096") > ++ (set_attr "neg_pool_range" "4084")] > + ) > + > + (define_insn "*arm_zero_extendqisi2_v6" > +@@ -4362,42 +4398,108 @@ > + ) > + > + (define_expand "extendhisi2" > +- [(set (match_operand:SI 0 "s_register_operand" "") > +- (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))] > ++ [(set (match_dup 2) > ++ (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "") > ++ (const_int 16))) > ++ (set (match_operand:SI 0 "s_register_operand" "") > ++ (ashiftrt:SI (match_dup 2) > ++ (const_int 16)))] > + "TARGET_EITHER" > +-{ > +- if (TARGET_THUMB1) > +- { > +- emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1])); > +- DONE; > +- } > +- if (MEM_P (operands[1])&& TARGET_ARM&& !arm_arch4) > +- { > +- emit_insn (gen_extendhisi2_mem (operands[0], operands[1])); > +- DONE; > +- } > ++ " > ++ { > ++ if (GET_CODE (operands[1]) == MEM) > ++ { > ++ if (TARGET_THUMB1) > ++ { > ++ emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1])); > ++ DONE; > ++ } > ++ else if (arm_arch4) > ++ { > ++ emit_insn (gen_rtx_SET (VOIDmode, operands[0], > ++ gen_rtx_SIGN_EXTEND (SImode, operands[1]))); > ++ DONE; > ++ } > ++ } > + > +- if (!arm_arch6&& !MEM_P (operands[1])) > +- { > +- rtx t = gen_lowpart (SImode, operands[1]); > +- rtx tmp = gen_reg_rtx (SImode); > +- emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16))); > +- emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (16))); > +- DONE; > +- } > +-}) > ++ if (TARGET_ARM&& GET_CODE (operands[1]) == MEM) > ++ { > ++ emit_insn (gen_extendhisi2_mem (operands[0], operands[1])); > ++ DONE; > ++ } > + > +-(define_split > +- [(parallel > +- [(set (match_operand:SI 0 "register_operand" "") > +- (sign_extend:SI (match_operand:HI 1 "register_operand" ""))) > +- (clobber (match_scratch:SI 2 ""))])] > +- "!arm_arch6" > +- [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16))) > +- (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))] > +-{ > +- operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0); > +-}) > ++ if (!s_register_operand (operands[1], HImode)) > ++ operands[1] = copy_to_mode_reg (HImode, operands[1]); > ++ > ++ if (arm_arch6) > ++ { > ++ if (TARGET_THUMB1) > ++ emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1])); > ++ else > ++ emit_insn (gen_rtx_SET (VOIDmode, operands[0], > ++ gen_rtx_SIGN_EXTEND (SImode, operands[1]))); > ++ > ++ DONE; > ++ } > ++ > ++ operands[1] = gen_lowpart (SImode, operands[1]); > ++ operands[2] = gen_reg_rtx (SImode); > ++ }" > ++) > ++ > ++(define_insn "thumb1_extendhisi2" > ++ [(set (match_operand:SI 0 "register_operand" "=l") > ++ (sign_extend:SI (match_operand:HI 1 "memory_operand" "m"))) > ++ (clobber (match_scratch:SI 2 "=&l"))] > ++ "TARGET_THUMB1&& !arm_arch6" > ++ "* > ++ { > ++ rtx ops[4]; > ++ rtx mem = XEXP (operands[1], 0); > ++ > ++ /* This code used to try to use 'V', and fix the address only if it was > ++ offsettable, but this fails for e.g. REG+48 because 48 is outside the > ++ range of QImode offsets, and offsettable_address_p does a QImode > ++ address check. */ > ++ > ++ if (GET_CODE (mem) == CONST) > ++ mem = XEXP (mem, 0); > ++ > ++ if (GET_CODE (mem) == LABEL_REF) > ++ return \"ldr\\t%0, %1\"; > ++ > ++ if (GET_CODE (mem) == PLUS) > ++ { > ++ rtx a = XEXP (mem, 0); > ++ rtx b = XEXP (mem, 1); > ++ > ++ if (GET_CODE (a) == LABEL_REF > ++ && GET_CODE (b) == CONST_INT) > ++ return \"ldr\\t%0, %1\"; > ++ > ++ if (GET_CODE (b) == REG) > ++ return \"ldrsh\\t%0, %1\"; > ++ > ++ ops[1] = a; > ++ ops[2] = b; > ++ } > ++ else > ++ { > ++ ops[1] = mem; > ++ ops[2] = const0_rtx; > ++ } > ++ > ++ gcc_assert (GET_CODE (ops[1]) == REG); > ++ > ++ ops[0] = operands[0]; > ++ ops[3] = operands[2]; > ++ output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops); > ++ return \"\"; > ++ }" > ++ [(set_attr "length" "4") > ++ (set_attr "type" "load_byte") > ++ (set_attr "pool_range" "1020")] > ++) > + > + ;; We used to have an early-clobber on the scratch register here. > + ;; However, there's a bug somewhere in reload which means that this > +@@ -4406,18 +4508,16 @@ > + ;; we try to verify the operands. Fortunately, we don't really need > + ;; the early-clobber: we can always use operand 0 if operand 2 > + ;; overlaps the address. > +-(define_insn "thumb1_extendhisi2" > ++(define_insn "*thumb1_extendhisi2_insn_v6" > + [(set (match_operand:SI 0 "register_operand" "=l,l") > + (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m"))) > + (clobber (match_scratch:SI 2 "=X,l"))] > +- "TARGET_THUMB1" > ++ "TARGET_THUMB1&& arm_arch6" > + "* > + { > + rtx ops[4]; > + rtx mem; > + > +- if (which_alternative == 0&& !arm_arch6) > +- return \"#\"; > + if (which_alternative == 0) > + return \"sxth\\t%0, %1\"; > + > +@@ -4465,10 +4565,7 @@ > + output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops); > + return \"\"; > + }" > +- [(set_attr_alternative "length" > +- [(if_then_else (eq_attr "is_arch6" "yes") > +- (const_int 2) (const_int 4)) > +- (const_int 4)]) > ++ [(set_attr "length" "2,4") > + (set_attr "type" "alu_shift,load_byte") > + (set_attr "pool_range" "*,1020")] > + ) > +@@ -4509,28 +4606,15 @@ > + }" > + ) > + > +-(define_split > +- [(set (match_operand:SI 0 "register_operand" "") > +- (sign_extend:SI (match_operand:HI 1 "register_operand" "")))] > +- "!arm_arch6" > +- [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16))) > +- (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))] > +-{ > +- operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0); > +-}) > +- > + (define_insn "*arm_extendhisi2" > +- [(set (match_operand:SI 0 "s_register_operand" "=r,r") > +- (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))] > ++ [(set (match_operand:SI 0 "s_register_operand" "=r") > ++ (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))] > + "TARGET_ARM&& arm_arch4&& !arm_arch6" > +- "@ > +- # > +- ldr%(sh%)\\t%0, %1" > +- [(set_attr "length" "8,4") > +- (set_attr "type" "alu_shift,load_byte") > ++ "ldr%(sh%)\\t%0, %1" > ++ [(set_attr "type" "load_byte") > + (set_attr "predicable" "yes") > +- (set_attr "pool_range" "*,256") > +- (set_attr "neg_pool_range" "*,244")] > ++ (set_attr "pool_range" "256") > ++ (set_attr "neg_pool_range" "244")] > + ) > + > + ;; ??? Check Thumb-2 pool range > +@@ -4592,45 +4676,46 @@ > + ) > + > + (define_expand "extendqisi2" > +- [(set (match_operand:SI 0 "s_register_operand" "") > +- (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")))] > ++ [(set (match_dup 2) > ++ (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "") > ++ (const_int 24))) > ++ (set (match_operand:SI 0 "s_register_operand" "") > ++ (ashiftrt:SI (match_dup 2) > ++ (const_int 24)))] > + "TARGET_EITHER" > +-{ > +- if (!arm_arch4&& MEM_P (operands[1])) > +- operands[1] = copy_to_mode_reg (QImode, operands[1]); > ++ " > ++ { > ++ if ((TARGET_THUMB || arm_arch4)&& GET_CODE (operands[1]) == MEM) > ++ { > ++ emit_insn (gen_rtx_SET (VOIDmode, operands[0], > ++ gen_rtx_SIGN_EXTEND (SImode, operands[1]))); > ++ DONE; > ++ } > + > +- if (!arm_arch6&& !MEM_P (operands[1])) > +- { > +- rtx t = gen_lowpart (SImode, operands[1]); > +- rtx tmp = gen_reg_rtx (SImode); > +- emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24))); > +- emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (24))); > +- DONE; > +- } > +-}) > ++ if (!s_register_operand (operands[1], QImode)) > ++ operands[1] = copy_to_mode_reg (QImode, operands[1]); > + > +-(define_split > +- [(set (match_operand:SI 0 "register_operand" "") > +- (sign_extend:SI (match_operand:QI 1 "register_operand" "")))] > +- "!arm_arch6" > +- [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24))) > +- (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))] > +-{ > +- operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0); > +-}) > ++ if (arm_arch6) > ++ { > ++ emit_insn (gen_rtx_SET (VOIDmode, operands[0], > ++ gen_rtx_SIGN_EXTEND (SImode, operands[1]))); > ++ DONE; > ++ } > ++ > ++ operands[1] = gen_lowpart (SImode, operands[1]); > ++ operands[2] = gen_reg_rtx (SImode); > ++ }" > ++) > + > + (define_insn "*arm_extendqisi" > +- [(set (match_operand:SI 0 "s_register_operand" "=r,r") > +- (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))] > ++ [(set (match_operand:SI 0 "s_register_operand" "=r") > ++ (sign_extend:SI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))] > + "TARGET_ARM&& arm_arch4&& !arm_arch6" > +- "@ > +- # > +- ldr%(sb%)\\t%0, %1" > +- [(set_attr "length" "8,4") > +- (set_attr "type" "alu_shift,load_byte") > ++ "ldr%(sb%)\\t%0, %1" > ++ [(set_attr "type" "load_byte") > + (set_attr "predicable" "yes") > +- (set_attr "pool_range" "*,256") > +- (set_attr "neg_pool_range" "*,244")] > ++ (set_attr "pool_range" "256") > ++ (set_attr "neg_pool_range" "244")] > + ) > + > + (define_insn "*arm_extendqisi_v6" > +@@ -4658,55 +4743,83 @@ > + (set_attr "predicable" "yes")] > + ) > + > +-(define_split > +- [(set (match_operand:SI 0 "register_operand" "") > +- (sign_extend:SI (match_operand:QI 1 "memory_operand" "")))] > +- "TARGET_THUMB1&& reload_completed" > +- [(set (match_dup 0) (match_dup 2)) > +- (set (match_dup 0) (sign_extend:SI (match_dup 3)))] > +-{ > +- rtx addr = XEXP (operands[1], 0); > ++(define_insn "*thumb1_extendqisi2" > ++ [(set (match_operand:SI 0 "register_operand" "=l,l") > ++ (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))] > ++ "TARGET_THUMB1&& !arm_arch6" > ++ "* > ++ { > ++ rtx ops[3]; > ++ rtx mem = XEXP (operands[1], 0); > + > +- if (GET_CODE (addr) == CONST) > +- addr = XEXP (addr, 0); > ++ if (GET_CODE (mem) == CONST) > ++ mem = XEXP (mem, 0); > + > +- if (GET_CODE (addr) == PLUS > +-&& REG_P (XEXP (addr, 0))&& REG_P (XEXP (addr, 1))) > +- /* No split necessary. */ > +- FAIL; > ++ if (GET_CODE (mem) == LABEL_REF) > ++ return \"ldr\\t%0, %1\"; > + > +- if (GET_CODE (addr) == PLUS > +-&& !REG_P (XEXP (addr, 0))&& !REG_P (XEXP (addr, 1))) > +- FAIL; > ++ if (GET_CODE (mem) == PLUS > ++&& GET_CODE (XEXP (mem, 0)) == LABEL_REF) > ++ return \"ldr\\t%0, %1\"; > + > +- if (reg_overlap_mentioned_p (operands[0], addr)) > +- { > +- rtx t = gen_lowpart (QImode, operands[0]); > +- emit_move_insn (t, operands[1]); > +- emit_insn (gen_thumb1_extendqisi2 (operands[0], t)); > +- DONE; > +- } > ++ if (which_alternative == 0) > ++ return \"ldrsb\\t%0, %1\"; > + > +- if (REG_P (addr)) > +- { > +- addr = gen_rtx_PLUS (Pmode, addr, operands[0]); > +- operands[2] = const0_rtx; > +- } > +- else if (GET_CODE (addr) != PLUS) > +- FAIL; > +- else if (REG_P (XEXP (addr, 0))) > +- { > +- operands[2] = XEXP (addr, 1); > +- addr = gen_rtx_PLUS (Pmode, XEXP (addr, 0), operands[0]); > +- } > +- else > +- { > +- operands[2] = XEXP (addr, 0); > +- addr = gen_rtx_PLUS (Pmode, XEXP (addr, 1), operands[0]); > +- } > ++ ops[0] = operands[0]; > + > +- operands[3] = change_address (operands[1], QImode, addr); > +-}) > ++ if (GET_CODE (mem) == PLUS) > ++ { > ++ rtx a = XEXP (mem, 0); > ++ rtx b = XEXP (mem, 1); > ++ > ++ ops[1] = a; > ++ ops[2] = b; > ++ > ++ if (GET_CODE (a) == REG) > ++ { > ++ if (GET_CODE (b) == REG) > ++ output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops); > ++ else if (REGNO (a) == REGNO (ops[0])) > ++ { > ++ output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops); > ++ output_asm_insn (\"lsl\\t%0, %0, #24\", ops); > ++ output_asm_insn (\"asr\\t%0, %0, #24\", ops); > ++ } > ++ else > ++ output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops); > ++ } > ++ else > ++ { > ++ gcc_assert (GET_CODE (b) == REG); > ++ if (REGNO (b) == REGNO (ops[0])) > ++ { > ++ output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops); > ++ output_asm_insn (\"lsl\\t%0, %0, #24\", ops); > ++ output_asm_insn (\"asr\\t%0, %0, #24\", ops); > ++ } > ++ else > ++ output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops); > ++ } > ++ } > ++ else if (GET_CODE (mem) == REG&& REGNO (ops[0]) == REGNO (mem)) > ++ { > ++ output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops); > ++ output_asm_insn (\"lsl\\t%0, %0, #24\", ops); > ++ output_asm_insn (\"asr\\t%0, %0, #24\", ops); > ++ } > ++ else > ++ { > ++ ops[1] = mem; > ++ ops[2] = const0_rtx; > ++ > ++ output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops); > ++ } > ++ return \"\"; > ++ }" > ++ [(set_attr "length" "2,6") > ++ (set_attr "type" "load_byte,load_byte") > ++ (set_attr "pool_range" "32,32")] > ++) > + > + (define_peephole2 > + [(set (match_operand:SI 0 "register_operand" "") > +@@ -4729,32 +4842,83 @@ > + operands[4] = change_address (operands[4], QImode, addr); > + }) > + > +-(define_insn "thumb1_extendqisi2" > ++(define_insn "*thumb1_extendqisi2_v6" > + [(set (match_operand:SI 0 "register_operand" "=l,l,l") > + (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))] > +- "TARGET_THUMB1" > +-{ > +- rtx addr; > ++ "TARGET_THUMB1&& arm_arch6" > ++ "* > ++ { > ++ rtx ops[3]; > ++ rtx mem; > + > +- if (which_alternative == 0&& arm_arch6) > +- return "sxtb\\t%0, %1"; > +- if (which_alternative == 0) > +- return "#"; > ++ if (which_alternative == 0) > ++ return \"sxtb\\t%0, %1\"; > ++ > ++ mem = XEXP (operands[1], 0); > + > +- addr = XEXP (operands[1], 0); > +- if (GET_CODE (addr) == PLUS > +-&& REG_P (XEXP (addr, 0))&& REG_P (XEXP (addr, 1))) > +- return "ldrsb\\t%0, %1"; > ++ if (GET_CODE (mem) == CONST) > ++ mem = XEXP (mem, 0); > ++ > ++ if (GET_CODE (mem) == LABEL_REF) > ++ return \"ldr\\t%0, %1\"; > ++ > ++ if (GET_CODE (mem) == PLUS > ++&& GET_CODE (XEXP (mem, 0)) == LABEL_REF) > ++ return \"ldr\\t%0, %1\"; > ++ if (which_alternative == 0) > ++ return \"ldrsb\\t%0, %1\"; > + > +- return "#"; > +-} > +- [(set_attr_alternative "length" > +- [(if_then_else (eq_attr "is_arch6" "yes") > +- (const_int 2) (const_int 4)) > +- (const_int 2) > +- (if_then_else (eq_attr "is_arch6" "yes") > +- (const_int 4) (const_int 6))]) > +- (set_attr "type" "alu_shift,load_byte,load_byte")] > ++ ops[0] = operands[0]; > ++ > ++ if (GET_CODE (mem) == PLUS) > ++ { > ++ rtx a = XEXP (mem, 0); > ++ rtx b = XEXP (mem, 1); > ++ > ++ ops[1] = a; > ++ ops[2] = b; > ++ > ++ if (GET_CODE (a) == REG) > ++ { > ++ if (GET_CODE (b) == REG) > ++ output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops); > ++ else if (REGNO (a) == REGNO (ops[0])) > ++ { > ++ output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops); > ++ output_asm_insn (\"sxtb\\t%0, %0\", ops); > ++ } > ++ else > ++ output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops); > ++ } > ++ else > ++ { > ++ gcc_assert (GET_CODE (b) == REG); > ++ if (REGNO (b) == REGNO (ops[0])) > ++ { > ++ output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops); > ++ output_asm_insn (\"sxtb\\t%0, %0\", ops); > ++ } > ++ else > ++ output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops); > ++ } > ++ } > ++ else if (GET_CODE (mem) == REG&& REGNO (ops[0]) == REGNO (mem)) > ++ { > ++ output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops); > ++ output_asm_insn (\"sxtb\\t%0, %0\", ops); > ++ } > ++ else > ++ { > ++ ops[1] = mem; > ++ ops[2] = const0_rtx; > ++ > ++ output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops); > ++ } > ++ return \"\"; > ++ }" > ++ [(set_attr "length" "2,2,4") > ++ (set_attr "type" "alu_shift,load_byte,load_byte") > ++ (set_attr "pool_range" "*,32,32")] > + ) > + > + (define_expand "extendsfdf2" > +Index: gcc-4_5-branch/gcc/testsuite/gcc.target/arm/pr42172-1.c > +=================================================================== > +--- gcc-4_5-branch.orig/gcc/testsuite/gcc.target/arm/pr42172-1.c > ++++ /dev/null > +@@ -1,19 +0,0 @@ > +-/* { dg-options "-O2" } */ > +- > +-struct A { > +- unsigned int f1 : 3; > +- unsigned int f2 : 3; > +- unsigned int f3 : 1; > +- unsigned int f4 : 1; > +- > +-}; > +- > +-void init_A (struct A *this) > +-{ > +- this->f1 = 0; > +- this->f2 = 1; > +- this->f3 = 0; > +- this->f4 = 0; > +-} > +- > +-/* { dg-final { scan-assembler-times "ldr" 1 } } */
On Mon, Dec 13, 2010 at 04:01:19PM -0800, Khem Raj wrote: > * This fixes the gcc ICE as seen compiling samba > > Signed-off-by: Khem Raj <raj.khem@gmail.com> I can confirm that with this and your other samba patch it compiles now fine on armv4t (om-gta02), Thanks
Patch
diff --git a/recipes/gcc/gcc-4.5.inc b/recipes/gcc/gcc-4.5.inc index df462e0..1116331 100644 --- a/recipes/gcc/gcc-4.5.inc +++ b/recipes/gcc/gcc-4.5.inc @@ -8,7 +8,7 @@ DEPENDS = "mpfr gmp libmpc libelf" NATIVEDEPS = "mpfr-native gmp-native libmpc-native" -INC_PR = "r24" +INC_PR = "r25" SRCREV = "167449" PV = "4.5" @@ -137,6 +137,7 @@ SRC_URI = "svn://gcc.gnu.org/svn/gcc/branches;module=${BRANCH} \ file://linaro/gcc-4.5-linaro-r99419.patch \ file://linaro/gcc-4.5-linaro-r99420.patch \ file://gcc-scalar-widening-pr45847.patch \ + file://gcc-revert-pr42172.patch \ " SRC_URI_append_mips64 = " file://mips64-nomultilib.patch " diff --git a/recipes/gcc/gcc-4.5/gcc-revert-pr42172.patch b/recipes/gcc/gcc-4.5/gcc-revert-pr42172.patch new file mode 100644 index 0000000..c49cdf1 --- /dev/null +++ b/recipes/gcc/gcc-4.5/gcc-revert-pr42172.patch @@ -0,0 +1,989 @@ +This reverts the fix for pr 42172 +http://gcc.gnu.org/bugzilla/show_bug.cgi?id=42172 +It causes regression in samba compilation for arches below armv7 +-Khem + +Index: gcc-4_5-branch/gcc/config/arm/arm.c +=================================================================== +--- gcc-4_5-branch.orig/gcc/config/arm/arm.c ++++ gcc-4_5-branch/gcc/config/arm/arm.c +@@ -6420,7 +6420,6 @@ static inline int + thumb1_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer) + { + enum machine_mode mode = GET_MODE (x); +- int total; + + switch (code) + { +@@ -6523,20 +6522,24 @@ thumb1_rtx_costs (rtx x, enum rtx_code c + return 14; + return 2; + +- case SIGN_EXTEND: + case ZERO_EXTEND: +- total = mode == DImode ? COSTS_N_INSNS (1) : 0; +- total += thumb1_rtx_costs (XEXP (x, 0), GET_CODE (XEXP (x, 0)), code); +- +- if (mode == SImode) +- return total; ++ /* XXX still guessing. */ ++ switch (GET_MODE (XEXP (x, 0))) ++ { ++ case QImode: ++ return (1 + (mode == DImode ? 4 : 0) ++ + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0)); ++ ++ case HImode: ++ return (4 + (mode == DImode ? 4 : 0) ++ + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0)); + +- if (arm_arch6) +- return total + COSTS_N_INSNS (1); ++ case SImode: ++ return (1 + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0)); + +- /* Assume a two-shift sequence. Increase the cost slightly so +- we prefer actual shifts over an extend operation. */ +- return total + 1 + COSTS_N_INSNS (2); ++ default: ++ return 99; ++ } + + default: + return 99; +@@ -7020,39 +7023,44 @@ arm_rtx_costs_1 (rtx x, enum rtx_code ou + return false; + + case SIGN_EXTEND: ++ if (GET_MODE_CLASS (mode) == MODE_INT) ++ { ++ *total = 0; ++ if (mode == DImode) ++ *total += COSTS_N_INSNS (1); ++ ++ if (GET_MODE (XEXP (x, 0)) != SImode) ++ { ++ if (arm_arch6) ++ { ++ if (GET_CODE (XEXP (x, 0)) != MEM) ++ *total += COSTS_N_INSNS (1); ++ } ++ else if (!arm_arch4 || GET_CODE (XEXP (x, 0)) != MEM) ++ *total += COSTS_N_INSNS (2); ++ } ++ ++ return false; ++ } ++ ++ /* Fall through */ + case ZERO_EXTEND: + *total = 0; + if (GET_MODE_CLASS (mode) == MODE_INT) + { +- rtx op = XEXP (x, 0); +- enum machine_mode opmode = GET_MODE (op); +- + if (mode == DImode) + *total += COSTS_N_INSNS (1); + +- if (opmode != SImode) ++ if (GET_MODE (XEXP (x, 0)) != SImode) + { +- if (MEM_P (op)) ++ if (arm_arch6) + { +- /* If !arm_arch4, we use one of the extendhisi2_mem +- or movhi_bytes patterns for HImode. For a QImode +- sign extension, we first zero-extend from memory +- and then perform a shift sequence. */ +- if (!arm_arch4 && (opmode != QImode || code == SIGN_EXTEND)) +- *total += COSTS_N_INSNS (2); ++ if (GET_CODE (XEXP (x, 0)) != MEM) ++ *total += COSTS_N_INSNS (1); + } +- else if (arm_arch6) +- *total += COSTS_N_INSNS (1); +- +- /* We don't have the necessary insn, so we need to perform some +- other operation. */ +- else if (TARGET_ARM && code == ZERO_EXTEND && mode == QImode) +- /* An and with constant 255. */ +- *total += COSTS_N_INSNS (1); +- else +- /* A shift sequence. Increase costs slightly to avoid +- combining two shifts into an extend operation. */ +- *total += COSTS_N_INSNS (2) + 1; ++ else if (!arm_arch4 || GET_CODE (XEXP (x, 0)) != MEM) ++ *total += COSTS_N_INSNS (GET_MODE (XEXP (x, 0)) == QImode ? ++ 1 : 2); + } + + return false; +@@ -7302,8 +7310,41 @@ arm_size_rtx_costs (rtx x, enum rtx_code + return false; + + case SIGN_EXTEND: ++ *total = 0; ++ if (GET_MODE_SIZE (GET_MODE (XEXP (x, 0))) < 4) ++ { ++ if (!(arm_arch4 && MEM_P (XEXP (x, 0)))) ++ *total += COSTS_N_INSNS (arm_arch6 ? 1 : 2); ++ } ++ if (mode == DImode) ++ *total += COSTS_N_INSNS (1); ++ return false; ++ + case ZERO_EXTEND: +- return arm_rtx_costs_1 (x, outer_code, total, 0); ++ *total = 0; ++ if (!(arm_arch4 && MEM_P (XEXP (x, 0)))) ++ { ++ switch (GET_MODE (XEXP (x, 0))) ++ { ++ case QImode: ++ *total += COSTS_N_INSNS (1); ++ break; ++ ++ case HImode: ++ *total += COSTS_N_INSNS (arm_arch6 ? 1 : 2); ++ ++ case SImode: ++ break; ++ ++ default: ++ *total += COSTS_N_INSNS (2); ++ } ++ } ++ ++ if (mode == DImode) ++ *total += COSTS_N_INSNS (1); ++ ++ return false; + + case CONST_INT: + if (const_ok_for_arm (INTVAL (x))) +Index: gcc-4_5-branch/gcc/config/arm/arm.md +=================================================================== +--- gcc-4_5-branch.orig/gcc/config/arm/arm.md ++++ gcc-4_5-branch/gcc/config/arm/arm.md +@@ -156,9 +156,6 @@ + ; patterns that share the same RTL in both ARM and Thumb code. + (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code"))) + +-; IS_ARCH6 is set to 'yes' when we are generating code form ARMv6. +-(define_attr "is_arch6" "no,yes" (const (symbol_ref "arm_arch6"))) +- + ;; Operand number of an input operand that is shifted. Zero if the + ;; given instruction does not shift one of its input operands. + (define_attr "shift" "" (const_int 0)) +@@ -4094,46 +4091,92 @@ + ) + + (define_expand "zero_extendhisi2" +- [(set (match_operand:SI 0 "s_register_operand" "") +- (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))] ++ [(set (match_dup 2) ++ (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "") ++ (const_int 16))) ++ (set (match_operand:SI 0 "s_register_operand" "") ++ (lshiftrt:SI (match_dup 2) (const_int 16)))] + "TARGET_EITHER" +-{ +- if (TARGET_ARM && !arm_arch4 && MEM_P (operands[1])) +- { +- emit_insn (gen_movhi_bytes (operands[0], operands[1])); +- DONE; +- } +- if (!arm_arch6 && !MEM_P (operands[1])) ++ " ++ { ++ if ((TARGET_THUMB1 || arm_arch4) && GET_CODE (operands[1]) == MEM) ++ { ++ emit_insn (gen_rtx_SET (VOIDmode, operands[0], ++ gen_rtx_ZERO_EXTEND (SImode, operands[1]))); ++ DONE; ++ } ++ if (TARGET_ARM && GET_CODE (operands[1]) == MEM) ++ { ++ emit_insn (gen_movhi_bytes (operands[0], operands[1])); ++ DONE; ++ } ++ ++ if (!s_register_operand (operands[1], HImode)) ++ operands[1] = copy_to_mode_reg (HImode, operands[1]); ++ ++ if (arm_arch6) ++ { ++ emit_insn (gen_rtx_SET (VOIDmode, operands[0], ++ gen_rtx_ZERO_EXTEND (SImode, operands[1]))); ++ DONE; ++ } ++ ++ operands[1] = gen_lowpart (SImode, operands[1]); ++ operands[2] = gen_reg_rtx (SImode); ++ }" ++) ++ ++(define_insn "*thumb1_zero_extendhisi2" ++ [(set (match_operand:SI 0 "register_operand" "=l") ++ (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))] ++ "TARGET_THUMB1 && !arm_arch6" ++ "* ++ rtx mem = XEXP (operands[1], 0); ++ ++ if (GET_CODE (mem) == CONST) ++ mem = XEXP (mem, 0); ++ ++ if (GET_CODE (mem) == LABEL_REF) ++ return \"ldr\\t%0, %1\"; ++ ++ if (GET_CODE (mem) == PLUS) + { +- rtx t = gen_lowpart (SImode, operands[1]); +- rtx tmp = gen_reg_rtx (SImode); +- emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16))); +- emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (16))); +- DONE; ++ rtx a = XEXP (mem, 0); ++ rtx b = XEXP (mem, 1); ++ ++ /* This can happen due to bugs in reload. */ ++ if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM) ++ { ++ rtx ops[2]; ++ ops[0] = operands[0]; ++ ops[1] = a; ++ ++ output_asm_insn (\"mov %0, %1\", ops); ++ ++ XEXP (mem, 0) = operands[0]; ++ } ++ ++ else if ( GET_CODE (a) == LABEL_REF ++ && GET_CODE (b) == CONST_INT) ++ return \"ldr\\t%0, %1\"; + } +-}) + +-(define_split +- [(set (match_operand:SI 0 "register_operand" "") +- (zero_extend:SI (match_operand:HI 1 "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)))] +-{ +- operands[2] = gen_lowpart (SImode, operands[1]); +-}) ++ return \"ldrh\\t%0, %1\"; ++ " ++ [(set_attr "length" "4") ++ (set_attr "type" "load_byte") ++ (set_attr "pool_range" "60")] ++) + +-(define_insn "*thumb1_zero_extendhisi2" ++(define_insn "*thumb1_zero_extendhisi2_v6" + [(set (match_operand:SI 0 "register_operand" "=l,l") + (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))] +- "TARGET_THUMB1" ++ "TARGET_THUMB1 && arm_arch6" + "* + rtx mem; + +- if (which_alternative == 0 && arm_arch6) +- return \"uxth\\t%0, %1\"; + if (which_alternative == 0) +- return \"#\"; ++ return \"uxth\\t%0, %1\"; + + mem = XEXP (operands[1], 0); + +@@ -4167,25 +4210,20 @@ + + return \"ldrh\\t%0, %1\"; + " +- [(set_attr_alternative "length" +- [(if_then_else (eq_attr "is_arch6" "yes") +- (const_int 2) (const_int 4)) +- (const_int 4)]) ++ [(set_attr "length" "2,4") + (set_attr "type" "alu_shift,load_byte") + (set_attr "pool_range" "*,60")] + ) + + (define_insn "*arm_zero_extendhisi2" +- [(set (match_operand:SI 0 "s_register_operand" "=r,r") +- (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))] ++ [(set (match_operand:SI 0 "s_register_operand" "=r") ++ (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))] + "TARGET_ARM && arm_arch4 && !arm_arch6" +- "@ +- # +- ldr%(h%)\\t%0, %1" +- [(set_attr "type" "alu_shift,load_byte") ++ "ldr%(h%)\\t%0, %1" ++ [(set_attr "type" "load_byte") + (set_attr "predicable" "yes") +- (set_attr "pool_range" "*,256") +- (set_attr "neg_pool_range" "*,244")] ++ (set_attr "pool_range" "256") ++ (set_attr "neg_pool_range" "244")] + ) + + (define_insn "*arm_zero_extendhisi2_v6" +@@ -4215,49 +4253,50 @@ + [(set (match_operand:SI 0 "s_register_operand" "") + (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))] + "TARGET_EITHER" +-{ +- if (TARGET_ARM && !arm_arch6 && GET_CODE (operands[1]) != MEM) +- { +- emit_insn (gen_andsi3 (operands[0], +- gen_lowpart (SImode, operands[1]), +- GEN_INT (255))); +- DONE; +- } +- if (!arm_arch6 && !MEM_P (operands[1])) ++ " ++ if (!arm_arch6 && GET_CODE (operands[1]) != MEM) + { +- rtx t = gen_lowpart (SImode, operands[1]); +- rtx tmp = gen_reg_rtx (SImode); +- emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24))); +- emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (24))); +- DONE; +- } +-}) ++ if (TARGET_ARM) ++ { ++ emit_insn (gen_andsi3 (operands[0], ++ gen_lowpart (SImode, operands[1]), ++ GEN_INT (255))); ++ } ++ else /* TARGET_THUMB */ ++ { ++ rtx temp = gen_reg_rtx (SImode); ++ rtx ops[3]; + +-(define_split +- [(set (match_operand:SI 0 "register_operand" "") +- (zero_extend:SI (match_operand:QI 1 "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)))] +-{ +- operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0); +- if (TARGET_ARM) +- { +- emit_insn (gen_andsi3 (operands[0], operands[2], GEN_INT (255))); ++ operands[1] = copy_to_mode_reg (QImode, operands[1]); ++ operands[1] = gen_lowpart (SImode, operands[1]); ++ ++ ops[0] = temp; ++ ops[1] = operands[1]; ++ ops[2] = GEN_INT (24); ++ ++ emit_insn (gen_rtx_SET (VOIDmode, ops[0], ++ gen_rtx_ASHIFT (SImode, ops[1], ops[2]))); ++ ++ ops[0] = operands[0]; ++ ops[1] = temp; ++ ops[2] = GEN_INT (24); ++ ++ emit_insn (gen_rtx_SET (VOIDmode, ops[0], ++ gen_rtx_LSHIFTRT (SImode, ops[1], ops[2]))); ++ } + DONE; + } +-}) ++ " ++) + + (define_insn "*thumb1_zero_extendqisi2" +- [(set (match_operand:SI 0 "register_operand" "=l,l") +- (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))] ++ [(set (match_operand:SI 0 "register_operand" "=l") ++ (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))] + "TARGET_THUMB1 && !arm_arch6" +- "@ +- # +- ldrb\\t%0, %1" +- [(set_attr "length" "4,2") +- (set_attr "type" "alu_shift,load_byte") +- (set_attr "pool_range" "*,32")] ++ "ldrb\\t%0, %1" ++ [(set_attr "length" "2") ++ (set_attr "type" "load_byte") ++ (set_attr "pool_range" "32")] + ) + + (define_insn "*thumb1_zero_extendqisi2_v6" +@@ -4273,17 +4312,14 @@ + ) + + (define_insn "*arm_zero_extendqisi2" +- [(set (match_operand:SI 0 "s_register_operand" "=r,r") +- (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))] ++ [(set (match_operand:SI 0 "s_register_operand" "=r") ++ (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))] + "TARGET_ARM && !arm_arch6" +- "@ +- # +- ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2" +- [(set_attr "length" "8,4") +- (set_attr "type" "alu_shift,load_byte") ++ "ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2" ++ [(set_attr "type" "load_byte") + (set_attr "predicable" "yes") +- (set_attr "pool_range" "*,4096") +- (set_attr "neg_pool_range" "*,4084")] ++ (set_attr "pool_range" "4096") ++ (set_attr "neg_pool_range" "4084")] + ) + + (define_insn "*arm_zero_extendqisi2_v6" +@@ -4362,42 +4398,108 @@ + ) + + (define_expand "extendhisi2" +- [(set (match_operand:SI 0 "s_register_operand" "") +- (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))] ++ [(set (match_dup 2) ++ (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "") ++ (const_int 16))) ++ (set (match_operand:SI 0 "s_register_operand" "") ++ (ashiftrt:SI (match_dup 2) ++ (const_int 16)))] + "TARGET_EITHER" +-{ +- if (TARGET_THUMB1) +- { +- emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1])); +- DONE; +- } +- if (MEM_P (operands[1]) && TARGET_ARM && !arm_arch4) +- { +- emit_insn (gen_extendhisi2_mem (operands[0], operands[1])); +- DONE; +- } ++ " ++ { ++ if (GET_CODE (operands[1]) == MEM) ++ { ++ if (TARGET_THUMB1) ++ { ++ emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1])); ++ DONE; ++ } ++ else if (arm_arch4) ++ { ++ emit_insn (gen_rtx_SET (VOIDmode, operands[0], ++ gen_rtx_SIGN_EXTEND (SImode, operands[1]))); ++ DONE; ++ } ++ } + +- if (!arm_arch6 && !MEM_P (operands[1])) +- { +- rtx t = gen_lowpart (SImode, operands[1]); +- rtx tmp = gen_reg_rtx (SImode); +- emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16))); +- emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (16))); +- DONE; +- } +-}) ++ if (TARGET_ARM && GET_CODE (operands[1]) == MEM) ++ { ++ emit_insn (gen_extendhisi2_mem (operands[0], operands[1])); ++ DONE; ++ } + +-(define_split +- [(parallel +- [(set (match_operand:SI 0 "register_operand" "") +- (sign_extend:SI (match_operand:HI 1 "register_operand" ""))) +- (clobber (match_scratch:SI 2 ""))])] +- "!arm_arch6" +- [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16))) +- (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))] +-{ +- operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0); +-}) ++ if (!s_register_operand (operands[1], HImode)) ++ operands[1] = copy_to_mode_reg (HImode, operands[1]); ++ ++ if (arm_arch6) ++ { ++ if (TARGET_THUMB1) ++ emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1])); ++ else ++ emit_insn (gen_rtx_SET (VOIDmode, operands[0], ++ gen_rtx_SIGN_EXTEND (SImode, operands[1]))); ++ ++ DONE; ++ } ++ ++ operands[1] = gen_lowpart (SImode, operands[1]); ++ operands[2] = gen_reg_rtx (SImode); ++ }" ++) ++ ++(define_insn "thumb1_extendhisi2" ++ [(set (match_operand:SI 0 "register_operand" "=l") ++ (sign_extend:SI (match_operand:HI 1 "memory_operand" "m"))) ++ (clobber (match_scratch:SI 2 "=&l"))] ++ "TARGET_THUMB1 && !arm_arch6" ++ "* ++ { ++ rtx ops[4]; ++ rtx mem = XEXP (operands[1], 0); ++ ++ /* This code used to try to use 'V', and fix the address only if it was ++ offsettable, but this fails for e.g. REG+48 because 48 is outside the ++ range of QImode offsets, and offsettable_address_p does a QImode ++ address check. */ ++ ++ if (GET_CODE (mem) == CONST) ++ mem = XEXP (mem, 0); ++ ++ if (GET_CODE (mem) == LABEL_REF) ++ return \"ldr\\t%0, %1\"; ++ ++ if (GET_CODE (mem) == PLUS) ++ { ++ rtx a = XEXP (mem, 0); ++ rtx b = XEXP (mem, 1); ++ ++ if (GET_CODE (a) == LABEL_REF ++ && GET_CODE (b) == CONST_INT) ++ return \"ldr\\t%0, %1\"; ++ ++ if (GET_CODE (b) == REG) ++ return \"ldrsh\\t%0, %1\"; ++ ++ ops[1] = a; ++ ops[2] = b; ++ } ++ else ++ { ++ ops[1] = mem; ++ ops[2] = const0_rtx; ++ } ++ ++ gcc_assert (GET_CODE (ops[1]) == REG); ++ ++ ops[0] = operands[0]; ++ ops[3] = operands[2]; ++ output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops); ++ return \"\"; ++ }" ++ [(set_attr "length" "4") ++ (set_attr "type" "load_byte") ++ (set_attr "pool_range" "1020")] ++) + + ;; We used to have an early-clobber on the scratch register here. + ;; However, there's a bug somewhere in reload which means that this +@@ -4406,18 +4508,16 @@ + ;; we try to verify the operands. Fortunately, we don't really need + ;; the early-clobber: we can always use operand 0 if operand 2 + ;; overlaps the address. +-(define_insn "thumb1_extendhisi2" ++(define_insn "*thumb1_extendhisi2_insn_v6" + [(set (match_operand:SI 0 "register_operand" "=l,l") + (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m"))) + (clobber (match_scratch:SI 2 "=X,l"))] +- "TARGET_THUMB1" ++ "TARGET_THUMB1 && arm_arch6" + "* + { + rtx ops[4]; + rtx mem; + +- if (which_alternative == 0 && !arm_arch6) +- return \"#\"; + if (which_alternative == 0) + return \"sxth\\t%0, %1\"; + +@@ -4465,10 +4565,7 @@ + output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops); + return \"\"; + }" +- [(set_attr_alternative "length" +- [(if_then_else (eq_attr "is_arch6" "yes") +- (const_int 2) (const_int 4)) +- (const_int 4)]) ++ [(set_attr "length" "2,4") + (set_attr "type" "alu_shift,load_byte") + (set_attr "pool_range" "*,1020")] + ) +@@ -4509,28 +4606,15 @@ + }" + ) + +-(define_split +- [(set (match_operand:SI 0 "register_operand" "") +- (sign_extend:SI (match_operand:HI 1 "register_operand" "")))] +- "!arm_arch6" +- [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16))) +- (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))] +-{ +- operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0); +-}) +- + (define_insn "*arm_extendhisi2" +- [(set (match_operand:SI 0 "s_register_operand" "=r,r") +- (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))] ++ [(set (match_operand:SI 0 "s_register_operand" "=r") ++ (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))] + "TARGET_ARM && arm_arch4 && !arm_arch6" +- "@ +- # +- ldr%(sh%)\\t%0, %1" +- [(set_attr "length" "8,4") +- (set_attr "type" "alu_shift,load_byte") ++ "ldr%(sh%)\\t%0, %1" ++ [(set_attr "type" "load_byte") + (set_attr "predicable" "yes") +- (set_attr "pool_range" "*,256") +- (set_attr "neg_pool_range" "*,244")] ++ (set_attr "pool_range" "256") ++ (set_attr "neg_pool_range" "244")] + ) + + ;; ??? Check Thumb-2 pool range +@@ -4592,45 +4676,46 @@ + ) + + (define_expand "extendqisi2" +- [(set (match_operand:SI 0 "s_register_operand" "") +- (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")))] ++ [(set (match_dup 2) ++ (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "") ++ (const_int 24))) ++ (set (match_operand:SI 0 "s_register_operand" "") ++ (ashiftrt:SI (match_dup 2) ++ (const_int 24)))] + "TARGET_EITHER" +-{ +- if (!arm_arch4 && MEM_P (operands[1])) +- operands[1] = copy_to_mode_reg (QImode, operands[1]); ++ " ++ { ++ if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM) ++ { ++ emit_insn (gen_rtx_SET (VOIDmode, operands[0], ++ gen_rtx_SIGN_EXTEND (SImode, operands[1]))); ++ DONE; ++ } + +- if (!arm_arch6 && !MEM_P (operands[1])) +- { +- rtx t = gen_lowpart (SImode, operands[1]); +- rtx tmp = gen_reg_rtx (SImode); +- emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24))); +- emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (24))); +- DONE; +- } +-}) ++ if (!s_register_operand (operands[1], QImode)) ++ operands[1] = copy_to_mode_reg (QImode, operands[1]); + +-(define_split +- [(set (match_operand:SI 0 "register_operand" "") +- (sign_extend:SI (match_operand:QI 1 "register_operand" "")))] +- "!arm_arch6" +- [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24))) +- (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))] +-{ +- operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0); +-}) ++ if (arm_arch6) ++ { ++ emit_insn (gen_rtx_SET (VOIDmode, operands[0], ++ gen_rtx_SIGN_EXTEND (SImode, operands[1]))); ++ DONE; ++ } ++ ++ operands[1] = gen_lowpart (SImode, operands[1]); ++ operands[2] = gen_reg_rtx (SImode); ++ }" ++) + + (define_insn "*arm_extendqisi" +- [(set (match_operand:SI 0 "s_register_operand" "=r,r") +- (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))] ++ [(set (match_operand:SI 0 "s_register_operand" "=r") ++ (sign_extend:SI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))] + "TARGET_ARM && arm_arch4 && !arm_arch6" +- "@ +- # +- ldr%(sb%)\\t%0, %1" +- [(set_attr "length" "8,4") +- (set_attr "type" "alu_shift,load_byte") ++ "ldr%(sb%)\\t%0, %1" ++ [(set_attr "type" "load_byte") + (set_attr "predicable" "yes") +- (set_attr "pool_range" "*,256") +- (set_attr "neg_pool_range" "*,244")] ++ (set_attr "pool_range" "256") ++ (set_attr "neg_pool_range" "244")] + ) + + (define_insn "*arm_extendqisi_v6" +@@ -4658,55 +4743,83 @@ + (set_attr "predicable" "yes")] + ) + +-(define_split +- [(set (match_operand:SI 0 "register_operand" "") +- (sign_extend:SI (match_operand:QI 1 "memory_operand" "")))] +- "TARGET_THUMB1 && reload_completed" +- [(set (match_dup 0) (match_dup 2)) +- (set (match_dup 0) (sign_extend:SI (match_dup 3)))] +-{ +- rtx addr = XEXP (operands[1], 0); ++(define_insn "*thumb1_extendqisi2" ++ [(set (match_operand:SI 0 "register_operand" "=l,l") ++ (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))] ++ "TARGET_THUMB1 && !arm_arch6" ++ "* ++ { ++ rtx ops[3]; ++ rtx mem = XEXP (operands[1], 0); + +- if (GET_CODE (addr) == CONST) +- addr = XEXP (addr, 0); ++ if (GET_CODE (mem) == CONST) ++ mem = XEXP (mem, 0); + +- if (GET_CODE (addr) == PLUS +- && REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1))) +- /* No split necessary. */ +- FAIL; ++ if (GET_CODE (mem) == LABEL_REF) ++ return \"ldr\\t%0, %1\"; + +- if (GET_CODE (addr) == PLUS +- && !REG_P (XEXP (addr, 0)) && !REG_P (XEXP (addr, 1))) +- FAIL; ++ if (GET_CODE (mem) == PLUS ++ && GET_CODE (XEXP (mem, 0)) == LABEL_REF) ++ return \"ldr\\t%0, %1\"; + +- if (reg_overlap_mentioned_p (operands[0], addr)) +- { +- rtx t = gen_lowpart (QImode, operands[0]); +- emit_move_insn (t, operands[1]); +- emit_insn (gen_thumb1_extendqisi2 (operands[0], t)); +- DONE; +- } ++ if (which_alternative == 0) ++ return \"ldrsb\\t%0, %1\"; + +- if (REG_P (addr)) +- { +- addr = gen_rtx_PLUS (Pmode, addr, operands[0]); +- operands[2] = const0_rtx; +- } +- else if (GET_CODE (addr) != PLUS) +- FAIL; +- else if (REG_P (XEXP (addr, 0))) +- { +- operands[2] = XEXP (addr, 1); +- addr = gen_rtx_PLUS (Pmode, XEXP (addr, 0), operands[0]); +- } +- else +- { +- operands[2] = XEXP (addr, 0); +- addr = gen_rtx_PLUS (Pmode, XEXP (addr, 1), operands[0]); +- } ++ ops[0] = operands[0]; + +- operands[3] = change_address (operands[1], QImode, addr); +-}) ++ if (GET_CODE (mem) == PLUS) ++ { ++ rtx a = XEXP (mem, 0); ++ rtx b = XEXP (mem, 1); ++ ++ ops[1] = a; ++ ops[2] = b; ++ ++ if (GET_CODE (a) == REG) ++ { ++ if (GET_CODE (b) == REG) ++ output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops); ++ else if (REGNO (a) == REGNO (ops[0])) ++ { ++ output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops); ++ output_asm_insn (\"lsl\\t%0, %0, #24\", ops); ++ output_asm_insn (\"asr\\t%0, %0, #24\", ops); ++ } ++ else ++ output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops); ++ } ++ else ++ { ++ gcc_assert (GET_CODE (b) == REG); ++ if (REGNO (b) == REGNO (ops[0])) ++ { ++ output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops); ++ output_asm_insn (\"lsl\\t%0, %0, #24\", ops); ++ output_asm_insn (\"asr\\t%0, %0, #24\", ops); ++ } ++ else ++ output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops); ++ } ++ } ++ else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem)) ++ { ++ output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops); ++ output_asm_insn (\"lsl\\t%0, %0, #24\", ops); ++ output_asm_insn (\"asr\\t%0, %0, #24\", ops); ++ } ++ else ++ { ++ ops[1] = mem; ++ ops[2] = const0_rtx; ++ ++ output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops); ++ } ++ return \"\"; ++ }" ++ [(set_attr "length" "2,6") ++ (set_attr "type" "load_byte,load_byte") ++ (set_attr "pool_range" "32,32")] ++) + + (define_peephole2 + [(set (match_operand:SI 0 "register_operand" "") +@@ -4729,32 +4842,83 @@ + operands[4] = change_address (operands[4], QImode, addr); + }) + +-(define_insn "thumb1_extendqisi2" ++(define_insn "*thumb1_extendqisi2_v6" + [(set (match_operand:SI 0 "register_operand" "=l,l,l") + (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))] +- "TARGET_THUMB1" +-{ +- rtx addr; ++ "TARGET_THUMB1 && arm_arch6" ++ "* ++ { ++ rtx ops[3]; ++ rtx mem; + +- if (which_alternative == 0 && arm_arch6) +- return "sxtb\\t%0, %1"; +- if (which_alternative == 0) +- return "#"; ++ if (which_alternative == 0) ++ return \"sxtb\\t%0, %1\"; ++ ++ mem = XEXP (operands[1], 0); + +- addr = XEXP (operands[1], 0); +- if (GET_CODE (addr) == PLUS +- && REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1))) +- return "ldrsb\\t%0, %1"; ++ if (GET_CODE (mem) == CONST) ++ mem = XEXP (mem, 0); ++ ++ if (GET_CODE (mem) == LABEL_REF) ++ return \"ldr\\t%0, %1\"; ++ ++ if (GET_CODE (mem) == PLUS ++ && GET_CODE (XEXP (mem, 0)) == LABEL_REF) ++ return \"ldr\\t%0, %1\"; ++ if (which_alternative == 0) ++ return \"ldrsb\\t%0, %1\"; + +- return "#"; +-} +- [(set_attr_alternative "length" +- [(if_then_else (eq_attr "is_arch6" "yes") +- (const_int 2) (const_int 4)) +- (const_int 2) +- (if_then_else (eq_attr "is_arch6" "yes") +- (const_int 4) (const_int 6))]) +- (set_attr "type" "alu_shift,load_byte,load_byte")] ++ ops[0] = operands[0]; ++ ++ if (GET_CODE (mem) == PLUS) ++ { ++ rtx a = XEXP (mem, 0); ++ rtx b = XEXP (mem, 1); ++ ++ ops[1] = a; ++ ops[2] = b; ++ ++ if (GET_CODE (a) == REG) ++ { ++ if (GET_CODE (b) == REG) ++ output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops); ++ else if (REGNO (a) == REGNO (ops[0])) ++ { ++ output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops); ++ output_asm_insn (\"sxtb\\t%0, %0\", ops); ++ } ++ else ++ output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops); ++ } ++ else ++ { ++ gcc_assert (GET_CODE (b) == REG); ++ if (REGNO (b) == REGNO (ops[0])) ++ { ++ output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops); ++ output_asm_insn (\"sxtb\\t%0, %0\", ops); ++ } ++ else ++ output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops); ++ } ++ } ++ else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem)) ++ { ++ output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops); ++ output_asm_insn (\"sxtb\\t%0, %0\", ops); ++ } ++ else ++ { ++ ops[1] = mem; ++ ops[2] = const0_rtx; ++ ++ output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops); ++ } ++ return \"\"; ++ }" ++ [(set_attr "length" "2,2,4") ++ (set_attr "type" "alu_shift,load_byte,load_byte") ++ (set_attr "pool_range" "*,32,32")] + ) + + (define_expand "extendsfdf2" +Index: gcc-4_5-branch/gcc/testsuite/gcc.target/arm/pr42172-1.c +=================================================================== +--- gcc-4_5-branch.orig/gcc/testsuite/gcc.target/arm/pr42172-1.c ++++ /dev/null +@@ -1,19 +0,0 @@ +-/* { dg-options "-O2" } */ +- +-struct A { +- unsigned int f1 : 3; +- unsigned int f2 : 3; +- unsigned int f3 : 1; +- unsigned int f4 : 1; +- +-}; +- +-void init_A (struct A *this) +-{ +- this->f1 = 0; +- this->f2 = 1; +- this->f3 = 0; +- this->f4 = 0; +-} +- +-/* { dg-final { scan-assembler-times "ldr" 1 } } */
* This fixes the gcc ICE as seen compiling samba Signed-off-by: Khem Raj <raj.khem@gmail.com> --- recipes/gcc/gcc-4.5.inc | 3 +- recipes/gcc/gcc-4.5/gcc-revert-pr42172.patch | 989 ++++++++++++++++++++++++++ 2 files changed, 991 insertions(+), 1 deletions(-) create mode 100644 recipes/gcc/gcc-4.5/gcc-revert-pr42172.patch