Hi I updated this patch to use const_ok_for_dimode_op to decide if a const is legal for xordi3 insn. The special cases of all 0 and all 1 are also handled.
Tested on arm qemu with all thumb/arm neon/non-neon combination. The testcase save-temps-1.c failed in arm/non-neon mode, it should be http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53145, it also failed in other arm configuration http://gcc.gnu.org/ml/gcc-testresults/2012-06/msg00755.html, so it is not a new regression. thanks Carrot 2012-07-05 Wei Guozhi <car...@google.com> PR target/53189 * gcc.target/arm/pr53189-4.c: New testcase. * gcc.target/arm/pr53189-5.c: New testcase. * gcc.target/arm/pr53189-6.c: New testcase. 2012-07-05 Wei Guozhi <car...@google.com> PR target/53189 * config/arm/arm.c (const_ok_for_dimode_op): Handle XOR op. * config/arm/constraints.md (Dg): New constraint. * config/arm/predicates.md (arm_xordi_operand): New predicate. (arm_immediate_xordi_operand): Likewise. * config/arm/arm.md (arm_xorsi3): Optimization for special constants. (xordi3): Extend it to handle 64bit constants. (xordi3_insn): Likewise. * config/arm/neon.md (xordi3_neon): Likewise. Index: testsuite/gcc.target/arm/pr53189-4.c =================================================================== --- testsuite/gcc.target/arm/pr53189-4.c (revision 0) +++ testsuite/gcc.target/arm/pr53189-4.c (revision 0) @@ -0,0 +1,8 @@ +/* { dg-options "-O2" } */ +/* { dg-require-effective-target arm32 } */ +/* { dg-final { scan-assembler-not "mov" } } */ + +void t0p(long long * p) +{ + *p ^= 0x100000003; +} Index: testsuite/gcc.target/arm/pr53189-5.c =================================================================== --- testsuite/gcc.target/arm/pr53189-5.c (revision 0) +++ testsuite/gcc.target/arm/pr53189-5.c (revision 0) @@ -0,0 +1,9 @@ +/* { dg-options "-O2" } */ +/* { dg-require-effective-target arm32 } */ +/* { dg-final { scan-assembler-times "mvn" 1 } } */ +/* { dg-final { scan-assembler-times "eor" 1 } } */ + +void t0p(long long * p) +{ + *p ^= 0x2FFFFFFFF; +} Index: testsuite/gcc.target/arm/pr53189-6.c =================================================================== --- testsuite/gcc.target/arm/pr53189-6.c (revision 0) +++ testsuite/gcc.target/arm/pr53189-6.c (revision 0) @@ -0,0 +1,9 @@ +/* { dg-options "-O2" } */ +/* { dg-require-effective-target arm32 } */ +/* { dg-final { scan-assembler-not "mov" } } */ +/* { dg-final { scan-assembler-times "eor" 1 } } */ + +void t0p(long long * p) +{ + *p ^= 0x200000000; +} Index: config/arm/arm.c =================================================================== --- config/arm/arm.c (revision 189245) +++ config/arm/arm.c (working copy) @@ -2524,6 +2524,10 @@ case PLUS: return arm_not_operand (hi, SImode) && arm_add_operand (lo, SImode); + case XOR: + return ((const_ok_for_arm (hi_val) || (hi_val == 0xFFFFFFFF)) + && (const_ok_for_arm (lo_val) || (lo_val == 0xFFFFFFFF))); + default: return 0; } Index: config/arm/neon.md =================================================================== --- config/arm/neon.md (revision 189245) +++ config/arm/neon.md (working copy) @@ -880,18 +880,20 @@ ) (define_insn "xordi3_neon" - [(set (match_operand:DI 0 "s_register_operand" "=w,?&r,?&r,?w") - (xor:DI (match_operand:DI 1 "s_register_operand" "%w,0,r,w") - (match_operand:DI 2 "s_register_operand" "w,r,r,w")))] + [(set (match_operand:DI 0 "s_register_operand" "=w,?&r,?&r,?w,?&r,?&r") + (xor:DI (match_operand:DI 1 "s_register_operand" "%w,0,r,w,0,r") + (match_operand:DI 2 "arm_xordi_operand" "w,r,r,w,Dg,Dg")))] "TARGET_NEON" "@ veor\t%P0, %P1, %P2 # # - veor\t%P0, %P1, %P2" - [(set_attr "neon_type" "neon_int_1,*,*,neon_int_1") - (set_attr "length" "*,8,8,*") - (set_attr "arch" "nota8,*,*,onlya8")] + veor\t%P0, %P1, %P2 + # + #" + [(set_attr "neon_type" "neon_int_1,*,*,neon_int_1,*,*") + (set_attr "length" "*,8,8,*,8,8") + (set_attr "arch" "nota8,*,*,onlya8,*,*")] ) (define_insn "one_cmpl<mode>2" Index: config/arm/constraints.md =================================================================== --- config/arm/constraints.md (revision 189245) +++ config/arm/constraints.md (working copy) @@ -31,7 +31,7 @@ ;; 'H' was previously used for FPA. ;; The following multi-letter normal constraints have been used: -;; in ARM/Thumb-2 state: Da, Db, Dc, Dd, Dn, Dl, DL, Dv, Dy, Di, Dt, Dz +;; in ARM/Thumb-2 state: Da, Db, Dc, Dd, Dg, Dn, Dl, DL, Dv, Dy, Di, Dt, Dz ;; in Thumb-1 state: Pa, Pb, Pc, Pd, Pe ;; in Thumb-2 state: Pj, PJ, Ps, Pt, Pu, Pv, Pw, Px, Py @@ -248,6 +248,12 @@ (and (match_code "const_int") (match_test "TARGET_32BIT && const_ok_for_dimode_op (ival, PLUS)"))) +(define_constraint "Dg" + "@internal + In ARM/Thumb-2 state a const_int that can be used by insn xordi." + (and (match_code "const_int") + (match_test "TARGET_32BIT && const_ok_for_dimode_op (ival, XOR)"))) + (define_constraint "Di" "@internal In ARM/Thumb-2 state a const_int or const_double where both the high Index: config/arm/predicates.md =================================================================== --- config/arm/predicates.md (revision 189245) +++ config/arm/predicates.md (working copy) @@ -104,6 +104,14 @@ (and (match_code "const_int,const_double") (match_test "arm_const_double_by_immediates (op)"))) +(define_predicate "arm_immediate_xordi_operand" + (and (match_code "const_int") + (match_test "const_ok_for_dimode_op (INTVAL (op), XOR)"))) + +(define_predicate "arm_xordi_operand" + (ior (match_operand 0 "arm_immediate_xordi_operand") + (match_operand 0 "s_register_operand"))) + (define_predicate "arm_neg_immediate_operand" (and (match_code "const_int") (match_test "const_ok_for_arm (-INTVAL (op))"))) Index: config/arm/arm.md =================================================================== --- config/arm/arm.md (revision 189245) +++ config/arm/arm.md (working copy) @@ -2968,17 +2968,30 @@ (define_expand "xordi3" [(set (match_operand:DI 0 "s_register_operand" "") (xor:DI (match_operand:DI 1 "s_register_operand" "") - (match_operand:DI 2 "s_register_operand" "")))] + (match_operand:DI 2 "arm_xordi_operand" "")))] "TARGET_32BIT" "" ) -(define_insn "*xordi3_insn" - [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") - (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r") - (match_operand:DI 2 "s_register_operand" "r,r")))] +(define_insn_and_split "*xordi3_insn" + [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r,&r") + (xor:DI (match_operand:DI 1 "s_register_operand" "%0, r, 0, r") + (match_operand:DI 2 "arm_xordi_operand" "r, r, Dg,Dg")))] "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON" "#" + "TARGET_32BIT && !TARGET_IWMMXT && reload_completed + && !(TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))" + [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2))) + (set (match_dup 3) (xor:SI (match_dup 4) (match_dup 5)))] + " + { + operands[3] = gen_highpart (SImode, operands[0]); + operands[0] = gen_lowpart (SImode, operands[0]); + operands[4] = gen_highpart (SImode, operands[1]); + operands[1] = gen_lowpart (SImode, operands[1]); + operands[5] = gen_highpart_mode (SImode, DImode, operands[2]); + operands[2] = gen_lowpart (SImode, operands[2]); + }" [(set_attr "length" "8") (set_attr "predicable" "yes")] ) @@ -3040,9 +3053,27 @@ (xor:SI (match_operand:SI 1 "s_register_operand" "%r,r") (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))] "TARGET_32BIT" - "@ - eor%?\\t%0, %1, %2 - #" + "* + { + if (CONST_INT_P (operands[2])) + { + HOST_WIDE_INT i = INTVAL (operands[2]) & 0xFFFFFFFF; + if (i == 0xFFFFFFFF) + return \"mvn%?\\t%0, %1\"; + if (i == 0) + { + if (!rtx_equal_p (operands[0], operands[1])) + return \"mov%?\\t%0, %1\"; + else + return \"\"; + } + } + + if (which_alternative == 0) + return \"eor%?\\t%0, %1, %2\"; + else + return \"#\"; + }" "TARGET_32BIT && GET_CODE (operands[2]) == CONST_INT && !const_ok_for_arm (INTVAL (operands[2]))" On Wed, May 30, 2012 at 5:22 PM, Carrot Wei <car...@google.com> wrote: > Hi > > This is the third part of the patches that deals with 64bit xor. It extends > the patterns xordi3, xordi3_insn and xordi3_neon to handle 64bit constant > operands. > > Tested on arm qemu without regression. > > OK for trunk? > > thanks > Carrot > > 2012-05-30 Wei Guozhi <car...@google.com> > > PR target/53447 > * gcc.target/arm/pr53447-3.c: New testcase. > > > 2012-05-30 Wei Guozhi <car...@google.com> > > PR target/53447 > * config/arm/arm.md (xordi3): Extend it to handle 64bit constants. > (xordi3_insn): Likewise. > * config/arm/neon.md (xordi3_neon): Likewise. > > > > > Index: testsuite/gcc.target/arm/pr53447-3.c > =================================================================== > --- testsuite/gcc.target/arm/pr53447-3.c (revision 0) > +++ testsuite/gcc.target/arm/pr53447-3.c (revision 0) > @@ -0,0 +1,8 @@ > +/* { dg-options "-O2" } */ > +/* { dg-require-effective-target arm32 } */ > +/* { dg-final { scan-assembler-not "mov" } } */ > + > +void t0p(long long * p) > +{ > + *p ^= 0x100000003; > +} > Index: config/arm/neon.md > =================================================================== > --- config/arm/neon.md (revision 187998) > +++ config/arm/neon.md (working copy) > @@ -878,18 +878,20 @@ > ) > > (define_insn "xordi3_neon" > - [(set (match_operand:DI 0 "s_register_operand" "=w,?&r,?&r,?w") > - (xor:DI (match_operand:DI 1 "s_register_operand" "%w,0,r,w") > - (match_operand:DI 2 "s_register_operand" "w,r,r,w")))] > + [(set (match_operand:DI 0 "s_register_operand" "=w,?&r,?&r,?w,?&r,?&r") > + (xor:DI (match_operand:DI 1 "s_register_operand" "%w,0,r,w,0,r") > + (match_operand:DI 2 "arm_di_operand" "w,r,r,w,Di,Di")))] > "TARGET_NEON" > "@ > veor\t%P0, %P1, %P2 > # > # > - veor\t%P0, %P1, %P2" > - [(set_attr "neon_type" "neon_int_1,*,*,neon_int_1") > - (set_attr "length" "*,8,8,*") > - (set_attr "arch" "nota8,*,*,onlya8")] > + veor\t%P0, %P1, %P2 > + # > + #" > + [(set_attr "neon_type" "neon_int_1,*,*,neon_int_1,*,*") > + (set_attr "length" "*,8,8,*,8,8") > + (set_attr "arch" "nota8,*,*,onlya8,*,*")] > ) > > (define_insn "one_cmpl<mode>2" > Index: config/arm/arm.md > =================================================================== > --- config/arm/arm.md (revision 187998) > +++ config/arm/arm.md (working copy) > @@ -2994,17 +2994,38 @@ > (define_expand "xordi3" > [(set (match_operand:DI 0 "s_register_operand" "") > (xor:DI (match_operand:DI 1 "s_register_operand" "") > - (match_operand:DI 2 "s_register_operand" "")))] > + (match_operand:DI 2 "arm_di_operand" "")))] > "TARGET_32BIT" > "" > ) > > -(define_insn "*xordi3_insn" > - [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") > - (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r") > - (match_operand:DI 2 "s_register_operand" "r,r")))] > +(define_insn_and_split "*xordi3_insn" > + [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r,&r") > + (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r,0,r") > + (match_operand:DI 2 "arm_di_operand" "r,r,Di,Di")))] > "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON" > "#" > + "TARGET_32BIT && !TARGET_IWMMXT && reload_completed" > + [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2))) > + (set (match_dup 3) (xor:SI (match_dup 4) (match_dup 5)))] > + " > + { > + operands[3] = gen_highpart (SImode, operands[0]); > + operands[0] = gen_lowpart (SImode, operands[0]); > + operands[4] = gen_highpart (SImode, operands[1]); > + operands[1] = gen_lowpart (SImode, operands[1]); > + if (GET_CODE (operands[2]) == CONST_INT) > + { > + HOST_WIDE_INT v = INTVAL (operands[2]); > + operands[5] = GEN_INT (ARM_SIGN_EXTEND ((v >> 32) & 0xFFFFFFFF)); > + operands[2] = GEN_INT (ARM_SIGN_EXTEND (v & 0xFFFFFFFF)); > + } > + else > + { > + operands[5] = gen_highpart (SImode, operands[2]); > + operands[2] = gen_lowpart (SImode, operands[2]); > + } > + }" > [(set_attr "length" "8") > (set_attr "predicable" "yes")] > )