diff options
author | Ramana Radhakrishnan <ramana.radhakrishnan@arm.com> | 2009-05-20 05:40:17 +0000 |
---|---|---|
committer | Ramana Radhakrishnan <ramana@gcc.gnu.org> | 2009-05-20 05:40:17 +0000 |
commit | a7994a57b9b7f80eb0f3d8ebe40184b963f25c59 (patch) | |
tree | 07ff4c1506b8be5787e9300cdec1fc410507712f /gcc | |
parent | 875d0f10a6fb79b1b4387baedeae9a21bc0b14a1 (diff) | |
download | gcc-a7994a57b9b7f80eb0f3d8ebe40184b963f25c59.zip gcc-a7994a57b9b7f80eb0f3d8ebe40184b963f25c59.tar.gz gcc-a7994a57b9b7f80eb0f3d8ebe40184b963f25c59.tar.bz2 |
Fix Thumb2 bic orn
2009-05-20 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>
* config/arm/arm.md (*arm_iorsi3): Refactored for only ARM.
(peephole ior (reg, int) -> mov, ior): Refactored for only ARM.
* config/arm/thumb2.md (*thumb_andsi_not_shiftsi_si): Allow bic
with shifts for Thumb2.
(orsi_notsi): New for orn.
(*thumb_orsi_notshiftsi_si): Allow orn with shifts.
(*thumb2_iorsi3): Rewrite support for iorsi for Thumb2.
* config/arm/arm.c (const_ok_for_op): Split case for IOR for
Thumb2.
(arm_gen_constant): Set can_invert for IOR and Thumb2, Add
comments. Don't invert remainder for IOR.
From-SVN: r147729
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 14 | ||||
-rw-r--r-- | gcc/config/arm/arm.c | 44 | ||||
-rw-r--r-- | gcc/config/arm/arm.md | 6 | ||||
-rw-r--r-- | gcc/config/arm/thumb2.md | 46 |
4 files changed, 105 insertions, 5 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 82f00eb..b64bdce 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,17 @@ +2009-05-20 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com> + + * config/arm/arm.md (*arm_iorsi3): Refactored for only ARM. + (peephole ior (reg, int) -> mov, ior): Refactored for only ARM. + * config/arm/thumb2.md (*thumb_andsi_not_shiftsi_si): Allow bic + with shifts for Thumb2. + (orsi_notsi): New for orn. + (*thumb_orsi_notshiftsi_si): Allow orn with shifts. + (*thumb2_iorsi3): Rewrite support for iorsi for Thumb2. + * config/arm/arm.c (const_ok_for_op): Split case for IOR for + Thumb2. + (arm_gen_constant): Set can_invert for IOR and Thumb2, Add + comments. Don't invert remainder for IOR. + 2009-05-19 Zdenek Dvorak <ook@ucw.cz> PR tree-optimization/40087 diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 8579ce4..eda5cea 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -2008,7 +2008,11 @@ const_ok_for_op (HOST_WIDE_INT i, enum rtx_code code) case MINUS: /* Should only occur with (MINUS I reg) => rsb */ case XOR: + return 0; + case IOR: + if (TARGET_THUMB2) + return const_ok_for_arm (ARM_SIGN_EXTEND (~i)); return 0; case AND: @@ -2185,15 +2189,20 @@ arm_gen_constant (enum rtx_code code, enum machine_mode mode, rtx cond, GEN_INT (ARM_SIGN_EXTEND (val)))); return 1; } + if (remainder == 0) { if (reload_completed && rtx_equal_p (target, source)) return 0; + if (generate) emit_constant_insn (cond, gen_rtx_SET (VOIDmode, target, source)); return 1; } + + if (TARGET_THUMB2) + can_invert = 1; break; case AND: @@ -2281,6 +2290,7 @@ arm_gen_constant (enum rtx_code code, enum machine_mode mode, rtx cond, /* Calculate a few attributes that may be useful for specific optimizations. */ + /* Count number of leading zeros. */ for (i = 31; i >= 0; i--) { if ((remainder & (1 << i)) == 0) @@ -2289,6 +2299,7 @@ arm_gen_constant (enum rtx_code code, enum machine_mode mode, rtx cond, break; } + /* Count number of leading 1's. */ for (i = 31; i >= 0; i--) { if ((remainder & (1 << i)) != 0) @@ -2297,6 +2308,7 @@ arm_gen_constant (enum rtx_code code, enum machine_mode mode, rtx cond, break; } + /* Count number of trailing zero's. */ for (i = 0; i <= 31; i++) { if ((remainder & (1 << i)) == 0) @@ -2305,6 +2317,7 @@ arm_gen_constant (enum rtx_code code, enum machine_mode mode, rtx cond, break; } + /* Count number of trailing 1's. */ for (i = 0; i <= 31; i++) { if ((remainder & (1 << i)) != 0) @@ -2492,6 +2505,17 @@ arm_gen_constant (enum rtx_code code, enum machine_mode mode, rtx cond, if (code == XOR) break; + /* Convert. + x = y | constant ( which is composed of set_sign_bit_copies of leading 1s + and the remainder 0s for e.g. 0xfff00000) + x = ~(~(y ashift set_sign_bit_copies) lshiftrt set_sign_bit_copies) + + This can be done in 2 instructions by using shifts with mov or mvn. + e.g. for + x = x | 0xfff00000; + we generate. + mvn r0, r0, asl #12 + mvn r0, r0, lsr #12 */ if (set_sign_bit_copies > 8 && (val & (-1 << (32 - set_sign_bit_copies))) == val) { @@ -2517,6 +2541,16 @@ arm_gen_constant (enum rtx_code code, enum machine_mode mode, rtx cond, return 2; } + /* Convert + x = y | constant (which has set_zero_bit_copies number of trailing ones). + to + x = ~((~y lshiftrt set_zero_bit_copies) ashift set_zero_bit_copies). + + For eg. r0 = r0 | 0xfff + mvn r0, r0, lsr #12 + mvn r0, r0, asl #12 + + */ if (set_zero_bit_copies > 8 && (remainder & ((1 << set_zero_bit_copies) - 1)) == remainder) { @@ -2542,6 +2576,13 @@ arm_gen_constant (enum rtx_code code, enum machine_mode mode, rtx cond, return 2; } + /* This will never be reached for Thumb2 because orn is a valid + instruction. This is for Thumb1 and the ARM 32 bit cases. + + x = y | constant (such that ~constant is a valid constant) + Transform this to + x = ~(~y & ~constant). + */ if (const_ok_for_arm (temp1 = ARM_SIGN_EXTEND (~val))) { if (generate) @@ -2651,7 +2692,8 @@ arm_gen_constant (enum rtx_code code, enum machine_mode mode, rtx cond, if (remainder & (1 << i)) num_bits_set++; - if (code == AND || (can_invert && num_bits_set > 16)) + if ((code == AND) + || (code != IOR && can_invert && num_bits_set > 16)) remainder = (~remainder) & 0xffffffff; else if (code == PLUS && num_bits_set > 16) remainder = (-remainder) & 0xffffffff; diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index 2b2d703..de78d28 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -2615,11 +2615,11 @@ [(set (match_operand:SI 0 "s_register_operand" "=r,r") (ior:SI (match_operand:SI 1 "s_register_operand" "r,r") (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))] - "TARGET_32BIT" + "TARGET_ARM" "@ orr%?\\t%0, %1, %2 #" - "TARGET_32BIT + "TARGET_ARM && GET_CODE (operands[2]) == CONST_INT && !const_ok_for_arm (INTVAL (operands[2]))" [(clobber (const_int 0))] @@ -2646,7 +2646,7 @@ (set (match_operand:SI 0 "arm_general_register_operand" "") (ior:SI (match_operand:SI 1 "arm_general_register_operand" "") (match_operand:SI 2 "const_int_operand" "")))] - "TARGET_32BIT + "TARGET_ARM && !const_ok_for_arm (INTVAL (operands[2])) && const_ok_for_arm (~INTVAL (operands[2]))" [(set (match_dup 3) (match_dup 2)) diff --git a/gcc/config/arm/thumb2.md b/gcc/config/arm/thumb2.md index 14b52d0..935ca08 100644 --- a/gcc/config/arm/thumb2.md +++ b/gcc/config/arm/thumb2.md @@ -57,7 +57,7 @@ [(match_operand:SI 2 "s_register_operand" "r") (match_operand:SI 3 "const_int_operand" "M")])) (match_operand:SI 1 "s_register_operand" "r")))] - "TARGET_ARM" + "TARGET_THUMB2" "bic%?\\t%0, %1, %2%S4" [(set_attr "predicable" "yes") (set_attr "shift" "2") @@ -1252,3 +1252,47 @@ (set_attr "length" "2")] ) +(define_insn "orsi_notsi_si" + [(set (match_operand:SI 0 "s_register_operand" "=r") + (ior:SI (not:SI (match_operand:SI 2 "s_register_operand" "r")) + (match_operand:SI 1 "reg_or_int_operand" "rK")))] + "TARGET_THUMB2" + "orn%?\\t%0, %1, %2" + [(set_attr "predicable" "yes")] +) + +(define_insn "*thumb_orsi_not_shiftsi_si" + [(set (match_operand:SI 0 "s_register_operand" "=r") + (ior:SI (not:SI (match_operator:SI 4 "shift_operator" + [(match_operand:SI 2 "s_register_operand" "r") + (match_operand:SI 3 "const_int_operand" "M")])) + (match_operand:SI 1 "s_register_operand" "r")))] + "TARGET_THUMB2" + "orn%?\\t%0, %1, %2%S4" + [(set_attr "predicable" "yes") + (set_attr "shift" "2") + (set_attr "type" "alu_shift")] +) + +(define_insn_and_split "*thumb2_iorsi3" + [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") + (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,r") + (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))] + "TARGET_THUMB2" + "@ + orr%?\\t%0, %1, %2 + orn%?\\t%0, %1, #%B2 + #" + "TARGET_THUMB2 + && GET_CODE (operands[2]) == CONST_INT + && !(const_ok_for_arm (INTVAL (operands[2])) + || const_ok_for_arm (~INTVAL (operands[2])))" + [(clobber (const_int 0))] + " + arm_split_constant (IOR, SImode, curr_insn, + INTVAL (operands[2]), operands[0], operands[1], 0); + DONE; + " + [(set_attr "length" "4,4,16") + (set_attr "predicable" "yes")] +) |