https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92729

--- Comment #6 from pipcet at gmail dot com ---
I've just pushed here

https://github.com/gcc-mirror/gcc/compare/master...pipcet:avr-ccmode-20200804?expand=1

the current state of my work as a series of git commits, sorted roughly from
large, mechanical, important changes to small, controversial, cosmetic ones.

I'm facing some problems:

1. It's hard to test. The test suite compiles okay, and I've tricked simulavr
into executing some test cases, but it's not as easy as simply running the test
suite, unless I'm missing something.

2. The assembler code often changes more than I thought it would. This makes
diffing it somewhat tedious.

3. Some peepholes need careful scrutiny. These are things like:

(define_peephole ; "*cpse.eq"
  [(set (cc0)
        (compare (match_operand:ALL1 1 "register_operand" "r,r")
                 (match_operand:ALL1 2 "reg_or_0_operand" "r,Y00")))
   (set (pc)
        (if_then_else (eq (cc0)
                          (const_int 0))
                      (label_ref (match_operand 0 "" ""))
                      (pc)))]
  "jump_over_one_insn_p (insn, operands[0])"
  "@
        cpse %1,%2
        cpse %1,__zero_reg__")

This replaces a flag-setting instruction plus a conditional branch with a
non-flag-setting conditional skip. Modifying only the obvious bits, this would
result in broken code which relied on the state of the CC flags after the
branch insn.

My current idea is to add a peephole2 pattern which adds a clobber of the CC
register to jump insns which don't need to preserve it, then require that extra
clobber in the above peephole. Not perfect, but it should catch most cases.

However, I'm unsure whether the approach of defining

(define_peephole2
  [(set (pc) (if_then_else (match_operator 0 "ordered_comparison_operator"
                                           [(reg:CC REG_CC) (const_int 0)])
                           (match_operand 1)
                           (match_operand 2)))]
  "peep2_reg_dead_p (1, gen_rtx_REG (CCmode, REG_CC))"
  [(parallel [(set (pc) (if_then_else (match_dup 0)
                                      (match_dup 1)
                                      (match_dup 2)))
              (clobber (reg:CC REG_CC))])])

is safe: if I'm looking at things correctly, peep2_reg_dead_p checks whether
the register is live in the instruction following the jump in the insn stream,
not the insn that the jump potentially goes to.

The good news is that I believe I've worked around the actual code quality
problems sufficiently for the patch set as it stands to be a good alternative
to dropping the AVR port.

I'd be really grateful for advice on how to test and improve this. Is there a
test suite somewhere that I've missed? Ideally, one that works with a free
simulator?

Reply via email to