On 25/01/17 10:58, Kyrill Tkachov wrote: > Hi all, > > We're hitting an ICE when expanding a DImode xor with an immediate on > TARGET_IWMMXT: > (insn 6 5 7 2 (set (reg:DI 111 [ t1.1_3 ]) > (xor:DI (reg:DI 110 [ t1.0_2 ]) > (const_int 85 [0x55]))) ./z32.c:13 -1 > (nil)) > > The problem is that the general xordi3 expander accepts some immediates > in operand 2 but the iwmmxt_xordi3 > define_insn only accepts register operands, and nothing forces the > operand into a register in between. > This doesn't affect the iordi3 or anddi3 expanders because their > predicates are designed to accept immediates > valid for the VORR and VBIC NEON instructions and thus check for > TARGET_NEON as well, so they don't accept any > immediates during expand time for TARGET_IWMMXT. > > A fix could be to modify arm_xordi_operand to allow only register > operands for TARGET_IWMMXT. > Another approach, used in this patch, is to force the constants into > registers in the expander itself. > > Bootstrapped and tested on arm-none-linux-gnueabihf (I don't have access > to iWMMXt hardware). > > Ok for trunk and the branches after some time? > This patch should only affect TARGET_IWMMXT and therefore is pretty safe > at any stage. > > Thanks, > Kyrill > > 2016-01-25 Kyrylo Tkachov <kyrylo.tkac...@arm.com> > > PR target/79145 > * config/arm/arm.md (xordi3): Force constant operand into a register > for TARGET_IWMMXT. > > 2016-01-25 Kyrylo Tkachov <kyrylo.tkac...@arm.com> > > PR target/79145 > * gcc.target/arm/pr79145.c: New test. >
OK. R. > iwmmxt-xor.patch > > > diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md > index > 2eee8bc5701297f52e5ed991f074f1069bde1b6e..48bf07e5b6c121944b38ab8d0d14b029d2b34560 > 100644 > --- a/gcc/config/arm/arm.md > +++ b/gcc/config/arm/arm.md > @@ -3328,7 +3328,14 @@ (define_expand "xordi3" > (xor:DI (match_operand:DI 1 "s_register_operand" "") > (match_operand:DI 2 "arm_xordi_operand" "")))] > "TARGET_32BIT" > - "" > + { > + /* The iWMMXt pattern for xordi3 accepts only register operands but we > want > + to reuse this expander for all TARGET_32BIT targets so just force the > + constants into a register. Unlike for the anddi3 and iordi3 there are > + no NEON instructions that take an immediate. */ > + if (TARGET_IWMMXT && !REG_P (operands[2])) > + operands[2] = force_reg (DImode, operands[2]); > + } > ) > > (define_insn_and_split "*xordi3_insn" > diff --git a/gcc/testsuite/gcc.target/arm/pr79145.c > b/gcc/testsuite/gcc.target/arm/pr79145.c > new file mode 100644 > index > 0000000000000000000000000000000000000000..667824400390d6fe72d05a85769d210791b8c378 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/arm/pr79145.c > @@ -0,0 +1,16 @@ > +/* { dg-do compile } */ > +/* { dg-skip-if "Test is specific to the iWMMXt" { arm*-*-* } { "-mcpu=*" } > { "-mcpu=iwmmxt" } } */ > +/* { dg-skip-if "Test is specific to the iWMMXt" { arm*-*-* } { "-mabi=*" } > { "-mabi=iwmmxt" } } */ > +/* { dg-skip-if "Test is specific to the iWMMXt" { arm*-*-* } { "-march=*" } > { "-march=iwmmxt" } } */ > +/* { dg-skip-if "Test is specific to ARM mode" { arm*-*-* } { "-mthumb" } { > "" } } */ > +/* { dg-require-effective-target arm32 } */ > +/* { dg-require-effective-target arm_iwmmxt_ok } */ > +/* { dg-options "-mcpu=iwmmxt" } */ > + > +int > +main (void) > +{ > + volatile long long t1; > + t1 ^= 0x55; > + return 0; > +} >