Hi all, In this PR we ICE because during post-reload splitting we generate the insn: (insn 27 26 11 2 (set (reg:SI 0 r0 [orig:121 D.4992 ] [121]) (and:SI (not:SI (const_int 1 [0x1])) (reg:SI 0 r0 [orig:121 D.4992 ] [121]))) (nil))
The splitter at fault is andsi_iorsi3_notsi that accepts a const_int in operands[3] and outputs (not (match_dup 3)). It should really be trying to constant fold the result first. This patch does that by calling simplify_gen_unary to generate the complement of operands[3] if it's a register or the appropriate const_int rtx with the correct folded result that will still properly match the arm bic-immediate instruction. Bootstrapped and tested on arm-none-eabi. Is this ok for trunk? This appears on GCC 4.9 and GCC 5 and I'll be testing the fix there as well. Ok for those branches if testing is successful? Thanks, Kyrill 2015-12-07 Kyrylo Tkachov <kyrylo.tkac...@arm.com> PR target/68648 * config/arm/arm.md (*andsi_iorsi3_notsi): Try to simplify the complement of operands[3] during splitting. 2015-12-07 Kyrylo Tkachov <kyrylo.tkac...@arm.com> PR target/68648 * gcc.c-torture/execute/pr68648.c: New test.
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index 2b48bbaf034b286d723536ec2aa6fe0f9b312911..dfb75c5f11c66c6b4a34ff3071b5a0957c3512cb 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -3274,8 +3274,22 @@ (define_insn_and_split "*andsi_iorsi3_notsi" "#" ; "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3" "&& reload_completed" [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2))) - (set (match_dup 0) (and:SI (not:SI (match_dup 3)) (match_dup 0)))] - "" + (set (match_dup 0) (and:SI (match_dup 4) (match_dup 5)))] + { + /* If operands[3] is a constant make sure to fold the NOT into it + to avoid creating a NOT of a CONST_INT. */ + rtx not_rtx = simplify_gen_unary (NOT, SImode, operands[3], SImode); + if (CONST_INT_P (not_rtx)) + { + operands[4] = operands[0]; + operands[5] = not_rtx; + } + else + { + operands[5] = operands[0]; + operands[4] = not_rtx; + } + } [(set_attr "length" "8") (set_attr "ce_count" "2") (set_attr "predicable" "yes") diff --git a/gcc/testsuite/gcc.c-torture/execute/pr68648.c b/gcc/testsuite/gcc.c-torture/execute/pr68648.c new file mode 100644 index 0000000000000000000000000000000000000000..fc66806a99a0abef7bd517ae2f5200b387e69ce4 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr68648.c @@ -0,0 +1,20 @@ +int __attribute__ ((noinline)) +foo (void) +{ + return 123; +} + +int __attribute__ ((noinline)) +bar (void) +{ + int c = 1; + c |= 4294967295 ^ (foo () | 4073709551608); + return c; +} + +int +main () +{ + if (bar () != 0x83fd4005) + __builtin_abort (); +}