diff mbox

[gcc-4.8-branch] path to fix PR60769

Message ID 53472941.3020703@redhat.com
State New
Headers show

Commit Message

Vladimir Makarov April 10, 2014, 11:29 p.m. UTC
The following patch fixes

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=60769

   The patch was bootstrapped and tested on x86/x86-64.

   Committed as rev. 209285.

2014-04-10  Vladimir Makarov  <vmakarov@redhat.com>

         PR rtl-optimization/60769
         * lra-constraints.c (simplify_operand_subreg): Force reload of
         paradoxical subreg if it is not in the class contents.

2014-04-10  Vladimir Makarov  <vmakarov@redhat.com>

         PR rtl-optimization/60769
         * g++.dg/pr60769.C: New.
diff mbox

Patch

Index: lra-constraints.c
===================================================================
--- lra-constraints.c	(revision 209283)
+++ lra-constraints.c	(working copy)
@@ -1156,6 +1156,8 @@  simplify_operand_subreg (int nop, enum m
   enum machine_mode mode;
   rtx reg, new_reg;
   rtx operand = *curr_id->operand_loc[nop];
+  enum reg_class regclass;
+  enum op_type type;
 
   before = after = NULL_RTX;
 
@@ -1164,6 +1166,7 @@  simplify_operand_subreg (int nop, enum m
 
   mode = GET_MODE (operand);
   reg = SUBREG_REG (operand);
+  type = curr_static_id->operand[nop].type;
   /* If we change address for paradoxical subreg of memory, the
      address might violate the necessary alignment or the access might
      be slow.  So take this into consideration.  We should not worry
@@ -1236,6 +1239,55 @@  simplify_operand_subreg (int nop, enum m
 			     "Inserting subreg reload");
       return true;
     }
+  /* Force a reload for a paradoxical subreg. For paradoxical subreg,
+     IRA allocates hardreg to the inner pseudo reg according to its mode
+     instead of the outermode, so the size of the hardreg may not be enough
+     to contain the outermode operand, in that case we may need to insert
+     reload for the reg. For the following two types of paradoxical subreg,
+     we need to insert reload:
+     1. If the op_type is OP_IN, and the hardreg could not be paired with
+        other hardreg to contain the outermode operand
+        (checked by in_hard_reg_set_p), we need to insert the reload.
+     2. If the op_type is OP_OUT or OP_INOUT.  */
+  else if (REG_P (reg)
+	   && REGNO (reg) >= FIRST_PSEUDO_REGISTER
+	   && (hard_regno = lra_get_regno_hard_regno (REGNO (reg))) >= 0
+	   && (hard_regno_nregs[hard_regno][GET_MODE (reg)]
+	       < hard_regno_nregs[hard_regno][mode])
+	   && (regclass = lra_get_allocno_class (REGNO (reg)))
+	   && (type != OP_IN
+	       || !in_hard_reg_set_p (reg_class_contents[regclass],
+				      mode, hard_regno)))
+    {
+      /* The class will be defined later in curr_insn_transform.  */
+      enum reg_class rclass
+	= (enum reg_class) targetm.preferred_reload_class (reg, ALL_REGS);
+      rtx subreg;
+      
+      new_reg = lra_create_new_reg_with_unique_value (mode, reg, rclass,
+						      "paradoxical subreg");
+      PUT_MODE (new_reg, mode);
+      subreg = simplify_gen_subreg (GET_MODE (reg), new_reg, mode, 0);
+      if (type != OP_OUT)
+	{
+	  push_to_sequence (before);
+	  lra_emit_move (subreg, reg);
+	  before = get_insns ();
+	  end_sequence ();
+	}
+      if (type != OP_IN)
+	{
+	  start_sequence ();
+	  lra_emit_move (reg, subreg);
+	  emit_insn (after);
+	  after = get_insns ();
+	  end_sequence ();
+	}
+      SUBREG_REG (operand) = new_reg;
+      lra_process_new_insns (curr_insn, before, after,
+                             "Inserting paradoxical subreg reload");
+      return true;
+    }
   return false;
 }
 
Index: testsuite/g++.dg/pr60769.C
===================================================================
--- testsuite/g++.dg/pr60769.C	(revision 0)
+++ testsuite/g++.dg/pr60769.C	(working copy)
@@ -0,0 +1,43 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O" } */
+
+template <class T> void fun(T);
+struct B {};
+struct R {
+  int *x;
+  B f;
+};
+R v(int &, R);
+void rfun(R &);
+struct A {
+  void m_fn2(R p1) {
+    R a = p1;
+    rfun(p1);
+    fun(this);
+    fun(a);
+  }
+};
+struct J {
+  A ep;
+  A ap;
+  int c2a;
+  void m_fn1(R &p2) {
+    R d, e, b;
+    v(c2a, p2);
+    e = v(c2a, b);
+    ap.m_fn2(e);
+    v(c2a, p2);
+    d = v(c2a, b);
+    ep.m_fn2(d);
+  }
+};
+struct N {
+  int &p_;
+  J cfo;
+};
+void fn3(N&n) {
+  R h;
+  n.cfo.m_fn1(h);
+}
+extern N &c;
+void fn1() { fn3(c); }