aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/lra-assigns.cc9
-rw-r--r--gcc/lra-constraints.cc136
-rw-r--r--gcc/testsuite/gcc.target/i386/pr110372.c14
3 files changed, 104 insertions, 55 deletions
diff --git a/gcc/lra-assigns.cc b/gcc/lra-assigns.cc
index 73fbef2..2f95121 100644
--- a/gcc/lra-assigns.cc
+++ b/gcc/lra-assigns.cc
@@ -1443,10 +1443,11 @@ assign_by_spills (void)
pass. Indicate that it is no longer spilled. */
bitmap_clear_bit (&all_spilled_pseudos, regno);
assign_hard_regno (hard_regno, regno);
- if (! reload_p)
- /* As non-reload pseudo assignment is changed we
- should reconsider insns referring for the
- pseudo. */
+ if (! reload_p || regno_allocno_class_array[regno] == ALL_REGS)
+ /* As non-reload pseudo assignment is changed we should
+ reconsider insns referring for the pseudo. Do the same if a
+ reload pseudo did not refine its class which can happens
+ when the pseudo occurs only in reload insns. */
bitmap_set_bit (&changed_pseudo_bitmap, regno);
}
}
diff --git a/gcc/lra-constraints.cc b/gcc/lra-constraints.cc
index 4dc2d70..123ff66 100644
--- a/gcc/lra-constraints.cc
+++ b/gcc/lra-constraints.cc
@@ -233,6 +233,34 @@ get_reg_class (int regno)
return NO_REGS;
}
+/* Return true if REG_CLASS has enough allocatable hard regs to keep value of
+ REG_MODE. */
+static bool
+enough_allocatable_hard_regs_p (enum reg_class reg_class,
+ enum machine_mode reg_mode)
+{
+ int i, j, hard_regno, class_size, nregs;
+
+ if (hard_reg_set_subset_p (reg_class_contents[reg_class], lra_no_alloc_regs))
+ return false;
+ class_size = ira_class_hard_regs_num[reg_class];
+ for (i = 0; i < class_size; i++)
+ {
+ hard_regno = ira_class_hard_regs[reg_class][i];
+ nregs = hard_regno_nregs (hard_regno, reg_mode);
+ if (nregs == 1)
+ return true;
+ for (j = 0; j < nregs; j++)
+ if (TEST_HARD_REG_BIT (lra_no_alloc_regs, hard_regno + j)
+ || ! TEST_HARD_REG_BIT (reg_class_contents[reg_class],
+ hard_regno + j))
+ break;
+ if (j >= nregs)
+ return true;
+ }
+ return false;
+}
+
/* Return true if REG satisfies (or will satisfy) reg class constraint
CL. Use elimination first if REG is a hard register. If REG is a
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,
enum reg_class rclass, common_class;
machine_mode reg_mode;
rtx src;
- int class_size, hard_regno, nregs, i, j;
int regno = REGNO (reg);
if (new_class != NULL)
@@ -291,26 +318,7 @@ in_class_p (rtx reg, enum reg_class cl, enum reg_class *new_class,
common_class = ira_reg_class_subset[rclass][cl];
if (new_class != NULL)
*new_class = common_class;
- if (hard_reg_set_subset_p (reg_class_contents[common_class],
- lra_no_alloc_regs))
- return false;
- /* Check that there are enough allocatable regs. */
- class_size = ira_class_hard_regs_num[common_class];
- for (i = 0; i < class_size; i++)
- {
- hard_regno = ira_class_hard_regs[common_class][i];
- nregs = hard_regno_nregs (hard_regno, reg_mode);
- if (nregs == 1)
- return true;
- for (j = 0; j < nregs; j++)
- if (TEST_HARD_REG_BIT (lra_no_alloc_regs, hard_regno + j)
- || ! TEST_HARD_REG_BIT (reg_class_contents[common_class],
- hard_regno + j))
- break;
- if (j >= nregs)
- return true;
- }
- return false;
+ return enough_allocatable_hard_regs_p (common_class, reg_mode);
}
}
@@ -2046,6 +2054,23 @@ update_and_check_small_class_inputs (int nop, int nalt,
return false;
}
+/* Print operand constraints for alternative ALT_NUMBER of the current
+ insn. */
+static void
+print_curr_insn_alt (int alt_number)
+{
+ for (int i = 0; i < curr_static_id->n_operands; i++)
+ {
+ const char *p = (curr_static_id->operand_alternative
+ [alt_number * curr_static_id->n_operands + i].constraint);
+ if (*p == '\0')
+ continue;
+ fprintf (lra_dump_file, " (%d) ", i);
+ for (; *p != '\0' && *p != ',' && *p != '#'; p++)
+ fputc (*p, lra_dump_file);
+ }
+}
+
/* Major function to choose the current insn alternative and what
operands should be reloaded and how. If ONLY_ALTERNATIVE is not
negative we should consider only this alternative. Return false if
@@ -2145,6 +2170,14 @@ process_alt_operands (int only_alternative)
if (!TEST_BIT (preferred, nalt))
continue;
+ if (lra_dump_file != NULL)
+ {
+ fprintf (lra_dump_file, " Considering alt=%d of insn %d: ",
+ nalt, INSN_UID (curr_insn));
+ print_curr_insn_alt (nalt);
+ fprintf (lra_dump_file, "\n");
+ }
+
bool matching_early_clobber[MAX_RECOG_OPERANDS];
curr_small_class_check++;
overall = losers = addr_losers = 0;
@@ -2671,8 +2704,7 @@ process_alt_operands (int only_alternative)
{
if (lra_dump_file != NULL)
fprintf (lra_dump_file,
- " alt=%d: Bad operand -- refuse\n",
- nalt);
+ " Bad operand -- refuse\n");
goto fail;
}
@@ -2701,8 +2733,7 @@ process_alt_operands (int only_alternative)
{
if (lra_dump_file != NULL)
fprintf (lra_dump_file,
- " alt=%d: Wrong mode -- refuse\n",
- nalt);
+ " Wrong mode -- refuse\n");
goto fail;
}
}
@@ -2769,8 +2800,7 @@ process_alt_operands (int only_alternative)
if (lra_dump_file != NULL)
fprintf
(lra_dump_file,
- " alt=%d: Strict low subreg reload -- refuse\n",
- nalt);
+ " Strict low subreg reload -- refuse\n");
goto fail;
}
losers++;
@@ -2832,8 +2862,7 @@ process_alt_operands (int only_alternative)
if (lra_dump_file != NULL)
fprintf
(lra_dump_file,
- " alt=%d: No input/output reload -- refuse\n",
- nalt);
+ " No input/output reload -- refuse\n");
goto fail;
}
@@ -2860,9 +2889,9 @@ process_alt_operands (int only_alternative)
{
if (lra_dump_file != NULL)
fprintf (lra_dump_file,
- " alt=%d: reload pseudo for op %d "
+ " reload pseudo for op %d "
"cannot hold the mode value -- refuse\n",
- nalt, nop);
+ nop);
goto fail;
}
@@ -2989,7 +3018,7 @@ process_alt_operands (int only_alternative)
/* If reload requires moving value through secondary
memory, it will need one more insn at least. */
- if (this_alternative != NO_REGS
+ if (this_alternative != NO_REGS
&& REG_P (op) && (cl = get_reg_class (REGNO (op))) != NO_REGS
&& ((curr_static_id->operand[nop].type != OP_OUT
&& targetm.secondary_memory_needed (GET_MODE (op), cl,
@@ -3046,8 +3075,8 @@ process_alt_operands (int only_alternative)
{
if (lra_dump_file != NULL)
fprintf (lra_dump_file,
- " alt=%d,overall=%d,losers=%d -- refuse\n",
- nalt, overall, losers);
+ " overall=%d,losers=%d -- refuse\n",
+ overall, losers);
goto fail;
}
@@ -3056,8 +3085,7 @@ process_alt_operands (int only_alternative)
{
if (lra_dump_file != NULL)
fprintf (lra_dump_file,
- " alt=%d, not enough small class regs -- refuse\n",
- nalt);
+ " not enough small class regs -- refuse\n");
goto fail;
}
curr_alt[nop] = this_alternative;
@@ -3238,8 +3266,8 @@ process_alt_operands (int only_alternative)
overall += LRA_LOSER_COST_FACTOR - 1;
}
if (lra_dump_file != NULL)
- fprintf (lra_dump_file, " alt=%d,overall=%d,losers=%d,rld_nregs=%d\n",
- nalt, overall, losers, reload_nregs);
+ fprintf (lra_dump_file, " overall=%d,losers=%d,rld_nregs=%d\n",
+ overall, losers, reload_nregs);
/* If this alternative can be made to work by reloading, and it
needs less reloading than the others checked so far, record
@@ -4355,18 +4383,9 @@ curr_insn_transform (bool check_only_p)
{
const char *p;
- fprintf (lra_dump_file, " Choosing alt %d in insn %u:",
+ fprintf (lra_dump_file, " Choosing alt %d in insn %u:",
goal_alt_number, INSN_UID (curr_insn));
- for (i = 0; i < n_operands; i++)
- {
- p = (curr_static_id->operand_alternative
- [goal_alt_number * n_operands + i].constraint);
- if (*p == '\0')
- continue;
- fprintf (lra_dump_file, " (%d) ", i);
- for (; *p != '\0' && *p != ',' && *p != '#'; p++)
- fputc (*p, lra_dump_file);
- }
+ print_curr_insn_alt (goal_alt_number);
if (INSN_CODE (curr_insn) >= 0
&& (p = get_insn_name (INSN_CODE (curr_insn))) != NULL)
fprintf (lra_dump_file, " {%s}", p);
@@ -4564,7 +4583,22 @@ curr_insn_transform (bool check_only_p)
continue;
}
else
- continue;
+ {
+ enum reg_class rclass, common_class;
+
+ if (REG_P (op) && goal_alt[i] != NO_REGS
+ && (regno = REGNO (op)) >= new_regno_start
+ && (rclass = get_reg_class (regno)) == ALL_REGS
+ && ((common_class = ira_reg_class_subset[rclass][goal_alt[i]])
+ != NO_REGS)
+ && common_class != ALL_REGS
+ && enough_allocatable_hard_regs_p (common_class,
+ GET_MODE (op)))
+ /* Refine reload pseudo class from chosen alternative
+ constraint. */
+ lra_change_class (regno, common_class, " Change to", true);
+ continue;
+ }
}
/* Operands that match previous ones have already been handled. */
@@ -5249,7 +5283,7 @@ lra_constraints (bool first_p)
the equiv. We could update the equiv insns after
transformations including an equiv insn deletion
but it is not worthy as such cases are extremely
- rare. */
+ rare. */
|| contains_deleted_insn_p (ira_reg_equiv[i].init_insns)
/* If it is not a reverse equivalence, we check that a
pseudo in rhs of the init insn is not dying in the
diff --git a/gcc/testsuite/gcc.target/i386/pr110372.c b/gcc/testsuite/gcc.target/i386/pr110372.c
new file mode 100644
index 0000000..dd7d76a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr110372.c
@@ -0,0 +1,14 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O -mno-sse2" } */
+
+typedef char __attribute__((__vector_size__ (16))) U;
+typedef int __attribute__((__vector_size__ (16))) V;
+
+V v;
+
+U
+foo0 (U u)
+{
+ v *= (V) u & 4;
+ return u;
+}