diff options
Diffstat (limited to 'meta-oe/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106802.patch')
-rw-r--r-- | meta-oe/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106802.patch | 948 |
1 files changed, 0 insertions, 948 deletions
diff --git a/meta-oe/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106802.patch b/meta-oe/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106802.patch deleted file mode 100644 index ade96fdd11..0000000000 --- a/meta-oe/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106802.patch +++ /dev/null @@ -1,948 +0,0 @@ -2011-09-12 Andrew Stubbs <ams@codesourcery.com> - - Backport from FSF mainline: - - 2011-08-30 Andrew Stubbs <ams@codesourcery.com> - - gcc/ - * config/arm/arm.c (optimal_immediate_sequence_1): Make b1, b2, - b3 and b4 unsigned. - - 2011-08-30 Andrew Stubbs <ams@codesourcery.com> - - gcc/ - * config/arm/arm.c (arm_gen_constant): Set can_negate correctly - when code is SET. - - 2011-08-26 Andrew Stubbs <ams@codesourcery.com> - - gcc/ - * config/arm/arm.c (struct four_ints): New type. - (count_insns_for_constant): Delete function. - (find_best_start): Delete function. - (optimal_immediate_sequence): New function. - (optimal_immediate_sequence_1): New function. - (arm_gen_constant): Move constant splitting code to - optimal_immediate_sequence. - Rewrite constant negation/invertion code. - - gcc/testsuite/ - * gcc.target/arm/thumb2-replicated-constant1.c: New file. - * gcc.target/arm/thumb2-replicated-constant2.c: New file. - * gcc.target/arm/thumb2-replicated-constant3.c: New file. - * gcc.target/arm/thumb2-replicated-constant4.c: New file. - - 2011-08-26 Andrew Stubbs <ams@codesourcery.com> - - gcc/ - * config/arm/arm-protos.h (const_ok_for_op): Add prototype. - * config/arm/arm.c (const_ok_for_op): Add support for addw/subw. - Remove prototype. Remove static function type. - * config/arm/arm.md (*arm_addsi3): Add addw/subw support. - Add arch attribute. - * config/arm/constraints.md (Pj, PJ): New constraints. - - 2011-04-20 Andrew Stubbs <ams@codesourcery.com> - - gcc/ - * config/arm/arm.c (arm_gen_constant): Move mowv support .... - (const_ok_for_op): ... to here. - - 2011-04-20 Andrew Stubbs <ams@codesourcery.com> - - gcc/ - * config/arm/arm.c (arm_gen_constant): Remove redundant can_invert. - - -=== modified file 'gcc/config/arm/arm-protos.h' ---- old/gcc/config/arm/arm-protos.h 2011-07-04 14:03:49 +0000 -+++ new/gcc/config/arm/arm-protos.h 2011-08-25 13:26:58 +0000 -@@ -46,6 +46,7 @@ - extern bool arm_small_register_classes_for_mode_p (enum machine_mode); - extern int arm_hard_regno_mode_ok (unsigned int, enum machine_mode); - extern int const_ok_for_arm (HOST_WIDE_INT); -+extern int const_ok_for_op (HOST_WIDE_INT, enum rtx_code); - extern int arm_split_constant (RTX_CODE, enum machine_mode, rtx, - HOST_WIDE_INT, rtx, rtx, int); - extern RTX_CODE arm_canonicalize_comparison (RTX_CODE, rtx *, rtx *); - -=== modified file 'gcc/config/arm/arm.c' ---- old/gcc/config/arm/arm.c 2011-08-24 17:35:16 +0000 -+++ new/gcc/config/arm/arm.c 2011-09-06 12:57:56 +0000 -@@ -63,6 +63,11 @@ - - void (*arm_lang_output_object_attributes_hook)(void); - -+struct four_ints -+{ -+ int i[4]; -+}; -+ - /* Forward function declarations. */ - static bool arm_needs_doubleword_align (enum machine_mode, const_tree); - static int arm_compute_static_chain_stack_bytes (void); -@@ -81,7 +86,6 @@ - static bool arm_legitimate_address_p (enum machine_mode, rtx, bool); - static int thumb_far_jump_used_p (void); - static bool thumb_force_lr_save (void); --static int const_ok_for_op (HOST_WIDE_INT, enum rtx_code); - static rtx emit_sfm (int, int); - static unsigned arm_size_return_regs (void); - static bool arm_assemble_integer (rtx, unsigned int, int); -@@ -129,7 +133,13 @@ - static int arm_comp_type_attributes (const_tree, const_tree); - static void arm_set_default_type_attributes (tree); - static int arm_adjust_cost (rtx, rtx, rtx, int); --static int count_insns_for_constant (HOST_WIDE_INT, int); -+static int optimal_immediate_sequence (enum rtx_code code, -+ unsigned HOST_WIDE_INT val, -+ struct four_ints *return_sequence); -+static int optimal_immediate_sequence_1 (enum rtx_code code, -+ unsigned HOST_WIDE_INT val, -+ struct four_ints *return_sequence, -+ int i); - static int arm_get_strip_length (int); - static bool arm_function_ok_for_sibcall (tree, tree); - static enum machine_mode arm_promote_function_mode (const_tree, -@@ -2525,7 +2535,7 @@ - } - - /* Return true if I is a valid constant for the operation CODE. */ --static int -+int - const_ok_for_op (HOST_WIDE_INT i, enum rtx_code code) - { - if (const_ok_for_arm (i)) -@@ -2533,7 +2543,21 @@ - - switch (code) - { -+ case SET: -+ /* See if we can use movw. */ -+ if (arm_arch_thumb2 && (i & 0xffff0000) == 0) -+ return 1; -+ else -+ return 0; -+ - case PLUS: -+ /* See if we can use addw or subw. */ -+ if (TARGET_THUMB2 -+ && ((i & 0xfffff000) == 0 -+ || ((-i) & 0xfffff000) == 0)) -+ return 1; -+ /* else fall through. */ -+ - case COMPARE: - case EQ: - case NE: -@@ -2649,68 +2673,41 @@ - 1); - } - --/* Return the number of instructions required to synthesize the given -- constant, if we start emitting them from bit-position I. */ --static int --count_insns_for_constant (HOST_WIDE_INT remainder, int i) --{ -- HOST_WIDE_INT temp1; -- int step_size = TARGET_ARM ? 2 : 1; -- int num_insns = 0; -- -- gcc_assert (TARGET_ARM || i == 0); -- -- do -- { -- int end; -- -- if (i <= 0) -- i += 32; -- if (remainder & (((1 << step_size) - 1) << (i - step_size))) -- { -- end = i - 8; -- if (end < 0) -- end += 32; -- temp1 = remainder & ((0x0ff << end) -- | ((i < end) ? (0xff >> (32 - end)) : 0)); -- remainder &= ~temp1; -- num_insns++; -- i -= 8 - step_size; -- } -- i -= step_size; -- } while (remainder); -- return num_insns; --} -- --static int --find_best_start (unsigned HOST_WIDE_INT remainder) -+/* Return a sequence of integers, in RETURN_SEQUENCE that fit into -+ ARM/THUMB2 immediates, and add up to VAL. -+ Thr function return value gives the number of insns required. */ -+static int -+optimal_immediate_sequence (enum rtx_code code, unsigned HOST_WIDE_INT val, -+ struct four_ints *return_sequence) - { - int best_consecutive_zeros = 0; - int i; - int best_start = 0; -+ int insns1, insns2; -+ struct four_ints tmp_sequence; - - /* If we aren't targetting ARM, the best place to start is always at -- the bottom. */ -- if (! TARGET_ARM) -- return 0; -- -- for (i = 0; i < 32; i += 2) -+ the bottom, otherwise look more closely. */ -+ if (TARGET_ARM) - { -- int consecutive_zeros = 0; -- -- if (!(remainder & (3 << i))) -+ for (i = 0; i < 32; i += 2) - { -- while ((i < 32) && !(remainder & (3 << i))) -- { -- consecutive_zeros += 2; -- i += 2; -- } -- if (consecutive_zeros > best_consecutive_zeros) -- { -- best_consecutive_zeros = consecutive_zeros; -- best_start = i - consecutive_zeros; -- } -- i -= 2; -+ int consecutive_zeros = 0; -+ -+ if (!(val & (3 << i))) -+ { -+ while ((i < 32) && !(val & (3 << i))) -+ { -+ consecutive_zeros += 2; -+ i += 2; -+ } -+ if (consecutive_zeros > best_consecutive_zeros) -+ { -+ best_consecutive_zeros = consecutive_zeros; -+ best_start = i - consecutive_zeros; -+ } -+ i -= 2; -+ } - } - } - -@@ -2737,13 +2734,161 @@ - the constant starting from `best_start', and also starting from - zero (i.e. with bit 31 first to be output). If `best_start' doesn't - yield a shorter sequence, we may as well use zero. */ -+ insns1 = optimal_immediate_sequence_1 (code, val, return_sequence, best_start); - if (best_start != 0 -- && ((((unsigned HOST_WIDE_INT) 1) << best_start) < remainder) -- && (count_insns_for_constant (remainder, 0) <= -- count_insns_for_constant (remainder, best_start))) -- best_start = 0; -- -- return best_start; -+ && ((((unsigned HOST_WIDE_INT) 1) << best_start) < val)) -+ { -+ insns2 = optimal_immediate_sequence_1 (code, val, &tmp_sequence, 0); -+ if (insns2 <= insns1) -+ { -+ *return_sequence = tmp_sequence; -+ insns1 = insns2; -+ } -+ } -+ -+ return insns1; -+} -+ -+/* As for optimal_immediate_sequence, but starting at bit-position I. */ -+static int -+optimal_immediate_sequence_1 (enum rtx_code code, unsigned HOST_WIDE_INT val, -+ struct four_ints *return_sequence, int i) -+{ -+ int remainder = val & 0xffffffff; -+ int insns = 0; -+ -+ /* Try and find a way of doing the job in either two or three -+ instructions. -+ -+ In ARM mode we can use 8-bit constants, rotated to any 2-bit aligned -+ location. We start at position I. This may be the MSB, or -+ optimial_immediate_sequence may have positioned it at the largest block -+ of zeros that are aligned on a 2-bit boundary. We then fill up the temps, -+ wrapping around to the top of the word when we drop off the bottom. -+ In the worst case this code should produce no more than four insns. -+ -+ In Thumb2 mode, we can use 32/16-bit replicated constants, and 8-bit -+ constants, shifted to any arbitrary location. We should always start -+ at the MSB. */ -+ do -+ { -+ int end; -+ unsigned int b1, b2, b3, b4; -+ unsigned HOST_WIDE_INT result; -+ int loc; -+ -+ gcc_assert (insns < 4); -+ -+ if (i <= 0) -+ i += 32; -+ -+ /* First, find the next normal 12/8-bit shifted/rotated immediate. */ -+ if (remainder & ((TARGET_ARM ? (3 << (i - 2)) : (1 << (i - 1))))) -+ { -+ loc = i; -+ if (i <= 12 && TARGET_THUMB2 && code == PLUS) -+ /* We can use addw/subw for the last 12 bits. */ -+ result = remainder; -+ else -+ { -+ /* Use an 8-bit shifted/rotated immediate. */ -+ end = i - 8; -+ if (end < 0) -+ end += 32; -+ result = remainder & ((0x0ff << end) -+ | ((i < end) ? (0xff >> (32 - end)) -+ : 0)); -+ i -= 8; -+ } -+ } -+ else -+ { -+ /* Arm allows rotates by a multiple of two. Thumb-2 allows -+ arbitrary shifts. */ -+ i -= TARGET_ARM ? 2 : 1; -+ continue; -+ } -+ -+ /* Next, see if we can do a better job with a thumb2 replicated -+ constant. -+ -+ We do it this way around to catch the cases like 0x01F001E0 where -+ two 8-bit immediates would work, but a replicated constant would -+ make it worse. -+ -+ TODO: 16-bit constants that don't clear all the bits, but still win. -+ TODO: Arithmetic splitting for set/add/sub, rather than bitwise. */ -+ if (TARGET_THUMB2) -+ { -+ b1 = (remainder & 0xff000000) >> 24; -+ b2 = (remainder & 0x00ff0000) >> 16; -+ b3 = (remainder & 0x0000ff00) >> 8; -+ b4 = remainder & 0xff; -+ -+ if (loc > 24) -+ { -+ /* The 8-bit immediate already found clears b1 (and maybe b2), -+ but must leave b3 and b4 alone. */ -+ -+ /* First try to find a 32-bit replicated constant that clears -+ almost everything. We can assume that we can't do it in one, -+ or else we wouldn't be here. */ -+ unsigned int tmp = b1 & b2 & b3 & b4; -+ unsigned int tmp2 = tmp + (tmp << 8) + (tmp << 16) -+ + (tmp << 24); -+ unsigned int matching_bytes = (tmp == b1) + (tmp == b2) -+ + (tmp == b3) + (tmp == b4); -+ if (tmp -+ && (matching_bytes >= 3 -+ || (matching_bytes == 2 -+ && const_ok_for_op (remainder & ~tmp2, code)))) -+ { -+ /* At least 3 of the bytes match, and the fourth has at -+ least as many bits set, or two of the bytes match -+ and it will only require one more insn to finish. */ -+ result = tmp2; -+ i = tmp != b1 ? 32 -+ : tmp != b2 ? 24 -+ : tmp != b3 ? 16 -+ : 8; -+ } -+ -+ /* Second, try to find a 16-bit replicated constant that can -+ leave three of the bytes clear. If b2 or b4 is already -+ zero, then we can. If the 8-bit from above would not -+ clear b2 anyway, then we still win. */ -+ else if (b1 == b3 && (!b2 || !b4 -+ || (remainder & 0x00ff0000 & ~result))) -+ { -+ result = remainder & 0xff00ff00; -+ i = 24; -+ } -+ } -+ else if (loc > 16) -+ { -+ /* The 8-bit immediate already found clears b2 (and maybe b3) -+ and we don't get here unless b1 is alredy clear, but it will -+ leave b4 unchanged. */ -+ -+ /* If we can clear b2 and b4 at once, then we win, since the -+ 8-bits couldn't possibly reach that far. */ -+ if (b2 == b4) -+ { -+ result = remainder & 0x00ff00ff; -+ i = 16; -+ } -+ } -+ } -+ -+ return_sequence->i[insns++] = result; -+ remainder &= ~result; -+ -+ if (code == SET || code == MINUS) -+ code = PLUS; -+ } -+ while (remainder); -+ -+ return insns; - } - - /* Emit an instruction with the indicated PATTERN. If COND is -@@ -2760,7 +2905,6 @@ - - /* As above, but extra parameter GENERATE which, if clear, suppresses - RTL generation. */ --/* ??? This needs more work for thumb2. */ - - static int - arm_gen_constant (enum rtx_code code, enum machine_mode mode, rtx cond, -@@ -2772,15 +2916,15 @@ - int final_invert = 0; - int can_negate_initial = 0; - int i; -- int num_bits_set = 0; - int set_sign_bit_copies = 0; - int clear_sign_bit_copies = 0; - int clear_zero_bit_copies = 0; - int set_zero_bit_copies = 0; -- int insns = 0; -+ int insns = 0, neg_insns, inv_insns; - unsigned HOST_WIDE_INT temp1, temp2; - unsigned HOST_WIDE_INT remainder = val & 0xffffffff; -- int step_size = TARGET_ARM ? 2 : 1; -+ struct four_ints *immediates; -+ struct four_ints pos_immediates, neg_immediates, inv_immediates; - - /* Find out which operations are safe for a given CODE. Also do a quick - check for degenerate cases; these can occur when DImode operations -@@ -2789,7 +2933,6 @@ - { - case SET: - can_invert = 1; -- can_negate = 1; - break; - - case PLUS: -@@ -2817,9 +2960,6 @@ - gen_rtx_SET (VOIDmode, target, source)); - return 1; - } -- -- if (TARGET_THUMB2) -- can_invert = 1; - break; - - case AND: -@@ -2861,6 +3001,7 @@ - gen_rtx_NOT (mode, source))); - return 1; - } -+ final_invert = 1; - break; - - case MINUS: -@@ -2883,7 +3024,6 @@ - source))); - return 1; - } -- can_negate = 1; - - break; - -@@ -2892,9 +3032,7 @@ - } - - /* If we can do it in one insn get out quickly. */ -- if (const_ok_for_arm (val) -- || (can_negate_initial && const_ok_for_arm (-val)) -- || (can_invert && const_ok_for_arm (~val))) -+ if (const_ok_for_op (val, code)) - { - if (generate) - emit_constant_insn (cond, -@@ -2947,15 +3085,6 @@ - switch (code) - { - case SET: -- /* See if we can use movw. */ -- if (arm_arch_thumb2 && (remainder & 0xffff0000) == 0) -- { -- if (generate) -- emit_constant_insn (cond, gen_rtx_SET (VOIDmode, target, -- GEN_INT (val))); -- return 1; -- } -- - /* See if we can do this by sign_extending a constant that is known - to be negative. This is a good, way of doing it, since the shift - may well merge into a subsequent insn. */ -@@ -3306,121 +3435,97 @@ - break; - } - -- for (i = 0; i < 32; i++) -- if (remainder & (1 << i)) -- num_bits_set++; -- -- if ((code == AND) -- || (code != IOR && can_invert && num_bits_set > 16)) -- remainder ^= 0xffffffff; -- else if (code == PLUS && num_bits_set > 16) -- remainder = (-remainder) & 0xffffffff; -- -- /* For XOR, if more than half the bits are set and there's a sequence -- of more than 8 consecutive ones in the pattern then we can XOR by the -- inverted constant and then invert the final result; this may save an -- instruction and might also lead to the final mvn being merged with -- some other operation. */ -- else if (code == XOR && num_bits_set > 16 -- && (count_insns_for_constant (remainder ^ 0xffffffff, -- find_best_start -- (remainder ^ 0xffffffff)) -- < count_insns_for_constant (remainder, -- find_best_start (remainder)))) -- { -- remainder ^= 0xffffffff; -- final_invert = 1; -+ /* Calculate what the instruction sequences would be if we generated it -+ normally, negated, or inverted. */ -+ if (code == AND) -+ /* AND cannot be split into multiple insns, so invert and use BIC. */ -+ insns = 99; -+ else -+ insns = optimal_immediate_sequence (code, remainder, &pos_immediates); -+ -+ if (can_negate) -+ neg_insns = optimal_immediate_sequence (code, (-remainder) & 0xffffffff, -+ &neg_immediates); -+ else -+ neg_insns = 99; -+ -+ if (can_invert || final_invert) -+ inv_insns = optimal_immediate_sequence (code, remainder ^ 0xffffffff, -+ &inv_immediates); -+ else -+ inv_insns = 99; -+ -+ immediates = &pos_immediates; -+ -+ /* Is the negated immediate sequence more efficient? */ -+ if (neg_insns < insns && neg_insns <= inv_insns) -+ { -+ insns = neg_insns; -+ immediates = &neg_immediates; -+ } -+ else -+ can_negate = 0; -+ -+ /* Is the inverted immediate sequence more efficient? -+ We must allow for an extra NOT instruction for XOR operations, although -+ there is some chance that the final 'mvn' will get optimized later. */ -+ if ((inv_insns + 1) < insns || (!final_invert && inv_insns < insns)) -+ { -+ insns = inv_insns; -+ immediates = &inv_immediates; - } - else - { - can_invert = 0; -- can_negate = 0; -+ final_invert = 0; - } - -- /* Now try and find a way of doing the job in either two or three -- instructions. -- We start by looking for the largest block of zeros that are aligned on -- a 2-bit boundary, we then fill up the temps, wrapping around to the -- top of the word when we drop off the bottom. -- In the worst case this code should produce no more than four insns. -- Thumb-2 constants are shifted, not rotated, so the MSB is always the -- best place to start. */ -- -- /* ??? Use thumb2 replicated constants when the high and low halfwords are -- the same. */ -- { -- /* Now start emitting the insns. */ -- i = find_best_start (remainder); -- do -- { -- int end; -- -- if (i <= 0) -- i += 32; -- if (remainder & (3 << (i - 2))) -- { -- end = i - 8; -- if (end < 0) -- end += 32; -- temp1 = remainder & ((0x0ff << end) -- | ((i < end) ? (0xff >> (32 - end)) : 0)); -- remainder &= ~temp1; -- -- if (generate) -- { -- rtx new_src, temp1_rtx; -- -- if (code == SET || code == MINUS) -- { -- new_src = (subtargets ? gen_reg_rtx (mode) : target); -- if (can_invert && code != MINUS) -- temp1 = ~temp1; -- } -- else -- { -- if ((final_invert || remainder) && subtargets) -- new_src = gen_reg_rtx (mode); -- else -- new_src = target; -- if (can_invert) -- temp1 = ~temp1; -- else if (can_negate) -- temp1 = -temp1; -- } -- -- temp1 = trunc_int_for_mode (temp1, mode); -- temp1_rtx = GEN_INT (temp1); -- -- if (code == SET) -- ; -- else if (code == MINUS) -- temp1_rtx = gen_rtx_MINUS (mode, temp1_rtx, source); -- else -- temp1_rtx = gen_rtx_fmt_ee (code, mode, source, temp1_rtx); -- -- emit_constant_insn (cond, -- gen_rtx_SET (VOIDmode, new_src, -- temp1_rtx)); -- source = new_src; -- } -- -- if (code == SET) -- { -- can_invert = 0; -- code = PLUS; -- } -- else if (code == MINUS) -+ /* Now output the chosen sequence as instructions. */ -+ if (generate) -+ { -+ for (i = 0; i < insns; i++) -+ { -+ rtx new_src, temp1_rtx; -+ -+ temp1 = immediates->i[i]; -+ -+ if (code == SET || code == MINUS) -+ new_src = (subtargets ? gen_reg_rtx (mode) : target); -+ else if ((final_invert || i < (insns - 1)) && subtargets) -+ new_src = gen_reg_rtx (mode); -+ else -+ new_src = target; -+ -+ if (can_invert) -+ temp1 = ~temp1; -+ else if (can_negate) -+ temp1 = -temp1; -+ -+ temp1 = trunc_int_for_mode (temp1, mode); -+ temp1_rtx = GEN_INT (temp1); -+ -+ if (code == SET) -+ ; -+ else if (code == MINUS) -+ temp1_rtx = gen_rtx_MINUS (mode, temp1_rtx, source); -+ else -+ temp1_rtx = gen_rtx_fmt_ee (code, mode, source, temp1_rtx); -+ -+ emit_constant_insn (cond, -+ gen_rtx_SET (VOIDmode, new_src, -+ temp1_rtx)); -+ source = new_src; -+ -+ if (code == SET) -+ { -+ can_negate = can_invert; -+ can_invert = 0; - code = PLUS; -- -- insns++; -- i -= 8 - step_size; -- } -- /* Arm allows rotates by a multiple of two. Thumb-2 allows arbitrary -- shifts. */ -- i -= step_size; -- } -- while (remainder); -- } -+ } -+ else if (code == MINUS) -+ code = PLUS; -+ } -+ } - - if (final_invert) - { - -=== modified file 'gcc/config/arm/arm.md' ---- old/gcc/config/arm/arm.md 2011-08-25 11:42:09 +0000 -+++ new/gcc/config/arm/arm.md 2011-08-25 13:26:58 +0000 -@@ -701,21 +701,24 @@ - ;; (plus (reg rN) (reg sp)) into (reg rN). In this case reload will - ;; put the duplicated register first, and not try the commutative version. - (define_insn_and_split "*arm_addsi3" -- [(set (match_operand:SI 0 "s_register_operand" "=r, k,r,r, k,r") -- (plus:SI (match_operand:SI 1 "s_register_operand" "%rk,k,r,rk,k,rk") -- (match_operand:SI 2 "reg_or_int_operand" "rI,rI,k,L, L,?n")))] -+ [(set (match_operand:SI 0 "s_register_operand" "=r, k,r,r, k, r, k,r, k, r") -+ (plus:SI (match_operand:SI 1 "s_register_operand" "%rk,k,r,rk,k, rk,k,rk,k, rk") -+ (match_operand:SI 2 "reg_or_int_operand" "rI,rI,k,Pj,Pj,L, L,PJ,PJ,?n")))] - "TARGET_32BIT" - "@ - add%?\\t%0, %1, %2 - add%?\\t%0, %1, %2 - add%?\\t%0, %2, %1 -- sub%?\\t%0, %1, #%n2 -- sub%?\\t%0, %1, #%n2 -+ addw%?\\t%0, %1, %2 -+ addw%?\\t%0, %1, %2 -+ sub%?\\t%0, %1, #%n2 -+ sub%?\\t%0, %1, #%n2 -+ subw%?\\t%0, %1, #%n2 -+ subw%?\\t%0, %1, #%n2 - #" - "TARGET_32BIT - && GET_CODE (operands[2]) == CONST_INT -- && !(const_ok_for_arm (INTVAL (operands[2])) -- || const_ok_for_arm (-INTVAL (operands[2]))) -+ && !const_ok_for_op (INTVAL (operands[2]), PLUS) - && (reload_completed || !arm_eliminable_register (operands[1]))" - [(clobber (const_int 0))] - " -@@ -724,8 +727,9 @@ - operands[1], 0); - DONE; - " -- [(set_attr "length" "4,4,4,4,4,16") -- (set_attr "predicable" "yes")] -+ [(set_attr "length" "4,4,4,4,4,4,4,4,4,16") -+ (set_attr "predicable" "yes") -+ (set_attr "arch" "*,*,*,t2,t2,*,*,t2,t2,*")] - ) - - (define_insn_and_split "*thumb1_addsi3" - -=== modified file 'gcc/config/arm/constraints.md' ---- old/gcc/config/arm/constraints.md 2011-01-03 20:52:22 +0000 -+++ new/gcc/config/arm/constraints.md 2011-08-25 13:26:58 +0000 -@@ -31,7 +31,7 @@ - ;; The following multi-letter normal constraints have been used: - ;; in ARM/Thumb-2 state: Da, Db, Dc, Dn, Dl, DL, Dv, Dy, Di, Dz - ;; in Thumb-1 state: Pa, Pb, Pc, Pd --;; in Thumb-2 state: Ps, Pt, Pu, Pv, Pw, Px -+;; in Thumb-2 state: Pj, PJ, Ps, Pt, Pu, Pv, Pw, Px - - ;; The following memory constraints have been used: - ;; in ARM/Thumb-2 state: Q, Ut, Uv, Uy, Un, Um, Us -@@ -74,6 +74,18 @@ - (and (match_code "const_int") - (match_test "(ival & 0xffff0000) == 0"))))) - -+(define_constraint "Pj" -+ "@internal A 12-bit constant suitable for an ADDW or SUBW instruction. (Thumb-2)" -+ (and (match_code "const_int") -+ (and (match_test "TARGET_THUMB2") -+ (match_test "(ival & 0xfffff000) == 0")))) -+ -+(define_constraint "PJ" -+ "@internal A constant that satisfies the Pj constrant if negated." -+ (and (match_code "const_int") -+ (and (match_test "TARGET_THUMB2") -+ (match_test "((-ival) & 0xfffff000) == 0")))) -+ - (define_register_constraint "k" "STACK_REG" - "@internal The stack register.") - - -=== added file 'gcc/testsuite/gcc.target/arm/thumb2-replicated-constant1.c' ---- old/gcc/testsuite/gcc.target/arm/thumb2-replicated-constant1.c 1970-01-01 00:00:00 +0000 -+++ new/gcc/testsuite/gcc.target/arm/thumb2-replicated-constant1.c 2011-08-25 13:31:00 +0000 -@@ -0,0 +1,27 @@ -+/* Ensure simple replicated constant immediates work. */ -+/* { dg-options "-mthumb -O2" } */ -+/* { dg-require-effective-target arm_thumb2_ok } */ -+ -+int -+foo1 (int a) -+{ -+ return a + 0xfefefefe; -+} -+ -+/* { dg-final { scan-assembler "add.*#-16843010" } } */ -+ -+int -+foo2 (int a) -+{ -+ return a - 0xab00ab00; -+} -+ -+/* { dg-final { scan-assembler "sub.*#-1426019584" } } */ -+ -+int -+foo3 (int a) -+{ -+ return a & 0x00cd00cd; -+} -+ -+/* { dg-final { scan-assembler "and.*#13435085" } } */ - -=== added file 'gcc/testsuite/gcc.target/arm/thumb2-replicated-constant2.c' ---- old/gcc/testsuite/gcc.target/arm/thumb2-replicated-constant2.c 1970-01-01 00:00:00 +0000 -+++ new/gcc/testsuite/gcc.target/arm/thumb2-replicated-constant2.c 2011-08-25 13:31:00 +0000 -@@ -0,0 +1,75 @@ -+/* Ensure split constants can use replicated patterns. */ -+/* { dg-options "-mthumb -O2" } */ -+/* { dg-require-effective-target arm_thumb2_ok } */ -+ -+int -+foo1 (int a) -+{ -+ return a + 0xfe00fe01; -+} -+ -+/* { dg-final { scan-assembler "add.*#-33489408" } } */ -+/* { dg-final { scan-assembler "add.*#1" } } */ -+ -+int -+foo2 (int a) -+{ -+ return a + 0xdd01dd00; -+} -+ -+/* { dg-final { scan-assembler "add.*#-587145984" } } */ -+/* { dg-final { scan-assembler "add.*#65536" } } */ -+ -+int -+foo3 (int a) -+{ -+ return a + 0x00443344; -+} -+ -+/* { dg-final { scan-assembler "add.*#4456516" } } */ -+/* { dg-final { scan-assembler "add.*#13056" } } */ -+ -+int -+foo4 (int a) -+{ -+ return a + 0x77330033; -+} -+ -+/* { dg-final { scan-assembler "add.*#1996488704" } } */ -+/* { dg-final { scan-assembler "add.*#3342387" } } */ -+ -+int -+foo5 (int a) -+{ -+ return a + 0x11221122; -+} -+ -+/* { dg-final { scan-assembler "add.*#285217024" } } */ -+/* { dg-final { scan-assembler "add.*#2228258" } } */ -+ -+int -+foo6 (int a) -+{ -+ return a + 0x66666677; -+} -+ -+/* { dg-final { scan-assembler "add.*#1717986918" } } */ -+/* { dg-final { scan-assembler "add.*#17" } } */ -+ -+int -+foo7 (int a) -+{ -+ return a + 0x99888888; -+} -+ -+/* { dg-final { scan-assembler "add.*#-2004318072" } } */ -+/* { dg-final { scan-assembler "add.*#285212672" } } */ -+ -+int -+foo8 (int a) -+{ -+ return a + 0xdddddfff; -+} -+ -+/* { dg-final { scan-assembler "add.*#-572662307" } } */ -+/* { dg-final { scan-assembler "addw.*#546" } } */ - -=== added file 'gcc/testsuite/gcc.target/arm/thumb2-replicated-constant3.c' ---- old/gcc/testsuite/gcc.target/arm/thumb2-replicated-constant3.c 1970-01-01 00:00:00 +0000 -+++ new/gcc/testsuite/gcc.target/arm/thumb2-replicated-constant3.c 2011-08-25 13:31:00 +0000 -@@ -0,0 +1,28 @@ -+/* Ensure negated/inverted replicated constant immediates work. */ -+/* { dg-options "-mthumb -O2" } */ -+/* { dg-require-effective-target arm_thumb2_ok } */ -+ -+int -+foo1 (int a) -+{ -+ return a | 0xffffff00; -+} -+ -+/* { dg-final { scan-assembler "orn.*#255" } } */ -+ -+int -+foo2 (int a) -+{ -+ return a & 0xffeeffee; -+} -+ -+/* { dg-final { scan-assembler "bic.*#1114129" } } */ -+ -+int -+foo3 (int a) -+{ -+ return a & 0xaaaaaa00; -+} -+ -+/* { dg-final { scan-assembler "and.*#-1431655766" } } */ -+/* { dg-final { scan-assembler "bic.*#170" } } */ - -=== added file 'gcc/testsuite/gcc.target/arm/thumb2-replicated-constant4.c' ---- old/gcc/testsuite/gcc.target/arm/thumb2-replicated-constant4.c 1970-01-01 00:00:00 +0000 -+++ new/gcc/testsuite/gcc.target/arm/thumb2-replicated-constant4.c 2011-08-25 13:31:00 +0000 -@@ -0,0 +1,22 @@ -+/* Ensure replicated constants don't make things worse. */ -+/* { dg-options "-mthumb -O2" } */ -+/* { dg-require-effective-target arm_thumb2_ok } */ -+ -+int -+foo1 (int a) -+{ -+ /* It might be tempting to use 0x01000100, but it wouldn't help. */ -+ return a + 0x01f001e0; -+} -+ -+/* { dg-final { scan-assembler "add.*#32505856" } } */ -+/* { dg-final { scan-assembler "add.*#480" } } */ -+ -+int -+foo2 (int a) -+{ -+ return a + 0x0f100e10; -+} -+ -+/* { dg-final { scan-assembler "add.*#252706816" } } */ -+/* { dg-final { scan-assembler "add.*#3600" } } */ - |