Patchwork PowerPC64 PR47935 fix

login
register
mail settings
Submitter Alan Modra
Date March 1, 2011, 3:39 p.m.
Message ID <20110301153913.GD13094@bubble.grove.modra.org>
Download mbox | patch
Permalink /patch/84949/
State New
Headers show

Comments

Alan Modra - March 1, 2011, 3:39 p.m.
The testcase in PR47935 shows combine offsetting a mem in a way that
we fail to detect as invalid for lwa.  Fixed as follows.  Patch
bootstrapped and regression tested powerpc64-linux.  OK to apply?

	PR target/47935
	* config/rs6000/predicates.md (lwa_operand): Check cmodel medium
	toc relative addresses for valid offsets.
David Edelsohn - March 1, 2011, 4:18 p.m.
On Tue, Mar 1, 2011 at 10:39 AM, Alan Modra <amodra@gmail.com> wrote:
> The testcase in PR47935 shows combine offsetting a mem in a way that
> we fail to detect as invalid for lwa.  Fixed as follows.  Patch
> bootstrapped and regression tested powerpc64-linux.  OK to apply?
>
>        PR target/47935
>        * config/rs6000/predicates.md (lwa_operand): Check cmodel medium
>        toc relative addresses for valid offsets.

Okay.

Thanks, David

Patch

Index: gcc/config/rs6000/predicates.md
===================================================================
--- gcc/config/rs6000/predicates.md	(revision 170587)
+++ gcc/config/rs6000/predicates.md	(working copy)
@@ -734,20 +734,32 @@  (define_predicate "zero_reg_mem_operand"
 (define_predicate "lwa_operand"
   (match_code "reg,subreg,mem")
 {
-  rtx inner = op;
+  rtx inner, addr, offset;
 
+  inner = op;
   if (reload_completed && GET_CODE (inner) == SUBREG)
     inner = SUBREG_REG (inner);
 
-  return gpc_reg_operand (inner, mode)
-    || (memory_operand (inner, mode)
-	&& GET_CODE (XEXP (inner, 0)) != PRE_INC
-	&& GET_CODE (XEXP (inner, 0)) != PRE_DEC
-	&& (GET_CODE (XEXP (inner, 0)) != PRE_MODIFY
-	    || legitimate_indexed_address_p (XEXP (XEXP (inner, 0), 1), 0))
-	&& (GET_CODE (XEXP (inner, 0)) != PLUS
-	    || GET_CODE (XEXP (XEXP (inner, 0), 1)) != CONST_INT
-	    || INTVAL (XEXP (XEXP (inner, 0), 1)) % 4 == 0));
+  if (gpc_reg_operand (inner, mode))
+    return true;
+  if (!memory_operand (inner, mode))
+    return false;
+  addr = XEXP (inner, 0);
+  if (GET_CODE (addr) == PRE_INC
+      || GET_CODE (addr) == PRE_DEC
+      || (GET_CODE (addr) == PRE_MODIFY
+	  && !legitimate_indexed_address_p (XEXP (addr, 1), 0)))
+    return false;
+  if (GET_CODE (addr) == LO_SUM
+      && GET_CODE (XEXP (addr, 0)) == REG
+      && GET_CODE (XEXP (addr, 1)) == CONST)
+    addr = XEXP (XEXP (addr, 1), 0);
+  if (GET_CODE (addr) != PLUS)
+    return true;
+  offset = XEXP (addr, 1);
+  if (GET_CODE (offset) != CONST_INT)
+    return true;
+  return INTVAL (offset) % 4 == 0;
 })
 
 ;; Return 1 if the operand, used inside a MEM, is a SYMBOL_REF.