PATCH, rs6000: fix ABI breakage with -mno-update

Ben Elliston bje@au1.ibm.com
Tue Feb 10 07:32:00 GMT 2009


I discovered that when passing -mno-update on powerpc and powerpc64
targets, GCC dutifully suppresses the use of the store-with-update
instructions in function prologues and for code generated for alloca.
This breaks the PowerPC64 ABI, which requires that the back chain be
updated atomically.

There was code in rs6000.{c,md} that explicitly tested TARGET_UPDATE to
do it one way or the other.  I think this was simply an oversight.  This
patch generates the store-with-update instructions unconditionally when
updating the back chain.

The diff below was generated with diff -w so that it's easier to see the
intent of the changes.  Some of the code nested within an `if' was
re-indented, which made the diff harder to read.  The actual indentation
in my patch is correct.

Tested on powerpc-linux and powerpc64-linux with a full regression test
run.  There were no regressions.  Okay for the trunk, or alternatively,
stage 1?

Thanks, Ben

2009-02-10  Ben Elliston  <bje@au.ibm.com>

        * config/rs6000/rs6000.md (allocate_stack): Always use an update
        form instruction to update the stack back chain word, even if the
        user has disabled the generation of update instructions.
        (movdi_<mode>_update_stack): New.
        (movsi_update_stack): Likewise.
        * config/rs6000/rs6000.c (rs6000_emit_allocate_stack): Likewise,
        always use an update form instruction to update the back chain.

Index: rs6000.c
===================================================================
--- rs6000.c	(revision 144044)
+++ rs6000.c	(working copy)
@@ -15542,6 +15542,7 @@
   rtx stack_reg = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
   rtx tmp_reg = gen_rtx_REG (Pmode, 0);
   rtx todec = gen_int_mode (-size, Pmode);
+  rtx par, set, mem;
 
   if (INTVAL (todec) != -size)
     {
@@ -15585,16 +15586,12 @@
 	warning (0, "stack limit expression is not supported");
     }
 
-  if (copy_r12 || copy_r11 || ! TARGET_UPDATE)
+  if (copy_r12 || copy_r11)
     emit_move_insn (copy_r11
                     ? gen_rtx_REG (Pmode, 11)
                     : gen_rtx_REG (Pmode, 12),
                     stack_reg);
 
-  if (TARGET_UPDATE)
-    {
-      rtx par, set, mem;
-
       if (size > 32767)
 	{
 	  /* Need a note here so that try_split doesn't get confused.  */
@@ -15606,9 +15603,9 @@
 	}
 
       insn = emit_insn (TARGET_32BIT
-			? gen_movsi_update (stack_reg, stack_reg,
+		    ? gen_movsi_update_stack (stack_reg, stack_reg,
 					    todec, stack_reg)
-			: gen_movdi_di_update (stack_reg, stack_reg,
+		    : gen_movdi_di_update_stack (stack_reg, stack_reg,
 					    todec, stack_reg));
       /* Since we didn't use gen_frame_mem to generate the MEM, grab
 	 it now and set the alias set/attributes. The above gen_*_update
@@ -15622,17 +15619,6 @@
       gcc_assert (MEM_P (mem));
       MEM_NOTRAP_P (mem) = 1;
       set_mem_alias_set (mem, get_frame_alias_set ());
-    }
-  else
-    {
-      insn = emit_insn (TARGET_32BIT
-			? gen_addsi3 (stack_reg, stack_reg, todec)
-			: gen_adddi3 (stack_reg, stack_reg, todec));
-      emit_move_insn (gen_frame_mem (Pmode, stack_reg),
-		      copy_r11
-                      ? gen_rtx_REG (Pmode, 11)
-                      : gen_rtx_REG (Pmode, 12));
-    }
 
   RTX_FRAME_RELATED_P (insn) = 1;
   REG_NOTES (insn) =
Index: rs6000.md
===================================================================
--- rs6000.md	(revision 144044)
+++ rs6000.md	(working copy)
@@ -10079,6 +10079,20 @@
    stdu %3,%2(%0)"
   [(set_attr "type" "store_ux,store_u")])
 
+;; This pattern is only conditional on TARGET_POWERPC64, as it is
+;; needed for stack allocation, even if the user passes -mno-update.
+(define_insn "movdi_<mode>_update_stack"
+  [(set (mem:DI (plus:P (match_operand:P 1 "gpc_reg_operand" "0,0")
+			 (match_operand:P 2 "reg_or_aligned_short_operand" "r,I")))
+	(match_operand:DI 3 "gpc_reg_operand" "r,r"))
+   (set (match_operand:P 0 "gpc_reg_operand" "=b,b")
+	(plus:P (match_dup 1) (match_dup 2)))]
+  "TARGET_POWERPC64"
+  "@
+   stdux %3,%0,%2
+   stdu %3,%2(%0)"
+  [(set_attr "type" "store_ux,store_u")])
+
 (define_insn "*movsi_update1"
   [(set (match_operand:SI 3 "gpc_reg_operand" "=r,r")
 	(mem:SI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
@@ -10121,6 +10135,20 @@
    {stu|stwu} %3,%2(%0)"
   [(set_attr "type" "store_ux,store_u")])
 
+;; This is an unconditional pattern; needed for stack allocation, even
+;; if the user passes -mno-update.
+(define_insn "movsi_update_stack"
+  [(set (mem:SI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
+			 (match_operand:SI 2 "reg_or_short_operand" "r,I")))
+	(match_operand:SI 3 "gpc_reg_operand" "r,r"))
+   (set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
+	(plus:SI (match_dup 1) (match_dup 2)))]
+  ""
+  "@
+   {stux|stwux} %3,%0,%2
+   {stu|stwu} %3,%2(%0)"
+  [(set_attr "type" "store_ux,store_u")])
+
 (define_insn "*movhi_update1"
   [(set (match_operand:HI 3 "gpc_reg_operand" "=r,r")
 	(mem:HI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
@@ -10543,6 +10571,7 @@
 { rtx chain = gen_reg_rtx (Pmode);
   rtx stack_bot = gen_rtx_MEM (Pmode, stack_pointer_rtx);
   rtx neg_op0;
+  rtx insn, par, set, mem;
 
   emit_move_insn (chain, stack_bot);
 
@@ -10569,10 +10598,6 @@
   else
     neg_op0 = GEN_INT (- INTVAL (operands[1]));
 
-  if (TARGET_UPDATE)
-    {
-      rtx insn, par, set, mem;
-
       insn = emit_insn ((* ((TARGET_32BIT) ? gen_movsi_update
 					   : gen_movdi_di_update))
 			(stack_pointer_rtx, stack_pointer_rtx, neg_op0,
@@ -10589,15 +10614,7 @@
       gcc_assert (MEM_P (mem));
       MEM_NOTRAP_P (mem) = 1;
       set_mem_alias_set (mem, get_frame_alias_set ());
-    }
 
-  else
-    {
-      emit_insn ((* ((TARGET_32BIT) ? gen_addsi3 : gen_adddi3))
-		 (stack_pointer_rtx, stack_pointer_rtx, neg_op0));
-      emit_move_insn (gen_frame_mem (Pmode, stack_pointer_rtx), chain);
-    }
-
   emit_move_insn (operands[0], virtual_stack_dynamic_rtx);
   DONE;
 }")




More information about the Gcc-patches mailing list