This is an archive of the discontinued LLVM Phabricator instance.

[AVR] Support left-rotations
ClosedPublic

Authored by Patryk27 on Jun 3 2023, 5:58 AM.

Details

Summary

Currently, trying to compile this code:

define i8 @test(i8 %0) {
start:
  %1 = call i8 @llvm.fshl.i8(i8 %0, i8 %0, i8 1)
  ret i8 %1
}

declare i8 @llvm.fshl.i8(i8, i8, i8)
./build/bin/llc -march=avr -mcpu=atmega32u4 test.ll

... will fail, saying:

LLVM ERROR: Cannot select: t9: i8 = ROL t2
  t2: i8,ch = CopyFromReg t0, Register:i8 %0
    t1: i8 = Register %0

(spotted in the wild at https://github.com/rust-lang/rust/issues/107261)

Curiously, fshl.u16 (and larger types) work, similarly as all fshrs,
which I think is related to the fact that ROLBRd is hard-coded to
require GPR8:$zero in AVRInstrInfo.td.

Now, I'm not really sure why it's been done this way and so I'm not 100%
sure my approach to solving this problem is correct as well - but
adjusting ROLBRd to work similarly as RORBRd seems to do the job.

Following the example from above, we now generate:

lsl r24
adc r24, r1

I've made sure the codegen is alright by cross-checking results using
simavr - I've checked following cases, having lhs as a variable:

  • 8-bit left/right rotations where rhs is constant/variable,
  • 16-bit left/right rotations where rhs is constant/variable,
  • 32-bit left/right rotations where rhs is constant/variable,

... and they all yielded correct results when compared with Rust's
.rotate_left() and .rotate_right().

Diff Detail

Event Timeline

Patryk27 created this revision.Jun 3 2023, 5:58 AM
Patryk27 requested review of this revision.Jun 3 2023, 5:58 AM
Herald added a project: Restricted Project. · View Herald TranscriptJun 3 2023, 5:58 AM
Patryk27 edited the summary of this revision. (Show Details)Jun 3 2023, 6:01 AM

Thanks. Could you please change your commit message to

[AVR] Fix incorrect operands of pseudo instruction 'ROLBRd'

Fixes https://github.com/llvm/llvm-project/issues/63098

This is the recommended form when committing to LLVM's repo.

benshi001 accepted this revision.Jun 3 2023, 7:59 PM
This revision is now accepted and ready to land.Jun 3 2023, 7:59 PM
This revision was automatically updated to reflect the committed changes.

I see you've already changed the commit message, so nothing more to do here, right? 🙂

I see you've already changed the commit message, so nothing more to do here, right? 🙂

Sure. Thanks!

aykevl added a subscriber: aykevl.Jun 5 2023, 5:09 AM

Sorry I only see this now, after it has been merged.

Curiously, fshl.u16 (and larger types) work, similarly as all fshrs, which I think is related to the fact that ROLBRd is hard-coded to require GPR8:$zero in AVRInstrInfo.td.

Now, I'm not really sure why it's been done this way and so I'm not 100% sure my approach to solving this problem is correct as well - but adjusting ROLBRd to work similarly as RORBRd seems to do the job.

There is a reason, namely that the instruction uses R1 and now doesn't say so in InstrInfo. I have added the use of R1 in D117426. With the use removed, interrupts may be miscompiled because R1 might not be saved/cleared/restored inside an interrupt when a ROLB pseudo instruction is used inside an interrupt.

In other words, the zero register dependency is required for correctness and this patch will lead to miscompilation in some edge cases.

Here is an example that miscompiles on current trunk: https://godbolt.org/z/6ha5rGqY3 (r1 is used but not saved/cleared).

llvm/test/CodeGen/AVR/pseudo/ROLBrd.mir
24–28

Why did you remove this test? I think it's useful (r1 vs r17).

Sorry I only see this now, after it has been merged.

Curiously, fshl.u16 (and larger types) work, similarly as all fshrs, which I think is related to the fact that ROLBRd is hard-coded to require GPR8:$zero in AVRInstrInfo.td.

Now, I'm not really sure why it's been done this way and so I'm not 100% sure my approach to solving this problem is correct as well - but adjusting ROLBRd to work similarly as RORBRd seems to do the job.

There is a reason, namely that the instruction uses R1 and now doesn't say so in InstrInfo. I have added the use of R1 in D117426. With the use removed, interrupts may be miscompiled because R1 might not be saved/cleared/restored inside an interrupt when a ROLB pseudo instruction is used inside an interrupt.

In other words, the zero register dependency is required for correctness and this patch will lead to miscompilation in some edge cases.

Here is an example that miscompiles on current trunk: https://godbolt.org/z/6ha5rGqY3 (r1 is used but not saved/cleared).

I have

  1. made a fix, though inefficient, but correct
  2. recover the test of avr-tiny.

I may need more time to find a proper fix to resolve both the crash and the incorrect generated ISR, but at least this solution is correct.

Sorry I only see this now, after it has been merged.

Curiously, fshl.u16 (and larger types) work, similarly as all fshrs, which I think is related to the fact that ROLBRd is hard-coded to require GPR8:$zero in AVRInstrInfo.td.

Now, I'm not really sure why it's been done this way and so I'm not 100% sure my approach to solving this problem is correct as well - but adjusting ROLBRd to work similarly as RORBRd seems to do the job.

There is a reason, namely that the instruction uses R1 and now doesn't say so in InstrInfo. I have added the use of R1 in D117426. With the use removed, interrupts may be miscompiled because R1 might not be saved/cleared/restored inside an interrupt when a ROLB pseudo instruction is used inside an interrupt.

In other words, the zero register dependency is required for correctness and this patch will lead to miscompilation in some edge cases.

Here is an example that miscompiles on current trunk: https://godbolt.org/z/6ha5rGqY3 (r1 is used but not saved/cleared).

Sorry I should merge it so quickly, at least wait for your review.

Patryk27 added inline comments.Jun 6 2023, 2:47 AM
llvm/test/CodeGen/AVR/pseudo/ROLBrd.mir
24–28

I removed the second assertion since the zero-register is not an input for that instruction anymore - I guess using two-pass test with --check-prefix (once for r1 and once for r17) would be nice here, though

aykevl added a comment.Jun 6 2023, 6:07 AM

Sorry I should merge it so quickly, at least wait for your review.

Don't worry - I haven't been very active lately on the AVR backend.
I have better organized my email now which is one reason why I am more likely to see these notifications. Maybe I'll get into AVR stuff again at some point - there are still a number of optimizations that I'd like to do :)