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
This commit is contained in:
parent
875d0f10a6
commit
a7994a57b9
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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))
|
||||
|
@ -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")]
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user