Patchwork [i386] : Fix PR 53961 in a different way

login
register
mail settings
Submitter Uros Bizjak
Date July 22, 2012, 3:39 p.m.
Message ID <CAFULd4aE9ypW7G1pP_YoAb9Mc0W3szj9ouoMznMD8LmRjr75rg@mail.gmail.com>
Download mbox | patch
Permalink /patch/172519/
State New
Headers show

Comments

Uros Bizjak - July 22, 2012, 3:39 p.m.
Hello!

The core of the problem was in fact the possibility of invalid
addresses to sneak through various LEA patterns.

Attached patch adds handling of SImode SUBREGs of addresses to generic
code. This way, we can use one LEA pattern that accepts all valid
address RTXes (modulo segment prefixed ones).

2012-07-22  Uros Bizjak  <ubizjak@gmail.com>

	PR target/53961
	* config/i386/i386.md (*lea): New insn pattern.
	(*lea_1): Remove.
	(*lea<mode>_2): Ditto.
	(*lea_{3,4,5,6}_zext): Ditto.
	* config/i386/constraints.md (j): Remove address constraint.
	* config/i386/i386.c (ix86_decompose_address): Allow SImode subreg
	of an address.
	(ix86_print_operand_address): Handle SImode subreg of an address.
	(ix86_avoid_lea_for_add): Reject zero-extended addresses for now.

Patch was bootstrapped and regression tested on x86_64-pc-linux-gnu
{,-m32}. I have also compiled a bunch of x32 testcases and there were
no code changes.

I have committed patch to mainline SVN, and will keep an eye on x32
regression testers.

Uros.

Patch

