Hello!

These problems were found by testing ZERO_EXTENDed addresses with x32
target. The problems were in handling of SUBREGs of parts.base and
parts.index and in usage of "offsetable operand", 'o' operand
constraint.

The patch does not generate zero extended addresses (yet), since there
is a problem in IRA/reload how "offsetable operand" addresses are
handled (I will post separate RFC patch for that).

2011-08-05  Uros Bizjak  <ubiz...@gmail.com>

        * config/i386/i386.md (*push<mode>2): Use "o" constraint instead
        of "m" for operand 0.  Add type and mode attribute.
        (*pushxf_nointeger"): Use "<" constraint for operand 0.
        (*pushdf_rex64): New pattern, split out of *pushdf.  Use "m"
        constraint instead of "o" for opreand 1.
        (*pushdf): Disable for TARGET_64BIT.  Correct mode attribute.

2011-08-05  Uros Bizjak  <ubiz...@gmail.com>

        * config/i386/predicates.md (lea_address_operand): Rename from
        no_seg_address_operand.
        * config/i386/i386.md (*lea_1): Update operand 1 predicate for rename.
        (*lea_1_zext): Ditto.
        (*lea_2): Ditto.
        (*lea_2_zext): Ditto.

2011-08-05  Uros Bizjak  <ubiz...@gmail.com>

        * config/i386/i386.c (ix86_print_operand_address): Handle SUBREGs of
        parts.base and parts.index.
        * config/i386/predicates.md (aligned_operand): Ditto.
        (cmpxchg8b_pic_memory_operand): Ditto.

Patch was tested on x86_64-pc-linux-gnu {,-m32} and was committed to
mainline SVN.

Uros.
Index: i386/i386.md
===================================================================
--- i386/i386.md        (revision 177430)
+++ i386/i386.md        (working copy)
@@ -1648,9 +1648,11 @@
 
 (define_insn "*push<mode>2"
   [(set (match_operand:DWI 0 "push_operand" "=<")
-       (match_operand:DWI 1 "general_no_elim_operand" "riF*m"))]
+       (match_operand:DWI 1 "general_no_elim_operand" "riF*o"))]
   ""
-  "#")
+  "#"
+  [(set_attr "type" "multi")
+   (set_attr "mode" "<MODE>")])
 
 (define_split
   [(set (match_operand:TI 0 "push_operand" "")
@@ -2704,7 +2706,7 @@
 ;; only once, but this ought to be handled elsewhere).
 
 (define_insn "*pushxf_nointeger"
-  [(set (match_operand:XF 0 "push_operand" "=X,X")
+  [(set (match_operand:XF 0 "push_operand" "=<,<")
        (match_operand:XF 1 "general_no_elim_operand" "f,*rFo"))]
   "optimize_function_for_size_p (cfun)"
 {
@@ -2724,6 +2726,18 @@
    (set (mem:XF (reg:P SP_REG)) (match_dup 1))]
   "operands[2] = GEN_INT (-GET_MODE_SIZE (XFmode));")
 
+(define_insn "*pushdf_rex64"
+  [(set (match_operand:DF 0 "push_operand" "=<,<,<")
+       (match_operand:DF 1 "general_no_elim_operand" "f,Yd*rFm,Y2"))]
+  "TARGET_64BIT"
+{
+  /* This insn should be already split before reg-stack.  */
+  gcc_unreachable ();
+}
+  [(set_attr "type" "multi")
+   (set_attr "unit" "i387,*,*")
+   (set_attr "mode" "DF,DI,DF")])
+
 ;; Size of pushdf is 3 (for sub) + 2 (for fstp) + memory operand size.
 ;; Size of pushdf using integer instructions is 2+2*memory operand size
 ;; On the average, pushdf using integers can be still shorter.
@@ -2731,14 +2745,14 @@
 (define_insn "*pushdf"
   [(set (match_operand:DF 0 "push_operand" "=<,<,<")
        (match_operand:DF 1 "general_no_elim_operand" "f,Yd*rFo,Y2"))]
-  ""
+  "!TARGET_64BIT"
 {
   /* This insn should be already split before reg-stack.  */
   gcc_unreachable ();
 }
   [(set_attr "type" "multi")
    (set_attr "unit" "i387,*,*")
-   (set_attr "mode" "DF,SI,DF")])
+   (set_attr "mode" "DF,DI,DF")])
 
 ;; %%% Kill this when call knows how to work this out.
 (define_split
@@ -5431,7 +5445,7 @@
 
 (define_insn "*lea_1"
   [(set (match_operand:SWI48 0 "register_operand" "=r")
-       (match_operand:SWI48 1 "no_seg_address_operand" "p"))]
+       (match_operand:SWI48 1 "lea_address_operand" "p"))]
   ""
   "lea{<imodesuffix>}\t{%a1, %0|%0, %a1}"
   [(set_attr "type" "lea")
@@ -5440,7 +5454,7 @@
 (define_insn "*lea_1_zext"
   [(set (match_operand:DI 0 "register_operand" "=r")
        (zero_extend:DI
-         (match_operand:SI 1 "no_seg_address_operand" "p")))]
+         (match_operand:SI 1 "lea_address_operand" "p")))]
   "TARGET_64BIT"
   "lea{l}\t{%a1, %k0|%k0, %a1}"
   [(set_attr "type" "lea")
@@ -5448,7 +5462,7 @@
 
 (define_insn "*lea_2"
   [(set (match_operand:SI 0 "register_operand" "=r")
-       (subreg:SI (match_operand:DI 1 "no_seg_address_operand" "p") 0))]
+       (subreg:SI (match_operand:DI 1 "lea_address_operand" "p") 0))]
   "TARGET_64BIT"
   "lea{l}\t{%a1, %0|%0, %a1}"
   [(set_attr "type" "lea")
@@ -5457,7 +5471,7 @@
 (define_insn "*lea_2_zext"
   [(set (match_operand:DI 0 "register_operand" "=r")
        (zero_extend:DI
-         (subreg:SI (match_operand:DI 1 "no_seg_address_operand" "p") 0)))]
+         (subreg:SI (match_operand:DI 1 "lea_address_operand" "p") 0)))]
   "TARGET_64BIT"
   "lea{l}\t{%a1, %k0|%k0, %a1}"
   [(set_attr "type" "lea")
Index: i386/predicates.md
===================================================================
--- i386/predicates.md  (revision 177430)
+++ i386/predicates.md  (working copy)
@@ -793,9 +793,9 @@
   (ior (match_operand 0 "register_operand")
        (match_operand 0 "const0_operand")))
 
