[LLVMdev] Instruction Combining Pass *Breaking* Struct Reads?

Nyx mcheva at cs.mcgill.ca
Mon Jun 29 05:54:26 PDT 2009


I'm in a situation where I have code that works fine if I don't run the
instruction combining optimization pass, but breaks when I do. The code in
question is meant to allocate space for two structs on the stack using
alloca, and then pass pointers to these to a callee function. One struct
serves to store the input to the function, the other serves for the callee
function to write its output. This is part of my calling mechanism. Once the
call is terminated, the caller will read from the output struct. The twist
is that I am not allocating the structs directly, I am allocating buffers of
bytes and casting the pointers into struct pointers.

The following snipper is without instruction combining being run:

	%2 = alloca i8, i32 16		; <i8*> [#uses=1]
	%3 = alloca i8, i32 12		; <i8*> [#uses=1]
	%4 = call i8* @"Environment::extend"(i8* inttoptr (i32 173374432 to i8*))	
; <i8*> [#uses=3]
	%5 = call i8* @"ArrayObj::create"(i32 0)		; <i8*> [#uses=1]
	%6 = call i8* @"Interpreter::callFunction"(i8* inttoptr (i32 147457088 to
i8*), i8* %5, i32 0)		; <i8*> [#uses=0]
	%7 = bitcast i8* %2 to { i64, i64 }*		; <{ i64, i64 }*> [#uses=3]
	%8 = bitcast i8* %3 to { i8*, i64 }*		; <{ i8*, i64 }*> [#uses=3]
	%9 = getelementptr { i64, i64 }* %7, i32 0, i32 0		; <i64*> [#uses=1]
	store i64 25, i64* %9
	%10 = getelementptr { i64, i64 }* %7, i32 0, i32 1		; <i64*> [#uses=1]
	store i64 1, i64* %10
	call void @fibonacci_0xa566d80({ i64, i64 }* %7, { i8*, i64 }* %8)
	%11 = getelementptr { i8*, i64 }* %8, i32 0, i32 1		; <i64*> [#uses=1]
	%12 = load i64* %11		; <i64> [#uses=1]
	%13 = icmp slt i64 %12, 1		; <i1> [#uses=1]
	br i1 %13, label %21, label %14

As you can see, I allocate two structs, one taking 16 bytes (containing two
i64 values), and one taking 12 bytes (containing a pointer and an i64 value,
this is on a 32-bit machine). I then cast those pointers to the proper
struct types (see values %7 and %8). I then call the fibonacci function, and
after that, I read the i64 value of the second struct (see values %11, %12)
and branch based on its value. This code works just fine when I run it.

Now, if I run the instruction combining pass, the above code gets turned
into this:

	%2 = alloca { i64, i64 }, align 8		; <{ i64, i64 }*> [#uses=3]
	%3 = alloca [12 x i8], align 1		; <[12 x i8]*> [#uses=3]
	%4 = call i8* @"Environment::extend"(i8* inttoptr (i32 148577248 to i8*))	
; <i8*> [#uses=3]
	%5 = call i8* @"ArrayObj::create"(i32 0)		; <i8*> [#uses=1]
	%6 = call i8* @"Interpreter::callFunction"(i8* inttoptr (i32 147883136 to
i8*), i8* %5, i32 0)		; <i8*> [#uses=0]
	%7 = bitcast [12 x i8]* %3 to { i8*, i64 }*		; <{ i8*, i64 }*> [#uses=1]
	%8 = getelementptr { i64, i64 }* %2, i64 0, i32 0		; <i64*> [#uses=1]
	store i64 25, i64* %8, align 8
	%9 = getelementptr { i64, i64 }* %2, i64 0, i32 1		; <i64*> [#uses=1]
	store i64 1, i64* %9, align 8
	call void @fibonacci_0x8dc0d80({ i64, i64 }* %2, { i8*, i64 }* %7)
	%10 = getelementptr [12 x i8]* %3, i64 0, i64 8		; <i8*> [#uses=1]
	%11 = bitcast i8* %10 to i64*		; <i64*> [#uses=1]
	%12 = load i64* %11		; <i64> [#uses=1]
	%13 = icmp slt i64 %12, 1		; <i1> [#uses=1]
	br i1 %13, label %21, label %14

This code does not work properly. If we take a look at value %10, we can see
that it tries to read a value at offset 8! This is obviously wrong, as the
value is an i64, and the size of the output struct is 12! Thus, the value
should be read at offset 4, not 8!

And here I find myself puzzled. I know the second struct really has size 12.
I know the alignment is 4. Why is it that the instruction combining pass
tries to read a value at offset 8, as if the pointer inside the output
struct took 8 bytes? Furthermore, why does it allocate one struct as a
struct, and one as a byte array? Is there a bug in this optimization pass,
or am I doing something wrong? Note that I am using LLVM version 2.5.

Any help would be appreciated!

- Max
-- 
View this message in context: http://www.nabble.com/Instruction-Combining-Pass-*Breaking*-Struct-Reads--tp24253572p24253572.html
Sent from the LLVM - Dev mailing list archive at Nabble.com.




More information about the llvm-dev mailing list