re PR rtl-optimization/67756 (ICE compiling Linux Kernel fs/namei.c on ARM)
authorVladimir Makarov <vmakarov@redhat.com>
Fri, 2 Oct 2015 15:04:59 +0000 (15:04 +0000)
committerVladimir Makarov <vmakarov@gcc.gnu.org>
Fri, 2 Oct 2015 15:04:59 +0000 (15:04 +0000)
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  Vladimir Makarov  <vmakarov@redhat.com>

PR rtl-optimization/67756
* gcc.target/arm/pr67756.c: New.

From-SVN: r228396

gcc/ChangeLog
gcc/lra-constraints.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/arm/pr67756.c [new file with mode: 0644]

index 152872207da37186f9d83f6ca8748aa917329432..b0856aae16c761adb396fb58990807ed61fb74f3 100644 (file)
@@ -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 7764f29f477b78e6fafdc1e8ea8a56471dd1b7ad..2c27f1abfe44600f0b910dbcf8f8649724185eb2 100644 (file)
@@ -855,10 +855,11 @@ narrow_reload_pseudo_class (rtx reg, enum reg_class cl)
    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 char *ins, enum reg_class goal_class,
         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 774f34775d0361c09662f513d796e964f166a491..bceeaaa8b313433b66f2f854917e047543e99e2e 100644 (file)
@@ -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.
diff --git a/gcc/testsuite/gcc.target/arm/pr67756.c b/gcc/testsuite/gcc.target/arm/pr67756.c
new file mode 100644 (file)
index 0000000..9314ff5
--- /dev/null
@@ -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;
+}