Tag Archives: Testing

After Updating: Finding Regressions

In my last post, I described how I sync up the ELLCC project with the LLVM project’s compiler, back-end, and run-time library. Today I’ll build the merged changes and look for problems that may have occurred as the result of the merge.

The first step is to build the newly merged files. I build the my modified LLVM stuff in a separate build directory called llvm-build. Full instructions for installing and building ELLCC are on the installation page. My regression build looks like this:

[~/ellcc] main% cd llvm-build/
[~/ellcc/llvm-build] main% make

I watch for compilation errors (of course!) as well as any warnings that may occur. After a successful build, install the new binaries:

[~/ellcc/llvm-build] main% make install

Now it’s time to see if anything got broken. The first step I use is to rebuild the ELLCC C run-time library, libecc. This is a good test because libecc uses a lot of language features and is compiled for all the targets:

[~/ellcc/llvm-build] main% cd ~/ellcc/libecc/obj/
[~/ellcc/libecc/obj] main% ls
arm/ i386/ Makefile microblaze/ mips/ nios2/ ppc/ ppc64/ sparc/ x86_64/
[~/ellcc/libecc/obj] main% make clean
[~/ellcc/libecc/obj] main% make

In this case, after updating to LLVM revision 132253, I got the following code generation error:

ecc: /home/rich/ellcc/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp:229: void llvm::AsmPrinter::EmitCFIFrameMove(const llvm::MachineMove&) const: Assertion `!Dst.isReg() && "Machine move not supported yet."' failed.

Time for a little investigation….

It turns out that in llvm/lib/Target/Mips/MipsMCAsmInfo.cpp the line

SupportsDebugInformation = true;

was added. Apparently this was a little premature. The libecc libraries are compiled with -g to enable debug information and the first file compiled chokes the code generator. I’ll comment that line out for now and see how much further I can get.

Now I’ve found something interesting. I get an assertion failure when libecc/src/c/stdlib/merge.c is compiled for Mips:

ecc: /home/rich/ellcc/llvm/lib/CodeGen/SplitKit.cpp:180: bool llvm::SplitAnalysis::calcLiveBlockInfo(): Assertion `BI.FirstUse >= Start' failed.
0 ecc 0x0000000001a6db1f
1 ecc 0x0000000001a6e65a
2 libpthread.so.0 0x00000037bea0eeb0
3 libc.so.6 0x00000037bde330c5 gsignal + 53
4 libc.so.6 0x00000037bde34a76 abort + 390
5 libc.so.6 0x00000037bde2b905 __assert_fail + 245
6 ecc 0x00000000015d7767
7 ecc 0x00000000015d7b10 llvm::SplitAnalysis::analyzeUses() + 512
...

Time to pull out LLVM’s trusty bugpoint. bugpoint is a tool that reduces a compilation failure to a smaller test case than can be attached to a bug report. The process is described here. In this case, I can guess this isn’t a front end problem because this code has been compiled for arm, i386, and microblaze targets prior to the mips build. I can also probably eliminate optimizer problems and assume it is a code generation problem.

Following the instructions here, I’ll make a reduced test case. The failing command line is:

../../../../../bin/mips-linux-ecc -c -g -Werror -MD -MP -O1 -fno-builtin -I../../../../src/c/include -I../../../../src/c/locale ../../../../src/c/stdlib/merge.c

so I’ll go into the appropriate build directory and run a slightly modified command (I added -emit-llvm -o merge.bc to get a bitcode intermediate file, I also removed the -g to reduce the size of the .bc file):

[~/ellcc] main% cd libecc/obj/mips/linux/c
[~/ellcc/libecc/obj/mips/linux/c] main% ../../../../../bin/mips-linux-ecc -c -Werror -MD -MP -O1 -fno-builtin -I../../../../src/c/include -I../../../../src/c/locale ../../../../src/c/stdlib/merge.c -emit-llvm -o merge.bc

First, I’ll try to generate code from the .bc file to verify that a code generation problem is occurring:

