From 599e1cf8b12f6d8d18d024a6f920bbc8fe6282fb Mon Sep 17 00:00:00 2001 From: Vladimir Makarov Date: Fri, 2 Oct 2015 15:04:59 +0000 Subject: [PATCH] re PR rtl-optimization/67756 (ICE compiling Linux Kernel fs/namei.c on ARM) 2015-10-02 Vladimir Makarov 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 PR rtl-optimization/67756 * gcc.target/arm/pr67756.c: New. From-SVN: r228396 --- gcc/ChangeLog | 7 +++ gcc/lra-constraints.c | 32 ++++++++----- gcc/testsuite/ChangeLog | 5 +++ gcc/testsuite/gcc.target/arm/pr67756.c | 62 ++++++++++++++++++++++++++ 4 files changed, 94 insertions(+), 12 deletions(-) create mode 100644 gcc/testsuite/gcc.target/arm/pr67756.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 152872207da..b0856aae16c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2015-10-02 Vladimir Makarov + + 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 * config/i386/i386.c (expand_vec_perm_even_odd_trunc): New. diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c index 7764f29f477..2c27f1abfe4 100644 --- a/gcc/lra-constraints.c +++ b/gcc/lra-constraints.c @@ -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 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 774f34775d0..bceeaaa8b31 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2015-10-02 Vladimir Makarov + + PR rtl-optimization/67756 + * gcc.target/arm/pr67756.c: New. + 2015-10-02 Jiong Wang * 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 index 00000000000..9314ff51e46 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/pr67756.c @@ -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; +}