Hi! rs6000.md has 2 sets of patterns for and with comparison, the non-_mask ones have !rs6000_is_valid_and_mask (operands[2], <MODE>mode) predicate and have an extra clobber for the case where the destination is not first cc reg, while the second set implicitly assumes the operand is a valid mask operand, don't have that extra clobber and split into and form that doesn't clobber the first cc reg. Unfortunately that implicit assumption doesn't hold when e.g. IRA creates such insn (replaces a pseudo with a const_int); then we match even when the operand isn't valid mask but split into something that requires it.
Fixed thusly, Segher has kindly bootstrapped/regtest it on powerpc* and pre-approved on IRC. Committed to trunk. 2016-12-09 Jakub Jelinek <ja...@redhat.com> PR target/72742 * config/rs6000/rs6000.md (*and<mode>3_imm_mask_dot, *and<mode>3_imm_mask_dot2): Add rs6000_is_valid_and_mask to insn condition. * gcc.c-torture/compile/pr72742.c: New test. --- gcc/config/rs6000/rs6000.md.jj 2016-12-07 10:11:32.000000000 +0100 +++ gcc/config/rs6000/rs6000.md 2016-12-09 16:30:50.604370286 +0100 @@ -3254,7 +3254,8 @@ (define_insn_and_split "*and<mode>3_imm_ (const_int 0))) (clobber (match_scratch:GPR 0 "=r,r"))] "(<MODE>mode == Pmode || UINTVAL (operands[2]) <= 0x7fffffff) - && rs6000_gen_cell_microcode" + && rs6000_gen_cell_microcode + && rs6000_is_valid_and_mask (operands[2], <MODE>mode)" "@ andi%e2. %0,%1,%u2 #" @@ -3279,7 +3280,8 @@ (define_insn_and_split "*and<mode>3_imm_ (and:GPR (match_dup 1) (match_dup 2)))] "(<MODE>mode == Pmode || UINTVAL (operands[2]) <= 0x7fffffff) - && rs6000_gen_cell_microcode" + && rs6000_gen_cell_microcode + && rs6000_is_valid_and_mask (operands[2], <MODE>mode)" "@ andi%e2. %0,%1,%u2 #" --- gcc/testsuite/gcc.c-torture/compile/pr72742.c.jj 2016-12-09 16:39:10.327036689 +0100 +++ gcc/testsuite/gcc.c-torture/compile/pr72742.c 2016-12-09 16:38:57.000000000 +0100 @@ -0,0 +1,79 @@ +/* PR target/72742 */ + +int a, b; +unsigned short int c; + +void +foo (int x, unsigned short int *y) +{ + int fx; + lab: + { + unsigned short int va; + if (x != 0) + { + c %= a < 0; + while (c < 17) + ++c; + b &= fx; + if ((a & (b != 0 ? *y : 0)) != 0) + { + va /= 3; + a += (va != 0) ? (va = a) : 0; + } + a = va && a; + goto lab; + y = &va; + } + } +} + +void +bar (int x, unsigned short int *y) +{ + int fx; + lab: + { + unsigned short int va; + if (x != 0) + { + c %= a < 0; + while (c < 17) + ++c; + b &= fx; + if ((a & (b != 0 ? *y : 24)) != 0) + { + va /= 3; + a += (va != 0) ? (va = a) : 0; + } + a = va && a; + goto lab; + y = &va; + } + } +} + +void +baz (int x, unsigned short int *y) +{ + int fx; + lab: + { + unsigned short int va; + if (x != 0) + { + c %= a < 0; + while (c < 17) + ++c; + b &= fx; + if ((a & (b != 0 ? *y : 25)) != 0) + { + va /= 3; + a += (va != 0) ? (va = a) : 0; + } + a = va && a; + goto lab; + y = &va; + } + } +} Jakub