This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

ARM condition code register handling


I did some looking at the test case for PR target/1532 on the ARM.
For that test case, with -O2, the compiler currently generates

_Z3fooii:
	@ args = 0, pretend = 0, frame = 0
	@ frame_needed = 0, uses_anonymous_args = 0
	@ link register save eliminated.
	cmp	r0, r1
	@ lr needed for prologue
	moveq	r3, #0
	beq	.L13
	bxgt	lr
	mov	r3, #2
.L13:
	cmp	r3, #1
	bgt	.L11
	cmp	r3, #0
	addeq	r0, r0, r1
	bxeq	lr
	bx	lr
.L11:
	cmp	r3, #2
	moveq	r0, r1
	bxeq	lr
	bx	lr

I looked into enabling TARGET_FIXED_CONDITION_CODE_REGS which I just
added for this test case on the i386.  The initial effect was not
much, because on the ARM the conditions have the same mode, so CSE
picks them up.

However, I noticed that because CSE picks up the conditions, the
effects of the jump bypass pass are severely blunted.  The jump bypass
pass works by identifying the register which controls a conditional
jump, but it appears to only look within one basic block.  When CSE
eliminates a setting of the condition code register, the jump bypass
pass can't figure out what is happening, even when it otherwise
could.

So I put in a bit of code to CSE to not eliminate sets of the
condition code register until after the jump bypass pass has been
run.  The patch to cse.c, and arm.c, is below.

That patch gave me the following assembler code:

_Z3fooii:
	@ args = 0, pretend = 0, frame = 0
	@ frame_needed = 0, uses_anonymous_args = 0
	@ link register save eliminated.
	cmp	r0, r1
	mov	r3, r0
	@ lr needed for prologue
	mov	r0, r1, asl #1
	bxeq	lr
	mov	r0, r3
	movle	r0, r1
	bx	lr

As you can see that is quite a bit better for this test case.

I'll probably pick this up again later.  Does anybody have any
thoughts on this general approach, in particular the change to CSE?

Ian

Index: cse.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cse.c,v
retrieving revision 1.283
diff -p -u -r1.283 cse.c
--- cse.c	24 Jan 2004 20:54:53 -0000	1.283
+++ cse.c	30 Jan 2004 18:50:50 -0000
@@ -201,6 +201,10 @@ Related expressions:
    so that it is possible to find out if there exists any
    register equivalent to an expression related to a given expression.  */
 
+/* True if being called after the loop optimization pass.  */
+
+static int cse_after_loop;
+
 /* One plus largest register number used in this function.  */
 
 static int max_reg;
@@ -5660,6 +5664,21 @@ cse_insn (rtx insn, rtx libcall_insn)
 	 are those before this instruction.  */
       sets[i].dest_hash = HASH (dest, mode);
 
+      /* Don't record assignments to condition code registers before
+	 the bypass_jumps pass.  */
+      if (! cse_after_loop
+	  && GET_CODE (dest) == REG
+	  && REGNO (dest) < FIRST_PSEUDO_REGISTER)
+	{
+	  unsigned int r1, r2;
+
+	  if ((*targetm.fixed_condition_code_regs) (&r1, &r2))
+	    {
+	      if (REGNO (dest) == r1 || REGNO (dest) == r2)
+		do_not_record = 1;
+	    }
+	}
+
       /* Don't enter a bit-field in the hash table
 	 because the value in it after the store
 	 may not equal what was stored, due to truncation.  */
@@ -6978,6 +6997,7 @@ cse_main (rtx f, int nregs, int after_lo
   val.path = xmalloc (sizeof (struct branch_path)
 		      * PARAM_VALUE (PARAM_MAX_CSE_PATH_LENGTH));
 
+  cse_after_loop = after_loop;
   cse_jumps_altered = 0;
   recorded_label_ref = 0;
   constant_pool_entries_cost = 0;
Index: config/arm/arm.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/arm/arm.c,v
retrieving revision 1.323
diff -p -u -r1.323 arm.c
--- config/arm/arm.c	28 Jan 2004 11:41:38 -0000	1.323
+++ config/arm/arm.c	30 Jan 2004 18:50:54 -0000
@@ -94,6 +94,7 @@ static Mnode *add_minipool_forward_ref (
 static Mnode *move_minipool_fix_backward_ref (Mnode *, Mnode *, HOST_WIDE_INT);
 static Mnode *add_minipool_backward_ref (Mfix *);
 static void assign_minipool_offsets (Mfix *);
+static bool arm_fixed_condition_code_regs (unsigned int *, unsigned int *);
 static void arm_print_value (FILE *, rtx);
 static void dump_minipool (rtx);
 static int arm_barrier_cost (rtx);
@@ -228,6 +229,9 @@ static void arm_setup_incoming_varargs (
 #undef  TARGET_ADDRESS_COST
 #define TARGET_ADDRESS_COST arm_address_cost
 
+#undef TARGET_FIXED_CONDITION_CODE_REGS
+#define TARGET_FIXED_CONDITION_CODE_REGS arm_fixed_condition_code_regs
+
 #undef  TARGET_MACHINE_DEPENDENT_REORG
 #define TARGET_MACHINE_DEPENDENT_REORG arm_reorg
 
@@ -5756,6 +5760,16 @@ arm_gen_compare_reg (enum rtx_code code,
 			  gen_rtx_COMPARE (mode, x, y)));
 
   return cc_reg;
+}
+
+/* Return the fixed register used for condition codes.  */
+
+static bool
+arm_fixed_condition_code_regs (unsigned int *p1, unsigned int *p2)
+{
+  *p1 = CC_REGNUM;
+  *p2 = INVALID_REGNUM;
+  return true;
 }
 
 /* Generate a sequence of insns that will generate the correct return


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]