diff mbox

patch to fix PR657756

Message ID 560E9E43.40509@redhat.com
State New
Headers show

Commit Message

Vladimir Makarov Oct. 2, 2015, 3:09 p.m. UTC
The following patch fixes

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67756

   The patch was bootstrapped and tested on x86-64.

Committed as rev. 228396.
diff mbox

Patch

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 228395)
+++ ChangeLog	(working copy)
@@ -1,3 +1,10 @@ 
+2015-10-02  Vladimir Makarov  <vmakarov@redhat.com>
+
+	PR rtl-optimization/67756
+	* lra-constraints.c (match_reload): Add a new parameter.  Use it
+	for creating a pseudo with the same value.
+	(curr_insn_transform): Pass a new argument to match_reload.
+
 2015-10-02  Kirill Yukhin  <kirill.yukhin@intel.com>
 
 	* config/i386/i386.c (expand_vec_perm_even_odd_trunc): New.
Index: lra-constraints.c
===================================================================
--- lra-constraints.c	(revision 228347)
+++ lra-constraints.c	(working copy)
@@ -855,10 +855,11 @@  narrow_reload_pseudo_class (rtx reg, enu
    numbers with end marker -1) with reg class GOAL_CLASS.  Add input
    and output reloads correspondingly to the lists *BEFORE and *AFTER.
    OUT might be negative.  In this case we generate input reloads for
