OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / explow.c
index beeab44..a635c7f 100644 (file)
@@ -384,18 +384,23 @@ convert_memory_address_addr_space (enum machine_mode to_mode ATTRIBUTE_UNUSED,
 
     case PLUS:
     case MULT:
-      /* For addition we can safely permute the conversion and addition
-        operation if one operand is a constant and converting the constant
-        does not change it or if one operand is a constant and we are
-        using a ptr_extend instruction  (POINTERS_EXTEND_UNSIGNED < 0).
+      /* FIXME: For addition, we used to permute the conversion and
+        addition operation only if one operand is a constant and
+        converting the constant does not change it or if one operand
+        is a constant and we are using a ptr_extend instruction
+        (POINTERS_EXTEND_UNSIGNED < 0) even if the resulting address
+        may overflow/underflow.  We relax the condition to include
+        zero-extend (POINTERS_EXTEND_UNSIGNED > 0) since the other
+        parts of the compiler depend on it.  See PR 49721.
+
         We can always safely permute them if we are making the address
         narrower.  */
       if (GET_MODE_SIZE (to_mode) < GET_MODE_SIZE (from_mode)
          || (GET_CODE (x) == PLUS
              && CONST_INT_P (XEXP (x, 1))
-             && (XEXP (x, 1) == convert_memory_address_addr_space
-                                  (to_mode, XEXP (x, 1), as)
-                 || POINTERS_EXTEND_UNSIGNED < 0)))
+             && (POINTERS_EXTEND_UNSIGNED != 0
+                 || XEXP (x, 1) == convert_memory_address_addr_space
+                                       (to_mode, XEXP (x, 1), as))))
        return gen_rtx_fmt_ee (GET_CODE (x), to_mode,
                               convert_memory_address_addr_space
                                 (to_mode, XEXP (x, 0), as),
@@ -1057,6 +1062,20 @@ emit_stack_restore (enum save_level save_level, rtx sa)
   /* The default is that we use a move insn.  */
   rtx (*fcn) (rtx, rtx) = gen_move_insn;
 
+  /* If stack_realign_drap, the x86 backend emits a prologue that aligns both
+     STACK_POINTER and HARD_FRAME_POINTER.
+     If stack_realign_fp, the x86 backend emits a prologue that aligns only
+     STACK_POINTER. This renders the HARD_FRAME_POINTER unusable for accessing
+     aligned variables, which is reflected in ix86_can_eliminate.
+     We normally still have the realigned STACK_POINTER that we can use.
+     But if there is a stack restore still present at reload, it can trigger 
+     mark_not_eliminable for the STACK_POINTER, leaving no way to eliminate
+     FRAME_POINTER into a hard reg.
+     To prevent this situation, we force need_drap if we emit a stack
+     restore.  */
+  if (SUPPORTS_STACK_ALIGNMENT)
+    crtl->need_drap = true;
+
   /* See if this machine has anything special to do for this kind of save.  */
   switch (save_level)
     {
@@ -1545,22 +1564,21 @@ probe_stack_range (HOST_WIDE_INT first, rtx size)
                                                 plus_constant (size, first)));
       emit_library_call (stack_check_libfunc, LCT_NORMAL, VOIDmode, 1, addr,
                         Pmode);
-      return;
     }
 
   /* Next see if we have an insn to check the stack.  */
 #ifdef HAVE_check_stack
-  if (HAVE_check_stack)
+  else if (HAVE_check_stack)
     {
       struct expand_operand ops[1];
       rtx addr = memory_address (Pmode,
                                 gen_rtx_fmt_ee (STACK_GROW_OP, Pmode,
                                                 stack_pointer_rtx,
                                                 plus_constant (size, first)));
-
+      bool success;
       create_input_operand (&ops[0], addr, Pmode);
-      if (maybe_expand_insn (CODE_FOR_check_stack, 1, ops))
-       return;
+      success = maybe_expand_insn (CODE_FOR_check_stack, 1, ops);
+      gcc_assert (success);
     }
 #endif