[~/ellcc/libecc/obj/mips/linux/c] main% ~/ellcc/bin/llc merge.bc
llc: /home/rich/ellcc/llvm/lib/CodeGen/SplitKit.cpp:180: bool llvm::SplitAnalysis::calcLiveBlockInfo(): Assertion `BI.FirstUse >= Start' failed.
0 llc 0x0000000000f49bef
1 llc 0x0000000000f4a72a
2 libpthread.so.0 0x00000037bea0eeb0
3 libc.so.6 0x00000037bde330c5 gsignal + 53
4 libc.so.6 0x00000037bde34a76 abort + 390
5 libc.so.6 0x00000037bde2b905 __assert_fail + 245
6 llc 0x0000000000bdec47
7 llc 0x0000000000bdeff0 llvm::SplitAnalysis::analyzeUses() + 512
8 llc 0x0000000000b7e1aa
9 llc 0x0000000000b67c8b llvm::RegAllocBase::allocatePhysRegs() + 267
10 llc 0x0000000000b7b31b
11 llc 0x0000000000e7919f llvm::FPPassManager::runOnFunction(llvm::Function&) + 655
12 llc 0x0000000000e7925b llvm::FPPassManager::runOnModule(llvm::Module&) + 75
13 llc 0x0000000000e78c97 llvm::MPPassManager::runOnModule(llvm::Module&) + 551
14 llc 0x0000000000e78dfb llvm::PassManagerImpl::run(llvm::Module&) + 187
15 llc 0x000000000055550a main + 4970
16 libc.so.6 0x00000037bde1ee5d __libc_start_main + 253
17 llc 0x0000000000553229
Stack dump:
0. Program arguments: /home/rich/ellcc/bin/llc merge.bc
1. Running pass 'Function Pass Manager' on module 'merge.bc'.
2. Running pass 'Greedy Register Allocator' on function '@mergesort'
Abort (core dumped)
[~/ellcc/libecc/obj/mips/linux/c] main%

Now we can use bugpoint to get a reduced test case:

[~/ellcc/libecc/obj/mips/linux/c] main% ~/ellcc/bin/bugpoint -run-llc merge.bc
...
[lots of output]
...
Checking instruction: %list2.1 = phi i8* [ undef, %if.then419 ], [ %list2.0.lcssa, %while.end415 ]
Checking instruction: tail call void @free(i8* %list2.1)

*** Attempting to perform final cleanups:
Emitted bitcode to 'bugpoint-reduced-simplified.bc'
[~/ellcc/libecc/obj/mips/linux/c] main%

I can get a readable version of the .bc file using llvm-dis and, just for fun, verify that it too fails:

[~/ellcc/libecc/obj/mips/linux/c] main% ~/ellcc/bin/llvm-dis bugpoint-reduced-simplified.bc
[~/ellcc/libecc/obj/mips/linux/c] main% ~/ellcc/bin/llc bugpoint-reduced-simplified.ll
llc: /home/rich/ellcc/llvm/lib/CodeGen/SplitKit.cpp:180: bool llvm::SplitAnalysis::calcLiveBlockInfo(): Assertion `BI.FirstUse >= Start' failed.
0 llc 0x0000000000f49bef
1 llc 0x0000000000f4a72a
2 libpthread.so.0 0x00000037bea0eeb0
3 libc.so.6 0x00000037bde330c5 gsignal + 53
4 libc.so.6 0x00000037bde34a76 abort + 390
5 libc.so.6 0x00000037bde2b905 __assert_fail + 245
6 llc 0x0000000000bdec47
7 llc 0x0000000000bdeff0 llvm::SplitAnalysis::analyzeUses() + 512
8 llc 0x0000000000b7e1aa
9 llc 0x0000000000b67c8b llvm::RegAllocBase::allocatePhysRegs() + 267
10 llc 0x0000000000b7b31b
11 llc 0x0000000000e7919f llvm::FPPassManager::runOnFunction(llvm::Function&) + 655
12 llc 0x0000000000e7925b llvm::FPPassManager::runOnModule(llvm::Module&) + 75
13 llc 0x0000000000e78c97 llvm::MPPassManager::runOnModule(llvm::Module&) + 551
14 llc 0x0000000000e78dfb llvm::PassManagerImpl::run(llvm::Module&) + 187
15 llc 0x000000000055550a main + 4970
16 libc.so.6 0x00000037bde1ee5d __libc_start_main + 253
17 llc 0x0000000000553229
Stack dump:
0. Program arguments: /home/rich/ellcc/bin/llc bugpoint-reduced-simplified.ll
1. Running pass 'Function Pass Manager' on module 'bugpoint-reduced-simplified.ll'.
2. Running pass 'Greedy Register Allocator' on function '@mergesort'
Abort (core dumped)
[~/ellcc/libecc/obj/mips/linux/c] main%

