Closed shepmaster closed 7 years ago
Cleaned up and added a test case in tree in 948b820c29ffb4e006769d18ced5fa37921d8826.
It looks like we are selecting
%R29R28<def> = LDDWRdYQ %R29R28, 1
As shown in the datasheet, this instruction is undefined
The result of these combinations is undefined:
LD r28, Y+
LD r29, Y+
LD r28, -Y
LD r29, -Y
This relates to #28
I don't think LLVM has any way currently to handle this.
Easiest and shittiest fix is to create a register class with only the X and Z instructions, and restrict the LDD
instruction to only using those two. This would mean that if we had a frame pointer, we would only have a single register to load and store from, which probably wouldn't work.
I think this will require a lot of effort to fix correctly. I imagine that the best way to implement this would be to add a new hook that returns the set of available registers to select on given a machine instruction.
This is similar to the AVRRegisterInfo::getReservedRegs
, although that operates on a function rather than a single instruction.
We could add a new virtual function the the TargetRegisterInfo
class also called getReservedRegs
but takes an instruction as input. We could then extend the register allocator to use the new method for each instruction.
llc -march=avr -mcpu=atmega328p ~/projects/llvm/git-svn/test/CodeGen/AVR/error-srcreg-destreg-same.ll -print-after-all 2>&1 | grep -E "IR Dump|LDD"
# *** IR Dump After Slot index numbering ***:
# *** IR Dump After Live Interval Analysis ***:
# *** IR Dump After Simple Register Coalescing ***:
# *** IR Dump After Rename Disconnected Subregister Components ***:
# *** IR Dump After Machine Instruction Scheduler ***:
# *** IR Dump After Debug Variable Analysis ***:
# *** IR Dump After Live Stack Slot Analysis ***:
# *** IR Dump After Virtual Register Map ***:
# *** IR Dump After Live Register Matrix ***:
# *** IR Dump After Virtual Register Rewriter ***:
2096B %R29R28<def> = LDDWRdYQ <fi#1>, 0; mem:LD2[FixedStack1](align=1)
2128B %R27R26<def> = LDDWRdYQ <fi#0>, 0; mem:LD2[FixedStack0](align=1)
# *** IR Dump After Stack Slot Coloring ***:
%R29R28<def> = LDDWRdYQ <fi#1>, 0; mem:LD2[FixedStack1](align=1)
%R27R26<def> = LDDWRdYQ <fi#0>, 0; mem:LD2[FixedStack0](align=1)
# *** IR Dump After Machine Loop Invariant Code Motion ***:
%R29R28<def> = LDDWRdYQ <fi#1>, 0; mem:LD2[FixedStack1](align=1)
%R27R26<def> = LDDWRdYQ <fi#0>, 0; mem:LD2[FixedStack0](align=1
It looks like the 'virtual register rewriter' pass is inserting the registers.
It looks like the root of this is in our implementation of AVRInstrInfo::loadRegFromStackSlot
.
I think I hit this same issue when compiling a C program of mine that uses 64-bit arithmetics and recursion: http://www.iki.fi/~msmakela/software/pentomino/pentomino.c (I thought it would make a nice test case). The poisonous combination is -DNDEBUG -O
. With -O3
alone it will compile, as long as I do not remove any assert()
statements from the functions fill()
and prune()
.
@dylanmckay any ideas on how we can work on this?
I did a small spike to check how long it would take to properly fix this in the register allocator a while back, it looks quite difficult because at the register allocator layer, there isn't really any visibility of the machine instructions that are being selected. There will be a way, but it's not an idiom I could see being used.
I'm looking into this again.
I've raised a bug on the LLVM bug tracker here, feel free to watchlist!
I've just fixed this in LLVM master!
It appears to me that the fix has not yet been merged to avr-llvm. As of this writing, the latest update to the avr-support branch is commit 01683bc2b6054420fc90b0aac0e6bed3b140fe63, dated December 5, 2016, 2 days before the commit to upstream. I can repeat the failure with that commit. I think that it would be better to not close the affected before the fix has been merged from upstream.
Unless there's a compelling reason to merge upstream back into this branch, I don't think it's worth it.
Now that all of the code from here is merged into LLVM master, and development occurs there, you should be using that instead of this fork.
Thanks for the clarification! That is even better. Not being aware of the merge to the LLVM master, I was wondering why there are AVR-specific changes in the upstream repository. Perhaps https://github.com/avr-llvm/llvm/wiki/Getting%20Started could be revised, replacing "git clone" commands with "svn checkout" commands.
It looks like README.md should point to http://clang.llvm.org/get_started.html instead of https://github.com/avr-llvm/llvm/wiki/Getting%20Started (which should also point to the upstream page).
I've added a big note to the wiki page you linked saying to use upstream LLVM instead.
I wouldn't link to the clang
getting started page as the patch to add AVR support to clang is still in code review.
testcase: