[LLVMdev] Transform: Eliminating boxing-unboxing in untyped languages

Ramkumar Ramachandra artagnon at gmail.com
Thu Jan 15 12:58:09 PST 2015


Hi,

I'm playing with an untyped language compiler that generates tons of
LLVM code on simple expressions. We can slowly build up to the full
complexity, but let's look at a simple example first:

The + operator that explicitly expects two integers, and those two
integers are provided literally in the same function in the same basic
block. So, (+ 3 4) generates the following. What's actually happening
is that 3 and 4 are getting boxed into a value_t struct before getting
unboxed immediately for the add operation. An InstCombine should be
able to fix this, no?

; ModuleID = 'My JIT'
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"

%value_t = type { i32, i64, i1, i8*, %value_t**, i64, double,
%value_t* (i32, %value_t**, ...)*, i8, i1, %value_t* }

declare i8* @gc_malloc(i64)

declare i64 @strlen(i8*)

; Function Attrs: nounwind
declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture
readonly, i64, i32, i1) #0

; Function Attrs: nounwind readnone
declare double @llvm.pow.f64(double, double) #1

; Function Attrs: nounwind
declare void @llvm.va_start(i8*) #0

; Function Attrs: nounwind
declare void @llvm.va_end(i8*) #0

declare %value_t* @println(i32, %value_t**, ...)

declare %value_t* @print(i32, %value_t**, ...)

declare %value_t* @cequ(i32, %value_t**, ...)

declare %value_t* @cstrjoin(i32, %value_t**, ...)

define %value_t* @anon0() gc "rgc" {
entry:
  %value = call i8* @gc_malloc(i64 ptrtoint (%value_t* getelementptr
(%value_t* null, i32 1) to i64))
  %malloc_value = bitcast i8* %value to %value_t*
  %boxptr = getelementptr inbounds %value_t* %malloc_value, i32 0, i32 0
  %boxptr1 = getelementptr inbounds %value_t* %malloc_value, i32 0, i32 1
  store i32 1, i32* %boxptr
  store i64 3, i64* %boxptr1
  %value2 = call i8* @gc_malloc(i64 ptrtoint (%value_t* getelementptr
(%value_t* null, i32 1) to i64))
  %malloc_value3 = bitcast i8* %value2 to %value_t*
  %boxptr4 = getelementptr inbounds %value_t* %malloc_value3, i32 0, i32 0
  %boxptr5 = getelementptr inbounds %value_t* %malloc_value3, i32 0, i32 1
  store i32 1, i32* %boxptr4
  store i64 4, i64* %boxptr5
  %load = load i32* %boxptr
  %is_dbl = icmp eq i32 %load, 6
  %value7 = call i8* @gc_malloc(i64 ptrtoint (%value_t* getelementptr
(%value_t* null, i32 1) to i64))
  %malloc_value8 = bitcast i8* %value7 to %value_t*
  %boxptr9 = getelementptr inbounds %value_t* %malloc_value8, i32 0, i32 0
  %boxptr10 = getelementptr inbounds %value_t* %malloc_value8, i32 0, i32 2
  store i32 2, i32* %boxptr9
  store i1 %is_dbl, i1* %boxptr10
  %load12 = load i32* %boxptr4
  %is_dbl13 = icmp eq i32 %load12, 6
  %value14 = call i8* @gc_malloc(i64 ptrtoint (%value_t* getelementptr
(%value_t* null, i32 1) to i64))
  %malloc_value15 = bitcast i8* %value14 to %value_t*
  %boxptr16 = getelementptr inbounds %value_t* %malloc_value15, i32 0, i32 0
  %boxptr17 = getelementptr inbounds %value_t* %malloc_value15, i32 0, i32 2
  store i32 2, i32* %boxptr16
  store i1 %is_dbl13, i1* %boxptr17
  %load19 = load i64* %boxptr5
  %load21 = load i64* %boxptr1
  %add = add i64 %load21, %load19
  %value22 = call i8* @gc_malloc(i64 ptrtoint (%value_t* getelementptr
(%value_t* null, i32 1) to i64))
  %malloc_value23 = bitcast i8* %value22 to %value_t*
  %boxptr24 = getelementptr inbounds %value_t* %malloc_value23, i32 0, i32 0
  %boxptr25 = getelementptr inbounds %value_t* %malloc_value23, i32 0, i32 1
  store i32 1, i32* %boxptr24
  store i64 %add, i64* %boxptr25
  ret %value_t* %malloc_value23
}

attributes #0 = { nounwind }
attributes #1 = { nounwind readnone }



More information about the llvm-dev mailing list