Hi, on 2023/12/6 16:13, HAO CHEN GUI wrote: > Hi, > SImode in float register is supported on P7 above. It causes "fctiw" > can't be generated on old 32-bit processors as the output operand of > fctiw insn is an SImode in float/double register. This patch fixes the > problem by adding one expand and one insn pattern for fctiw. The output > of new pattern is DImode. When the targets don't support SImode in > float register, it calls the new insn pattern and convert the DImode > to SImode via stack. > > Compared to last version, > https://gcc.gnu.org/pipermail/gcc-patches/2023-December/638860.html > the main change is to change the mode of output operand of the new > insn from SFmode to DImode so that it can call stfiwx pattern directly. > No need additional unspecs. > > Bootstrapped and tested on x86 and powerpc64-linux BE and LE with > no regressions. Is this OK for trunk? > > Thanks > Gui Haochen > > ChangeLog > rs6000: enable fctiw on old archs
Nit: s/rchs/old archs with stfiwx enabled/ > > The powerpc 32-bit processors (e.g. 5470) supports "fctiw" instruction, > but the instruction can't be generated on such platforms as the insn is > guard by TARGET_POPCNTD. The root cause is SImode in float register is > supported from Power7. Actually implementation of "fctiw" only needs > stfiwx which is supported by the old 32-bit processors. This patch > enables "fctiw" expand for these processors. > > gcc/ > PR target/112707 > * config/rs6000/rs6000.md (expand lrint<mode>si2): New. > (insn lrint<mode>si2): Rename to... > (*lrint<mode>si): ...this. > (lrint<mode>si_di): New. > > gcc/testsuite/ > PR target/112707 > * gcc.target/powerpc/pr112707-1.c: New. > > patch.diff > diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md > index 2a1b5ecfaee..dfb7f19c6ad 100644 > --- a/gcc/config/rs6000/rs6000.md > +++ b/gcc/config/rs6000/rs6000.md > @@ -6722,7 +6722,27 @@ (define_insn "lrint<mode>di2" > "fctid %0,%1" > [(set_attr "type" "fp")]) > > -(define_insn "lrint<mode>si2" > +(define_expand "lrint<mode>si2" > + [(set (match_operand:SI 0 "gpc_reg_operand" "=d") > + (unspec:SI [(match_operand:SFDF 1 "gpc_reg_operand" "<rreg2>")] > + UNSPEC_FCTIW))] > + "TARGET_HARD_FLOAT && TARGET_STFIWX" > +{ > + /* For those old archs in which SImode can't be hold in float registers, > + call lrint<mode>si_internal2 to put the result in SFmode then Nit: s/_internal2/_di/ s/SFmode/DImode/ OK for trunk with the above nits fixed, thanks! BR, Kewen > + convert it via stack. */ > + if (!TARGET_POPCNTD) > + { > + rtx tmp = gen_reg_rtx (DImode); > + emit_insn (gen_lrint<mode>si_di (tmp, operands[1])); > + rtx stack = rs6000_allocate_stack_temp (SImode, false, true); > + emit_insn (gen_stfiwx (stack, tmp)); > + emit_move_insn (operands[0], stack); > + DONE; > + } > +}) > + > +(define_insn "*lrint<mode>si" > [(set (match_operand:SI 0 "gpc_reg_operand" "=d") > (unspec:SI [(match_operand:SFDF 1 "gpc_reg_operand" "<rreg2>")] > UNSPEC_FCTIW))] > @@ -6730,6 +6750,14 @@ (define_insn "lrint<mode>si2" > "fctiw %0,%1" > [(set_attr "type" "fp")]) > > +(define_insn "lrint<mode>si_di" > + [(set (match_operand:DI 0 "gpc_reg_operand" "=d") > + (unspec:DI [(match_operand:SFDF 1 "gpc_reg_operand" "<rreg2>")] > + UNSPEC_FCTIW))] > + "TARGET_HARD_FLOAT && !TARGET_POPCNTD" > + "fctiw %0,%1" > + [(set_attr "type" "fp")]) > + > (define_insn "btrunc<mode>2" > [(set (match_operand:SFDF 0 "gpc_reg_operand" "=d,wa") > (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "d,wa")] > diff --git a/gcc/testsuite/gcc.target/powerpc/pr112707-1.c > b/gcc/testsuite/gcc.target/powerpc/pr112707-1.c > new file mode 100644 > index 00000000000..cce6bd7f690 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/powerpc/pr112707-1.c > @@ -0,0 +1,16 @@ > +/* { dg-do compile } */ > +/* { dg-options "-O2 -mdejagnu-cpu=7450 -fno-math-errno" } */ > +/* { dg-require-effective-target ilp32 } */ > +/* { dg-skip-if "" { has_arch_ppc64 } } */ > +/* { dg-final { scan-assembler-times {\mfctiw\M} 2 } } */ > +/* { dg-final { scan-assembler-times {\mstfiwx\M} 2 } } */ > + > +int test1 (double a) > +{ > + return __builtin_irint (a); > +} > + > +int test2 (float a) > +{ > + return __builtin_irint (a); > +}