This is the mail archive of the gcc-patches@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]

[PATCH/AARCH64v2 2/2] Fix PR 61345: rtx_cost ICEing on simple code


Hi,
  The problem here is aarch64_rtx_costs for IF_THEN_ELSE does not
handle the case where the first operand is a non comparison.  This
happens when the combine is combing a few RTLs and calling
set_src_cost to check the costs of the newly created rtl.

OK?  Built and tested on aarch64-elf with no regressions.

Thanks,
Andrew Pinski

ChangeLog:
	* config/aarch64/aarch64.c (aarch64_if_then_else_costs): Allow non comparisons
	for OP0.

testsuite/ChangeLog:
	* gcc.c-torture/compile/20140528-1.c: New testcase.

---
 gcc/config/aarch64/aarch64.c                     |   36 ++++++++++++++-------
 gcc/testsuite/gcc.c-torture/compile/20140528-1.c |    9 +++++
 2 files changed, 33 insertions(+), 12 deletions(-)
 create mode 100644 gcc/testsuite/gcc.c-torture/compile/20140528-1.c

diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 77a6706..ce4eb3c 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -4855,19 +4855,33 @@ aarch64_rtx_arith_op_extract_p (rtx x, enum machine_mode mode)
 static bool
 aarch64_if_then_else_costs (rtx op0, rtx op1, rtx op2, int *cost, bool speed)
 {
+  rtx inner;
+  rtx comparator;
+  enum rtx_code cmpcode;
+
+  if (COMPARISON_P (op0))
+    {
+      inner = XEXP (op0, 0);
+      comparator = XEXP (op0, 1);
+      cmpcode = GET_CODE (op0);
+    }
+  else
+    {
+      inner = op0;
+      comparator = const0_rtx;
+      cmpcode = NE;
+    }
+
   if (GET_CODE (op1) == PC || GET_CODE (op2) == PC)
     {
       /* Conditional branch.  */
-      if (GET_MODE_CLASS (GET_MODE (XEXP (op0, 0))) == MODE_CC)
+      if (GET_MODE_CLASS (GET_MODE (inner)) == MODE_CC)
 	return true;
       else
 	{
-	  if (GET_CODE (op0) == NE
-	      || GET_CODE (op0) == EQ)
+	  if (cmpcode == NE
+	      || cmpcode == EQ)
 	    {
-	      rtx inner = XEXP (op0, 0);
-	      rtx comparator = XEXP (op0, 1);
-
 	      if (comparator == const0_rtx)
 		{
 		  /* TBZ/TBNZ/CBZ/CBNZ.  */
@@ -4877,23 +4891,21 @@ aarch64_if_then_else_costs (rtx op0, rtx op1, rtx op2, int *cost, bool speed)
 			 	       0, speed);
 		else
 		  /* CBZ/CBNZ.  */
-		  *cost += rtx_cost (inner, GET_CODE (op0), 0, speed);
+		  *cost += rtx_cost (inner, cmpcode, 0, speed);
 
 	        return true;
 	      }
 	    }
-	  else if (GET_CODE (op0) == LT
-		   || GET_CODE (op0) == GE)
+	  else if (cmpcode == LT
+		   || cmpcode == GE)
 	    {
-	      rtx comparator = XEXP (op0, 1);
-
 	      /* TBZ/TBNZ.  */
 	      if (comparator == const0_rtx)
 		return true;
 	    }
 	}
     }
-  else if (GET_MODE_CLASS (GET_MODE (XEXP (op0, 0))) == MODE_CC)
+  else if (GET_MODE_CLASS (GET_MODE (inner)) == MODE_CC)
     {
       /* It's a conditional operation based on the status flags,
 	 so it must be some flavor of CSEL.  */
diff --git a/gcc/testsuite/gcc.c-torture/compile/20140528-1.c b/gcc/testsuite/gcc.c-torture/compile/20140528-1.c
new file mode 100644
index 0000000..d227802
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/20140528-1.c
@@ -0,0 +1,9 @@
+unsigned f(unsigned flags, unsigned capabilities)
+{
+  unsigned gfp_mask;
+  unsigned gfp_notmask = 0;
+  gfp_mask = flags & ((1 << 25) - 1);
+  if (!(capabilities & 0x00000001))
+    gfp_mask |= 0x1000000u;
+  return (gfp_mask & ~gfp_notmask);
+}
-- 
1.7.2.5


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