-;; Return true if op if a valid address, and does not contain
+;; Return true if op if a valid address for LEA, and does not contain
 ;; a segment override.
-(define_predicate "no_seg_address_operand"
+(define_predicate "lea_address_operand"
   (match_operand 0 "address_operand")
 {
   struct ix86_address parts;
@@ -840,6 +840,11 @@
   ok = ix86_decompose_address (op, &parts);
   gcc_assert (ok);
 
+  if (parts.base && GET_CODE (parts.base) == SUBREG)
+    parts.base = SUBREG_REG (parts.base);
+  if (parts.index && GET_CODE (parts.index) == SUBREG)
+    parts.index = SUBREG_REG (parts.index);
+
   /* Look for some component that isn't known to be aligned.  */
   if (parts.index)
     {
@@ -903,6 +908,12 @@
 
   ok = ix86_decompose_address (XEXP (op, 0), &parts);
   gcc_assert (ok);
+
+  if (parts.base && GET_CODE (parts.base) == SUBREG)
+    parts.base = SUBREG_REG (parts.base);
+  if (parts.index && GET_CODE (parts.index) == SUBREG)
+    parts.index = SUBREG_REG (parts.index);
+
   if (parts.base == NULL_RTX
       || parts.base == arg_pointer_rtx
       || parts.base == frame_pointer_rtx
Index: i386/i386.c
===================================================================
--- i386/i386.c (revision 177430)
+++ i386/i386.c (working copy)
@@ -14098,6 +14098,20 @@ ix86_print_operand_address (FILE *file, rtx addr)
 
   gcc_assert (ok);
 
+  if (parts.base && GET_CODE (parts.base) == SUBREG)
+    {
+      rtx tmp = SUBREG_REG (parts.base);
+      parts.base = simplify_subreg (GET_MODE (parts.base),
+                                   tmp, GET_MODE (tmp), 0);
+    }
+
+  if (parts.index && GET_CODE (parts.index) == SUBREG)
+    {
+      rtx tmp = SUBREG_REG (parts.index);
+      parts.index = simplify_subreg (GET_MODE (parts.index),
+                                    tmp, GET_MODE (tmp), 0);
+    }
+
   base = parts.base;
   index = parts.index;
   disp = parts.disp;

Reply via email to