As noted in the PR, there are a few insns in the ARM backend which use const_int_operand as a predicate, but which have constraints like "I" or "M".
With the predicate accepting all constants, it's possible for a pass such as combine to create an insn where the constant operand matches the loose predicate, but will not match the tighter constraint. WIth no other alternatives to choose from, lra/reload won't be able to fixup the insn.
The right way (IMHO) is to tighten the predicate in these cases. This patch introduces const_int_I_operand and const_int_M_operand.
Bootstrapped on arm7l-unknown-linux-gnu (without java which fails for unrelated reasons) and regression tested. One system didn't have GDB installed, so the atomic and guality tests were noisy and due to time constraints, I haven't re-run them.
OK for the trunk?
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8d0c021..6c170d3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2014-04-03 Jeff Law <l...@redhat.com> + + PR target/60657 + * arm/predicates.md (const_int_I_operand): New predicate. + (const_int_M_operand): Similarly. + * arm/arm.md (insv_zero): Use const_int_M_operand instead of + const_int_operand. + (insv_t2, extv_reg, extzv_t2): Likewise. + (load_multiple_with_writeback): Similarly for const_int_I_operand. + (pop_multiple_with_writeback_and_return): Likewise. + (vfp_pop_multiple_with_writeback): Likewise + 2014-04-03 Richard Biener <rguent...@suse.de> * tree-streamer.h (struct streamer_tree_cache_d): Add next_idx diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index 4df24a2..4b81ee2 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -2784,8 +2784,8 @@ (define_insn "insv_zero" [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r") - (match_operand:SI 1 "const_int_operand" "M") - (match_operand:SI 2 "const_int_operand" "M")) + (match_operand:SI 1 "const_int_M_operand" "M") + (match_operand:SI 2 "const_int_M_operand" "M")) (const_int 0))] "arm_arch_thumb2" "bfc%?\t%0, %2, %1" @@ -2797,8 +2797,8 @@ (define_insn "insv_t2" [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r") - (match_operand:SI 1 "const_int_operand" "M") - (match_operand:SI 2 "const_int_operand" "M")) + (match_operand:SI 1 "const_int_M_operand" "M") + (match_operand:SI 2 "const_int_M_operand" "M")) (match_operand:SI 3 "s_register_operand" "r"))] "arm_arch_thumb2" "bfi%?\t%0, %3, %2, %1" @@ -4480,8 +4480,8 @@ (define_insn "*extv_reg" [(set (match_operand:SI 0 "s_register_operand" "=r") (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r") - (match_operand:SI 2 "const_int_operand" "M") - (match_operand:SI 3 "const_int_operand" "M")))] + (match_operand:SI 2 "const_int_M_operand" "M") + (match_operand:SI 3 "const_int_M_operand" "M")))] "arm_arch_thumb2" "sbfx%?\t%0, %1, %3, %2" [(set_attr "length" "4") @@ -4493,8 +4493,8 @@ (define_insn "extzv_t2" [(set (match_operand:SI 0 "s_register_operand" "=r") (zero_extract:SI (match_operand:SI 1 "s_register_operand" "r") - (match_operand:SI 2 "const_int_operand" "M") - (match_operand:SI 3 "const_int_operand" "M")))] + (match_operand:SI 2 "const_int_M_operand" "M") + (match_operand:SI 3 "const_int_M_operand" "M")))] "arm_arch_thumb2" "ubfx%?\t%0, %1, %3, %2" [(set_attr "length" "4") @@ -12073,7 +12073,7 @@ [(match_parallel 0 "load_multiple_operation" [(set (match_operand:SI 1 "s_register_operand" "+rk") (plus:SI (match_dup 1) - (match_operand:SI 2 "const_int_operand" "I"))) + (match_operand:SI 2 "const_int_I_operand" "I"))) (set (match_operand:SI 3 "s_register_operand" "=rk") (mem:SI (match_dup 1))) ])] @@ -12102,7 +12102,7 @@ [(return) (set (match_operand:SI 1 "s_register_operand" "+rk") (plus:SI (match_dup 1) - (match_operand:SI 2 "const_int_operand" "I"))) + (match_operand:SI 2 "const_int_I_operand" "I"))) (set (match_operand:SI 3 "s_register_operand" "=rk") (mem:SI (match_dup 1))) ])] @@ -12155,7 +12155,7 @@ [(match_parallel 0 "pop_multiple_fp" [(set (match_operand:SI 1 "s_register_operand" "+rk") (plus:SI (match_dup 1) - (match_operand:SI 2 "const_int_operand" "I"))) + (match_operand:SI 2 "const_int_I_operand" "I"))) (set (match_operand:DF 3 "vfp_hard_register_operand" "") (mem:DF (match_dup 1)))])] "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP" diff --git a/gcc/config/arm/predicates.md b/gcc/config/arm/predicates.md index ce5c9a8..6273e88 100644 --- a/gcc/config/arm/predicates.md +++ b/gcc/config/arm/predicates.md @@ -153,6 +153,14 @@ (ior (match_operand 0 "arm_rhs_operand") (match_operand 0 "memory_operand"))) +(define_predicate "const_int_I_operand" + (and (match_operand 0 "const_int_operand") + (match_test "satisfies_constraint_I (op)"))) + +(define_predicate "const_int_M_operand" + (and (match_operand 0 "const_int_operand") + (match_test "satisfies_constraint_M (op)"))) + ;; This doesn't have to do much because the constant is already checked ;; in the shift_operator predicate. (define_predicate "shift_amount_operand" diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 3a58dc2..94d354c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2014-04-03 Jeff Law <l...@redhat.com> + + PR target/60657 + * gcc.target/arm/pr60657.c: New test. + 2014-04-03 Richard Biener <rguent...@suse.de> PR tree-optimization/60740 diff --git a/gcc/testsuite/gcc.target/arm/pr60657.c b/gcc/testsuite/gcc.target/arm/pr60657.c new file mode 100644 index 0000000..d70e58c --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/pr60657.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=armv7-a" } */ + + +void foo (void); + +void +bar (int x, int y) +{ + y = 9999; + if (x & (1 << y)) + foo (); +