I'm working on the AVR cc0 -> CCmode conversion (bug#92729). One problem is that the cmpelim pass is currently very strict in requiring insns of the form
(parallel [(set (reg:SI) (op:SI ... ...)) (clobber (reg:CC REG_CC))]) when in fact AVR's insns often have the form (parallel [(set (reg:SI) (op:SI ... ...)) (clobber (scratch:QI)) (clobber (reg:CC REG_CC))]) The attached patch relaxes checks in the cmpelim code to recognize such insns, and makes it attempt to recognize (parallel [(set (reg:CC REG_CC) (compare:CC ... ...)) (set (reg:SI (op:SI ... ...))) (clobber (scratch:QI))]) as a new insn for that example. This appears to work. I've bootstrapped and run the test suite with the patch, without differences.
From 788bf691aed9f27e1719a6c2e61b12f2a24e6b5d Mon Sep 17 00:00:00 2001 From: Pip Cet <pipcet@gmail.com> Date: Tue, 4 Aug 2020 18:44:26 +0000 Subject: [PATCH] cmpelim: handle extra clobbers Handle extra clobbers in CC-clobbering insns when attempting to recognize the corresponding CC-setting insn. This is for the AVR CCmode conversion. AVR has insns like (define_insn "andhi3" [(set (match_operand:HI 0 ...) (and:HI (match_operand:HI 1 ...) (match_operand:HI 2 ...))) (clobber (match_scratch:QI 3 ...)) (clobber (reg:CC REG_CC))] ...) which can be profitably converted into CC-setting variants. 2020-08-04 Pip Cet <pipcet@gmail.com> gcc/ChangeLog: * compare-elim.c (arithmetic_flags_clobber_p): Allow extra clobbers. (try_validate_parallel): (try_eliminate_compare): Likewise. --- gcc/compare-elim.c | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/gcc/compare-elim.c b/gcc/compare-elim.c index 85f3e344074..295c32b0953 100644 --- a/gcc/compare-elim.c +++ b/gcc/compare-elim.c @@ -202,7 +202,7 @@ arithmetic_flags_clobber_p (rtx_insn *insn) if (asm_noperands (pat) >= 0) return false; - if (GET_CODE (pat) == PARALLEL && XVECLEN (pat, 0) == 2) + if (GET_CODE (pat) == PARALLEL && XVECLEN (pat, 0) >= 2) { x = XVECEXP (pat, 0, 0); if (GET_CODE (x) != SET) @@ -211,7 +211,7 @@ arithmetic_flags_clobber_p (rtx_insn *insn) if (!REG_P (x)) return false; - x = XVECEXP (pat, 0, 1); + x = XVECEXP (pat, 0, XVECLEN (pat, 0) - 1); if (GET_CODE (x) == CLOBBER) { x = XEXP (x, 0); @@ -663,6 +663,16 @@ static rtx try_validate_parallel (rtx set_a, rtx set_b) { rtx par = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, set_a, set_b)); + if (GET_CODE (set_b) == PARALLEL) + { + int len = XVECLEN (set_b, 0); + rtvec v = rtvec_alloc (len); + RTVEC_ELT (v, 0) = set_a; + for (int i = 0; i < len - 1; i++) + RTVEC_ELT (v, i + 1) = XVECEXP (set_b, 0, i); + + par = gen_rtx_PARALLEL (VOIDmode, v); + } rtx_insn *insn = make_insn_raw (par); if (insn_invalid_p (insn, false)) @@ -873,10 +883,25 @@ try_eliminate_compare (struct comparison *cmp) [(set (reg:CCM) (compare:CCM (operation) (immediate))) (set (reg) (operation)] */ - rtvec v = rtvec_alloc (2); + /* Rotate + [(set A B) + (clobber (scratch)) + ... + (clobber (reg:CCM))]] + + to + + [(set (reg:CCM) (compare:CCM (operation) (immediate))) + (set A B) + (clobber (scratch)) + ...] */ + + int len = XVECLEN (PATTERN (insn), 0); + rtvec v = rtvec_alloc (len); RTVEC_ELT (v, 0) = y; - RTVEC_ELT (v, 1) = x; - + for (int i = 0; i < len - 1; i++) + RTVEC_ELT (v, i + 1) = XVECEXP (PATTERN (insn), 0, i); + rtx pat = gen_rtx_PARALLEL (VOIDmode, v); /* Succeed if the new instruction is valid. Note that we may have started -- 2.28.0