Hi,
For thumb1, arm-gcc rewrites move insn into subtract of ZERO in peephole2
pass intentionally, then executes
pass_if_after_reload/pass_regrename/pass_cprop_hardreg sequentially.
In this scenario, copy propagation opportunities are missed because:
1. the move insns are re-written.
2. pass_cprop_hardreg currently don't notice the subtract of ZERO.
This patch fixes the problem and the logic is:
1. notice the plus/subtract of ZERO in pass_cprop_hardreg.
2. if the last insn providing information about conditional codes is in
the form of "dest_reg = src_reg - 0", record the src_reg in newly added
field thumb1_cc_op0_src of structure machine_function.
3. in pattern "cbranchsi4_insn", check thumb1_cc_op0_src along with
thumb1_cc_op0 to save one comparison insn.
I measured the patch on CSiBE, about 600 bytes are saved for both O2 and Os
on cortex-m0 without any regression.
I also tested the patch on
arm-none-eabi+cortex-m0/arm-none-eabi+cortex-m3/i686-pc-linux and no
regressions introduced.
So is it OK?
Thanks
2012-08-13 Bin Cheng <[email protected]>
* regcprop.c (copyprop_hardreg_forward_1) Notice copies in the form
of
subtract of ZERO.
* config/arm/arm.h (thumb1_cc_op0_src) New field.
* config/arm/arm.c (thumb1_final_prescan_insn) Record
thumb1_cc_op0_src.
* config/arm/arm.md (cbranchsi4_insn) Check thumb1_cc_op0_src along
with
thumb1_cc_op0.
Index: gcc/config/arm/arm.c
===================================================================
--- gcc/config/arm/arm.c (revision 189835)
+++ gcc/config/arm/arm.c (working copy)
@@ -21663,6 +21663,8 @@
if (cfun->machine->thumb1_cc_insn)
{
if (modified_in_p (cfun->machine->thumb1_cc_op0, insn)
+ || (cfun->machine->thumb1_cc_op0_src != NULL_RTX
+ && modified_in_p (cfun->machine->thumb1_cc_op0_src, insn))
|| modified_in_p (cfun->machine->thumb1_cc_op1, insn))
CC_STATUS_INIT;
}
@@ -21672,13 +21674,18 @@
rtx set = single_set (insn);
cfun->machine->thumb1_cc_insn = insn;
cfun->machine->thumb1_cc_op0 = SET_DEST (set);
+ cfun->machine->thumb1_cc_op0_src = NULL_RTX;
cfun->machine->thumb1_cc_op1 = const0_rtx;
cfun->machine->thumb1_cc_mode = CC_NOOVmode;
if (INSN_CODE (insn) == CODE_FOR_thumb1_subsi3_insn)
{
rtx src1 = XEXP (SET_SRC (set), 1);
if (src1 == const0_rtx)
- cfun->machine->thumb1_cc_mode = CCmode;
+ {
+ cfun->machine->thumb1_cc_mode = CCmode;
+ /* Record the minuend in thumb1_subsi3_insn pattern. */
+ cfun->machine->thumb1_cc_op0_src = XEXP (SET_SRC (set), 0);
+ }
}
}
else if (conds != CONDS_NOCOND)
Index: gcc/config/arm/arm.h
===================================================================
--- gcc/config/arm/arm.h (revision 189835)
+++ gcc/config/arm/arm.h (working copy)
@@ -1459,9 +1459,17 @@
is not needed. */
int return_used_this_function;
/* When outputting Thumb-1 code, record the last insn that provides
- information about condition codes, and the comparison operands. */
+ information about condition codes, and the comparison operands.
+
+ If the last insn that provides information about condition codes
+ is in the form of "dest_reg = src_reg - 0", record the src_reg in
+ thumb1_cc_op0_src, and for following insn sequence:
+ dest_reg = src_reg - 0;
+ if (src_reg ?= 0) goto label;
+ the comparison insn can also be saved. */
rtx thumb1_cc_insn;
rtx thumb1_cc_op0;
+ rtx thumb1_cc_op0_src;
rtx thumb1_cc_op1;
/* Also record the CC mode that is supported. */
enum machine_mode thumb1_cc_mode;
Index: gcc/config/arm/arm.md
===================================================================
--- gcc/config/arm/arm.md (revision 189835)
+++ gcc/config/arm/arm.md (working copy)
@@ -7018,7 +7018,8 @@
rtx t = cfun->machine->thumb1_cc_insn;
if (t != NULL_RTX)
{
- if (!rtx_equal_p (cfun->machine->thumb1_cc_op0, operands[1])
+ if ((!rtx_equal_p (cfun->machine->thumb1_cc_op0, operands[1])
+ && !rtx_equal_p (cfun->machine->thumb1_cc_op0_src, operands[1]))
|| !rtx_equal_p (cfun->machine->thumb1_cc_op1, operands[2]))
t = NULL_RTX;
if (cfun->machine->thumb1_cc_mode == CC_NOOVmode)
@@ -7034,6 +7035,7 @@
output_asm_insn ("cmp\t%1, %2", operands);
cfun->machine->thumb1_cc_insn = insn;
cfun->machine->thumb1_cc_op0 = operands[1];
+ cfun->machine->thumb1_cc_op0_src = NULL_RTX;
cfun->machine->thumb1_cc_op1 = operands[2];
cfun->machine->thumb1_cc_mode = CCmode;
}
Index: gcc/regcprop.c
===================================================================
--- gcc/regcprop.c (revision 189835)
+++ gcc/regcprop.c (working copy)
@@ -1019,8 +1019,18 @@
note_stores (PATTERN (insn), kill_set_value, &ksvd);
/* Notice copies. */
- if (set && REG_P (SET_DEST (set)) && REG_P (SET_SRC (set)))
- copy_value (SET_DEST (set), SET_SRC (set), vd);
+ if (set && REG_P (SET_DEST (set)))
+ {
+ if (REG_P (SET_SRC (set)))
+ copy_value (SET_DEST (set), SET_SRC (set), vd);
+ /* ARM backend intentionally rewrite move insn into subtract of 0 if
+ the condition codes will be useful, so also notice this case. */
+ else if ((GET_CODE (SET_SRC (set)) == PLUS
+ || GET_CODE (SET_SRC (set)) == MINUS)
+ && REG_P (XEXP (SET_SRC (set), 0))
+ && XEXP (SET_SRC (set), 1) == const0_rtx)
+ copy_value (SET_DEST (set), XEXP (SET_SRC (set), 0), vd);
+ }
if (insn == BB_END (bb))
break;