1// RUN: tco -o - %s | FileCheck %s 2 3// Global box initialization (test must come first because llvm globals are emitted first). 4// CHECK-LABEL: @globalx = internal global { ptr, i64, i32, i8, i8, i8, i8 } { ptr null, i64 ptrtoint (ptr getelementptr (i32, ptr null, i32 1) to i64), i32 20240719, i8 0, i8 9, i8 2, i8 0 } 5fir.global internal @globalx : !fir.box<!fir.heap<i32>> { 6 %c0 = arith.constant 0 : index 7 %0 = fir.convert %c0 : (index) -> !fir.heap<i32> 8 %1 = fir.embox %0 : (!fir.heap<i32>) -> !fir.box<!fir.heap<i32>> 9 fir.has_value %1 : !fir.box<!fir.heap<i32>> 10} 11 12// CHECK-LABEL: @globaly = internal global { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] } { ptr null, i64 ptrtoint (ptr getelementptr (float, ptr null, i32 1) to i64), i32 20240719, i8 1, i8 27, i8 2, i8 0,{{.*}}[3 x i64] [i64 1, i64 0, i64 ptrtoint (ptr getelementptr (float, ptr null, i32 1) to i64)] 13fir.global internal @globaly : !fir.box<!fir.heap<!fir.array<?xf32>>> { 14 %c0 = arith.constant 0 : index 15 %0 = fir.convert %c0 : (index) -> !fir.heap<!fir.array<?xf32>> 16 %1 = fir.shape %c0 : (index) -> !fir.shape<1> 17 %2 = fir.embox %0(%1) : (!fir.heap<!fir.array<?xf32>>, !fir.shape<1>) -> !fir.box<!fir.heap<!fir.array<?xf32>>> 18 fir.has_value %2 : !fir.box<!fir.heap<!fir.array<?xf32>>> 19} 20 21// CHECK-LABEL: declare void @g(ptr) 22func.func private @g(%b : !fir.box<f32>) 23// CHECK-LABEL: declare void @ga(ptr) 24func.func private @ga(%b : !fir.box<!fir.array<?xf32>>) 25 26// CHECK-LABEL: define void @f 27// CHECK: (ptr captures(none) %[[ARG:.*]]) 28func.func @f(%a : !fir.ref<f32>) { 29 // CHECK: %[[DESC:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8 } 30 // CHECK: %[[INS0:.*]] = insertvalue {{.*}} { ptr undef, i64 ptrtoint (ptr getelementptr (float, ptr null, i32 1) to i64), i32 20240719, i8 0, i8 27, i8 0, i8 0 }, ptr %[[ARG]], 0 31 // CHECK: store {{.*}} %[[INS0]], {{.*}} %[[DESC]] 32 %b = fir.embox %a : (!fir.ref<f32>) -> !fir.box<f32> 33 34 // CHECK: call void @g({{.*}} %[[DESC]]) 35 fir.call @g(%b) : (!fir.box<f32>) -> () 36 // CHECK: ret void 37 return 38} 39 40// CHECK-LABEL: define void @fa 41// CHECK: (ptr captures(none) %[[ARG:.*]]) 42func.func @fa(%a : !fir.ref<!fir.array<100xf32>>) { 43 %c = fir.convert %a : (!fir.ref<!fir.array<100xf32>>) -> !fir.ref<!fir.array<?xf32>> 44 %c1 = arith.constant 1 : index 45 %c100 = arith.constant 100 : index 46 %d = fir.shape %c100 : (index) -> !fir.shape<1> 47 // CHECK: %[[INS70:.*]] = insertvalue {{.*}} { ptr undef, i64 ptrtoint (ptr getelementptr (float, ptr null, i32 1) to i64), i32 20240719, i8 1, i8 27, i8 0, i8 0, {{.*}} }, ptr %{{.*}}, 0 48 %b = fir.embox %c(%d) : (!fir.ref<!fir.array<?xf32>>, !fir.shape<1>) -> !fir.box<!fir.array<?xf32>> 49 // CHECK: call void @ga( 50 fir.call @ga(%b) : (!fir.box<!fir.array<?xf32>>) -> () 51 // CHECK: ret void 52 return 53} 54 55// Boxing of a scalar character of dynamic length 56// CHECK-LABEL: define void @b1( 57// CHECK-SAME: ptr captures(none) %[[res:.*]], ptr captures(none) %[[arg0:.*]], i64 %[[arg1:.*]]) 58func.func @b1(%arg0 : !fir.ref<!fir.char<1,?>>, %arg1 : index) -> !fir.box<!fir.char<1,?>> { 59 // CHECK: %[[alloca:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8 } 60 // CHECK: %[[size:.*]] = mul i64 ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64), %[[arg1]] 61 // CHECK: insertvalue {{.*}} undef, i64 %[[size]], 1 62 // CHECK: insertvalue {{.*}} i32 20240719, 2 63 // CHECK: insertvalue {{.*}} ptr %[[arg0]], 0 64 %x = fir.embox %arg0 typeparams %arg1 : (!fir.ref<!fir.char<1,?>>, index) -> !fir.box<!fir.char<1,?>> 65 // CHECK: store {{.*}}, ptr %[[alloca]] 66 // CHECK: call void @llvm.memcpy.p0.p0.i32(ptr %[[res]], ptr %[[alloca]], i32 24, i1 false) 67 return %x : !fir.box<!fir.char<1,?>> 68} 69 70// Boxing of a dynamic array of character with static length (5) 71// CHECK-LABEL: define void @b2( 72// CHECK-SAME: ptr captures(none) %[[res]], 73// CHECK-SAME: ptr captures(none) %[[arg0:.*]], i64 %[[arg1:.*]]) 74func.func @b2(%arg0 : !fir.ref<!fir.array<?x!fir.char<1,5>>>, %arg1 : index) -> !fir.box<!fir.array<?x!fir.char<1,5>>> { 75 %1 = fir.shape %arg1 : (index) -> !fir.shape<1> 76 // CHECK: %[[alloca:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] } 77 // CHECK: insertvalue {{.*}} { ptr undef, i64 ptrtoint (ptr getelementptr ([5 x i8], ptr null, i32 1) to i64), i32 20240719, i8 1, i8 40, i8 0, i8 0, {{.*}} }, i64 %[[arg1]], 7, 0, 1 78 // CHECK: insertvalue {{.*}} %{{.*}}, i64 ptrtoint (ptr getelementptr ([5 x i8], ptr null, i32 1) to i64), 7, 0, 2 79 // CHECK: insertvalue {{.*}} ptr %[[arg0]], 0 80 %2 = fir.embox %arg0(%1) : (!fir.ref<!fir.array<?x!fir.char<1,5>>>, !fir.shape<1>) -> !fir.box<!fir.array<?x!fir.char<1,5>>> 81 // CHECK: store {{.*}}, ptr %[[alloca]] 82 // CHECK: call void @llvm.memcpy.p0.p0.i32(ptr %[[res]], ptr %[[alloca]], i32 48, i1 false) 83 return %2 : !fir.box<!fir.array<?x!fir.char<1,5>>> 84} 85 86// Boxing of a dynamic array of character of dynamic length 87// CHECK-LABEL: define void @b3( 88// CHECK-SAME: ptr captures(none) %[[res:.*]], ptr captures(none) %[[arg0:.*]], i64 %[[arg1:.*]], i64 %[[arg2:.*]]) 89func.func @b3(%arg0 : !fir.ref<!fir.array<?x!fir.char<1,?>>>, %arg1 : index, %arg2 : index) -> !fir.box<!fir.array<?x!fir.char<1,?>>> { 90 %1 = fir.shape %arg2 : (index) -> !fir.shape<1> 91 // CHECK: %[[alloca:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] } 92 // CHECK: %[[size:.*]] = mul i64 ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64), %[[arg1]] 93 // CHECK: insertvalue {{.*}} i64 %[[size]], 1 94 // CHECK: insertvalue {{.*}} i32 20240719, 2 95 // CHECK: insertvalue {{.*}} i64 %[[arg2]], 7, 0, 1 96 // CHECK: insertvalue {{.*}} i64 %[[size]], 7, 0, 2 97 // CHECK: insertvalue {{.*}} ptr %[[arg0]], 0 98 %2 = fir.embox %arg0(%1) typeparams %arg1 : (!fir.ref<!fir.array<?x!fir.char<1,?>>>, !fir.shape<1>, index) -> !fir.box<!fir.array<?x!fir.char<1,?>>> 99 // CHECK: store {{.*}}, ptr %[[alloca]] 100 // CHECK: call void @llvm.memcpy.p0.p0.i32(ptr %[[res]], ptr %[[alloca]], i32 48, i1 false) 101 return %2 : !fir.box<!fir.array<?x!fir.char<1,?>>> 102} 103 104// Boxing of a static array of character of dynamic length 105// CHECK-LABEL: define void @b4( 106// CHECK-SAME: ptr captures(none) %[[res:.*]], ptr captures(none) %[[arg0:.*]], i64 %[[arg1:.*]]) 107func.func @b4(%arg0 : !fir.ref<!fir.array<7x!fir.char<1,?>>>, %arg1 : index) -> !fir.box<!fir.array<7x!fir.char<1,?>>> { 108 %c_7 = arith.constant 7 : index 109 %1 = fir.shape %c_7 : (index) -> !fir.shape<1> 110 // CHECK: %[[alloca:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] } 111 // CHECK: %[[size:.*]] = mul i64 ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64), %[[arg1]] 112 // CHECK: insertvalue {{.*}} i64 %[[size]], 1 113 // CHECK: insertvalue {{.*}} i32 20240719, 2 114 // CHECK: insertvalue {{.*}} i64 7, 7, 0, 1 115 // CHECK: insertvalue {{.*}} i64 %[[size]], 7, 0, 2 116 // CHECK: insertvalue {{.*}} ptr %[[arg0]], 0 117 %x = fir.embox %arg0(%1) typeparams %arg1 : (!fir.ref<!fir.array<7x!fir.char<1,?>>>, !fir.shape<1>, index) -> !fir.box<!fir.array<7x!fir.char<1,?>>> 118 // CHECK: store {{.*}}, ptr %[[alloca]] 119 // CHECK: call void @llvm.memcpy.p0.p0.i32(ptr %[[res]], ptr %[[alloca]], i32 48, i1 false) 120 return %x : !fir.box<!fir.array<7x!fir.char<1,?>>> 121} 122 123// Storing a fir.box into a fir.ref<fir.box> (modifying descriptors). 124// CHECK-LABEL: define void @b5( 125// CHECK-SAME: ptr captures(none) %[[arg0:.*]], ptr %[[arg1:.*]]) 126func.func @b5(%arg0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?x?xf32>>>>, %arg1 : !fir.box<!fir.heap<!fir.array<?x?xf32>>>) { 127 fir.store %arg1 to %arg0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?x?xf32>>>> 128 // CHECK: call void @llvm.memcpy.p0.p0.i32(ptr %0, ptr %1, i32 72, i1 false) 129 return 130} 131 132func.func private @callee6(!fir.box<none>) -> i32 133 134// CHECK-LABEL: define i32 @box6( 135// CHECK-SAME: ptr captures(none) %[[ARG0:.*]], i64 %[[ARG1:.*]], i64 %[[ARG2:.*]]) 136func.func @box6(%0 : !fir.ref<!fir.array<?x?x?x?xf32>>, %1 : index, %2 : index) -> i32 { 137 %c100 = arith.constant 100 : index 138 %c50 = arith.constant 50 : index 139 %c30 = arith.constant 30 : index 140 %c6 = arith.constant 6 : index 141 %shape = fir.shape %c100, %c50, %c30, %c6 : (index, index, index, index) -> !fir.shape<4> 142 %3 = fir.undefined index 143 %c41 = arith.constant 41 : index 144 %c2 = arith.constant 2 : index 145 %c24 = arith.constant 24 : index 146 %c1 = arith.constant 1 : index 147 %c3 = arith.constant 3 : index 148 149 // CHECK: %[[i:.*]] = sub i64 %[[ARG1]], 1 150 // CHECK: %[[i100:.*]] = mul i64 %[[i]], 100 151 // CHECK: %[[i100p40:.*]] = add i64 %[[i100]], 40 152 // CHECK: %[[diff:.*]] = sub i64 %[[ARG2]], %[[ARG1]] 153 // CHECK: %[[dp2:.*]] = add i64 %[[diff]], 2 154 // CHECK: %[[sdp2:.*]] = sdiv i64 %[[dp2]], 2 155 // CHECK: %[[cmp:.*]] = icmp sgt i64 %[[sdp2]], 0 156 // CHECK: %[[extent:.*]] = select i1 %[[cmp]], i64 %[[sdp2]], i64 0 157 // CHECK: insertvalue { ptr, i64, i32, i8, i8, i8, i8, [2 x [3 x i64]] } { ptr undef, i64 ptrtoint (ptr getelementptr (float, ptr null, i32 1) to i64), i32 20240719, i8 2, i8 27, i8 0, i8 0, [2 x [3 x i64]] [{{\[}}3 x i64] [i64 1, i64 undef, i64 undef], [3 x i64] undef] }, i64 %[[extent]], 7, 0, 1 158 // CHECK: insertvalue { ptr, i64, i32, i8, i8, i8, i8, [2 x [3 x i64]] } %{{.*}}, i64 mul (i64 ptrtoint (ptr getelementptr (float, ptr null, i32 1) to i64), i64 200), 7, 0, 2 159 // CHECK: %[[op25:.*]] = add i64 25000, %[[i100p40]] 160 // CHECK: insertvalue { ptr, i64, i32, i8, i8, i8, i8, [2 x [3 x i64]] } %{{.*}}, i64 1, 7, 1, 0 161 // CHECK: insertvalue { ptr, i64, i32, i8, i8, i8, i8, [2 x [3 x i64]] } %{{.*}}, i64 4, 7, 1, 1 162 // CHECK: insertvalue { ptr, i64, i32, i8, i8, i8, i8, [2 x [3 x i64]] } %{{.*}}, i64 mul (i64 ptrtoint (ptr getelementptr (float, ptr null, i32 1) to i64), i64 30000), 7, 1, 2 163 // CHECK: %[[op300:.*]] = add i64 300000, %[[op25]] 164 // CHECK: %[[ptr:.*]] = getelementptr float, ptr %[[ARG0]], i64 %[[op300]] 165 // CHECK: insertvalue { ptr, i64, i32, i8, i8, i8, i8, [2 x [3 x i64]] } %{{.*}}, ptr %[[ptr]], 0 166 // CHECK: store { ptr, i64, i32, i8, i8, i8, i8, [2 x [3 x i64]] } %{{.*}}, ptr %[[mem:[0-9]+]] 167 168 169 %slice = fir.slice %c41, %3, %3, %1, %2, %c2, %c6, %c24, %c6, %c3, %3, %3 : (index, index, index, index, index, index, index, index, index, index, index, index) -> !fir.slice<4> 170 %box = fir.embox %0(%shape)[%slice] : (!fir.ref<!fir.array<?x?x?x?xf32>>, !fir.shape<4>, !fir.slice<4>) -> !fir.box<!fir.array<?x?x?x?xf32>> 171 %nonebox = fir.convert %box : (!fir.box<!fir.array<?x?x?x?xf32>>) -> !fir.box<none> 172 // CHECK: %[[call:.*]] = call i32 @callee6(ptr %[[mem]]) 173 %rv = fir.call @callee6(%nonebox) : (!fir.box<none>) -> i32 174 // CHECK: ret i32 %[[call]] 175 return %rv : i32 176} 177