PR debug/25023
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 13 Dec 2005 08:08:46 +0000 (08:08 +0000)
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 13 Dec 2005 08:08:46 +0000 (08:08 +0000)
PR target/25293
* expr.c (emit_move_resolve_push): Handle PRE_MODIFY
and POST_MODIFY with CONST_INT adjustment equal to PUSH_ROUNDING.
Fix POST_INC/POST_DEC handling if PUSH_ROUNDING is not identity.
* config/i386/i386.md (pushhi2, pushqi2): Use pushl instead of pushw.
Set mode to SI, adjust constraints.
(pushhi2_rex64, pushqi2_rex64): Set mode to DI.
* config/i386/i386.h (PUSH_ROUNDING): Round up to 4 instead of 2 for
32-bit code.

* gcc.target/i386/pr25293.c: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@108463 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/i386/i386.h
gcc/config/i386/i386.md
gcc/expr.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/i386/pr25293.c [new file with mode: 0644]

index 222bda4..cc2131f 100644 (file)
@@ -1,3 +1,16 @@
+2005-12-13  Jakub Jelinek  <jakub@redhat.com>
+
+       PR debug/25023
+       PR target/25293
+       * expr.c (emit_move_resolve_push): Handle PRE_MODIFY
+       and POST_MODIFY with CONST_INT adjustment equal to PUSH_ROUNDING.
+       Fix POST_INC/POST_DEC handling if PUSH_ROUNDING is not identity.
+       * config/i386/i386.md (pushhi2, pushqi2): Use pushl instead of pushw.
+       Set mode to SI, adjust constraints.
+       (pushhi2_rex64, pushqi2_rex64): Set mode to DI.
+       * config/i386/i386.h (PUSH_ROUNDING): Round up to 4 instead of 2 for
+       32-bit code.
+
 2005-12-13  Carlos O'Donell <carlos@codesourcery.com>
 
        * c-cppbuiltin.c (builtin_define_float_constants): Add
index e0dbd6b..de29adb 100644 (file)
@@ -1374,9 +1374,10 @@ enum reg_class
 
 /* If we generate an insn to push BYTES bytes,
    this says how many the stack pointer really advances by.
-   On 386 pushw decrements by exactly 2 no matter what the position was.
-   On the 386 there is no pushb; we use pushw instead, and this
-   has the effect of rounding up to 2.
+   On 386, we have pushw instruction that decrements by exactly 2 no
+   matter what the position was, there is no pushb.
+   But as CIE data alignment factor on this arch is -4, we need to make
+   sure all stack pointer adjustments are in multiple of 4.
 
    For 64bit ABI we round up to 8 bytes.
  */
@@ -1384,7 +1385,7 @@ enum reg_class
 #define PUSH_ROUNDING(BYTES) \
   (TARGET_64BIT                     \
    ? (((BYTES) + 7) & (-8))  \
-   : (((BYTES) + 1) & (-2)))
+   : (((BYTES) + 3) & (-4)))
 
 /* If defined, the maximum amount of space required for outgoing arguments will
    be computed and placed into the variable
index d0bfc8a..4498319 100644 (file)
   "ix86_expand_move (HImode, operands); DONE;")
 
 (define_insn "*pushhi2"
-  [(set (match_operand:HI 0 "push_operand" "=<,<")
-       (match_operand:HI 1 "general_no_elim_operand" "n,r*m"))]
+  [(set (match_operand:HI 0 "push_operand" "=X")
+       (match_operand:HI 1 "nonmemory_no_elim_operand" "rn"))]
   "!TARGET_64BIT"
-  "@
-   push{w}\t{|WORD PTR }%1
-   push{w}\t%1"
+  "push{l}\t%k1"
   [(set_attr "type" "push")
-   (set_attr "mode" "HI")])
+   (set_attr "mode" "SI")])
 
 ;; For 64BIT abi we always round up to 8 bytes.
 (define_insn "*pushhi2_rex64"
   "TARGET_64BIT"
   "push{q}\t%q1"
   [(set_attr "type" "push")
-   (set_attr "mode" "QI")])
+   (set_attr "mode" "DI")])
 
 (define_insn "*movhi_1"
   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m")
   "ix86_expand_move (QImode, operands); DONE;")
 
 ;; emit_push_insn when it calls move_by_pieces requires an insn to
-;; "push a byte".  But actually we use pushw, which has the effect
-;; of rounding the amount pushed up to a halfword.
+;; "push a byte".  But actually we use pushl, which has the effect
+;; of rounding the amount pushed up to a word.
 
 (define_insn "*pushqi2"
-  [(set (match_operand:QI 0 "push_operand" "=X,X")
-       (match_operand:QI 1 "nonmemory_no_elim_operand" "n,r"))]
+  [(set (match_operand:QI 0 "push_operand" "=X")
+       (match_operand:QI 1 "nonmemory_no_elim_operand" "rn"))]
   "!TARGET_64BIT"
-  "@
-   push{w}\t{|word ptr }%1
-   push{w}\t%w1"
+  "push{l}\t%k1"
   [(set_attr "type" "push")
-   (set_attr "mode" "HI")])
+   (set_attr "mode" "SI")])
 
 ;; For 64BIT abi we always round up to 8 bytes.
 (define_insn "*pushqi2_rex64"
   "TARGET_64BIT"
   "push{q}\t%q1"
   [(set_attr "type" "push")
-   (set_attr "mode" "QI")])
+   (set_attr "mode" "DI")])
 
 ;; Situation is quite tricky about when to choose full sized (SImode) move
 ;; over QImode moves.  For Q_REG -> Q_REG move we use full size only for
index de66a0d..2e26ef0 100644 (file)
@@ -2852,6 +2852,19 @@ emit_move_resolve_push (enum machine_mode mode, rtx x)
 #endif
   if (code == PRE_DEC || code == POST_DEC)
     adjust = -adjust;
+  else if (code == PRE_MODIFY || code == POST_MODIFY)
+    {
+      rtx expr = XEXP (XEXP (x, 0), 1);
+      HOST_WIDE_INT val;
+
+      gcc_assert (GET_CODE (expr) == PLUS || GET_CODE (expr) == MINUS);
+      gcc_assert (GET_CODE (XEXP (expr, 1)) == CONST_INT);
+      val = INTVAL (XEXP (expr, 1));
+      if (GET_CODE (expr) == MINUS)
+       val = -val;
+      gcc_assert (adjust == val || adjust == -val);
+      adjust = val;
+    }
 
   /* Do not use anti_adjust_stack, since we don't want to update
      stack_pointer_delta.  */
