-
Notifications
You must be signed in to change notification settings - Fork 14
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Assertion failed: (MI && "No instruction defining live value"), function computeDeadValues #26
Comments
This sounds like it might be a bug mentioned to me on llvm-commits a while ago. I'll fetch more details later. |
Here's the bug I was thinking of http://llvm.org/viewvc/llvm-project?view=revision&revision=293934
It doesn't sound as relevant now that I remember it. |
I didn't re-bugpoint, but a segfault is still present even with the proposed LLVM 4.0 merge into Rust:
|
I tried cherry-picking the commit you mentioned (llvm-mirror/llvm@5340452) but it seems like I get the same assertion. |
Looking in the debugger, it seems like some data got out of agreement somewhere. I think it's saying that the store came from offset 1676, but that's blank:
|
I tried to debug this quite a bit. With the latest llvm this changed a bit. Now |
So after a lot of debugging I still don't know whats going on but here are my findings. Here is the instruction map before 1832 gets removed:
The function which removes it is InlineSpiller::coalesceStackAccess. So I tried to prevent that function to remove the instruction but the result is the same. The InlineSpiller remvoes the instruction somewhere in the postOptimization step. For some reason we end up with this total broken live range which then blows up:
All 3 indexes point to same machine instruction:
I also found this somewhat related bug: http://lists.llvm.org/pipermail/llvm-dev/2012-July/051741.html Maybe someone has an idea what is going on? |
Interestingly, the OP of the mailing list post you linked is one of the three original people that worked on AVR-LLVM, so it's fairly likely it's related, if not the same! |
Cherry picking this from the mailing list thread
For what it's worth, the original llvm-avr sources had a comment on LDDWRdYQ to the effect of it being a workaround for something. It was never clear what it was a workaround for though. |
We could fix this properly, or we could work around it by adding a guard condition to skip the call to I suspect that it will be unnecessary to check for earlyclobber slots because if the existing slots always come from Would be nice to fix it properly though |
Good news! The mailing list thread and bug report shown in @brainlag's investigation reminded me of a very old At some point, the earlyclobber flag was added to LDDWRdYQ, which was originally introduced to work around this bug. albeit with a completely different way of showing itself. I've removed the earlyclobber flag which fixes this issue. At some point it would be nice to see the register allocator esoteric handle cases like this though. |
Here's the important bit |
Thanks for all of the hours spent @brainlag, it took a few hours to put all of the pieces together, but the debugging you did filled the last piece of the puzzle! |
We should cherry-pick this, but it's probably not worth it until #90 lands |
I think i saw a similar workaround in MIPS and/or ARM but those didn't mention the bug. |
I still don't know what this earlyclobber flag is supposed to do but don't you think we also should remove it from LDDWRdPtrQ too (AVRInstrInfo.td#L1224)? This fixes #37 for me and also #95. And then there is still LDDRdPtrQ, which also has a earlyclobber flag but didn't trigger a error yet. |
The In AVR, this is used on pseudo instructions because some of the expansion patterns introduce additional instructions which overwrite some registers. For example, we often turn 16-bit load pseudo instructions into something like this LDD r12, X+ ; load from pointer into r12, postincrement the pointer value
LDD r13, X Because the expanded instruction sequence always write to the source pointer register, that means that none of the other registers in the instruction can overlap with the X register, namely I believe that removing the earlyclobber hint will remove this constraint from the register allocator. This would reduce register pressure, but it will also corrupt the values we store into registers. This could explain why it fixes #37 and #95. Here is the mailing list posting where it was originally introduced. This is my understanding of earlyclobber at least. |
So do you think LDDWRdPtrQ is different to LDDWRdYQ or are we getting away without adding earlyclobber to it? This workaround for bug 13375 is for both instructions. |
Ok nevermind, LDDWRdYQ is already a special case of LDDWRdPtrQ. |
As you've implied but I'll be concrete Leaving earlyclobber off This works around the bug in |
Here's a smaller testcase: ; ModuleID = 'bugpoint-reduced-simplified.bc'
source_filename = "bugpoint-output-3cab020.bc"
target datalayout = "e-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8"
target triple = "avr-unknown-unknown"
%"num::bignum::Big32x40" = type { [0 x i8], i16, [0 x i8], [40 x i32], [0 x i8] }
define void @"core::num::flt2dec::strategy::dragon::format_exact"() unnamed_addr {
start:
%_72 = alloca %"num::bignum::Big32x40", align 1
%0 = getelementptr inbounds %"num::bignum::Big32x40", %"num::bignum::Big32x40"* null, i16 0, i32 3
%1 = bitcast [40 x i32]* %0 to i8*
%2 = getelementptr inbounds %"num::bignum::Big32x40", %"num::bignum::Big32x40"* %_72, i16 0, i32 3
%3 = bitcast [40 x i32]* %2 to i8*
call void @llvm.memcpy.p0i8.p0i8.i16(i8* nonnull %3, i8* nonnull %1, i16 160, i32 1, i1 false)
%4 = getelementptr inbounds %"num::bignum::Big32x40", %"num::bignum::Big32x40"* %_72, i16 0, i32 3, i16 0
br label %"core::slice::<impl core::ops::index::IndexMut<I> for [T]>::index_mut.exit.i.i"
"core::slice::<impl core::ops::index::IndexMut<I> for [T]>::index_mut.exit.i.i": ; preds = %"core::num::bignum::Big32x40::div_rem_small.exit.i.bb2.i.i_crit_edge", %start
br i1 undef, label %"core::num::bignum::Big32x40::div_rem_small.exit.i", label %"<u32 as core::num::bignum::FullOps>::full_div_rem.exit.lr.ph.i.i"
"<u32 as core::num::bignum::FullOps>::full_div_rem.exit.lr.ph.i.i": ; preds = %"core::slice::<impl core::ops::index::IndexMut<I> for [T]>::index_mut.exit.i.i"
br label %"<u32 as core::num::bignum::FullOps>::full_div_rem.exit.i.i"
"<u32 as core::num::bignum::FullOps>::full_div_rem.exit.i.i": ; preds = %"<u32 as core::num::bignum::FullOps>::full_div_rem.exit.i.i", %"<u32 as core::num::bignum::FullOps>::full_div_rem.exit.lr.ph.i.i"
%5 = load i32, i32* undef, align 1
%6 = zext i32 %5 to i64
%7 = or i64 0, %6
%8 = udiv i64 %7, 1000000000
%9 = trunc i64 %8 to i32
store i32 %9, i32* undef, align 1
%10 = icmp eq i32* undef, %4
br i1 %10, label %"core::num::bignum::Big32x40::div_rem_small.exit.i", label %"<u32 as core::num::bignum::FullOps>::full_div_rem.exit.i.i"
"core::num::bignum::Big32x40::div_rem_small.exit.i": ; preds = %"<u32 as core::num::bignum::FullOps>::full_div_rem.exit.i.i", %"core::slice::<impl core::ops::index::IndexMut<I> for [T]>::index_mut.exit.i.i"
%11 = icmp ugt i16 undef, 9
br i1 %11, label %"core::num::bignum::Big32x40::div_rem_small.exit.i.bb2.i.i_crit_edge", label %bb7.i74
"core::num::bignum::Big32x40::div_rem_small.exit.i.bb2.i.i_crit_edge": ; preds = %"core::num::bignum::Big32x40::div_rem_small.exit.i"
br label %"core::slice::<impl core::ops::index::IndexMut<I> for [T]>::index_mut.exit.i.i"
bb7.i74: ; preds = %"core::num::bignum::Big32x40::div_rem_small.exit.i"
unreachable
}
; Function Attrs: argmemonly nounwind
declare void @llvm.memcpy.p0i8.p0i8.i16(i8* nocapture writeonly, i8* nocapture readonly, i16, i32, i1) #0
attributes #0 = { argmemonly nounwind } |
A reproduction:
Original
The text was updated successfully, but these errors were encountered: