Commit 15961e4a by Vladimir Makarov Committed by Vladimir Makarov

re PR target/79131 (ICE: in extract_constrain_insn, at recog.c:2213, big-endian ARM)

2017-01-26  Vladimir Makarov  <vmakarov@redhat.com>

	PR target/79131
	* lra-assigns.c (setup_live_pseudos_and_spill_after_risky): Take
	endianess for subregs into account.
	* lra-constraints.c (lra_constraints): Do risky transformations
	always on the first iteration.
	* lra-lives.c (check_pseudos_live_through_calls): Add arg
	last_call_used_reg_set.
	(process_bb_lives): Define and use last_call_used_reg_set.
	* lra.c (lra): Always continue after lra_constraints on the first
	iteration.

2017-01-26  Vladimir Makarov  <vmakarov@redhat.com>

	PR target/79131
	* gcc.target/arm/pr79131.c: New.

From-SVN: r244942
parent b63144aa
2017-01-26 Vladimir Makarov <vmakarov@redhat.com>
PR target/79131
* lra-assigns.c (setup_live_pseudos_and_spill_after_risky): Take
endianess for subregs into account.
* lra-constraints.c (lra_constraints): Do risky transformations
always on the first iteration.
* lra-lives.c (check_pseudos_live_through_calls): Add arg
last_call_used_reg_set.
(process_bb_lives): Define and use last_call_used_reg_set.
* lra.c (lra): Always continue after lra_constraints on the first
iteration.
2017-01-26 Kirill Yukhin <kirill.yukhin@gmail.com> 2017-01-26 Kirill Yukhin <kirill.yukhin@gmail.com>
* gcc.target/i386/avx512bw-kshiftlq-2.c: Use unsigned long long * gcc.target/i386/avx512bw-kshiftlq-2.c: Use unsigned long long
......
...@@ -1179,9 +1179,19 @@ setup_live_pseudos_and_spill_after_risky_transforms (bitmap ...@@ -1179,9 +1179,19 @@ setup_live_pseudos_and_spill_after_risky_transforms (bitmap
/* If it is multi-register pseudos they should start on /* If it is multi-register pseudos they should start on
the same hard register. */ the same hard register. */
|| hard_regno != reg_renumber[conflict_regno]) || hard_regno != reg_renumber[conflict_regno])
add_to_hard_reg_set (&conflict_set, {
lra_reg_info[conflict_regno].biggest_mode, int conflict_hard_regno = reg_renumber[conflict_regno];
reg_renumber[conflict_regno]); machine_mode biggest_mode = lra_reg_info[conflict_regno].biggest_mode;
int biggest_nregs = hard_regno_nregs[conflict_hard_regno][biggest_mode];
int nregs_diff = (biggest_nregs
- (hard_regno_nregs
[conflict_hard_regno]
[PSEUDO_REGNO_MODE (conflict_regno)]));
add_to_hard_reg_set (&conflict_set,
biggest_mode,
conflict_hard_regno
- (WORDS_BIG_ENDIAN ? nregs_diff : 0));
}
if (! overlaps_hard_reg_set_p (conflict_set, mode, hard_regno)) if (! overlaps_hard_reg_set_p (conflict_set, mode, hard_regno))
{ {
update_lives (regno, false); update_lives (regno, false);
......
...@@ -4511,7 +4511,10 @@ lra_constraints (bool first_p) ...@@ -4511,7 +4511,10 @@ lra_constraints (bool first_p)
&& REGNO (pic_offset_table_rtx) >= FIRST_PSEUDO_REGISTER) && REGNO (pic_offset_table_rtx) >= FIRST_PSEUDO_REGISTER)
lra_risky_transformations_p = true; lra_risky_transformations_p = true;
else else
lra_risky_transformations_p = false; /* On the first iteration we should check IRA assignment
correctness. In rare cases, the assignments can be wrong as
early clobbers operands are ignored in IRA. */
lra_risky_transformations_p = first_p;
new_insn_uid_start = get_max_uid (); new_insn_uid_start = get_max_uid ();
new_regno_start = first_p ? lra_constraint_new_regno_start : max_reg_num (); new_regno_start = first_p ? lra_constraint_new_regno_start : max_reg_num ();
/* Mark used hard regs for target stack size calulations. */ /* Mark used hard regs for target stack size calulations. */
......
...@@ -560,10 +560,11 @@ lra_setup_reload_pseudo_preferenced_hard_reg (int regno, ...@@ -560,10 +560,11 @@ lra_setup_reload_pseudo_preferenced_hard_reg (int regno,
} }
/* Check that REGNO living through calls and setjumps, set up conflict /* Check that REGNO living through calls and setjumps, set up conflict
regs, and clear corresponding bits in PSEUDOS_LIVE_THROUGH_CALLS and regs using LAST_CALL_USED_REG_SET, and clear corresponding bits in
PSEUDOS_LIVE_THROUGH_SETJUMPS. */ PSEUDOS_LIVE_THROUGH_CALLS and PSEUDOS_LIVE_THROUGH_SETJUMPS. */
static inline void static inline void
check_pseudos_live_through_calls (int regno) check_pseudos_live_through_calls (int regno,
HARD_REG_SET last_call_used_reg_set)
{ {
int hr; int hr;
...@@ -571,7 +572,7 @@ check_pseudos_live_through_calls (int regno) ...@@ -571,7 +572,7 @@ check_pseudos_live_through_calls (int regno)
return; return;
sparseset_clear_bit (pseudos_live_through_calls, regno); sparseset_clear_bit (pseudos_live_through_calls, regno);
IOR_HARD_REG_SET (lra_reg_info[regno].conflict_hard_regs, IOR_HARD_REG_SET (lra_reg_info[regno].conflict_hard_regs,
call_used_reg_set); last_call_used_reg_set);
for (hr = 0; hr < FIRST_PSEUDO_REGISTER; hr++) for (hr = 0; hr < FIRST_PSEUDO_REGISTER; hr++)
if (HARD_REGNO_CALL_PART_CLOBBERED (hr, PSEUDO_REGNO_MODE (regno))) if (HARD_REGNO_CALL_PART_CLOBBERED (hr, PSEUDO_REGNO_MODE (regno)))
...@@ -604,11 +605,13 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p) ...@@ -604,11 +605,13 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p)
rtx_insn *next; rtx_insn *next;
rtx link, *link_loc; rtx link, *link_loc;
bool need_curr_point_incr; bool need_curr_point_incr;
HARD_REG_SET last_call_used_reg_set;
reg_live_out = df_get_live_out (bb); reg_live_out = df_get_live_out (bb);
sparseset_clear (pseudos_live); sparseset_clear (pseudos_live);
sparseset_clear (pseudos_live_through_calls); sparseset_clear (pseudos_live_through_calls);
sparseset_clear (pseudos_live_through_setjumps); sparseset_clear (pseudos_live_through_setjumps);
CLEAR_HARD_REG_SET (last_call_used_reg_set);
REG_SET_TO_HARD_REG_SET (hard_regs_live, reg_live_out); REG_SET_TO_HARD_REG_SET (hard_regs_live, reg_live_out);
AND_COMPL_HARD_REG_SET (hard_regs_live, eliminable_regset); AND_COMPL_HARD_REG_SET (hard_regs_live, eliminable_regset);
EXECUTE_IF_SET_IN_BITMAP (reg_live_out, FIRST_PSEUDO_REGISTER, j, bi) EXECUTE_IF_SET_IN_BITMAP (reg_live_out, FIRST_PSEUDO_REGISTER, j, bi)
...@@ -795,7 +798,8 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p) ...@@ -795,7 +798,8 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p)
need_curr_point_incr need_curr_point_incr
|= mark_regno_live (reg->regno, reg->biggest_mode, |= mark_regno_live (reg->regno, reg->biggest_mode,
curr_point); curr_point);
check_pseudos_live_through_calls (reg->regno); check_pseudos_live_through_calls (reg->regno,
last_call_used_reg_set);
} }
for (reg = curr_static_id->hard_regs; reg != NULL; reg = reg->next) for (reg = curr_static_id->hard_regs; reg != NULL; reg = reg->next)
...@@ -831,15 +835,27 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p) ...@@ -831,15 +835,27 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p)
if (call_p) if (call_p)
{ {
if (flag_ipa_ra) if (! flag_ipa_ra)
COPY_HARD_REG_SET(last_call_used_reg_set, call_used_reg_set);
else
{ {
HARD_REG_SET this_call_used_reg_set; HARD_REG_SET this_call_used_reg_set;
get_call_reg_set_usage (curr_insn, &this_call_used_reg_set, get_call_reg_set_usage (curr_insn, &this_call_used_reg_set,
call_used_reg_set); call_used_reg_set);
bool flush = (! hard_reg_set_empty_p (last_call_used_reg_set)
&& ! hard_reg_set_equal_p (last_call_used_reg_set,
this_call_used_reg_set));
EXECUTE_IF_SET_IN_SPARSESET (pseudos_live, j) EXECUTE_IF_SET_IN_SPARSESET (pseudos_live, j)
IOR_HARD_REG_SET (lra_reg_info[j].actual_call_used_reg_set, {
this_call_used_reg_set); IOR_HARD_REG_SET (lra_reg_info[j].actual_call_used_reg_set,
this_call_used_reg_set);
if (flush)
check_pseudos_live_through_calls
(j, last_call_used_reg_set);
}
COPY_HARD_REG_SET(last_call_used_reg_set, this_call_used_reg_set);
} }
sparseset_ior (pseudos_live_through_calls, sparseset_ior (pseudos_live_through_calls,
...@@ -866,7 +882,8 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p) ...@@ -866,7 +882,8 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p)
need_curr_point_incr need_curr_point_incr
|= mark_regno_live (reg->regno, reg->biggest_mode, |= mark_regno_live (reg->regno, reg->biggest_mode,
curr_point); curr_point);
check_pseudos_live_through_calls (reg->regno); check_pseudos_live_through_calls (reg->regno,
last_call_used_reg_set);
} }
for (reg = curr_static_id->hard_regs; reg != NULL; reg = reg->next) for (reg = curr_static_id->hard_regs; reg != NULL; reg = reg->next)
...@@ -1009,7 +1026,7 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p) ...@@ -1009,7 +1026,7 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p)
if (sparseset_cardinality (pseudos_live_through_calls) == 0) if (sparseset_cardinality (pseudos_live_through_calls) == 0)
break; break;
if (sparseset_bit_p (pseudos_live_through_calls, j)) if (sparseset_bit_p (pseudos_live_through_calls, j))
check_pseudos_live_through_calls (j); check_pseudos_live_through_calls (j, last_call_used_reg_set);
} }
if (need_curr_point_incr) if (need_curr_point_incr)
......
...@@ -2295,7 +2295,7 @@ void ...@@ -2295,7 +2295,7 @@ void
lra (FILE *f) lra (FILE *f)
{ {
int i; int i;
bool live_p, scratch_p, inserted_p; bool live_p, inserted_p;
lra_dump_file = f; lra_dump_file = f;
...@@ -2332,7 +2332,6 @@ lra (FILE *f) ...@@ -2332,7 +2332,6 @@ lra (FILE *f)
lra_constraint_new_regno_start = lra_new_regno_start = max_reg_num (); lra_constraint_new_regno_start = lra_new_regno_start = max_reg_num ();
lra_bad_spill_regno_start = INT_MAX; lra_bad_spill_regno_start = INT_MAX;
remove_scratches (); remove_scratches ();
scratch_p = lra_constraint_new_regno_start != max_reg_num ();
/* A function that has a non-local label that can reach the exit /* A function that has a non-local label that can reach the exit
block via non-exceptional paths must save all call-saved block via non-exceptional paths must save all call-saved
...@@ -2372,11 +2371,12 @@ lra (FILE *f) ...@@ -2372,11 +2371,12 @@ lra (FILE *f)
for (;;) for (;;)
{ {
/* We should try to assign hard registers to scratches even /* We should try to assign hard registers to scratches even
if there were no RTL transformations in if there were no RTL transformations in lra_constraints.
lra_constraints. */ Also we should check IRA assignments on the first
iteration as they can be wrong because of early clobbers
operands which are ignored in IRA. */
if (! lra_constraints (lra_constraint_iter == 0) if (! lra_constraints (lra_constraint_iter == 0)
&& (lra_constraint_iter > 1 && lra_constraint_iter > 1)
|| (! scratch_p && ! caller_save_needed)))
break; break;
/* Constraint transformations may result in that eliminable /* Constraint transformations may result in that eliminable
hard regs become uneliminable and pseudos which use them hard regs become uneliminable and pseudos which use them
......
2017-01-26 Vladimir Makarov <vmakarov@redhat.com>
PR target/79131
* gcc.target/arm/pr79131.c: New.
2017-01-26 Bin Cheng <bin.cheng@arm.com> 2017-01-26 Bin Cheng <bin.cheng@arm.com>
* gcc.target/aarch64/ldp_vec_64_1.c: Xfail. * gcc.target/aarch64/ldp_vec_64_1.c: Xfail.
......
/* { dg-do compile } */
/* { dg-options "-O2 -mbig-endian" } */
long long a;
enum { NILFS_SEGMENT_USAGE_ACTIVE, NILFS_SEGMENT_USAGE_DIRTY } b;
void nilfs_sufile_mod_counter(long long p1) {
long c = p1;
unsigned d = __builtin_bswap64(a);
a = __builtin_bswap64(d + c);
}
void nilfs_sufile_do_free() {
int e, f;
e = __builtin_bswap32(b) & 1 << NILFS_SEGMENT_USAGE_DIRTY;
f = e;
nilfs_sufile_mod_counter(f ? -1 : 0);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment