Skip to content

Commit 1f7e5a7

Browse files
committed
LRA: Refine reload pseudo class
For given testcase a reload pseudo happened to occur only in reload insns created on one constraint sub-pass. Therefore its initial class (ALL_REGS) was not refined and the reload insns were not processed on the next constraint sub-passes. This resulted into the wrong insn. PR rtl-optimization/110372 gcc/ChangeLog: * lra-assigns.cc (assign_by_spills): Add reload insns involving reload pseudos with non-refined class to be processed on the next sub-pass. * lra-constraints.cc (enough_allocatable_hard_regs_p): New func. (in_class_p): Use it. (print_curr_insn_alt): New func. (process_alt_operands): Use it. Improve debug info. (curr_insn_transform): Use print_curr_insn_alt. Refine reload pseudo class if it is not refined yet. gcc/testsuite/ChangeLog: * gcc.target/i386/pr110372.c: New.
1 parent c496d15 commit 1f7e5a7

File tree

3 files changed

+104
-55
lines changed

3 files changed

+104
-55
lines changed

gcc/lra-assigns.cc

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1443,10 +1443,11 @@ assign_by_spills (void)
14431443
pass. Indicate that it is no longer spilled. */
14441444
bitmap_clear_bit (&all_spilled_pseudos, regno);
14451445
assign_hard_regno (hard_regno, regno);
1446-
if (! reload_p)
1447-
/* As non-reload pseudo assignment is changed we
1448-
should reconsider insns referring for the
1449-
pseudo. */
1446+
if (! reload_p || regno_allocno_class_array[regno] == ALL_REGS)
1447+
/* As non-reload pseudo assignment is changed we should
1448+
reconsider insns referring for the pseudo. Do the same if a
1449+
reload pseudo did not refine its class which can happens
1450+
when the pseudo occurs only in reload insns. */
14501451
bitmap_set_bit (&changed_pseudo_bitmap, regno);
14511452
}
14521453
}

gcc/lra-constraints.cc

Lines changed: 85 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,34 @@ get_reg_class (int regno)
233233
return NO_REGS;
234234
}
235235

236+
/* Return true if REG_CLASS has enough allocatable hard regs to keep value of
237+
REG_MODE. */
238+
static bool
239+
enough_allocatable_hard_regs_p (enum reg_class reg_class,
240+
enum machine_mode reg_mode)
241+
{
242+
int i, j, hard_regno, class_size, nregs;
243+
244+
if (hard_reg_set_subset_p (reg_class_contents[reg_class], lra_no_alloc_regs))
245+
return false;
246+
class_size = ira_class_hard_regs_num[reg_class];
247+
for (i = 0; i < class_size; i++)
248+
{
249+
hard_regno = ira_class_hard_regs[reg_class][i];
250+
nregs = hard_regno_nregs (hard_regno, reg_mode);
251+
if (nregs == 1)
252+
return true;
253+
for (j = 0; j < nregs; j++)
254+
if (TEST_HARD_REG_BIT (lra_no_alloc_regs, hard_regno + j)
255+
|| ! TEST_HARD_REG_BIT (reg_class_contents[reg_class],
256+
hard_regno + j))
257+
break;
258+
if (j >= nregs)
259+
return true;
260+
}
261+
return false;
262+
}
263+
236264
/* Return true if REG satisfies (or will satisfy) reg class constraint
237265
CL. Use elimination first if REG is a hard register. If REG is a
238266
reload pseudo created by this constraints pass, assume that it will
@@ -252,7 +280,6 @@ in_class_p (rtx reg, enum reg_class cl, enum reg_class *new_class,
252280
enum reg_class rclass, common_class;
253281
machine_mode reg_mode;
254282
rtx src;
255-
int class_size, hard_regno, nregs, i, j;
256283
int regno = REGNO (reg);
257284

258285
if (new_class != NULL)
@@ -291,26 +318,7 @@ in_class_p (rtx reg, enum reg_class cl, enum reg_class *new_class,
291318
common_class = ira_reg_class_subset[rclass][cl];
292319
if (new_class != NULL)
293320
*new_class = common_class;
294-
if (hard_reg_set_subset_p (reg_class_contents[common_class],
295-
lra_no_alloc_regs))
296-
return false;
297-
/* Check that there are enough allocatable regs. */
298-
class_size = ira_class_hard_regs_num[common_class];
299-
for (i = 0; i < class_size; i++)
300-
{
301-
hard_regno = ira_class_hard_regs[common_class][i];
302-
nregs = hard_regno_nregs (hard_regno, reg_mode);
303-
if (nregs == 1)
304-
return true;
305-
for (j = 0; j < nregs; j++)
306-
if (TEST_HARD_REG_BIT (lra_no_alloc_regs, hard_regno + j)
307-
|| ! TEST_HARD_REG_BIT (reg_class_contents[common_class],
308-
hard_regno + j))
309-
break;
310-
if (j >= nregs)
311-
return true;
312-
}
313-
return false;
321+
return enough_allocatable_hard_regs_p (common_class, reg_mode);
314322
}
315323
}
316324

