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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@147729
138bc75d-0d04-0410-961f-
82ee72b054a4
+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
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:
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:
/* 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)
break;
}
+ /* Count number of leading 1's. */
for (i = 31; i >= 0; i--)
{
if ((remainder & (1 << i)) != 0)
break;
}
+ /* Count number of trailing zero's. */
for (i = 0; i <= 31; i++)
{
if ((remainder & (1 << i)) == 0)
break;
}
+ /* Count number of trailing 1's. */
for (i = 0; i <= 31; i++)
{
if ((remainder & (1 << i)) != 0)
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)
{
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)
{
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)
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;
[(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))]
(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))
[(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")
(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")]
+)