[PATCH, RFC] Handling non-trivial comparisons with cond-exec
Richard Earnshaw
rearnsha@arm.com
Tue Oct 14 11:15:00 GMT 2003
Richard,
The ARM/Thumb back-end is in effect two back-ends rolled into one. For
ARM code we use a condition code register and define
HAVE_conditional_execution. For Thumb code we hide the condition code
register and use cbranch patterns to control code flow. I'm trying to add
optimizations to the Thumb compiler to allow the condition-code setting
effects of data processing operations to be used instead of an explicit
compare with zero. So, for example instead of
sub r0, r0, #1
cmp r0, #0
bge <dest>
we can emit
sub r0, r0, #1
bpl <dest>
This involves recognizing RTL of the form
(parallel [
(set (pc) (if_then_else
(ge (plus (reg) (const_int -1))
(const_int 0))
(label)
(pc)))
(set (reg) (plus (reg) (const_int -1)))])
Unfortunately, this is breaking one of the invariants that the
HAVE_conditional_execution code makes: that a comparison is always a
register (actually, the invariant should be that it's always a comparison
of a register against zero, but the second test isn't enforced).
So adding a pattern for the above causes an abort in
init_propagate_block_info.
It seems to me that what I need to achieve is for the
conditional_execution code to behave like a no-op if the branch is not
trivial (since unless it is we can't track the condition accurately).
This patch effectively achieves that by only trying to apply the cond-exec
tracking if a block ends with a simple comparison (where simple is defined
as a comparison of a reg (or subreg of a reg) and zero.
Does this sound OK, or have I missed anything?
R.
<date> Richard Earnshaw <rearnsha@arm.com>
* jump.c (any_simple_condjump_p): New function.
* rtl.h: Declare it.
* flow.c (init_propagate_block_info): Only do conditional-execution
processing if the condjump is simple.
-------------- next part --------------
Index: flow.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/flow.c,v
retrieving revision 1.562
diff -p -r1.562 flow.c
*** flow.c 12 Sep 2003 15:07:50 -0000 1.562
--- flow.c 14 Oct 2003 10:58:12 -0000
*************** init_propagate_block_info (basic_block b
*** 1861,1871 ****
free_reg_cond_life_info);
pbi->reg_cond_reg = BITMAP_XMALLOC ();
! /* If this block ends in a conditional branch, for each register live
! from one side of the branch and not the other, record the register
! as conditionally dead. */
if (GET_CODE (bb->end) == JUMP_INSN
! && any_condjump_p (bb->end))
{
regset_head diff_head;
regset diff = INITIALIZE_REG_SET (diff_head);
--- 1861,1872 ----
free_reg_cond_life_info);
pbi->reg_cond_reg = BITMAP_XMALLOC ();
! /* If this block ends in a conditional branch, for each register
! live from one side of the branch and not the other, record the
! register as conditionally dead. Only do this if the condition is
! simple enough. */
if (GET_CODE (bb->end) == JUMP_INSN
! && any_simple_condjump_p (bb->end))
{
regset_head diff_head;
regset diff = INITIALIZE_REG_SET (diff_head);
Index: jump.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/jump.c,v
retrieving revision 1.236
diff -p -r1.236 jump.c
*** jump.c 22 Jul 2003 23:15:28 -0000 1.236
--- jump.c 14 Oct 2003 10:58:12 -0000
*************** any_condjump_p (rtx insn)
*** 1172,1177 ****
--- 1172,1217 ----
|| (a == PC && (b == LABEL_REF || b == RETURN)));
}
+ /* Return true when insn is a conditional jump that has a simple
+ condition. A simple condition is a comparison of a register (maybe
+ via a subreg) and zero.
+
+ The behaviour is similar to any_condjump_p except for the additional
+ restriction. */
+
+ int
+ any_simple_condjump_p (rtx insn)
+ {
+ rtx x = pc_set (insn);
+ rtx cond, reg;
+ enum rtx_code a, b;
+
+ if (!x)
+ return 0;
+ if (GET_CODE (SET_SRC (x)) != IF_THEN_ELSE)
+ return 0;
+
+ cond = XEXP (SET_SRC (x), 0);
+
+ if (GET_RTX_CLASS (GET_CODE (cond)) != '<')
+ return 0;
+
+ reg = XEXP (cond, 0);
+
+ if (GET_CODE (reg) == SUBREG)
+ reg = SUBREG_REG (reg);
+
+ if (GET_CODE (reg) != REG
+ || XEXP (cond, 1) != const0_rtx)
+ return 0;
+
+ a = GET_CODE (XEXP (SET_SRC (x), 1));
+ b = GET_CODE (XEXP (SET_SRC (x), 2));
+
+ return ((b == PC && (a == LABEL_REF || a == RETURN))
+ || (a == PC && (b == LABEL_REF || b == RETURN)));
+ }
+
/* Return the label of a conditional jump. */
rtx
Index: rtl.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/rtl.h,v
retrieving revision 1.435
diff -p -r1.435 rtl.h
*** rtl.h 12 Sep 2003 15:07:50 -0000 1.435
--- rtl.h 14 Oct 2003 10:58:12 -0000
*************** extern void cse_end_of_basic_block (rtx,
*** 1974,1979 ****
--- 1974,1980 ----
extern int comparison_dominates_p (enum rtx_code, enum rtx_code);
extern int condjump_p (rtx);
extern int any_condjump_p (rtx);
+ extern int any_simple_condjump_p (rtx);
extern int any_uncondjump_p (rtx);
extern int safe_to_remove_jump_p (rtx);
extern rtx pc_set (rtx);
More information about the Gcc-patches
mailing list