diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3408e67b2c5..8a10820be2b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2019-03-06 Peter Bergner + + PR rtl-optimization/88845 + * config/rs6000/rs6000.c (rs6000_emit_move_si_sf_subreg): Enable during + LRA. + * lra.c (remove_scratches_1): New function. + (remove_scratches): Use it. + (lra_emit_move): Likewise. + 2019-03-06 Claudiu Zissulescu * config/arc/arc-c.def (__ARC_UNALIGNED__): Set it on diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index b489bef4501..d72a51a01bf 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -9890,7 +9890,7 @@ valid_sf_si_move (rtx dest, rtx src, machine_mode mode) static bool rs6000_emit_move_si_sf_subreg (rtx dest, rtx source, machine_mode mode) { - if (TARGET_DIRECT_MOVE_64BIT && !lra_in_progress && !reload_completed + if (TARGET_DIRECT_MOVE_64BIT && !reload_completed && (!SUBREG_P (dest) || !sf_subreg_operand (dest, mode)) && SUBREG_P (source) && sf_subreg_operand (source, mode)) { diff --git a/gcc/lra.c b/gcc/lra.c index f1300652889..bef2f676a78 100644 --- a/gcc/lra.c +++ b/gcc/lra.c @@ -159,6 +159,7 @@ static void invalidate_insn_recog_data (int); static int get_insn_freq (rtx_insn *); static void invalidate_insn_data_regno_info (lra_insn_recog_data_t, rtx_insn *, int); +static void remove_scratches_1 (rtx_insn *); /* Expand all regno related info needed for LRA. */ static void @@ -494,7 +495,11 @@ lra_emit_move (rtx x, rtx y) if (rtx_equal_p (x, y)) return; old = max_reg_num (); - emit_move_insn (x, y); + rtx_insn *insn = emit_move_insn (x, y); + /* The move pattern may require scratch registers, so convert them + into real registers now. */ + if (insn != NULL_RTX) + remove_scratches_1 (insn); if (REG_P (x)) lra_reg_info[ORIGINAL_REGNO (x)].last_reload = ++lra_curr_reload_num; /* Function emit_move can create pseudos -- so expand the pseudo @@ -2077,47 +2082,53 @@ lra_register_new_scratch_op (rtx_insn *insn, int nop, int icode) add_reg_note (insn, REG_UNUSED, op); } -/* Change scratches onto pseudos and save their location. */ +/* Change INSN's scratches into pseudos and save their location. */ static void -remove_scratches (void) +remove_scratches_1 (rtx_insn *insn) { int i; bool insn_changed_p; - basic_block bb; - rtx_insn *insn; rtx reg; lra_insn_recog_data_t id; struct lra_static_insn_data *static_id; + id = lra_get_insn_recog_data (insn); + static_id = id->insn_static_data; + insn_changed_p = false; + for (i = 0; i < static_id->n_operands; i++) + if (GET_CODE (*id->operand_loc[i]) == SCRATCH + && GET_MODE (*id->operand_loc[i]) != VOIDmode) + { + insn_changed_p = true; + *id->operand_loc[i] = reg + = lra_create_new_reg (static_id->operand[i].mode, + *id->operand_loc[i], ALL_REGS, NULL); + lra_register_new_scratch_op (insn, i, id->icode); + if (lra_dump_file != NULL) + fprintf (lra_dump_file, + "Removing SCRATCH in insn #%u (nop %d)\n", + INSN_UID (insn), i); + } + if (insn_changed_p) + /* Because we might use DF right after caller-saves sub-pass + we need to keep DF info up to date. */ + df_insn_rescan (insn); +} + +/* Change scratches into pseudos and save their location. */ +static void +remove_scratches (void) +{ + basic_block bb; + rtx_insn *insn; + scratches.create (get_max_uid ()); bitmap_initialize (&scratch_bitmap, ®_obstack); bitmap_initialize (&scratch_operand_bitmap, ®_obstack); FOR_EACH_BB_FN (bb, cfun) FOR_BB_INSNS (bb, insn) if (INSN_P (insn)) - { - id = lra_get_insn_recog_data (insn); - static_id = id->insn_static_data; - insn_changed_p = false; - for (i = 0; i < static_id->n_operands; i++) - if (GET_CODE (*id->operand_loc[i]) == SCRATCH - && GET_MODE (*id->operand_loc[i]) != VOIDmode) - { - insn_changed_p = true; - *id->operand_loc[i] = reg - = lra_create_new_reg (static_id->operand[i].mode, - *id->operand_loc[i], ALL_REGS, NULL); - lra_register_new_scratch_op (insn, i, id->icode); - if (lra_dump_file != NULL) - fprintf (lra_dump_file, - "Removing SCRATCH in insn #%u (nop %d)\n", - INSN_UID (insn), i); - } - if (insn_changed_p) - /* Because we might use DF right after caller-saves sub-pass - we need to keep DF info up to date. */ - df_insn_rescan (insn); - } + remove_scratches_1 (insn); } /* Changes pseudos created by function remove_scratches onto scratches. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 9b2951f631f..9a65e3a8147 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-03-06 Peter Bergner + + PR rtl-optimization/88845 + * gcc.target/powerpc/pr88845.c: New test. + 2019-03-06 Marek Polacek PR c++/87378 - bogus -Wredundant-move warning. diff --git a/gcc/testsuite/gcc.target/powerpc/pr88845.c b/gcc/testsuite/gcc.target/powerpc/pr88845.c new file mode 100644 index 00000000000..a939fa950bf --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr88845.c @@ -0,0 +1,24 @@ +/* { dg-do compile { target powerpc*-*-linux* } } */ +/* { dg-skip-if "" { powerpc*-*-darwin* } } */ +/* { dg-skip-if "" { powerpc*-*-*spe* } } */ +/* { dg-require-effective-target powerpc_p8vector_ok } */ +/* { dg-options "-mdejagnu-cpu=power8 -O2" } */ +/* { dg-final { scan-assembler {\mmtvsrd\M} { target { lp64 } } } } */ +/* { dg-final { scan-assembler {\mxscvspdpn\M} { target { lp64 } } } } */ + +/* Verify that we do not ICE and that we generate a direct move + for float types when compiling for 64-bit. */ + +struct a { + unsigned ui; + float f; +}; + +void +foo (void) +{ + float e; + struct a s; + e = s.f; + __asm__("" : : "d" (e)); +}