diff options
author | Yvan Roux <yvan.roux@linaro.org> | 2015-10-29 21:33:58 +0100 |
---|---|---|
committer | Linaro Code Review <review@review.linaro.org> | 2015-10-30 09:17:16 +0000 |
commit | ede2bc0bb8687ec7f0a7039067d700685f162dfa (patch) | |
tree | 314d2e35d9f930119f4432ce83dcccf801a65600 | |
parent | bc579c355a3f0d15576d01fd65c8c6fb3c7f4314 (diff) |
gcc/
Backport from trunk r227382.
2015-09-01 Vladimir Makarov <vmakarov@redhat.com>
PR target/61578
* lra-lives.c (process_bb_lives): Process move pseudos with the
same value for copies and preferences
* lra-constraints.c (match_reload): Create match reload pseudo
with the same value from single dying input pseudo.
gcc/
Backport from trunk r228097.
2015-09-24 Vladimir Makarov <vmakarov@redhat.com>
PR target/61578
* ira-color.c (update_allocno_cost): Add parameter.
(update_costs_from_allocno): Decrease conflict cost. Pass the new
parameter.
gcc/
Backport from trunk r228153.
2015-09-25 Vladimir Makarov <vmakarov@redhat.com>
PR target/61578
* lra-constarints.c (match_reload): Check presence of the input pseudo
in the output pseudo.
gcc/
Backport from trunk r228396.
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.
gcc/testsuite/
Backport from trunk r228396.
2015-10-02 Vladimir Makarov <vmakarov@redhat.com>
PR rtl-optimization/67756
* gcc.target/arm/pr67756.c: New.
gcc/testsuite/
Backport from trunk r228445.
2015-10-03 Bernd Edlinger <bernd.edlinger@hotmail.de>
* gcc.target/arm/pr67756.c: Fixed warnings.
Change-Id: I14c44b8447f4c7d95698b7028273bf3918769900
-rw-r--r-- | gcc/ira-color.c | 25 | ||||
-rw-r--r-- | gcc/lra-constraints.c | 44 | ||||
-rw-r--r-- | gcc/lra-lives.c | 21 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/arm/pr67756.c | 64 |
4 files changed, 127 insertions, 27 deletions
diff --git a/gcc/ira-color.c b/gcc/ira-color.c index e104f00d3ac..cca2a4f26cd 100644 --- a/gcc/ira-color.c +++ b/gcc/ira-color.c @@ -1331,10 +1331,12 @@ get_next_update_cost (ira_allocno_t *allocno, ira_allocno_t *from, int *divisor) return true; } -/* Increase costs of HARD_REGNO by UPDATE_COST for ALLOCNO. Return - true if we really modified the cost. */ +/* Increase costs of HARD_REGNO by UPDATE_COST and conflict cost by + UPDATE_CONFLICT_COST for ALLOCNO. Return true if we really + modified the cost. */ static bool -update_allocno_cost (ira_allocno_t allocno, int hard_regno, int update_cost) +update_allocno_cost (ira_allocno_t allocno, int hard_regno, + int update_cost, int update_conflict_cost) { int i; enum reg_class aclass = ALLOCNO_CLASS (allocno); @@ -1350,7 +1352,7 @@ update_allocno_cost (ira_allocno_t allocno, int hard_regno, int update_cost) (&ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (allocno), aclass, 0, ALLOCNO_CONFLICT_HARD_REG_COSTS (allocno)); ALLOCNO_UPDATED_HARD_REG_COSTS (allocno)[i] += update_cost; - ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (allocno)[i] += update_cost; + ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (allocno)[i] += update_conflict_cost; return true; } @@ -1362,7 +1364,7 @@ static void update_costs_from_allocno (ira_allocno_t allocno, int hard_regno, int divisor, bool decr_p, bool record_p) { - int cost, update_cost; + int cost, update_cost, update_conflict_cost; machine_mode mode; enum reg_class rclass, aclass; ira_allocno_t another_allocno, from = NULL; @@ -1403,11 +1405,20 @@ update_costs_from_allocno (ira_allocno_t allocno, int hard_regno, if (decr_p) cost = -cost; - update_cost = cp->freq * cost / divisor; + update_conflict_cost = update_cost = cp->freq * cost / divisor; + + if (ALLOCNO_COLOR_DATA (another_allocno) != NULL + && (ALLOCNO_COLOR_DATA (allocno)->first_thread_allocno + != ALLOCNO_COLOR_DATA (another_allocno)->first_thread_allocno)) + /* Decrease conflict cost of ANOTHER_ALLOCNO if it is not + in the same allocation thread. */ + update_conflict_cost /= COST_HOP_DIVISOR; + if (update_cost == 0) continue; - if (! update_allocno_cost (another_allocno, hard_regno, update_cost)) + if (! update_allocno_cost (another_allocno, hard_regno, + update_cost, update_conflict_cost)) continue; queue_update_cost (another_allocno, allocno, divisor * COST_HOP_DIVISOR); if (record_p && ALLOCNO_COLOR_DATA (another_allocno) != NULL) diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c index bf153afcbda..d9786c599b9 100644 --- a/gcc/lra-constraints.c +++ b/gcc/lra-constraints.c @@ -867,10 +867,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, clobber; @@ -940,20 +941,34 @@ match_reload (signed char out, signed char *ins, enum reg_class goal_class, they live in the same place. When we create a pseudo we assign value of original pseudo (if any) from which we created the new pseudo. If we create the pseudo from the - input pseudo, the new pseudo will no conflict with the input - pseudo which is wrong when the input pseudo lives after the - insn and as the new pseudo value is changed by the insn - output. Therefore we create the new pseudo from the output. + input pseudo, the new pseudo will have no conflict with the + input pseudo which is wrong when the input pseudo lives after + the insn and as the new pseudo value is changed by the insn + output. Therefore we create the new pseudo from the output + except the case when we have single matched dying input + pseudo. We cannot reuse the current output register because we might 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 - = lra_create_new_reg_with_unique_value (outmode, out_rtx, - goal_class, ""); + = (! 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)) + && (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, + goal_class, "")); } /* In operand can be got from transformations before processing insn constraints. One example of such transformations is subreg @@ -3876,13 +3891,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)) @@ -3892,7 +3912,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/lra-lives.c b/gcc/lra-lives.c index fd9e29cce66..a6846dfc9a4 100644 --- a/gcc/lra-lives.c +++ b/gcc/lra-lives.c @@ -777,28 +777,33 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p) lra_hard_reg_usage[reg->regno] += freq; call_p = CALL_P (curr_insn); + src_regno = (set != NULL_RTX && REG_P (SET_SRC (set)) + ? REGNO (SET_SRC (set)) : -1); + dst_regno = (set != NULL_RTX && REG_P (SET_DEST (set)) + ? REGNO (SET_DEST (set)) : -1); if (complete_info_p - && set != NULL_RTX - && REG_P (SET_DEST (set)) && REG_P (SET_SRC (set)) + && src_regno >= 0 && dst_regno >= 0 /* Check that source regno does not conflict with destination regno to exclude most impossible preferences. */ - && ((((src_regno = REGNO (SET_SRC (set))) >= FIRST_PSEUDO_REGISTER - && ! sparseset_bit_p (pseudos_live, src_regno)) + && (((src_regno >= FIRST_PSEUDO_REGISTER + && (! sparseset_bit_p (pseudos_live, src_regno) + || (dst_regno >= FIRST_PSEUDO_REGISTER + && lra_reg_val_equal_p (src_regno, + lra_reg_info[dst_regno].val, + lra_reg_info[dst_regno].offset)))) || (src_regno < FIRST_PSEUDO_REGISTER && ! TEST_HARD_REG_BIT (hard_regs_live, src_regno))) /* It might be 'inheritance pseudo <- reload pseudo'. */ || (src_regno >= lra_constraint_new_regno_start - && ((int) REGNO (SET_DEST (set)) - >= lra_constraint_new_regno_start) + && dst_regno >= lra_constraint_new_regno_start /* Remember to skip special cases where src/dest regnos are the same, e.g. insn SET pattern has matching constraints like =r,0. */ - && src_regno != (int) REGNO (SET_DEST (set))))) + && src_regno != dst_regno))) { int hard_regno = -1, regno = -1; - dst_regno = REGNO (SET_DEST (set)); if (dst_regno >= lra_constraint_new_regno_start && src_regno >= lra_constraint_new_regno_start) { diff --git a/gcc/testsuite/gcc.target/arm/pr67756.c b/gcc/testsuite/gcc.target/arm/pr67756.c new file mode 100644 index 00000000000..d2e1a8270d6 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/pr67756.c @@ -0,0 +1,64 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target arm_hard_vfp_ok } */ +/* { dg-options "-O2 -mapcs -march=armv7-a -mfloat-abi=hard -mfpu=vfpv3-d16" } */ + +int inode_permission (), try_break_deleg (); +int mutex_lock (), mutex_unlock (); +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; +} |