diff options
-rw-r--r-- | gcc/lra-assigns.cc | 9 | ||||
-rw-r--r-- | gcc/lra-constraints.cc | 136 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr110372.c | 14 |
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; +} |