Patchwork [ARM] Improve optimization to transform TST into LSLS

login
register
mail settings
Submitter Richard Earnshaw
Date June 24, 2010, 10:52 p.m.
Message ID <4C23E1AC.5070602@buzzard.freeserve.co.uk>
Download mbox | patch
Permalink /patch/56867/
State New
Headers show

Comments

Richard Earnshaw - June 24, 2010, 10:52 p.m.
We recently added a pattern to the Thumb2 machine description to try to 
transform TST reg, # (1 << n) into LSLS reg, #(31-n).  Subsequent 
discussions on another patch led me to realize that this patch could 
probably be done a better way.  Experimentation bears this out: the 
following patch saves a further 0.1% when compiling CSiBE.

This version of the patch uses a peephole2 rather than a combine pattern 
to spot the optimization.  This has two benefits:
1) The pattern will not be used if there's no scratch available 
(probably better, since tst only costs 2 bytes, but spilling can often 
cost significantly more).
2) It gives rise to further optimization opportunities, such as 
if-conversion, that the other patch did not support.

Tested on arm-eabi and committed to trunk.

R.

2010-06-24  Richard Earnshaw  <rearnsha@arm.com>

	* thumb2.md (thumb2_tlobits_cbranch): Delete.
	(peephole2 to convert zero_extract/compare of single bit to
	 lshift/compare): New.

Patch

diff --git a/gcc/config/arm/thumb2.md b/gcc/config/arm/thumb2.md
index 7045d14..3985183 100644
--- a/gcc/config/arm/thumb2.md
+++ b/gcc/config/arm/thumb2.md
@@ -1509,88 +1509,31 @@ 
    (set_attr "predicable" "yes")]
 )
 
-(define_insn "*thumb2_tlobits_cbranch"
-  [(set (pc)
-	(if_then_else
-	 (match_operator 0 "equality_operator"
-	  [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l,h,h")
-			    (match_operand:SI 2 "const_int_operand" "i,Pu,i")
-			    (const_int 0))
-	   (const_int 0)])
-	 (label_ref (match_operand 3 "" ""))
-	 (pc)))
-   (clobber (match_scratch:SI 4 "=l,X,r"))
-   (clobber (reg:CC CC_REGNUM))]
-  "TARGET_THUMB2"
-  "*
-  {
-  if (which_alternative == 0)
-    {
-      rtx op[3];
-      op[0] = operands[4];
-      op[1] = operands[1];
-      op[2] = GEN_INT (32 - INTVAL (operands[2]));
-
-      output_asm_insn (\"lsls\\t%0, %1, %2\", op);
-      switch (get_attr_length (insn))
-	{
-	  case 4:  return \"b%d0\\t%l3\";
-	  case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
-	  default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
-	}
-    }
-  else
-    {
-      rtx op[3];
-
-      if (which_alternative == 1)
-	{
-	  op[0] = operands[1];
-	  op[1] = GEN_INT ((1 << INTVAL (operands[2])) - 1);
-	  output_asm_insn (\"tst\\t%0, %1\", op);
-	}
-      else
-	{
-	  op[0] = operands[4];
-	  op[1] = operands[1];
-	  op[2] = GEN_INT (32 - INTVAL (operands[2]));
-	  output_asm_insn (\"lsls\\t%0, %1, %2\", op);
-	}
+(define_peephole2
+  [(set (match_operand:CC_NOOV 0 "cc_register" "")
+	(compare:CC_NOOV (zero_extract:SI
+			  (match_operand:SI 1 "low_register_operand" "")
+			  (const_int 1)
+			  (match_operand:SI 2 "const_int_operand" ""))
+			 (const_int 0)))
+   (match_scratch:SI 3 "l")
+   (set (pc)
+	(if_then_else (match_operator:CC_NOOV 4 "equality_operator"
+		       [(match_dup 0) (const_int 0)])
+		      (match_operand 5 "" "")
+		      (match_operand 6 "" "")))]
+  "TARGET_THUMB2
+   && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32)"
+  [(parallel [(set (match_dup 0)
+		   (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
+				    (const_int 0)))
+	      (clobber (match_dup 3))])
+   (set (pc)
+	(if_then_else (match_op_dup 4 [(match_dup 0) (const_int 0)])
+		      (match_dup 5) (match_dup 6)))]
+  "
+  operands[2] = GEN_INT (31 - INTVAL (operands[2]));
+  operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[4]) == NE ? LT : GE,
+				VOIDmode, operands[0], const0_rtx);
+  ")
 
-      switch (get_attr_length (insn))
-	{
-	  case 6:  return \"b%d0\\t%l3\";
-	  case 8:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
-	  default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
-	}
-    }
-  }"
-  [(set (attr "far_jump")
-	(if_then_else
-	    (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
-		 (le (minus (match_dup 3) (pc)) (const_int 2048)))
-	    (const_string "no")
-	    (const_string "yes")))
-   (set (attr "length")
-	(if_then_else
-	  (eq (symbol_ref ("which_alternative"))
-			  (const_int 0))
-	  (if_then_else
-	    (and (ge (minus (match_dup 3) (pc)) (const_int -250))
-		 (le (minus (match_dup 3) (pc)) (const_int 256)))
-	    (const_int 4)
-	    (if_then_else
-		(and (ge (minus (match_dup 3) (pc)) (const_int -2040))
-		     (le (minus (match_dup 3) (pc)) (const_int 2048)))
-		(const_int 6)
-		(const_int 8)))
-	  (if_then_else
-	    (and (ge (minus (match_dup 3) (pc)) (const_int -250))
-		 (le (minus (match_dup 3) (pc)) (const_int 256)))
-	    (const_int 6)
-	    (if_then_else
-		(and (ge (minus (match_dup 3) (pc)) (const_int -2040))
-		     (le (minus (match_dup 3) (pc)) (const_int 2048)))
-		(const_int 8)
-		(const_int 10)))))]
-)