I keep a non-modified copy of the LLVM/clang sources for comparison purposes.
I’ll try the test case with the stock top of tree LLVM as a sanity check before I file a bug report:

[~] main% cd ~/vendor/llvm-build/llvm
[~/vendor/llvm-build/llvm] main% svn update
At revision 132287.
[~/vendor/llvm-build/llvm] main% cd tools/clang/
[~/vendor/llvm-build/llvm/tools/clang] main% svn update
At revision 132287.
[~/vendor/llvm-build/llvm/tools/clang] main% cd ../../../llvm
llvm/ llvm-build/
[~/vendor/llvm-build/llvm/tools/clang] main% cd ../../../llvm-build/
[~/vendor/llvm-build/llvm-build] main% make install

This build places binaries in my ~/vendor/llvm-build/bin directory. To verify the bug, I’ll use the new llc:

[~/ellcc/libecc/obj/mips/linux/c] main% ~/vendor/llvm-build/bin/llc bugpoint-reduced-simplified.ll
llc: /home/rich/vendor/llvm-build/llvm/lib/CodeGen/SplitKit.cpp:180: bool llvm::SplitAnalysis::calcLiveBlockInfo(): Assertion `BI.FirstUse >= Start' failed.
0 llc 0x0000000000f4b6cf
1 llc 0x0000000000f4c20a
2 libpthread.so.0 0x00000037bea0eeb0
3 libc.so.6 0x00000037bde330c5 gsignal + 53
4 libc.so.6 0x00000037bde34a76 abort + 390
5 libc.so.6 0x00000037bde2b905 __assert_fail + 245
6 llc 0x0000000000be0777
7 llc 0x0000000000be0b20 llvm::SplitAnalysis::analyzeUses() + 512
8 llc 0x0000000000b7fcda
9 llc 0x0000000000b697bb llvm::RegAllocBase::allocatePhysRegs() + 267
10 llc 0x0000000000b7ce4b
11 llc 0x0000000000e7ac1f llvm::FPPassManager::runOnFunction(llvm::Function&) + 655
12 llc 0x0000000000e7acdb llvm::FPPassManager::runOnModule(llvm::Module&) + 75
13 llc 0x0000000000e7a717 llvm::MPPassManager::runOnModule(llvm::Module&) + 551
14 llc 0x0000000000e7a87b llvm::PassManagerImpl::run(llvm::Module&) + 187
15 llc 0x000000000055524a main + 4970
16 libc.so.6 0x00000037bde1ee5d __libc_start_main + 253
17 llc 0x0000000000552f69
Stack dump:
0. Program arguments: /home/rich/vendor/llvm-build/bin/llc bugpoint-reduced-simplified.ll
1. Running pass 'Function Pass Manager' on module 'bugpoint-reduced-simplified.ll'.
2. Running pass 'Greedy Register Allocator' on function '@mergesort'
Abort (core dumped)
[~/ellcc/libecc/obj/mips/linux/c] main%

After renaming the test case to MipsGRAassert.ll, I submitted the bug to the LLVM project here.