Hi Sehger,
Segher Boessenkool <seg...@kernel.crashing.org> writes: > On Tue, Mar 01, 2022 at 10:28:57PM +0800, Jiufu Guo wrote: >> Segher Boessenkool <seg...@kernel.crashing.org> writes: >> > No. insn_cost is only for correct, existing instructions, not for >> > made-up nonsense. I created insn_cost precisely to get away from that >> > aspect of rtx_cost (and some other issues, like, it is incredibly hard >> > and cumbersome to write a correct rtx_cost). >> >> Thanks! The implementations of hook insn_cost are align with this >> design, they are checking insn's attributes and COSTS_N_INSNS. >> >> One question on the speciall case: >> For instruction: "r119:DI=0x100803004101001" >> Would we treat it as valid instruction? > > Currently we do, alternative 6 in *movdi_internal64: we allow any r<-n. > This is costed as 5 insns (cost=20). > > It generally is better to split things into patterns close to the > eventual machine isntructions as early as possible: all the more generic > optimisations can take advantage of that then. Get it! > >> A patch, which is attached the end of this mail, accepts >> "r119:DI=0x100803004101001" as input of insn_cost. >> In this patch, >> - A tmp instruction is generated via make_insn_raw. >> - A few calls to rtx_cost (in cse_insn) is replaced by insn_cost. >> - In hook of insn_cost, checking the special 'constant' instruction. >> Are these make sense? > > I'll review that patch inline. > >> > That is one reason why it is better to generate (close to) machine >> > insns as early as possible: it makes it much easier to estimate >> > realistic costs. (Another important reason is it allows other >> > optimisations, without us having to do any work for it!) >> Get it! In the middle of an optimization pass, 'interim' >> instruction maybe acceptable. While it would better to outputs >> only contains 'valid machine insn' from any RTL passes. > > Acceptable only if there is a very good reason for it, really :-( > >> --- a/gcc/config/rs6000/rs6000.cc >> +++ b/gcc/config/rs6000/rs6000.cc >> @@ -22131,6 +22131,16 @@ rs6000_debug_rtx_costs (rtx x, machine_mode mode, >> int outer_code, >> static int >> rs6000_insn_cost (rtx_insn *insn, bool speed) >> { >> + /* Handle special 'constant int' insn. */ >> + rtx set = PATTERN (insn); >> + if (GET_CODE (set) == SET && CONSTANT_P (SET_SRC (set))) >> + { >> + rtx src = SET_SRC (set); >> + machine_mode mode = GET_MODE (SET_DEST (set)); >> + if (CONST_INT_P (src) || CONST_WIDE_INT_P (src)) >> + return COSTS_N_INSNS (num_insns_constant (src, mode)); >> + } >> + >> if (recog_memoized (insn) < 0) >> return 0; > > Why would such a set not recog()? Thanks. This code is not need at the top of function insn_cost. recog_memoized could check insn_code on 'insn'. > > Needs a comment in any case, to say what this is a workaround for. > >> +static int insn_cost_x (rtx_insn *, rtx); > > Don't declare functions, just put their definitions before their first > use. (And use a better name please :-) ) Get it. :-) > >> static int >> -notreg_cost (rtx x, machine_mode mode, enum rtx_code outer, int opno) >> +notreg_cost (rtx x, machine_mode mode, enum rtx_code outer, int opno, >> + rtx_insn *insn = NULL) > > Don't use default arguments like this, it is an abomination. Thanks. > >> @@ -709,9 +713,21 @@ notreg_cost (rtx x, machine_mode mode, enum rtx_code >> outer, int opno) >> && subreg_lowpart_p (x) >> && TRULY_NOOP_TRUNCATION_MODES_P (int_mode, inner_mode)) >> ? 0 >> + : insn != NULL ? insn_cost_x (insn, x) >> : rtx_cost (x, mode, outer, opno, optimize_this_for_speed_p) * 2); >> } > > You can just always use insn_cost? insn_cost -> pattern_cost -> > set_src_cost -> rtx_cost. That works for COST at least, not sure about > COST_IN, maybe that needs a little more care (cse.c works with invalid > insns all over the place :-( ) > This experiement patch just replace part of rtx_cost with insn_cost. In case, COST is called outside cse_insn, 'insn' may not be set, and then 'insn_cost' may not work. This would need to be enhanced. >> >> +/* Internal function, to get cost when use X to replace source of insn >> + which is a SET. */ >> + >> +static int >> +insn_cost_x (rtx_insn *insn, rtx x) >> +{ >> + INSN_CODE (insn) = -1; >> + SET_SRC (PATTERN (insn)) = x; >> + return insn_cost (insn, optimize_this_for_speed_p); >> +} > > You need to restore stuff as well? In this patch, this function is called on a tmp_insn, so I did not restore it. If using the original 'insn' of cse_insn to invoked 'insn_cost_x', fields of 'insn' should be restored. > >> @@ -4603,6 +4619,7 @@ cse_insn (rtx_insn *insn) >> >> Nothing in this loop changes the hash table or the register chains. */ >> >> + rtx_insn *tmp_insn = NULL; >> for (i = 0; i < n_sets; i++) >> { >> bool repeat = false; >> @@ -4638,6 +4655,10 @@ cse_insn (rtx_insn *insn) >> mode = GET_MODE (src) == VOIDmode ? GET_MODE (dest) : GET_MODE (src); >> sets[i].mode = mode; >> >> + if (tmp_insn == NULL_RTX && src && dest && dest != pc_rtx >> + && src != pc_rtx) >> + tmp_insn = make_insn_raw (gen_rtx_SET (copy_rtx (dest), copy_rtx(src))); > > src and dest are always non-nil here. I'll have to read the code better > to know about the (pc) stuff. > >> @@ -5103,7 +5124,7 @@ cse_insn (rtx_insn *insn) >> src_cost = src_regcost = -1; >> else >> { >> - src_cost = COST (src, mode); >> + src_cost = COST_SRC (tmp_insn, src, mode); > > I think you can just leave this as COST? > Yes, it would be better to just use COST, and update COST macro to use insn_cost. Thanks a lot for your greate help! BR, Jiufu > > Segher