@@ -2046,6 +2054,23 @@ update_and_check_small_class_inputs (int nop, int nalt,
20462054
return false;
20472055
}
20482056

2057+
/* Print operand constraints for alternative ALT_NUMBER of the current
2058+
insn. */
2059+
static void
2060+
print_curr_insn_alt (int alt_number)
2061+
{
2062+
for (int i = 0; i < curr_static_id->n_operands; i++)
2063+
{
2064+
const char *p = (curr_static_id->operand_alternative
2065+
[alt_number * curr_static_id->n_operands + i].constraint);
2066+
if (*p == '\0')
2067+
continue;
2068+
fprintf (lra_dump_file, " (%d) ", i);
2069+
for (; *p != '\0' && *p != ',' && *p != '#'; p++)
2070+
fputc (*p, lra_dump_file);
2071+
}
2072+
}
2073+
20492074
/* Major function to choose the current insn alternative and what
20502075
operands should be reloaded and how. If ONLY_ALTERNATIVE is not
20512076
negative we should consider only this alternative. Return false if
@@ -2145,6 +2170,14 @@ process_alt_operands (int only_alternative)
21452170
if (!TEST_BIT (preferred, nalt))
21462171
continue;
21472172

2173+
if (lra_dump_file != NULL)
2174+
{
2175+
fprintf (lra_dump_file, " Considering alt=%d of insn %d: ",
2176+
nalt, INSN_UID (curr_insn));
2177+
print_curr_insn_alt (nalt);
2178+
fprintf (lra_dump_file, "\n");
2179+
}
2180+
21482181
bool matching_early_clobber[MAX_RECOG_OPERANDS];
21492182
curr_small_class_check++;
21502183
overall = losers = addr_losers = 0;
@@ -2671,8 +2704,7 @@ process_alt_operands (int only_alternative)
26712704
{
26722705
if (lra_dump_file != NULL)
26732706
fprintf (lra_dump_file,
2674-
" alt=%d: Bad operand -- refuse\n",
2675-
nalt);
2707+
" Bad operand -- refuse\n");
26762708
goto fail;
26772709
}
26782710

@@ -2701,8 +2733,7 @@ process_alt_operands (int only_alternative)
27012733
{
27022734
if (lra_dump_file != NULL)
27032735
fprintf (lra_dump_file,
2704-
" alt=%d: Wrong mode -- refuse\n",
2705-
nalt);
2736+
" Wrong mode -- refuse\n");
27062737
goto fail;
27072738
}
27082739
}
@@ -2769,8 +2800,7 @@ process_alt_operands (int only_alternative)
27692800
if (lra_dump_file != NULL)
27702801
fprintf
27712802
(lra_dump_file,
2772-
" alt=%d: Strict low subreg reload -- refuse\n",
2773-
nalt);
2803+
" Strict low subreg reload -- refuse\n");
27742804
goto fail;
27752805
}
27762806
losers++;
@@ -2832,8 +2862,7 @@ process_alt_operands (int only_alternative)
28322862
if (lra_dump_file != NULL)
28332863
fprintf
28342864
(lra_dump_file,
2835-
" alt=%d: No input/output reload -- refuse\n",
2836-
nalt);
2865+
" No input/output reload -- refuse\n");
28372866
goto fail;
28382867
}
28392868

@@ -2860,9 +2889,9 @@ process_alt_operands (int only_alternative)
28602889
{
28612890
if (lra_dump_file != NULL)
28622891
fprintf (lra_dump_file,
2863-
" alt=%d: reload pseudo for op %d "
2892+
" reload pseudo for op %d "
28642893
"cannot hold the mode value -- refuse\n",
2865-
nalt, nop);
2894+
nop);
28662895
goto fail;
28672896
}
28682897

@@ -2989,7 +3018,7 @@ process_alt_operands (int only_alternative)
29893018

29903019
/* If reload requires moving value through secondary
29913020
memory, it will need one more insn at least. */
2992-
if (this_alternative != NO_REGS
3021+
if (this_alternative != NO_REGS
29933022
&& REG_P (op) && (cl = get_reg_class (REGNO (op))) != NO_REGS
29943023
&& ((curr_static_id->operand[nop].type != OP_OUT
29953024
&& targetm.secondary_memory_needed (GET_MODE (op), cl,
@@ -3046,8 +3075,8 @@ process_alt_operands (int only_alternative)
30463075
{
30473076
if (lra_dump_file != NULL)
30483077
fprintf (lra_dump_file,
3049-
" alt=%d,overall=%d,losers=%d -- refuse\n",
3050-
nalt, overall, losers);
3078+
" overall=%d,losers=%d -- refuse\n",
3079+
overall, losers);
30513080
goto fail;
30523081
}
30533082

@@ -3056,8 +3085,7 @@ process_alt_operands (int only_alternative)
30563085
{
30573086
if (lra_dump_file != NULL)
30583087
fprintf (lra_dump_file,
3059-
" alt=%d, not enough small class regs -- refuse\n",
3060-
nalt);
3088+
" not enough small class regs -- refuse\n");
30613089
goto fail;
30623090
}
30633091
curr_alt[nop] = this_alternative;
@@ -3238,8 +3266,8 @@ process_alt_operands (int only_alternative)
32383266
overall += LRA_LOSER_COST_FACTOR - 1;
32393267
}
32403268
if (lra_dump_file != NULL)
3241-
fprintf (lra_dump_file, " alt=%d,overall=%d,losers=%d,rld_nregs=%d\n",
3242-
nalt, overall, losers, reload_nregs);
3269+
fprintf (lra_dump_file, " overall=%d,losers=%d,rld_nregs=%d\n",
3270+
overall, losers, reload_nregs);
32433271

32443272
/* If this alternative can be made to work by reloading, and it
32453273
needs less reloading than the others checked so far, record
@@ -4355,18 +4383,9 @@ curr_insn_transform (bool check_only_p)
43554383
{
43564384
const char *p;
43574385

4358-
fprintf (lra_dump_file, " Choosing alt %d in insn %u:",
4386+
fprintf (lra_dump_file, " Choosing alt %d in insn %u:",
43594387
goal_alt_number, INSN_UID (curr_insn));
4360-
for (i = 0; i < n_operands; i++)
4361-
{
4362-
p = (curr_static_id->operand_alternative
4363-
[goal_alt_number * n_operands + i].constraint);
4364-
if (*p == '\0')
4365-
continue;
4366-
fprintf (lra_dump_file, " (%d) ", i);
4367-
for (; *p != '\0' && *p != ',' && *p != '#'; p++)
4368-
fputc (*p, lra_dump_file);
4369-
}
4388+
print_curr_insn_alt (goal_alt_number);
43704389
if (INSN_CODE (curr_insn) >= 0
43714390
&& (p = get_insn_name (INSN_CODE (curr_insn))) != NULL)
43724391
fprintf (lra_dump_file, " {%s}", p);
@@ -4564,7 +4583,22 @@ curr_insn_transform (bool check_only_p)
45644583
continue;
45654584
}
45664585
else
4567-
continue;
4586+
{
4587+
enum reg_class rclass, common_class;
4588+
4589+
if (REG_P (op) && goal_alt[i] != NO_REGS
4590+
&& (regno = REGNO (op)) >= new_regno_start
4591+
&& (rclass = get_reg_class (regno)) == ALL_REGS
4592+
&& ((common_class = ira_reg_class_subset[rclass][goal_alt[i]])
4593+
!= NO_REGS)
4594+
&& common_class != ALL_REGS
4595+
&& enough_allocatable_hard_regs_p (common_class,
4596+
GET_MODE (op)))
4597+
/* Refine reload pseudo class from chosen alternative
4598+
constraint. */
4599+
lra_change_class (regno, common_class, " Change to", true);
4600+
continue;
4601+
}
45684602
}
45694603

45704604
/* Operands that match previous ones have already been handled. */
@@ -5249,7 +5283,7 @@ lra_constraints (bool first_p)
52495283
the equiv. We could update the equiv insns after
52505284
transformations including an equiv insn deletion
52515285
but it is not worthy as such cases are extremely
5252-
rare. */
5286+
rare. */
52535287
|| contains_deleted_insn_p (ira_reg_equiv[i].init_insns)
52545288
/* If it is not a reverse equivalence, we check that a
52555289
pseudo in rhs of the init insn is not dying in the
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/* { dg-do compile { target { ! ia32 } } } */
2+
/* { dg-options "-O -mno-sse2" } */
3+
4+
typedef char __attribute__((__vector_size__ (16))) U;
5+
typedef int __attribute__((__vector_size__ (16))) V;
6+
7+
V v;
8+
9+
U
10+
foo0 (U u)
11+
{
12+
v *= (V) u & 4;
13+
return u;
14+
}

0 commit comments

Comments
 (0)