-   matched input operands INS.  */
+   matched input operands INS.  EARLY_CLOBBER_P is a flag that the
+   output operand is early clobbered for chosen alternative.  */
 static void
 match_reload (signed char out, signed char *ins, enum reg_class goal_class,
-	      rtx_insn **before, rtx_insn **after)
+	      rtx_insn **before, rtx_insn **after, bool early_clobber_p)
 {
   int i, in;
   rtx new_in_reg, new_out_reg, reg;
@@ -939,17 +940,19 @@  match_reload (signed char out, signed ch
 	 have a situation like "a <- a op b", where the constraints
 	 force the second input operand ("b") to match the output
 	 operand ("a").  "b" must then be copied into a new register
-	 so that it doesn't clobber the current value of "a".  */
+	 so that it doesn't clobber the current value of "a".
+
+	 We can not use the same value if the output pseudo is
+	 early clobbered or the input pseudo is mentioned in the
+	 output, e.g. as an address part in memory, because
+	 output reload will actually extend the pseudo liveness.
+	 We don't care about eliminable hard regs here as we are
+	 interesting only in pseudos.  */
 
       new_in_reg = new_out_reg
-	= (ins[1] < 0 && REG_P (in_rtx)
+	= (! early_clobber_p && ins[1] < 0 && REG_P (in_rtx)
 	   && (int) REGNO (in_rtx) < lra_new_regno_start
 	   && find_regno_note (curr_insn, REG_DEAD, REGNO (in_rtx))
-	   /* We can not use the same value if the pseudo is mentioned
-	      in the output, e.g. as an address part in memory,
-	      becuase output reload will actually extend the pseudo
-	      liveness.  We don't care about eliminable hard regs here
-	      as we are interesting only in pseudos.  */
 	   && (out < 0 || regno_use_in (REGNO (in_rtx), out_rtx) == NULL_RTX)
 	   ? lra_create_new_reg (inmode, in_rtx, goal_class, "")
 	   : lra_create_new_reg_with_unique_value (outmode, out_rtx,
@@ -3867,13 +3870,18 @@  curr_insn_transform (bool check_only_p)
 	  match_inputs[0] = i;
 	  match_inputs[1] = -1;
 	  match_reload (goal_alt_matched[i][0], match_inputs,
-			goal_alt[i], &before, &after);
+			goal_alt[i], &before, &after,
+			curr_static_id->operand_alternative
+			[goal_alt_number * n_operands + goal_alt_matched[i][0]]
+			.earlyclobber);
 	}
       else if (curr_static_id->operand[i].type == OP_OUT
 	       && (curr_static_id->operand[goal_alt_matched[i][0]].type
 		   == OP_IN))
 	/* Generate reloads for output and matched inputs.  */
-	match_reload (i, goal_alt_matched[i], goal_alt[i], &before, &after);
+	match_reload (i, goal_alt_matched[i], goal_alt[i], &before, &after,
+		      curr_static_id->operand_alternative
+		      [goal_alt_number * n_operands + i].earlyclobber);
       else if (curr_static_id->operand[i].type == OP_IN
 	       && (curr_static_id->operand[goal_alt_matched[i][0]].type
 		   == OP_IN))
@@ -3883,7 +3891,7 @@  curr_insn_transform (bool check_only_p)
 	  for (j = 0; (k = goal_alt_matched[i][j]) >= 0; j++)
 	    match_inputs[j + 1] = k;
 	  match_inputs[j + 1] = -1;
-	  match_reload (-1, match_inputs, goal_alt[i], &before, &after);
+	  match_reload (-1, match_inputs, goal_alt[i], &before, &after, false);
 	}
       else
 	/* We must generate code in any case when function
Index: testsuite/ChangeLog
===================================================================
--- testsuite/ChangeLog	(revision 228395)
+++ testsuite/ChangeLog	(working copy)
@@ -1,3 +1,8 @@ 
+2015-10-02  Vladimir Makarov  <vmakarov@redhat.com>
+
+	PR rtl-optimization/67756
+	* gcc.target/arm/pr67756.c: New.
+
 2015-10-02  Jiong Wang  <jiong.wang@arm.com>
 
 	* gcc.target/aarch64/tlsle12_tiny_1.c: New testcase for tiny model.
Index: testsuite/gcc.target/arm/pr67756.c
===================================================================
--- testsuite/gcc.target/arm/pr67756.c	(revision 0)
+++ testsuite/gcc.target/arm/pr67756.c	(working copy)
@@ -0,0 +1,62 @@ 
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_hard_vfp_ok } */
+/* { dg-options "-O2 -mapcs -march=armv7-a -mfloat-abi=hard -mfpu=vfpv3-d16" } */
+
+struct mutex
+{
+};
+struct dentry
+{
+  struct inode *d_inode;
+};
+struct inode
+{
+  const struct inode_operations *i_op;
+  struct super_block *i_sb;
+    union
+    {
+      const unsigned int i_nlink;
+    };
+  unsigned long i_state;
+  struct mutex i_mutex;
+};
+struct super_block
+{
+  unsigned int s_max_links;
+};
+struct inode_operations
+{
+  int (*link) (struct dentry *, struct inode *, struct dentry *);
+} __attribute__ ((__aligned__ ((1 << 6))));
+static inline __attribute__ ((always_inline))
+__attribute__ ((no_instrument_function))
+int may_create (struct inode *dir, struct dentry *child)
+{
+  if (child->d_inode)
+    return -17;
+  return inode_permission (dir, 0x00000002 | 0x00000001);
+}
+
+int
+vfs_link (struct dentry *old_dentry, struct inode *dir,
+	  struct dentry *new_dentry, struct inode **delegated_inode)
+{
+  struct inode *inode = old_dentry->d_inode;
+  unsigned max_links = dir->i_sb->s_max_links;
+  int error;
+  error = may_create (dir, new_dentry);
+  if (error)
+    return error;
+  mutex_lock (&inode->i_mutex);
+  if (inode->i_nlink == 0 && !(inode->i_state & (1 << 10)))
+    error = -2;
+  else if (max_links && inode->i_nlink >= max_links)
+    error = -31;
+  else
+    {
+      error = try_break_deleg (inode, delegated_inode);
+      error = dir->i_op->link (old_dentry, dir, new_dentry);
+    }
+  mutex_unlock (&inode->i_mutex);
+  return error;
+}