OLD | NEW |
(Empty) | |
| 1 ; RUN: opt %s -simplify-struct-reg-signatures -S | FileCheck %s |
| 2 |
| 3 %struct = type { i32, i32 } |
| 4 %rec_struct = type {%rec_struct*} |
| 5 %rec_problem_struct = type{void (%rec_problem_struct)*} |
| 6 %rec_pair_1 = type {%rec_pair_2*} |
| 7 %rec_pair_2 = type {%rec_pair_1*} |
| 8 |
| 9 ; externs |
| 10 declare void @extern_func(%struct) |
| 11 declare %struct @struct_returning_extern(i32, %struct) |
| 12 |
| 13 define void @main(%struct* byval %ptr) { |
| 14 %val = load %struct* %ptr |
| 15 call void @extern_func(%struct %val) |
| 16 ret void |
| 17 } |
| 18 |
| 19 define void @two_param_func(%struct %val1, %struct %val2) { |
| 20 call void @extern_func(%struct %val1) |
| 21 call void @extern_func(%struct %val2) |
| 22 ret void |
| 23 } |
| 24 |
| 25 define i32 @another_func(i32 %a, %struct %str, i64 %b) { |
| 26 call void @two_param_func(%struct %str, %struct %str) |
| 27 call void @extern_func(%struct %str) |
| 28 ret i32 0 |
| 29 } |
| 30 |
| 31 define %struct @returns_struct(i32 %an_int, %struct %val) { |
| 32 %tmp = call %struct @struct_returning_extern(i32 %an_int, %struct %val) |
| 33 ret %struct %tmp |
| 34 } |
| 35 |
| 36 define i32 @lots_of_call_attrs() { |
| 37 %tmp.0 = insertvalue %struct undef, i32 1, 0 |
| 38 %tmp.1 = insertvalue %struct %tmp.0, i32 2, 1 |
| 39 %ret = tail call zeroext i32 @another_func(i32 1, %struct %tmp.1, i64 2) reado
nly |
| 40 ret i32 %ret |
| 41 } |
| 42 |
| 43 declare void @rec_struct_ok(%rec_struct*) |
| 44 declare void @rec_struct_mod(%rec_struct) |
| 45 |
| 46 define void @rec_call_sreg(%rec_problem_struct %r) { |
| 47 %tmp = extractvalue %rec_problem_struct %r, 0 |
| 48 call void %tmp(%rec_problem_struct %r) |
| 49 ret void |
| 50 } |
| 51 |
| 52 declare void @pairs(%rec_pair_1) |
| 53 |
| 54 %rec_returning = type { %rec_returning (%rec_returning)* } |
| 55 |
| 56 define %rec_returning @rec_returning_fun(%rec_returning %str) { |
| 57 %tmp = extractvalue %rec_returning %str, 0 |
| 58 %ret = call %rec_returning %tmp(%rec_returning %str) |
| 59 ret %rec_returning %ret |
| 60 } |
| 61 |
| 62 %direct_def = type { void(%struct)*, %struct } |
| 63 |
| 64 define void @direct_caller(%direct_def %def) { |
| 65 %func = extractvalue %direct_def %def, 0 |
| 66 %param = extractvalue %direct_def %def, 1 |
| 67 call void %func(%struct %param) |
| 68 ret void |
| 69 } |
| 70 |
| 71 ; new type declarations: |
| 72 ; CHECK: %struct = type { i32, i32 } |
| 73 ; CHECK-NEXT: %rec_struct = type { %rec_struct* } |
| 74 ; CHECK-NEXT: %rec_problem_struct.2 = type { void (%rec_problem_struct.2*)* } |
| 75 ; CHECK-NEXT: %rec_pair_1 = type { %rec_pair_2* } |
| 76 ; CHECK-NEXT: %rec_pair_2 = type { %rec_pair_1* } |
| 77 ; CHECK-NEXT: %rec_returning.6 = type { void (%rec_returning.6*, %rec_returning.
6*)* } |
| 78 ; CHECK-NEXT: %direct_def.8 = type { void (%struct*)*, %struct } |
| 79 |
| 80 ; verify that parameters are mapped correctly: single param, two, and combo |
| 81 ; with non-struct regs |
| 82 ; CHECK-NOT: declare void @extern_func(%struct) |
| 83 ; CHECK-NOT: declare %struct @struct_returning_extern(i32, %struct) |
| 84 ; CHECK: declare void @extern_func(%struct* byval) |
| 85 ; CHECK: declare void @struct_returning_extern(%struct* sret, i32, %struct* byva
l) |
| 86 |
| 87 ; CHECK: define void @two_param_func(%struct* byval %val1.ptr, %struct* byval %v
al2.ptr) |
| 88 ; CHECK-NOT: define void @two_param_func(%struct %val1, %struct %val2) |
| 89 |
| 90 ; CHECK: define i32 @another_func(i32 %a, %struct* byval %str.ptr, i64 %b) |
| 91 ; CHECK: call void @two_param_func(%struct* byval %str.sreg.ptr, %struct* byval
%str.sreg.ptr1) |
| 92 |
| 93 ; verify return value and codegen |
| 94 ; CHECK: define void @returns_struct(%struct* sret %retVal, i32 %an_int, %struct
* byval %val.ptr) |
| 95 ; CHECK-NEXT: %val.sreg = load %struct* %val.ptr |
| 96 ; CHECK-NEXT: %1 = alloca %struct |
| 97 ; CHECK-NEXT: %val.sreg.ptr = alloca %struct |
| 98 ; CHECK-NEXT: store %struct %val.sreg, %struct* %val.sreg.ptr |
| 99 ; CHECK-NEXT: call void @struct_returning_extern(%struct* sret %1, i32 %an_int,
%struct* byval %val.sreg.ptr) |
| 100 ; CHECK-NEXT: %tmp.sreg = load %struct* %1 |
| 101 ; CHECK-NEXT: store %struct %tmp.sreg, %struct* %retVal |
| 102 ; CHECK-NEXT: ret void |
| 103 |
| 104 ; verify attributes are copied |
| 105 ; CHECK: %1 = tail call zeroext i32 @another_func(i32 1, %struct* byval %tmp.1.p
tr, i64 2) #0 |
| 106 ; CHECK-NEXT: ret i32 %1 |
| 107 |
| 108 ; compliant recursive structs are kept as-is |
| 109 ; CHECK: declare void @rec_struct_ok(%rec_struct*) |
| 110 ; CHECK: declare void @rec_struct_mod(%rec_struct* byval) |
| 111 |
| 112 ; non-compliant structs are correctly mapped and calls are changed |
| 113 ; CHECK: define void @rec_call_sreg(%rec_problem_struct.2* byval %r.ptr) |
| 114 ; CHECK: call void %tmp(%rec_problem_struct.2* byval %r.sreg.ptr) |
| 115 |
| 116 ; pair structs |
| 117 ; CHECK: declare void @pairs(%rec_pair_1* byval) |
| 118 ; CHECK: define void @rec_returning_fun(%rec_returning.6* sret %retVal, %rec_ret
urning.6* byval %str.ptr) |
| 119 ; CHECK-NEXT: %str.sreg = load %rec_returning.6* %str.ptr |
| 120 ; CHECK-NEXT: %tmp = extractvalue %rec_returning.6 %str.sreg, 0 |
| 121 ; CHECK-NEXT: %1 = alloca %rec_returning.6 |
| 122 ; CHECK-NEXT: %str.sreg.ptr = alloca %rec_returning.6 |
| 123 ; CHECK-NEXT: store %rec_returning.6 %str.sreg, %rec_returning.6* %str.sreg.pt
r |
| 124 ; CHECK-NEXT: call void %tmp(%rec_returning.6* sret %1, %rec_returning.6* byva
l %str.sreg.ptr) |
| 125 ; CHECK-NEXT: %ret.sreg = load %rec_returning.6* %1 |
| 126 ; CHECK-NEXT: store %rec_returning.6 %ret.sreg, %rec_returning.6* %retVal |
| 127 ; CHECK-NEXT: ret void |
| 128 |
| 129 ; CHECK: define void @direct_caller(%direct_def.8* byval %def.ptr) |
| 130 ; CHECK-NEXT: %def.sreg = load %direct_def.8* %def.ptr |
| 131 ; CHECK-NEXT: %func = extractvalue %direct_def.8 %def.sreg, 0 |
| 132 ; CHECK-NEXT: %param = extractvalue %direct_def.8 %def.sreg, 1 |
| 133 ; CHECK-NEXT: %param.ptr = alloca %struct |
| 134 ; CHECK-NEXT: store %struct %param, %struct* %param.ptr |
| 135 ; CHECK-NEXT: call void %func(%struct* byval %param.ptr) |
| 136 ; CHECK-NEXT: ret void |
| 137 |
| 138 |
| 139 ; this is at the end, corresponds to the call marked as readonly |
| 140 ; CHECK: attributes #0 = { readonly } |
OLD | NEW |