| OLD | NEW |
| 1 ; RUN: opt < %s -expand-varargs -S | FileCheck %s | 1 ; RUN: opt < %s -expand-varargs -S | FileCheck %s |
| 2 | 2 |
| 3 target datalayout = "p:32:32:32" | 3 target datalayout = "p:32:32:32" |
| 4 | 4 |
| 5 %va_list = type i8* | 5 %va_list = type i8* |
| 6 | 6 |
| 7 declare void @llvm.va_start(i8*) | 7 declare void @llvm.va_start(i8*) |
| 8 declare void @llvm.va_end(i8*) | 8 declare void @llvm.va_end(i8*) |
| 9 declare void @llvm.va_copy(i8*, i8*) | 9 declare void @llvm.va_copy(i8*, i8*) |
| 10 | 10 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 37 define void @varargs_func_2(i8* nocapture %o8, i8* nocapture readonly %fmt, ...)
{ | 37 define void @varargs_func_2(i8* nocapture %o8, i8* nocapture readonly %fmt, ...)
{ |
| 38 ; CHECK-LABEL: @varargs_func_2( | 38 ; CHECK-LABEL: @varargs_func_2( |
| 39 entry: | 39 entry: |
| 40 %o16 = bitcast i8* %o8 to i16* | 40 %o16 = bitcast i8* %o8 to i16* |
| 41 %o32 = bitcast i8* %o8 to i32* | 41 %o32 = bitcast i8* %o8 to i32* |
| 42 %o64 = bitcast i8* %o8 to i64* | 42 %o64 = bitcast i8* %o8 to i64* |
| 43 %ofloat = bitcast i8* %o8 to float* | 43 %ofloat = bitcast i8* %o8 to float* |
| 44 %odouble = bitcast i8* %o8 to double* | 44 %odouble = bitcast i8* %o8 to double* |
| 45 | 45 |
| 46 %arglist_alloc = alloca [4 x i32], align 4 | 46 %arglist_alloc = alloca [4 x i32], align 4 |
| 47 %arglist = getelementptr inbounds [4 x i32]* %arglist_alloc, i32 0, i32 0 | 47 %arglist = getelementptr inbounds [4 x i32], [4 x i32]* %arglist_alloc, i32 0,
i32 0 |
| 48 %arglist.i8 = bitcast [4 x i32]* %arglist_alloc to i8* | 48 %arglist.i8 = bitcast [4 x i32]* %arglist_alloc to i8* |
| 49 call void @llvm.va_start(i8* %arglist.i8) | 49 call void @llvm.va_start(i8* %arglist.i8) |
| 50 br label %start | 50 br label %start |
| 51 | 51 |
| 52 start: | 52 start: |
| 53 %idx = phi i32 [ 0, %entry ], [ %inc, %next ] | 53 %idx = phi i32 [ 0, %entry ], [ %inc, %next ] |
| 54 %fmt.gep = getelementptr inbounds i8* %fmt, i32 %idx | 54 %fmt.gep = getelementptr inbounds i8, i8* %fmt, i32 %idx |
| 55 %arg.type = load i8* %fmt.gep | 55 %arg.type = load i8, i8* %fmt.gep |
| 56 switch i8 %arg.type, label %next [ | 56 switch i8 %arg.type, label %next [ |
| 57 i8 0, label %done | 57 i8 0, label %done |
| 58 i8 1, label %type.i8 | 58 i8 1, label %type.i8 |
| 59 i8 2, label %type.i16 | 59 i8 2, label %type.i16 |
| 60 i8 3, label %type.i32 | 60 i8 3, label %type.i32 |
| 61 i8 4, label %type.i64 | 61 i8 4, label %type.i64 |
| 62 i8 5, label %type.float | 62 i8 5, label %type.float |
| 63 i8 6, label %type.double | 63 i8 6, label %type.double |
| 64 ] | 64 ] |
| 65 | 65 |
| 66 type.i8: ; CHECK: type.i8: | 66 type.i8: ; CHECK: type.i8: |
| 67 %i8 = va_arg i32* %arglist, i8 | 67 %i8 = va_arg i32* %arglist, i8 |
| 68 store i8 %i8, i8* %o8 | 68 store i8 %i8, i8* %o8 |
| 69 br label %next | 69 br label %next |
| 70 ; CHECK-NEXT: %arglist1 = bitcast i32* %arglist to i8** | 70 ; CHECK-NEXT: %arglist1 = bitcast i32* %arglist to i8** |
| 71 ; CHECK-NEXT: %arglist_current = load i8** %arglist1 | 71 ; CHECK-NEXT: %arglist_current = load i8*, i8** %arglist1 |
| 72 ; CHECK-NEXT: %[[P2I:[0-9]+]] = ptrtoint i8* %arglist_current to i32 | 72 ; CHECK-NEXT: %[[P2I:[0-9]+]] = ptrtoint i8* %arglist_current to i32 |
| 73 ; %A8 = (uintptr_t)Addr + Alignment - 1 | 73 ; %A8 = (uintptr_t)Addr + Alignment - 1 |
| 74 ; CHECK-NEXT: %[[A8:[0-9]+]] = add nuw i32 %[[P2I]], sub nuw (i32 ptrtoint (i8*
getelementptr ({ i1, i8 }* null, i64 0, i32 1) to i32), i32 1) | 74 ; CHECK-NEXT: %[[A8:[0-9]+]] = add nuw i32 %[[P2I]], sub nuw (i32 ptrtoint (i8*
getelementptr ({ i1, i8 }, { i1, i8 }* null, i64 0, i32 1) to i32), i32 1) |
| 75 ; %B8 = %1 & ~(uintptr_t)(Alignment - 1) | 75 ; %B8 = %1 & ~(uintptr_t)(Alignment - 1) |
| 76 ; CHECK-NEXT: %[[B8:[0-9]+]] = and i32 %[[A8]], xor (i32 sub nuw (i32 ptrtoint (
i8* getelementptr ({ i1, i8 }* null, i64 0, i32 1) to i32), i32 1), i32 -1) | 76 ; CHECK-NEXT: %[[B8:[0-9]+]] = and i32 %[[A8]], xor (i32 sub nuw (i32 ptrtoint (
i8* getelementptr ({ i1, i8 }, { i1, i8 }* null, i64 0, i32 1) to i32), i32 1),
i32 -1) |
| 77 ; CHECK-NEXT: %[[C8:[0-9]+]] = inttoptr i32 %[[B8]] to i8* | 77 ; CHECK-NEXT: %[[C8:[0-9]+]] = inttoptr i32 %[[B8]] to i8* |
| 78 ; CHECK-NEXT: %i8 = load i8* %[[C8]] | 78 ; CHECK-NEXT: %i8 = load i8, i8* %[[C8]] |
| 79 ; CHECK-NEXT: %arglist_next = getelementptr inbounds i8* %[[C8]], i32 1 | 79 ; CHECK-NEXT: %arglist_next = getelementptr inbounds i8, i8* %[[C8]], i32 1 |
| 80 ; CHECK-NEXT: store i8* %arglist_next, i8** %arglist1 | 80 ; CHECK-NEXT: store i8* %arglist_next, i8** %arglist1 |
| 81 ; CHECK-NEXT: store i8 %i8, i8* %o8 | 81 ; CHECK-NEXT: store i8 %i8, i8* %o8 |
| 82 ; CHECK-NEXT: br label %next | 82 ; CHECK-NEXT: br label %next |
| 83 | 83 |
| 84 type.i16: ; CHECK: type.i16: | 84 type.i16: ; CHECK: type.i16: |
| 85 %i16 = va_arg i32* %arglist, i16 | 85 %i16 = va_arg i32* %arglist, i16 |
| 86 store i16 %i16, i16* %o16 | 86 store i16 %i16, i16* %o16 |
| 87 br label %next | 87 br label %next |
| 88 ; CHECK: %[[A16:[0-9]+]] = add nuw i32 %4, sub nuw (i32 ptrtoint (i16* gete
lementptr ({ i1, i16 }* null, i64 0, i32 1) to i32), i32 1) | 88 ; CHECK: %[[A16:[0-9]+]] = add nuw i32 %4, sub nuw (i32 ptrtoint (i16* gete
lementptr ({ i1, i16 }, { i1, i16 }* null, i64 0, i32 1) to i32), i32 1) |
| 89 ; CHECK-NEXT: %[[B16:[0-9]+]] = and i32 %[[A16]], xor (i32 sub nuw (i32 ptrtoint
(i16* getelementptr ({ i1, i16 }* null, i64 0, i32 1) to i32), i32 1), i32 -1) | 89 ; CHECK-NEXT: %[[B16:[0-9]+]] = and i32 %[[A16]], xor (i32 sub nuw (i32 ptrtoint
(i16* getelementptr ({ i1, i16 }, { i1, i16 }* null, i64 0, i32 1) to i32), i32
1), i32 -1) |
| 90 ; CHECK-NEXT: %[[C16:[0-9]+]] = inttoptr i32 %[[B16]] to i16* | 90 ; CHECK-NEXT: %[[C16:[0-9]+]] = inttoptr i32 %[[B16]] to i16* |
| 91 ; CHECK-NEXT: %i16 = load i16* %[[C16]] | 91 ; CHECK-NEXT: %i16 = load i16, i16* %[[C16]] |
| 92 | 92 |
| 93 type.i32: ; CHECK: type.i32: | 93 type.i32: ; CHECK: type.i32: |
| 94 %i32 = va_arg i32* %arglist, i32 | 94 %i32 = va_arg i32* %arglist, i32 |
| 95 store i32 %i32, i32* %o32 | 95 store i32 %i32, i32* %o32 |
| 96 br label %next | 96 br label %next |
| 97 ; CHECK: %[[A32:[0-9]+]] = add nuw i32 %8, sub nuw (i32 ptrtoint (i32* gete
lementptr ({ i1, i32 }* null, i64 0, i32 1) to i32), i32 1) | 97 ; CHECK: %[[A32:[0-9]+]] = add nuw i32 %8, sub nuw (i32 ptrtoint (i32* gete
lementptr ({ i1, i32 }, { i1, i32 }* null, i64 0, i32 1) to i32), i32 1) |
| 98 ; CHECK-NEXT: %[[B32:[0-9]+]] = and i32 %[[A32]], xor (i32 sub nuw (i32 ptrtoint
(i32* getelementptr ({ i1, i32 }* null, i64 0, i32 1) to i32), i32 1), i32 -1) | 98 ; CHECK-NEXT: %[[B32:[0-9]+]] = and i32 %[[A32]], xor (i32 sub nuw (i32 ptrtoint
(i32* getelementptr ({ i1, i32 }, { i1, i32 }* null, i64 0, i32 1) to i32), i32
1), i32 -1) |
| 99 ; CHECK-NEXT: %[[C32:[0-9]+]] = inttoptr i32 %[[B32]] to i32* | 99 ; CHECK-NEXT: %[[C32:[0-9]+]] = inttoptr i32 %[[B32]] to i32* |
| 100 ; CHECK-NEXT: %i32 = load i32* %[[C32]] | 100 ; CHECK-NEXT: %i32 = load i32, i32* %[[C32]] |
| 101 | 101 |
| 102 type.i64: ; CHECK: type.i64: | 102 type.i64: ; CHECK: type.i64: |
| 103 %i64 = va_arg i32* %arglist, i64 | 103 %i64 = va_arg i32* %arglist, i64 |
| 104 store i64 %i64, i64* %o64 | 104 store i64 %i64, i64* %o64 |
| 105 br label %next | 105 br label %next |
| 106 ; CHECK: %[[A64:[0-9]+]] = add nuw i32 %12, sub nuw (i32 ptrtoint (i64* get
elementptr ({ i1, i64 }* null, i64 0, i32 1) to i32), i32 1) | 106 ; CHECK: %[[A64:[0-9]+]] = add nuw i32 %12, sub nuw (i32 ptrtoint (i64* get
elementptr ({ i1, i64 }, { i1, i64 }* null, i64 0, i32 1) to i32), i32 1) |
| 107 ; CHECK-NEXT: %[[B64:[0-9]+]] = and i32 %[[A64]], xor (i32 sub nuw (i32 ptrtoint
(i64* getelementptr ({ i1, i64 }* null, i64 0, i32 1) to i32), i32 1), i32 -1) | 107 ; CHECK-NEXT: %[[B64:[0-9]+]] = and i32 %[[A64]], xor (i32 sub nuw (i32 ptrtoint
(i64* getelementptr ({ i1, i64 }, { i1, i64 }* null, i64 0, i32 1) to i32), i32
1), i32 -1) |
| 108 ; CHECK-NEXT: %[[C64:[0-9]+]] = inttoptr i32 %[[B64]] to i64* | 108 ; CHECK-NEXT: %[[C64:[0-9]+]] = inttoptr i32 %[[B64]] to i64* |
| 109 ; CHECK-NEXT: %i64 = load i64* %[[C64]] | 109 ; CHECK-NEXT: %i64 = load i64, i64* %[[C64]] |
| 110 | 110 |
| 111 type.float: ; CHECK: type.float: | 111 type.float: ; CHECK: type.float: |
| 112 %float = va_arg i32* %arglist, float | 112 %float = va_arg i32* %arglist, float |
| 113 store float %float, float* %ofloat | 113 store float %float, float* %ofloat |
| 114 br label %next | 114 br label %next |
| 115 ; CHECK: %[[AF:[0-9]+]] = add nuw i32 %16, sub nuw (i32 ptrtoint (float* ge
telementptr ({ i1, float }* null, i64 0, i32 1) to i32), i32 1) | 115 ; CHECK: %[[AF:[0-9]+]] = add nuw i32 %16, sub nuw (i32 ptrtoint (float* ge
telementptr ({ i1, float }, { i1, float }* null, i64 0, i32 1) to i32), i32 1) |
| 116 ; CHECK-NEXT: %[[BF:[0-9]+]] = and i32 %[[AF]], xor (i32 sub nuw (i32 ptrtoint (
float* getelementptr ({ i1, float }* null, i64 0, i32 1) to i32), i32 1), i32 -1
) | 116 ; CHECK-NEXT: %[[BF:[0-9]+]] = and i32 %[[AF]], xor (i32 sub nuw (i32 ptrtoint (
float* getelementptr ({ i1, float }, { i1, float }* null, i64 0, i32 1) to i32),
i32 1), i32 -1) |
| 117 ; CHECK-NEXT: %[[CF:[0-9]+]] = inttoptr i32 %[[BF]] to float* | 117 ; CHECK-NEXT: %[[CF:[0-9]+]] = inttoptr i32 %[[BF]] to float* |
| 118 ; CHECK-NEXT: %float = load float* %[[CF]] | 118 ; CHECK-NEXT: %float = load float, float* %[[CF]] |
| 119 | 119 |
| 120 type.double: ; CHECK: type.double: | 120 type.double: ; CHECK: type.double: |
| 121 %double = va_arg i32* %arglist, double | 121 %double = va_arg i32* %arglist, double |
| 122 store double %double, double* %odouble | 122 store double %double, double* %odouble |
| 123 br label %next | 123 br label %next |
| 124 ; CHECK: %[[AD:[0-9]+]] = add nuw i32 %20, sub nuw (i32 ptrtoint (double* g
etelementptr ({ i1, double }* null, i64 0, i32 1) to i32), i32 1) | 124 ; CHECK: %[[AD:[0-9]+]] = add nuw i32 %20, sub nuw (i32 ptrtoint (double* g
etelementptr ({ i1, double }, { i1, double }* null, i64 0, i32 1) to i32), i32 1
) |
| 125 ; CHECK-NEXT: %[[BD:[0-9]+]] = and i32 %[[AD]], xor (i32 sub nuw (i32 ptrtoint (
double* getelementptr ({ i1, double }* null, i64 0, i32 1) to i32), i32 1), i32
-1) | 125 ; CHECK-NEXT: %[[BD:[0-9]+]] = and i32 %[[AD]], xor (i32 sub nuw (i32 ptrtoint (
double* getelementptr ({ i1, double }, { i1, double }* null, i64 0, i32 1) to i3
2), i32 1), i32 -1) |
| 126 ; CHECK-NEXT: %[[CD:[0-9]+]] = inttoptr i32 %[[BD]] to double* | 126 ; CHECK-NEXT: %[[CD:[0-9]+]] = inttoptr i32 %[[BD]] to double* |
| 127 ; CHECK-NEXT: %double = load double* %[[CD]] | 127 ; CHECK-NEXT: %double = load double, double* %[[CD]] |
| 128 | 128 |
| 129 next: | 129 next: |
| 130 %inc = add i32 %idx, 1 | 130 %inc = add i32 %idx, 1 |
| 131 br label %start | 131 br label %start |
| 132 | 132 |
| 133 done: | 133 done: |
| 134 call void @llvm.va_end(i8* %arglist.i8) | 134 call void @llvm.va_end(i8* %arglist.i8) |
| 135 ret void | 135 ret void |
| 136 } | 136 } |
| 137 | 137 |
| 138 | 138 |
| 139 define i32 @varargs_call1() { | 139 define i32 @varargs_call1() { |
| 140 %result = call i32 (i32, ...)* @varargs_func(i32 111, i64 222, i32 333, double
4.0) | 140 %result = call i32 (i32, ...) @varargs_func(i32 111, i64 222, i32 333, double
4.0) |
| 141 ret i32 %result | 141 ret i32 %result |
| 142 } | 142 } |
| 143 ; CHECK-LABEL: @varargs_call1( | 143 ; CHECK-LABEL: @varargs_call1( |
| 144 ; CHECK-NEXT: %vararg_buffer = alloca { i64, i32, double } | 144 ; CHECK-NEXT: %vararg_buffer = alloca { i64, i32, double } |
| 145 ; CHECK-NEXT: %vararg_lifetime_bitcast = bitcast { i64, i32, double }* %vararg_b
uffer to i8* | 145 ; CHECK-NEXT: %vararg_lifetime_bitcast = bitcast { i64, i32, double }* %vararg_b
uffer to i8* |
| 146 ; CHECK-NEXT: call void @llvm.lifetime.start(i64 24, i8* %vararg_lifetime_bitcas
t) | 146 ; CHECK-NEXT: call void @llvm.lifetime.start(i64 24, i8* %vararg_lifetime_bitcas
t) |
| 147 ; CHECK-NEXT: %vararg_ptr = getelementptr inbounds { i64, i32, double }* %vararg
_buffer, i32 0, i32 0 | 147 ; CHECK-NEXT: %vararg_ptr = getelementptr inbounds { i64, i32, double }, { i64,
i32, double }* %vararg_buffer, i32 0, i32 0 |
| 148 ; CHECK-NEXT: store i64 222, i64* %vararg_ptr | 148 ; CHECK-NEXT: store i64 222, i64* %vararg_ptr |
| 149 ; CHECK-NEXT: %vararg_ptr1 = getelementptr inbounds { i64, i32, double }* %varar
g_buffer, i32 0, i32 1 | 149 ; CHECK-NEXT: %vararg_ptr1 = getelementptr inbounds { i64, i32, double }, { i64,
i32, double }* %vararg_buffer, i32 0, i32 1 |
| 150 ; CHECK-NEXT: store i32 333, i32* %vararg_ptr1 | 150 ; CHECK-NEXT: store i32 333, i32* %vararg_ptr1 |
| 151 ; CHECK-NEXT: %vararg_ptr2 = getelementptr inbounds { i64, i32, double }* %varar
g_buffer, i32 0, i32 2 | 151 ; CHECK-NEXT: %vararg_ptr2 = getelementptr inbounds { i64, i32, double }, { i64,
i32, double }* %vararg_buffer, i32 0, i32 2 |
| 152 ; CHECK-NEXT: store double 4.{{0*}}e+00, double* %vararg_ptr2 | 152 ; CHECK-NEXT: store double 4.{{0*}}e+00, double* %vararg_ptr2 |
| 153 ; CHECK-NEXT: %result = call i32 bitcast (i32 (i32, i8*)* @varargs_func to i32 (
i32, { i64, i32, double }*)*)(i32 111, { i64, i32, double }* %vararg_buffer) | 153 ; CHECK-NEXT: %result = call i32 bitcast (i32 (i32, i8*)* @varargs_func to i32 (
i32, { i64, i32, double }*)*)(i32 111, { i64, i32, double }* %vararg_buffer) |
| 154 ; CHECK-NEXT: call void @llvm.lifetime.end(i64 24, i8* %vararg_lifetime_bitcast) | 154 ; CHECK-NEXT: call void @llvm.lifetime.end(i64 24, i8* %vararg_lifetime_bitcast) |
| 155 ; CHECK-NEXT: ret i32 %result | 155 ; CHECK-NEXT: ret i32 %result |
| 156 | 156 |
| 157 | 157 |
| 158 ; Check that the pass works when there are no variable arguments. | 158 ; Check that the pass works when there are no variable arguments. |
| 159 define i32 @call_with_zero_varargs() { | 159 define i32 @call_with_zero_varargs() { |
| 160 %result = call i32 (i32, ...)* @varargs_func(i32 111) | 160 %result = call i32 (i32, ...) @varargs_func(i32 111) |
| 161 ret i32 %result | 161 ret i32 %result |
| 162 } | 162 } |
| 163 ; CHECK-LABEL: @call_with_zero_varargs( | 163 ; CHECK-LABEL: @call_with_zero_varargs( |
| 164 ; We have a dummy i32 field to deal with buggy programs: | 164 ; We have a dummy i32 field to deal with buggy programs: |
| 165 ; CHECK-NEXT: %vararg_buffer = alloca { i32 } | 165 ; CHECK-NEXT: %vararg_buffer = alloca { i32 } |
| 166 ; CHECK-NEXT: %vararg_lifetime_bitcast = bitcast { i32 }* %vararg_buffer to i8* | 166 ; CHECK-NEXT: %vararg_lifetime_bitcast = bitcast { i32 }* %vararg_buffer to i8* |
| 167 ; CHECK-NEXT: call void @llvm.lifetime.start(i64 4, i8* %vararg_lifetime_bitcast
) | 167 ; CHECK-NEXT: call void @llvm.lifetime.start(i64 4, i8* %vararg_lifetime_bitcast
) |
| 168 ; CHECK-NEXT: %result = call i32 bitcast (i32 (i32, i8*)* @varargs_func to i32 (
i32, { i32 }*)*)(i32 111, { i32 }* %vararg_buffer) | 168 ; CHECK-NEXT: %result = call i32 bitcast (i32 (i32, i8*)* @varargs_func to i32 (
i32, { i32 }*)*)(i32 111, { i32 }* %vararg_buffer) |
| 169 ; CHECK-NEXT: call void @llvm.lifetime.end(i64 4, i8* %vararg_lifetime_bitcast) | 169 ; CHECK-NEXT: call void @llvm.lifetime.end(i64 4, i8* %vararg_lifetime_bitcast) |
| 170 ; CHECK-NEXT: ret i32 %result | 170 ; CHECK-NEXT: ret i32 %result |
| (...skipping 13 matching lines...) Expand all Loading... |
| 184 ; CHECK: call void @llvm.lifetime.start(i64 8, i8* %vararg_lifetime_bitcast) | 184 ; CHECK: call void @llvm.lifetime.start(i64 8, i8* %vararg_lifetime_bitcast) |
| 185 ; CHECK: %result = invoke i32 bitcast (i32 (i32, i8*)* @varargs_func to i32 (i32
, { i64 }*)*)(i32 111, { i64 }* %vararg_buffer) | 185 ; CHECK: %result = invoke i32 bitcast (i32 (i32, i8*)* @varargs_func to i32 (i32
, { i64 }*)*)(i32 111, { i64 }* %vararg_buffer) |
| 186 ; CHECK-NEXT: to label %cont unwind label %lpad | 186 ; CHECK-NEXT: to label %cont unwind label %lpad |
| 187 ; CHECK: cont: | 187 ; CHECK: cont: |
| 188 ; CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* %vararg_lifetime_bitcast) | 188 ; CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* %vararg_lifetime_bitcast) |
| 189 ; CHECK: lpad: | 189 ; CHECK: lpad: |
| 190 ; CHECK: call void @llvm.lifetime.end(i64 8, i8* %vararg_lifetime_bitcast) | 190 ; CHECK: call void @llvm.lifetime.end(i64 8, i8* %vararg_lifetime_bitcast) |
| 191 | 191 |
| 192 | 192 |
| 193 define void @varargs_multiple_calls() { | 193 define void @varargs_multiple_calls() { |
| 194 %call1 = call i32 (i32, ...)* @varargs_func(i32 11, i64 22, i32 33) | 194 %call1 = call i32 (i32, ...) @varargs_func(i32 11, i64 22, i32 33) |
| 195 %call2 = call i32 (i32, ...)* @varargs_func(i32 44, i64 55, i32 66) | 195 %call2 = call i32 (i32, ...) @varargs_func(i32 44, i64 55, i32 66) |
| 196 ret void | 196 ret void |
| 197 } | 197 } |
| 198 ; CHECK-LABEL: @varargs_multiple_calls( | 198 ; CHECK-LABEL: @varargs_multiple_calls( |
| 199 ; The added allocas should appear at the start of the function. | 199 ; The added allocas should appear at the start of the function. |
| 200 ; CHECK: %vararg_buffer{{.*}} = alloca { i64, i32 } | 200 ; CHECK: %vararg_buffer{{.*}} = alloca { i64, i32 } |
| 201 ; CHECK: %vararg_buffer{{.*}} = alloca { i64, i32 } | 201 ; CHECK: %vararg_buffer{{.*}} = alloca { i64, i32 } |
| 202 ; CHECK: %call1 = call i32 bitcast (i32 (i32, i8*)* @varargs_func to i32 (i32, {
i64, i32 }*)*)(i32 11, { i64, i32 }* %vararg_buffer{{.*}}) | 202 ; CHECK: %call1 = call i32 bitcast (i32 (i32, i8*)* @varargs_func to i32 (i32, {
i64, i32 }*)*)(i32 11, { i64, i32 }* %vararg_buffer{{.*}}) |
| 203 ; CHECK: %call2 = call i32 bitcast (i32 (i32, i8*)* @varargs_func to i32 (i32, {
i64, i32 }*)*)(i32 44, { i64, i32 }* %vararg_buffer{{.*}}) | 203 ; CHECK: %call2 = call i32 bitcast (i32 (i32, i8*)* @varargs_func to i32 (i32, {
i64, i32 }*)*)(i32 44, { i64, i32 }* %vararg_buffer{{.*}}) |
| 204 | 204 |
| 205 | 205 |
| 206 | 206 |
| 207 define i32 @va_arg_i32(i8* %arglist) { | 207 define i32 @va_arg_i32(i8* %arglist) { |
| 208 %result = va_arg i8* %arglist, i32 | 208 %result = va_arg i8* %arglist, i32 |
| 209 ret i32 %result | 209 ret i32 %result |
| 210 } | 210 } |
| 211 ; CHECK-LABEL: define i32 @va_arg_i32(i8* %arglist) { | 211 ; CHECK-LABEL: define i32 @va_arg_i32(i8* %arglist) { |
| 212 ; CHECK-NEXT: %arglist1 = bitcast i8* %arglist to i32** | 212 ; CHECK-NEXT: %arglist1 = bitcast i8* %arglist to i32** |
| 213 ; CHECK-NEXT: %arglist_current = load i32** %arglist1 | 213 ; CHECK-NEXT: %arglist_current = load i32*, i32** %arglist1 |
| 214 ; CHECK-NEXT: %1 = ptrtoint i32* %arglist_current to i32 | 214 ; CHECK-NEXT: %1 = ptrtoint i32* %arglist_current to i32 |
| 215 ; CHECK-NEXT: %2 = add nuw i32 %1, sub nuw (i32 ptrtoint (i32* getelementptr ({
i1, i32 }* null, i64 0, i32 1) to i32), i32 1) | 215 ; CHECK-NEXT: %2 = add nuw i32 %1, sub nuw (i32 ptrtoint (i32* getelementptr ({
i1, i32 }, { i1, i32 }* null, i64 0, i32 1) to i32), i32 1) |
| 216 ; CHECK-NEXT: %3 = and i32 %2, xor (i32 sub nuw (i32 ptrtoint (i32* getelementpt
r ({ i1, i32 }* null, i64 0, i32 1) to i32), i32 1), i32 -1) | 216 ; CHECK-NEXT: %3 = and i32 %2, xor (i32 sub nuw (i32 ptrtoint (i32* getelementpt
r ({ i1, i32 }, { i1, i32 }* null, i64 0, i32 1) to i32), i32 1), i32 -1) |
| 217 ; CHECK-NEXT: %4 = inttoptr i32 %3 to i32* | 217 ; CHECK-NEXT: %4 = inttoptr i32 %3 to i32* |
| 218 ; CHECK-NEXT: %result = load i32* %4 | 218 ; CHECK-NEXT: %result = load i32, i32* %4 |
| 219 ; CHECK-NEXT: %arglist_next = getelementptr inbounds i32* %4, i32 1 | 219 ; CHECK-NEXT: %arglist_next = getelementptr inbounds i32, i32* %4, i32 1 |
| 220 ; CHECK-NEXT: store i32* %arglist_next, i32** %arglist1 | 220 ; CHECK-NEXT: store i32* %arglist_next, i32** %arglist1 |
| 221 ; CHECK-NEXT: ret i32 %result | 221 ; CHECK-NEXT: ret i32 %result |
| 222 | 222 |
| 223 | 223 |
| 224 define i64 @va_arg_i64(i8* %arglist) { | 224 define i64 @va_arg_i64(i8* %arglist) { |
| 225 %result = va_arg i8* %arglist, i64 | 225 %result = va_arg i8* %arglist, i64 |
| 226 ret i64 %result | 226 ret i64 %result |
| 227 } | 227 } |
| 228 ; CHECK-LABEL: define i64 @va_arg_i64(i8* %arglist) { | 228 ; CHECK-LABEL: define i64 @va_arg_i64(i8* %arglist) { |
| 229 ; CHECK-NEXT: %arglist1 = bitcast i8* %arglist to i64** | 229 ; CHECK-NEXT: %arglist1 = bitcast i8* %arglist to i64** |
| 230 ; CHECK-NEXT: %arglist_current = load i64** %arglist1 | 230 ; CHECK-NEXT: %arglist_current = load i64*, i64** %arglist1 |
| 231 ; CHECK-NEXT: %1 = ptrtoint i64* %arglist_current to i32 | 231 ; CHECK-NEXT: %1 = ptrtoint i64* %arglist_current to i32 |
| 232 ; CHECK-NEXT: %2 = add nuw i32 %1, sub nuw (i32 ptrtoint (i64* getelementptr ({
i1, i64 }* null, i64 0, i32 1) to i32), i32 1) | 232 ; CHECK-NEXT: %2 = add nuw i32 %1, sub nuw (i32 ptrtoint (i64* getelementptr ({
i1, i64 }, { i1, i64 }* null, i64 0, i32 1) to i32), i32 1) |
| 233 ; CHECK-NEXT: %3 = and i32 %2, xor (i32 sub nuw (i32 ptrtoint (i64* getelementpt
r ({ i1, i64 }* null, i64 0, i32 1) to i32), i32 1), i32 -1) | 233 ; CHECK-NEXT: %3 = and i32 %2, xor (i32 sub nuw (i32 ptrtoint (i64* getelementpt
r ({ i1, i64 }, { i1, i64 }* null, i64 0, i32 1) to i32), i32 1), i32 -1) |
| 234 ; CHECK-NEXT: %4 = inttoptr i32 %3 to i64* | 234 ; CHECK-NEXT: %4 = inttoptr i32 %3 to i64* |
| 235 ; CHECK-NEXT: %result = load i64* %4 | 235 ; CHECK-NEXT: %result = load i64, i64* %4 |
| 236 ; CHECK-NEXT: %arglist_next = getelementptr inbounds i64* %4, i32 1 | 236 ; CHECK-NEXT: %arglist_next = getelementptr inbounds i64, i64* %4, i32 1 |
| 237 ; CHECK-NEXT: store i64* %arglist_next, i64** %arglist1 | 237 ; CHECK-NEXT: store i64* %arglist_next, i64** %arglist1 |
| 238 ; CHECK-NEXT: ret i64 %result | 238 ; CHECK-NEXT: ret i64 %result |
| 239 | 239 |
| 240 | 240 |
| 241 define void @do_va_copy(i8* %dest, i8* %src) { | 241 define void @do_va_copy(i8* %dest, i8* %src) { |
| 242 call void @llvm.va_copy(i8* %dest, i8* %src) | 242 call void @llvm.va_copy(i8* %dest, i8* %src) |
| 243 ret void | 243 ret void |
| 244 } | 244 } |
| 245 ; CHECK-LABEL: define void @do_va_copy( | 245 ; CHECK-LABEL: define void @do_va_copy( |
| 246 ; CHECK-NEXT: %vacopy_src = bitcast i8* %src to i8** | 246 ; CHECK-NEXT: %vacopy_src = bitcast i8* %src to i8** |
| 247 ; CHECK-NEXT: %vacopy_dest = bitcast i8* %dest to i8** | 247 ; CHECK-NEXT: %vacopy_dest = bitcast i8* %dest to i8** |
| 248 ; CHECK-NEXT: %vacopy_currentptr = load i8** %vacopy_src | 248 ; CHECK-NEXT: %vacopy_currentptr = load i8*, i8** %vacopy_src |
| 249 ; CHECK-NEXT: store i8* %vacopy_currentptr, i8** %vacopy_dest | 249 ; CHECK-NEXT: store i8* %vacopy_currentptr, i8** %vacopy_dest |
| 250 ; CHECK-NEXT: ret void | 250 ; CHECK-NEXT: ret void |
| OLD | NEW |