Hi, I would like to have a ping.....
BR, Jeff (Jiufu Guo) Jiufu Guo <guoji...@linux.ibm.com> writes: > Hi, > > Currently, we have the pattern "movsf_from_si2" which was trying > to support moving high part DI to SF. > > The pattern looks like: XX:SF=bitcast:SF(subreg(YY:DI>>32),0) > It only accepts the "ashiftrt" for ">>", but "lshiftrt" is also ok. > And the offset of "subreg" is hard code 0, which only works for LE. > > "movsf_from_si2" is updated to cover BE for "subreg", and cover > the logical shift for ":DI>>32". > > Pass bootstrap and regression on ppc64{,le}. > Is this ok for trunk? > > BR, > Jeff (Jiufu Guo) > > PR target/108338 > > gcc/ChangeLog: > > * config/rs6000/predicates.md (lowpart_subreg_operator): New > define_predicate. > * config/rs6000/rs6000.md (any_rshift): New code_iterator. > (movsf_from_si2): Rename to ... > (movsf_from_si2_<code>): ... this. > > gcc/testsuite/ChangeLog: > > * gcc.target/powerpc/pr108338.c: New test. > > --- > gcc/config/rs6000/predicates.md | 5 +++ > gcc/config/rs6000/rs6000.md | 11 +++--- > gcc/testsuite/gcc.target/powerpc/pr108338.c | 40 +++++++++++++++++++++ > 3 files changed, 51 insertions(+), 5 deletions(-) > create mode 100644 gcc/testsuite/gcc.target/powerpc/pr108338.c > > diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md > index > 3552d908e9d149a30993e3e6568466de537336be..e25b3b4864f681d47e9d5c2eb88bcde0aea6d17b > 100644 > --- a/gcc/config/rs6000/predicates.md > +++ b/gcc/config/rs6000/predicates.md > @@ -2098,3 +2098,8 @@ (define_predicate "macho_pic_address" > else > return false; > }) > + > +(define_predicate "lowpart_subreg_operator" > + (and (match_code "subreg") > + (match_test "subreg_lowpart_offset (mode, GET_MODE (SUBREG_REG (op))) > + == SUBREG_BYTE (op)"))) > diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md > index > 1a9a7b1a47918f39fc91038607f21a8ba9a2e740..8c92cbf976de915136ad5dba24e69a363d21438d > 100644 > --- a/gcc/config/rs6000/rs6000.md > +++ b/gcc/config/rs6000/rs6000.md > @@ -8299,18 +8299,19 @@ (define_insn_and_split "movsf_from_si" > "*, *, p9v, p8v, *, *, > p8v, p8v, p8v, *")]) > > +(define_code_iterator any_rshift [ashiftrt lshiftrt]) > + > ;; For extracting high part element from DImode register like: > ;; {%1:SF=unspec[r122:DI>>0x20#0] 86;clobber scratch;} > ;; split it before reload with "and mask" to avoid generating shift right > ;; 32 bit then shift left 32 bit. > -(define_insn_and_split "movsf_from_si2" > +(define_insn_and_split "movsf_from_si2_<code>" > [(set (match_operand:SF 0 "gpc_reg_operand" "=wa") > (unspec:SF > - [(subreg:SI > - (ashiftrt:DI > + [(match_operator:SI 3 "lowpart_subreg_operator" > + [(any_rshift:DI > (match_operand:DI 1 "input_operand" "r") > - (const_int 32)) > - 0)] > + (const_int 32))])] > UNSPEC_SF_FROM_SI)) > (clobber (match_scratch:DI 2 "=r"))] > "TARGET_NO_SF_SUBREG" > diff --git a/gcc/testsuite/gcc.target/powerpc/pr108338.c > b/gcc/testsuite/gcc.target/powerpc/pr108338.c > new file mode 100644 > index > 0000000000000000000000000000000000000000..6db65595343c2407fc32f68f5f52a1f7196c371d > --- /dev/null > +++ b/gcc/testsuite/gcc.target/powerpc/pr108338.c > @@ -0,0 +1,40 @@ > +// { dg-do run } > +// { dg-options "-O2 -save-temps" } > + > +float __attribute__ ((noipa)) sf_from_di_off0 (long long l) > +{ > + char buff[16]; > + *(long long*)buff = l; > + float f = *(float*)(buff); > + return f; > +} > + > +float __attribute__ ((noipa)) sf_from_di_off4 (long long l) > +{ > + char buff[16]; > + *(long long*)buff = l; > + float f = *(float*)(buff + 4); > + return f; > +} > + > +/* Under lp64, parameter 'l' is in one DI reg, then bitcast sub DI to SF. */ > +/* { dg-final { scan-assembler-times {\mxscvspdpn\M} 2 { target { lp64 && > has_arch_pwr8 } } } } */ > +/* { dg-final { scan-assembler-times {\mmtvsrd\M} 2 { target { lp64 && > has_arch_pwr8 } } } } */ > +/* { dg-final { scan-assembler-times {\mrldicr\M} 1 { target { lp64 && > has_arch_pwr8 } } } } */ > +/* { dg-final { scan-assembler-times {\msldi\M} 1 { target { lp64 && > has_arch_pwr8 } } } } */ > + > +union di_sf_sf > +{ > + struct {float f1; float f2;}; > + long long l; > +}; > + > +int main() > +{ > + union di_sf_sf v; > + v.f1 = 1.0f; > + v.f2 = 2.0f; > + if (sf_from_di_off0 (v.l) != 1.0f || sf_from_di_off4 (v.l) != 2.0f ) > + __builtin_abort (); > + return 0; > +}