@@ -2865,13 +2878,13 @@ emit_move_resolve_push (enum machine_mode mode, rtx x)
     {
     case PRE_INC:
     case PRE_DEC:
+    case PRE_MODIFY:
       temp = stack_pointer_rtx;
       break;
     case POST_INC:
-      temp = plus_constant (stack_pointer_rtx, -GET_MODE_SIZE (mode));
-      break;
     case POST_DEC:
-      temp = plus_constant (stack_pointer_rtx, GET_MODE_SIZE (mode));
+    case POST_MODIFY:
+      temp = plus_constant (stack_pointer_rtx, -adjust);
       break;
     default:
       gcc_unreachable ();
index ce14f6a..5b71d70 100644 (file)
@@ -1,3 +1,9 @@
+2005-12-13  Jakub Jelinek  <jakub@redhat.com>
+
+       PR debug/25023
+       PR target/25293
+       * gcc.target/i386/pr25293.c: New test.
+
 2005-12-13  Petr Machata  <machata@post.cz>
 
        PR c++/24907
diff --git a/gcc/testsuite/gcc.target/i386/pr25293.c b/gcc/testsuite/gcc.target/i386/pr25293.c
new file mode 100644 (file)
index 0000000..6217da2
--- /dev/null
@@ -0,0 +1,51 @@
+/* PR target/25293 */
+/* { dg-do compile } */
+/* { dg-options "-mpreferred-stack-boundary=2 -mtune=i586 -O2 -fomit-frame-pointer -g" } */
+/* { dg-require-effective-target ilp32 } */
+
+struct T { unsigned short t1, t2, t3, t4, t5, t6, t7; };
+struct S { struct T s1; unsigned short s2, s3; };
+unsigned short v1;
+int f1 (void);
+int f2 (struct T);
+int f3 (const char *);
+
+int
+foo (struct S *x, struct T y)
+{
+  unsigned short a, b, c;
+  unsigned long d, e;
+  int f = 0;
+  y.t6 = 6;
+  a = y.t7;
+  b = y.t6;
+  c = y.t7;
+  switch (a)
+    {
+    case 8:
+    case 7:
+      c = 9;
+      break;
+    case 1:
+    case 6:
+    case 3:
+      b = 16;
+      c = 9;
+      break;
+    }
+  if ((f = f1 ()))
+    goto error;
+  if ((f = f2 (y)))
+    goto error;
+  d = (long) &y;
+  e = (long) &x->s1;
+  __asm __volatile ("" : "+D" (e), "+S" (d) :: "memory");
+  x->s2 = b;
+  x->s3 = c;
+  f3 ("foo");
+  return 0;
+error:
+  if (v1 >= 1)
+    f3 ("bar");
+  return f;
+}