Rather than using unspecs in doloop insns to stop combine creating these insns, use legitimate_combined_insn.
I'm not sure why the original patch implementing legitimate_combined_insn did not store the result of recog to the insn but it seems good to me, and would allow the recog call in ix86_legitimate_combined_insn to be omitted. (I tested that too, not shown here.) Bootstrapped and regression tested powerpc64le-linux, powerpc64-linux, x86_64-linux. OK for mainline? PR target/72749 * combine.c (recog_for_combine_1): Set INSN_CODE before calling target legitimate_combined_insn. * config/rs6000/rs6000.c (TARGET_LEGITIMATE_COMBINED_INSN): Define. (rs6000_legitimate_combined_insn): New function. * config/rs6000/rs6000.md (UNSPEC_DOLOOP): Delete, and remove all uses. (ctr<mode>_internal3): Rename from *ctr<mode>_internal5. (ctr<mode>_internal4): Rename from *ctr<mode>_internal6. (ctr<mode>_internal1, ctr<mode>_internal2): Remove '*' from name. diff --git a/gcc/combine.c b/gcc/combine.c index 3043f2a..73a74ac 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -11199,6 +11199,7 @@ recog_for_combine_1 (rtx *pnewpat, rtx_insn *insn, rtx *pnotes) old_icode = INSN_CODE (insn); PATTERN (insn) = pat; REG_NOTES (insn) = notes; + INSN_CODE (insn) = insn_code_number; /* Allow targets to reject combined insn. */ if (!targetm.legitimate_combined_insn (insn)) diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 02b521c..76ba81b 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -1558,6 +1558,9 @@ static const struct attribute_spec rs6000_attribute_table[] = #undef TARGET_CONST_NOT_OK_FOR_DEBUG_P #define TARGET_CONST_NOT_OK_FOR_DEBUG_P rs6000_const_not_ok_for_debug_p +#undef TARGET_LEGITIMATE_COMBINED_INSN +#define TARGET_LEGITIMATE_COMBINED_INSN rs6000_legitimate_combined_insn + #undef TARGET_ASM_FUNCTION_PROLOGUE #define TARGET_ASM_FUNCTION_PROLOGUE rs6000_output_function_prologue #undef TARGET_ASM_FUNCTION_EPILOGUE @@ -9076,6 +9079,49 @@ rs6000_const_not_ok_for_debug_p (rtx x) return false; } + +/* Implement the TARGET_LEGITIMATE_COMBINED_INSN hook. */ + +static bool +rs6000_legitimate_combined_insn (rtx_insn *insn) +{ + switch (INSN_CODE (insn)) + { + /* Reject creating doloop insns. Combine should not be allowed + to create these for a number of reasons: + 1) In a nested loop, if combine creates one of these in an + outer loop and the register allocator happens to allocate ctr + to the outer loop insn, then the inner loop can't use ctr. + Inner loops ought to be more highly optimized. + 2) Combine often wants to create one of these from what was + originally a three insn sequence, first combining the three + insns to two, then to ctrsi/ctrdi. When ctrsi/ctrdi is not + allocated ctr, the splitter takes use back to the three insn + sequence. It's better to stop combine at the two insn + sequence. + 3) Faced with not being able to allocate ctr for ctrsi/crtdi + insns, the register allocator sometimes uses floating point + or vector registers for the pseudo. Since ctrsi/ctrdi is a + jump insn and output reloads are not implemented for jumps, + the ctrsi/ctrdi splitters need to handle all possible cases. + That's a pain, and it gets to be seriously difficult when a + splitter that runs after reload needs memory to transfer from + a gpr to fpr. See PR70098 and PR71763 which are not fixed + for the difficult case. It's better to not create problems + in the first place. */ + case CODE_FOR_ctrsi_internal1: + case CODE_FOR_ctrdi_internal1: + case CODE_FOR_ctrsi_internal2: + case CODE_FOR_ctrdi_internal2: + case CODE_FOR_ctrsi_internal3: + case CODE_FOR_ctrdi_internal3: + case CODE_FOR_ctrsi_internal4: + case CODE_FOR_ctrdi_internal4: + return false; + } + return true; +} + /* Construct the SYMBOL_REF for the tls_get_addr function. */ static GTY(()) rtx rs6000_tls_symbol; diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index f7c1ab2..9442b07 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -149,7 +149,6 @@ (define_c_enum "unspec" UNSPEC_IEEE128_MOVE UNSPEC_IEEE128_CONVERT UNSPEC_SIGNBIT - UNSPEC_DOLOOP UNSPEC_SF_FROM_SI UNSPEC_SI_FROM_SF ]) @@ -12740,7 +12739,6 @@ (define_expand "ctr<mode>" (set (match_dup 0) (plus:P (match_dup 0) (const_int -1))) - (unspec [(const_int 0)] UNSPEC_DOLOOP) (clobber (match_scratch:CC 2 "")) (clobber (match_scratch:P 3 ""))])] "" @@ -12751,9 +12749,8 @@ (define_expand "ctr<mode>" ;; JUMP_INSNs. ;; For the length attribute to be calculated correctly, the ;; label MUST be operand 0. -;; The UNSPEC is present to prevent combine creating this pattern. -(define_insn "*ctr<mode>_internal1" +(define_insn "ctr<mode>_internal1" [(set (pc) (if_then_else (ne (match_operand:P 1 "register_operand" "c,*b,*b,*b") (const_int 1)) @@ -12762,7 +12759,6 @@ (define_insn "*ctr<mode>_internal1" (set (match_operand:P 2 "nonimmediate_operand" "=1,*r,m,*d*wi*c*l") (plus:P (match_dup 1) (const_int -1))) - (unspec [(const_int 0)] UNSPEC_DOLOOP) (clobber (match_scratch:CC 3 "=X,&x,&x,&x")) (clobber (match_scratch:P 4 "=X,X,&r,r"))] "" @@ -12778,7 +12774,7 @@ (define_insn "*ctr<mode>_internal1" [(set_attr "type" "branch") (set_attr "length" "*,16,20,20")]) -(define_insn "*ctr<mode>_internal2" +(define_insn "ctr<mode>_internal2" [(set (pc) (if_then_else (ne (match_operand:P 1 "register_operand" "c,*b,*b,*b") (const_int 1)) @@ -12787,7 +12783,6 @@ (define_insn "*ctr<mode>_internal2" (set (match_operand:P 2 "nonimmediate_operand" "=1,*r,m,*d*wi*c*l") (plus:P (match_dup 1) (const_int -1))) - (unspec [(const_int 0)] UNSPEC_DOLOOP) (clobber (match_scratch:CC 3 "=X,&x,&x,&x")) (clobber (match_scratch:P 4 "=X,X,&r,r"))] "" @@ -12805,7 +12800,7 @@ (define_insn "*ctr<mode>_internal2" ;; Similar but use EQ -(define_insn "*ctr<mode>_internal5" +(define_insn "ctr<mode>_internal3" [(set (pc) (if_then_else (eq (match_operand:P 1 "register_operand" "c,*b,*b,*b") (const_int 1)) @@ -12814,7 +12809,6 @@ (define_insn "*ctr<mode>_internal5" (set (match_operand:P 2 "nonimmediate_operand" "=1,*r,m,*d*wi*c*l") (plus:P (match_dup 1) (const_int -1))) - (unspec [(const_int 0)] UNSPEC_DOLOOP) (clobber (match_scratch:CC 3 "=X,&x,&x,&x")) (clobber (match_scratch:P 4 "=X,X,&r,r"))] "" @@ -12830,7 +12824,7 @@ (define_insn "*ctr<mode>_internal5" [(set_attr "type" "branch") (set_attr "length" "*,16,20,20")]) -(define_insn "*ctr<mode>_internal6" +(define_insn "ctr<mode>_internal4" [(set (pc) (if_then_else (eq (match_operand:P 1 "register_operand" "c,*b,*b,*b") (const_int 1)) @@ -12839,7 +12833,6 @@ (define_insn "*ctr<mode>_internal6" (set (match_operand:P 2 "nonimmediate_operand" "=1,*r,m,*d*wi*c*l") (plus:P (match_dup 1) (const_int -1))) - (unspec [(const_int 0)] UNSPEC_DOLOOP) (clobber (match_scratch:CC 3 "=X,&x,&x,&x")) (clobber (match_scratch:P 4 "=X,X,&r,r"))] "" @@ -12866,7 +12859,6 @@ (define_split (match_operand 6 "" ""))) (set (match_operand:P 0 "int_reg_operand" "") (plus:P (match_dup 1) (const_int -1))) - (unspec [(const_int 0)] UNSPEC_DOLOOP) (clobber (match_scratch:CC 3 "")) (clobber (match_scratch:P 4 ""))] "reload_completed" @@ -12892,7 +12884,6 @@ (define_split (match_operand 6 "" ""))) (set (match_operand:P 0 "nonimmediate_operand" "") (plus:P (match_dup 1) (const_int -1))) - (unspec [(const_int 0)] UNSPEC_DOLOOP) (clobber (match_scratch:CC 3 "")) (clobber (match_scratch:P 4 ""))] "reload_completed && ! gpc_reg_operand (operands[0], SImode)" diff --git a/gcc/testsuite/gcc.c-torture/compile/pr72749.c b/gcc/testsuite/gcc.c-torture/compile/pr72749.c new file mode 100644 index 0000000..2ef4d9a --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr72749.c @@ -0,0 +1,21 @@ +/* { dg-options "-O2 -fsched2-use-superblocks" } */ + +int as; + +void +ji (int *x4) +{ + if (0) + { + unsigned int pv; + + while (as < 0) + { + for (*x4 = 0; *x4 < 1; ++(*x4)) +yj: + x4 = (int *)&pv; + ++as; + } + } + goto yj; +} -- Alan Modra Australia Development Lab, IBM