Index: i386.c
===================================================================
--- i386.c	(revision 189746)
+++ i386.c	(working copy)
@@ -11576,9 +11576,18 @@  ix86_decompose_address (rtx addr, struct ix86_addr
   int retval = 1;
   enum ix86_address_seg seg = SEG_DEFAULT;
 
+  /* Allow SImode subregs of DImode addresses,
+     they will be emitted with addr32 prefix.  */
+  if (TARGET_64BIT && GET_MODE (addr) == SImode)
+    {
+      if (GET_CODE (addr) == SUBREG
+	  && GET_MODE (XEXP (addr, 0)) == DImode)
+	addr = SUBREG_REG (addr);
+    }
+
   /* Allow zero-extended SImode addresses,
      they will be emitted with addr32 prefix.  */
-  if (TARGET_64BIT && GET_MODE (addr) == DImode)
+  else if (TARGET_64BIT && GET_MODE (addr) == DImode)
     {
       if (GET_CODE (addr) == ZERO_EXTEND
 	  && GET_MODE (XEXP (addr, 0)) == SImode)
@@ -14755,10 +14764,10 @@  ix86_print_operand_address (FILE *file, rtx addr)
     }
   else
     {
-      /* Print SImode register names for zero-extended
-	 addresses to force addr32 prefix.  */
+      /* Print SImode register names to force addr32 prefix.  */
       if (TARGET_64BIT
-	  && (GET_CODE (addr) == ZERO_EXTEND
+	  && (GET_CODE (addr) == SUBREG
+	      || GET_CODE (addr) == ZERO_EXTEND
 	      || GET_CODE (addr) == AND))
 	{
 	  gcc_assert (!code);
@@ -16855,6 +16864,11 @@  ix86_avoid_lea_for_add (rtx insn, rtx operands[])
   unsigned int regno1 = true_regnum (operands[1]);
   unsigned int regno2 = true_regnum (operands[2]);
 
+  /* FIXME: Handle zero-extended addresses.  */
+  if (GET_CODE (operands[1]) == ZERO_EXTEND
+      || GET_CODE (operands[1]) == AND)
+    return false;
+
   /* Check if we need to optimize.  */
   if (!TARGET_OPT_AGU || optimize_function_for_size_p (cfun))
     return false;
Index: predicates.md
===================================================================
--- predicates.md	(revision 189746)
+++ predicates.md	(working copy)
@@ -830,11 +830,6 @@ 
   struct ix86_address parts;
   int ok;
 
-  /*  LEA handles zero-extend by itself.  */
-  if (GET_CODE (op) == ZERO_EXTEND
-      || GET_CODE (op) == AND)
-    return false;
-
   ok = ix86_decompose_address (op, &parts);
   gcc_assert (ok);
   return parts.seg == SEG_DEFAULT;
Index: constraints.md
===================================================================
--- constraints.md	(revision 189746)
+++ constraints.md	(working copy)
@@ -19,7 +19,7 @@ 
 
 ;;; Unused letters:
 ;;;     B     H           T
-;;;           h  k          v
+;;;           h jk          v
 
 ;; Integer register constraints.
 ;; It is not necessary to define 'r' here.
@@ -133,11 +133,6 @@ 
   (and (not (match_test "TARGET_X32"))
        (match_operand 0 "memory_operand")))
 
-(define_address_constraint "j"
-  "@internal Address operand that can be zero extended in LEA instruction."
-  (and (not (match_code "const_int"))
-       (match_operand 0 "address_operand")))
-
 ;; Integer constant constraints.
 (define_constraint "I"
   "Integer constant in the range 0 @dots{} 31, for 32-bit shifts."
Index: i386.md
===================================================================
--- i386.md	(revision 189746)
+++ i386.md	(working copy)
@@ -5508,25 +5508,21 @@ 
   [(set_attr "type" "alu")
    (set_attr "mode" "QI")])
 
-(define_insn_and_split "*lea_1"
-  [(set (match_operand:SI 0 "register_operand" "=r")
-	(subreg:SI (match_operand:DI 1 "lea_address_operand" "p") 0))]
-  "TARGET_64BIT"
-  "lea{l}\t{%E1, %0|%0, %E1}"
-  "&& reload_completed && ix86_avoid_lea_for_addr (insn, operands)"
-  [(const_int 0)]
-{
-  ix86_split_lea_for_addr (operands, SImode);
-  DONE;
-}
-  [(set_attr "type" "lea")
-   (set_attr "mode" "SI")])
-
-(define_insn_and_split "*lea<mode>_2"
+(define_insn_and_split "*lea<mode>"
   [(set (match_operand:SWI48 0 "register_operand" "=r")
 	(match_operand:SWI48 1 "lea_address_operand" "p"))]
   ""
-  "lea{<imodesuffix>}\t{%E1, %0|%0, %E1}"
+{
+  rtx addr = operands[1];
+
+  if (GET_CODE (addr) == SUBREG)
+    return "lea{l}\t{%E1, %0|%0, %E1}";
+  else if (GET_CODE (addr) == ZERO_EXTEND
+	   || GET_CODE (addr) == AND)
+    return "lea{l}\t{%E1, %k0|%k0, %E1}";
+  else 
+    return "lea{<imodesuffix>}\t{%E1, %0|%0, %E1}";
+}
   "reload_completed && ix86_avoid_lea_for_addr (insn, operands)"
   [(const_int 0)]
 {
@@ -5536,44 +5532,6 @@ 
   [(set_attr "type" "lea")
    (set_attr "mode" "<MODE>")])
 
-(define_insn "*lea_3_zext"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-	(zero_extend:DI
-	  (subreg:SI (match_operand:DI 1 "lea_address_operand" "j") 0)))]
-  "TARGET_64BIT"
-  "lea{l}\t{%E1, %k0|%k0, %E1}"
-  [(set_attr "type" "lea")
-   (set_attr "mode" "SI")])
-
-(define_insn "*lea_4_zext"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-	(zero_extend:DI
-	  (match_operand:SI 1 "lea_address_operand" "j")))]
-  "TARGET_64BIT"
-  "lea{l}\t{%E1, %k0|%k0, %E1}"
-  [(set_attr "type" "lea")
-   (set_attr "mode" "SI")])
-
-(define_insn "*lea_5_zext"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-	(and:DI
-	  (subreg:DI (match_operand:SI 1 "lea_address_operand" "p") 0)
-	  (match_operand:DI 2 "const_32bit_mask" "n")))]
-  "TARGET_64BIT"
-  "lea{l}\t{%E1, %k0|%k0, %E1}"
-  [(set_attr "type" "lea")
-   (set_attr "mode" "SI")])
-
-(define_insn "*lea_6_zext"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-	(and:DI
-	  (match_operand:DI 1 "lea_address_operand" "p")
-	  (match_operand:DI 2 "const_32bit_mask" "n")))]
-  "TARGET_64BIT"
-  "lea{l}\t{%E1, %k0|%k0, %E1}"
-  [(set_attr "type" "lea")
-   (set_attr "mode" "SI")])
-
 (define_insn "*add<mode>_1"
   [(set (match_operand:SWI48 0 "nonimmediate_operand" "=r,rm,r,r")
 	(plus:SWI48