Jakub Jelinek <[email protected]> writes:
> On Tue, Feb 16, 2021 at 01:09:43PM +0000, Richard Sandiford wrote:
>> Can I put in a plea to put this in recog.[hc], and possibly also make
>> it a copy constructor for recog_data_d? I can't think of any legitimate
>> cases in which we'd want to copy the whole structure, instead of just
>> the active parts.
>
> Good idea. So like this?
>
> 2021-02-16 Jakub Jelinek <[email protected]>
>
> PR target/99104
> * recog.h (recog_data_d::recog_data_d ()): New defaulted default ctor.
> (recog_data_d::recog_data_d (const recog_data_d &)): Declare.
> (recog_data_d::operator = (const recog_data_d &)): Declare.
> * recog.c (recog_data_d::operator = (const recog_data_d &)): New
> assignment operator.
> (recog_data_d::recog_data_d (const recog_data_d &)): New copy ctor.
OK, thanks.
Richard
> * config/i386/i386.c (distance_non_agu_define): Don't call
> extract_insn_cached here.
> (ix86_lea_outperforms): Save and restore recog_data around call
> to distance_non_agu_define and distance_agu_use.
> (ix86_ok_to_clobber_flags): Remove.
> (ix86_avoid_lea_for_add): Don't call ix86_ok_to_clobber_flags.
> (ix86_avoid_lea_for_addr): Likewise. Adjust function comment.
> * config/i386/i386.m (*lea<mode>): Change from define_insn_and_split
> into define_insn. Move the splitting to define_peephole2 and
> check there using peep2_regno_dead_p if FLAGS_REG is dead.
>
> * gcc.dg/pr99104.c: New test.
>
> --- gcc/recog.h.jj 2021-01-15 19:04:42.436445517 +0100
> +++ gcc/recog.h 2021-02-16 14:26:00.384934711 +0100
> @@ -372,6 +372,12 @@ struct recog_data_d
>
> /* In case we are caching, hold insn data was generated for. */
> rtx_insn *insn;
> +
> + recog_data_d () = default;
> + /* Copy constructor and assignment operator, so that when copying the
> + structure we copy only the active elements. */
> + recog_data_d (const recog_data_d &);
> + recog_data_d &operator = (const recog_data_d &);
> };
>
> extern struct recog_data_d recog_data;
> --- gcc/recog.c.jj 2021-02-16 08:57:21.277960594 +0100
> +++ gcc/recog.c 2021-02-16 14:26:42.235464536 +0100
> @@ -109,7 +109,41 @@ init_recog (void)
> {
> volatile_ok = 1;
> }
> +
> +/* recog_data_d assignment operator, so that recog_data_d copying
> + only copies the active elements. */
> +
> +recog_data_d &
> +recog_data_d::operator = (const recog_data_d &src)
> +{
> + n_operands = src.n_operands;
> + n_dups = src.n_dups;
> + n_alternatives = src.n_alternatives;
> + is_asm = src.is_asm;
> + insn = src.insn;
> + for (int i = 0; i < src.n_operands; i++)
> + {
> + operand[i] = src.operand[i];
> + operand_loc[i] = src.operand_loc[i];
> + constraints[i] = src.constraints[i];
> + is_operator[i] = src.is_operator[i];
> + operand_mode[i] = src.operand_mode[i];
> + operand_type[i] = src.operand_type[i];
> + }
> + for (int i = 0; i < src.n_dups; i++)
> + {
> + dup_loc[i] = src.dup_loc[i];
> + dup_num[i] = src.dup_num[i];
> + }
> + return *this;
> +}
>
> +/* recog_data_d copy constructor, so that recog_data_d construction
> + only copies the active elements. */
> +recog_data_d::recog_data_d (const recog_data_d &src)
> +{
> + *this = src;
> +}
>
> /* Return true if labels in asm operands BODY are LABEL_REFs. */
>
> --- gcc/config/i386/i386.c.jj 2021-02-16 08:58:55.197890195 +0100
> +++ gcc/config/i386/i386.c 2021-02-16 14:20:19.061764891 +0100
> @@ -14754,11 +14754,6 @@ distance_non_agu_define (unsigned int re
> }
> }
>
> - /* get_attr_type may modify recog data. We want to make sure
> - that recog data is valid for instruction INSN, on which
> - distance_non_agu_define is called. INSN is unchanged here. */
> - extract_insn_cached (insn);
> -
> if (!found)
> return -1;
>
> @@ -14928,17 +14923,15 @@ ix86_lea_outperforms (rtx_insn *insn, un
> return true;
> }
>
> - rtx_insn *rinsn = recog_data.insn;
> + /* Remember recog_data content. */
> + struct recog_data_d recog_data_save = recog_data;
>
> dist_define = distance_non_agu_define (regno1, regno2, insn);
> dist_use = distance_agu_use (regno0, insn);
>
> - /* distance_non_agu_define can call extract_insn_cached. If this function
> - is called from define_split conditions, that can break insn splitting,
> - because split_insns works by clearing recog_data.insn and then modifying
> - recog_data.operand array and match the various split conditions. */
> - if (recog_data.insn != rinsn)
> - recog_data.insn = NULL;
> + /* distance_non_agu_define can call get_attr_type which can call
> + recog_memoized, restore recog_data back to previous content. */
> + recog_data = recog_data_save;
>
> if (dist_define < 0 || dist_define >= LEA_MAX_STALL)
> {
> @@ -14968,38 +14961,6 @@ ix86_lea_outperforms (rtx_insn *insn, un
> return dist_define >= dist_use;
> }
>
> -/* Return true if it is legal to clobber flags by INSN and
> - false otherwise. */
> -
> -static bool
> -ix86_ok_to_clobber_flags (rtx_insn *insn)
> -{
> - basic_block bb = BLOCK_FOR_INSN (insn);
> - df_ref use;
> - bitmap live;
> -
> - while (insn)
> - {
> - if (NONDEBUG_INSN_P (insn))
> - {
> - FOR_EACH_INSN_USE (use, insn)
> - if (DF_REF_REG_USE_P (use) && DF_REF_REGNO (use) == FLAGS_REG)
> - return false;
> -
> - if (insn_defines_reg (FLAGS_REG, INVALID_REGNUM, insn))
> - return true;
> - }
> -
> - if (insn == BB_END (bb))
> - break;
> -
> - insn = NEXT_INSN (insn);
> - }
> -
> - live = df_get_live_out(bb);
> - return !REGNO_REG_SET_P (live, FLAGS_REG);
> -}
> -
> /* Return true if we need to split op0 = op1 + op2 into a sequence of
> move and add to avoid AGU stalls. */
>
> @@ -15012,10 +14973,6 @@ ix86_avoid_lea_for_add (rtx_insn *insn,
> if (!TARGET_OPT_AGU || optimize_function_for_size_p (cfun))
> return false;
>
> - /* Check it is correct to split here. */
> - if (!ix86_ok_to_clobber_flags(insn))
> - return false;
> -
> regno0 = true_regnum (operands[0]);
> regno1 = true_regnum (operands[1]);
> regno2 = true_regnum (operands[2]);
> @@ -15051,7 +15008,7 @@ ix86_use_lea_for_mov (rtx_insn *insn, rt
> }
>
> /* Return true if we need to split lea into a sequence of
> - instructions to avoid AGU stalls. */
> + instructions to avoid AGU stalls during peephole2. */
>
> bool
> ix86_avoid_lea_for_addr (rtx_insn *insn, rtx operands[])
> @@ -15071,10 +15028,6 @@ ix86_avoid_lea_for_addr (rtx_insn *insn,
> && REG_P (XEXP (operands[1], 0))))
> return false;
>
> - /* Check if it is OK to split here. */
> - if (!ix86_ok_to_clobber_flags (insn))
> - return false;
> -
> ok = ix86_decompose_address (operands[1], &parts);
> gcc_assert (ok);
>
> --- gcc/config/i386/i386.md.jj 2021-01-13 10:12:07.036506101 +0100
> +++ gcc/config/i386/i386.md 2021-02-16 13:48:13.650317709 +0100
> @@ -5176,7 +5176,7 @@ (define_expand "floatunsdidf2"
>
> ;; Load effective address instructions
>
> -(define_insn_and_split "*lea<mode>"
> +(define_insn "*lea<mode>"
> [(set (match_operand:SWI48 0 "register_operand" "=r")
> (match_operand:SWI48 1 "address_no_seg_operand" "Ts"))]
> "ix86_hardreg_mov_ok (operands[0], operands[1])"
> @@ -5189,38 +5189,36 @@ (define_insn_and_split "*lea<mode>"
> else
> return "lea{<imodesuffix>}\t{%E1, %0|%0, %E1}";
> }
> - "reload_completed && ix86_avoid_lea_for_addr (insn, operands)"
> + [(set_attr "type" "lea")
> + (set (attr "mode")
> + (if_then_else
> + (match_operand 1 "SImode_address_operand")
> + (const_string "SI")
> + (const_string "<MODE>")))])
> +
> +(define_peephole2
> + [(set (match_operand:SWI48 0 "register_operand")
> + (match_operand:SWI48 1 "address_no_seg_operand"))]
> + "ix86_hardreg_mov_ok (operands[0], operands[1])
> + && peep2_regno_dead_p (0, FLAGS_REG)
> + && ix86_avoid_lea_for_addr (peep2_next_insn (0), operands)"
> [(const_int 0)]
> {
> machine_mode mode = <MODE>mode;
> - rtx pat;
> -
> - /* ix86_avoid_lea_for_addr re-recognizes insn and may
> - change operands[] array behind our back. */
> - pat = PATTERN (curr_insn);
> -
> - operands[0] = SET_DEST (pat);
> - operands[1] = SET_SRC (pat);
>
> /* Emit all operations in SImode for zero-extended addresses. */
> if (SImode_address_operand (operands[1], VOIDmode))
> mode = SImode;
>
> - ix86_split_lea_for_addr (curr_insn, operands, mode);
> + ix86_split_lea_for_addr (peep2_next_insn (0), operands, mode);
>
> /* Zero-extend return register to DImode for zero-extended addresses. */
> if (mode != <MODE>mode)
> - emit_insn (gen_zero_extendsidi2
> - (operands[0], gen_lowpart (mode, operands[0])));
> + emit_insn (gen_zero_extendsidi2 (operands[0],
> + gen_lowpart (mode, operands[0])));
>
> DONE;
> -}
> - [(set_attr "type" "lea")
> - (set (attr "mode")
> - (if_then_else
> - (match_operand 1 "SImode_address_operand")
> - (const_string "SI")
> - (const_string "<MODE>")))])
> +})
>
> ;; Add instructions
>
> --- gcc/testsuite/gcc.dg/pr99104.c.jj 2021-02-16 11:47:08.793255200 +0100
> +++ gcc/testsuite/gcc.dg/pr99104.c 2021-02-16 11:47:08.793255200 +0100
> @@ -0,0 +1,15 @@
> +/* PR target/99104 */
> +/* { dg-do compile { target int128 } } */
> +/* { dg-options "-O2 -fsel-sched-pipelining -fselective-scheduling2
> -funroll-loops" } */
> +
> +__int128 a;
> +int b;
> +int foo (void);
> +
> +int __attribute__ ((simd))
> +bar (void)
> +{
> + a = ~a;
> + if (foo ())
> + b = 0;
> +}
>
>
> Jakub