llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
28.62k stars 11.83k forks source link

LiveIntervalAnalysis assertion failure for SPARC back-end #1912

Closed llvmbot closed 14 years ago

llvmbot commented 17 years ago
Bugzilla Link 1540
Resolution FIXED
Resolved on Feb 22, 2010 12:48
Version 1.0
OS Linux
Attachments Test-case causing failure (bugpoint reduced to this)
Reporter LLVM Bugzilla Contributor
CC @lattner,@ggreif

Extended Description

I have tried to compile LLVM bytecode for the SPEC CPU2000 benchmark bzip2 to SPARC assembly in a cross-compiler setting (LLVM running on x86_64). I am using llvm-2.0 as distributed in a tar-ball from llvm.org.

Bugpoint reduced the error to this case: ; ModuleID = 'bugpoint-reduced-simplified.bc' target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64" target triple = "x86_64-unknown-linux-gnu" @​seedi = external global i64 ; <i64*> [#uses=1]

define i32 @​spec_random_load(i32 %fd) { entry: br i1 false, label %bb, label %bb69

bb: ; preds = %entry br i1 false, label %cond_true12, label %bb56

cond_true12: ; preds = %bb %tmp21 = load i64 @​seedi ; [#uses=1] %tmp24 = srem i64 %tmp21, 127773 ; [#uses=1] %tmp26 = mul i64 %tmp24, 16807 ; [#uses=1] %tmp29 = sub i64 %tmp26, 0 ; [#uses=1] %storemerge = add i64 0, %tmp29 ; [#uses=1] %tmp3940 = sitofp i64 %storemerge to float ; [#uses=1] %tmp41 = mul float %tmp3940, 0x3E00000000000000 ; [#uses=1] %tmp4142 = fpext float %tmp41 to double ; [#uses=1] %tmp47 = mul double %tmp4142, 2.560000e+02 ; [#uses=1] %tmp4748 = fptosi double %tmp47 to i32 ; [#uses=1] %tmp474849 = trunc i32 %tmp4748 to i8 ; [#uses=1] store i8 %tmp474849, i8 null ret i32 0

bb56: ; preds = %bb ret i32 0

bb69: ; preds = %entry ret i32 0 }

the command: llc -march=sparc -f -o bzip2.s bugpoint-reduced-function.bc

crashes: llc: /.../llvm/llvm-2.0/include/llvm/CodeGen/LiveIntervalAnalysis.h:121: llvm::LiveInterval& llvm::LiveIntervals::getInterval(unsigned int): Assertion `I != r2iMap_.end() && "Interval does not exist for register"' failed.

Some analysis shows that the error occurs in expanded floating-point bytecodes.

llvmbot commented 17 years ago

Fixed. http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20070709/051824.html

lattner commented 17 years ago

Ah, I thought aliasing would be enough (it was before), ok. Thanks Evan!

llvmbot commented 17 years ago

Nevermind, it's implicitly defining %D0(1) but using %F0. So that's correctly. The bug is in SparcRegisterInfo.td:

def D0 : Rd< 0, "F0", [F0, F1]>, DwarfRegNum<32>;

This states D0 aliases F0, F1 but does not specify F0 and F1 as sub-registers of D0. I'll fix this.

llvmbot commented 17 years ago

I know. That's not the problem. SparcGenInstrInfo.inc also looks alright. This is CALL's implicit defs:

static const unsigned ImplicitList3[] = { SP::O0, SP::O1, SP::O2, SP::O3, SP::O4, SP::O5, SP::O7, SP::G1, SP::G2, SP::G3, SP::G4, SP::G5, SP::G6, SP::G7, SP::D0, SP::D1, SP::D2, SP:\:D3, SP::D4, SP::D5, SP::D6, SP::D7, SP::D8, SP::D9, SP::D10, SP::D11, SP::D12, SP::D13, SP::D14, SP::D15, 0 };

Looks ok. But when ScheduleDAG creates the MI, it's getting an incorrectly list of implicit defs.

lattner commented 17 years ago

Ugh, funness. Check this out:

def D0 : Rd< 0, "F0", [F0, F1]>, DwarfRegNum<32>; def D1 : Rd< 2, "F2", [F2, F3]>, DwarfRegNum<34>;

Note that the D0 register prints as "F0".

llvmbot commented 17 years ago

Strangeness:

12 CALL , %O0<imp-def,dead>, %O1<imp-def,dead>, %O2, %O3, %O4, %O5, %O7<imp-def,dead>, %G1<imp-def,dead>, %G2, %G3<imp-def>, %G4, %G5, %G6, %G7, %F0<imp-def,dead>, %F2<imp-def,dead>, %F4<imp-def,dead>, %F6<imp-def,dead>, %F8<imp-def,dead>, %F10<imp-def,dead>, %F12<im\p-def,dead>, %F14<imp-def,dead>, %F16<imp-def,dead>, %F18<imp-def,dead>, %F20<imp-def,dead>, %F22<imp-def,dead>, %F24<imp-def,dead>, %F26<imp-def,dead>, %F28<imp-def,dead>, %F30<imp-def,dead>, %O0<imp-use,kill>, %O1<imp-use,kill>, %O2<imp-use,kill>, %O3<imp-use,kill>, %O4<imp-use,kill>, %O5<imp-use,kill> CALL %mreg(73) %mreg(74) %mreg(75)
%mreg(76) %mreg(77) %mreg(78) %mreg(80) %mreg(50)
%mreg(51) %mreg(52) \ %mreg(53) %mreg(54) %mreg(55)
%mreg(56) %mreg(1) %mreg(2) %mreg(9) %mreg(10)
%mreg(11) %mreg(12) %mreg(13) %m\reg(14) %mreg(15) %mreg(16) %mreg(3) %mreg(4) %mreg(5) %mreg(6)
%mreg(7) %mreg(8) %mreg(73) %mreg(74) %mreg(7\5)
%mreg(76) %mreg(77) %mreg(78) 16 %reg1025 = FMOVS %F0 FMOVS %reg1025 %mreg(17)

According to this CALL implicitly defines %F0(1), but the FMOVS uses %F0(17) (aka %D0 which consists of both %F0 and %F1). That messes live interval up. But SparcInstrInfo.td defines CALL as this:

let Uses = [O0, O1, O2, O3, O4, O5], hasDelaySlot = 1, isCall = 1, noResults = 1, Defs = [O0, O1, O2, O3, O4, O5, O7, G1, G2, G3, G4, G5, G6, G7, D0, D1, D2, D3, D4, D5, D6, D7, D8, D9, D10, D11, D12, D13, D14, D15] in { def CALL : InstSP<(ops calltarget:$dst), "call $dst", []> { bits<30> disp; let op = 1; let Inst{29-0} = disp; }

So CALL should implicitly define %F0(17) instead of %F0(1). What is going on?

lattner commented 17 years ago

Here is a simple reduced testcase for llvm/llvm-bugzilla-archive#1540 :

declare float @​sinf(float) declare double @​sin(double) define double @​test_sin(float %F) { %G = call float @​sinf( float %F ) ; [#uses=1] %H = fpext float %G to double ; [#uses=1] %I = call double @​sin( double %H ) ; [#uses=1] ret double %I }

$ llvm-as < t.ll | llc -march=sparc

If this is a sparc backend bug, let me know and I'll be happy to fix it.

-Chris

lattner commented 17 years ago

Bug llvm/llvm-bugzilla-archive#1550 has been marked as a duplicate of this bug.

lattner commented 17 years ago

This appears to be a liveness bug of some sort. When I run: $ llc attachment.cgi -march=sparc -f -print-machineinstrs -debug | & less

I see:

144 CALL , .... %F0<imp-def,dead>, .... 148 %reg1048 = FMOVS %F0

If F0 is dead at 144, it can't be killed at 148. Evan, thoughts?

Of interest, the Sparc CALL instruction is marked as clobbering D0, which is aliased to F0/F1. Perhaps this is part of the problem?

-Chris

nlewycky commented 17 years ago

Confirmed with current SVN.

llc: /home/nicholas/llvm-commit/include/llvm/CodeGen/LiveIntervalAnalysis.h:102: llvm::LiveInterval& llvm::LiveIntervals::getInterval(unsigned int): Assertion `I != r2iMap_.end() && "Interval does not exist for register"' failed.

Program received signal SIGABRT, Aborted. [Switching to Thread -137754928 (LWP 1290)] 0xffffe405 in __kernel_vsyscall () (gdb) bt

​0 0xffffe405 in __kernel_vsyscall ()

​1 0xf7ccbd60 in raise () from /lib/i686/cmov/libc.so.6

​2 0xf7ccd5b1 in abort () from /lib/i686/cmov/libc.so.6

​3 0xf7cc542b in __assert_fail () from /lib/i686/cmov/libc.so.6

​4 0x087baa01 in llvm::LiveIntervals::getInterval (this=0x8a7dfa8, reg=17)

at /home/nicholas/llvm-commit/include/llvm/CodeGen/LiveIntervalAnalysis.h:102

​5 0x087b4ff6 in llvm::SimpleRegisterCoalescing::JoinCopy (this=0x8a7e4a8,

CopyMI=0x8a80e00, SrcReg=17, DstReg=1048, PhysOnly=false)
at SimpleRegisterCoalescing.cpp:220

​6 0x087b59e5 in llvm::SimpleRegisterCoalescing::CopyCoallesceInMBB (

this=0x8a7e4a8, MBB=0x8a7f428, TryAgain=0xffc3116c, PhysOnly=false)
at SimpleRegisterCoalescing.cpp:799

​7 0x087b5bc0 in llvm::SimpleRegisterCoalescing::joinIntervals (

this=0x8a7e4a8) at SimpleRegisterCoalescing.cpp:816

​8 0x087b63e3 in llvm::SimpleRegisterCoalescing::runOnMachineFunction (

this=0x8a7e4a8, fn=@0x8a7ef20) at SimpleRegisterCoalescing.cpp:1042

​9 0x0843e6d0 in llvm::MachineFunctionPass::runOnFunction (this=0x8a7e4a8,

F=@0x8a790c0)
at /home/nicholas/llvm-commit/include/llvm/CodeGen/MachineFunctionPass.h:41

​10 0x088da4be in llvm::FPPassManager::runOnFunction (this=0x8a78208,

F=@0x8a790c0) at PassManager.cpp:1140

​11 0x088da742 in llvm::FunctionPassManagerImpl::run (this=0x8a7ad10,

F=@0x8a790c0) at PassManager.cpp:1098

​12 0x088da890 in llvm::FunctionPassManager::run (this=0xffc3146c,

F=@0x8a790c0) at PassManager.cpp:1043

​13 0x0840983f in main (argc=6, argv=0xffc31574) at llc.cpp:295