665 lines · plain
1// RUN: mlir-opt %s --pass-pipeline="builtin.module(llvm.func(sroa))" --split-input-file | FileCheck %s2 3// CHECK-LABEL: llvm.func @memset4llvm.func @memset() -> i32 {5 // CHECK-DAG: %[[ALLOCA_LEN:.*]] = llvm.mlir.constant(1 : i32) : i326 // CHECK-DAG: %[[ALLOCA:.*]] = llvm.alloca %[[ALLOCA_LEN]] x i327 // CHECK-DAG: %[[MEMSET_VALUE:.*]] = llvm.mlir.constant(42 : i8) : i88 // After SROA, only one i32 will be actually used, so only 4 bytes will be set.9 // CHECK-DAG: %[[MEMSET_LEN:.*]] = llvm.mlir.constant(4 : i32) : i3210 %0 = llvm.mlir.constant(1 : i32) : i3211 %1 = llvm.alloca %0 x !llvm.array<10 x i32> {alignment = 8 : i64} : (i32) -> !llvm.ptr12 %memset_value = llvm.mlir.constant(42 : i8) : i813 // 16 bytes means it will span over the first 4 i32 entries14 %memset_len = llvm.mlir.constant(16 : i32) : i3215 // CHECK: "llvm.intr.memset"(%[[ALLOCA]], %[[MEMSET_VALUE]], %[[MEMSET_LEN]]) <{isVolatile = false}>16 "llvm.intr.memset"(%1, %memset_value, %memset_len) <{isVolatile = false}> : (!llvm.ptr, i8, i32) -> ()17 %2 = llvm.getelementptr %1[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<10 x i32>18 %3 = llvm.load %2 : !llvm.ptr -> i3219 llvm.return %3 : i3220}21 22// -----23 24// CHECK-LABEL: llvm.func @memset_inline25llvm.func @memset_inline() -> i32 {26 // CHECK-DAG: %[[ALLOCA_LEN:.*]] = llvm.mlir.constant(1 : i32) : i3227 // CHECK-DAG: %[[ALLOCA:.*]] = llvm.alloca %[[ALLOCA_LEN]] x i3228 // CHECK-DAG: %[[MEMSET_VALUE:.*]] = llvm.mlir.constant(42 : i8) : i829 // After SROA, only one i32 will be actually used, so only 4 bytes will be set.30 %0 = llvm.mlir.constant(1 : i32) : i3231 %1 = llvm.alloca %0 x !llvm.array<10 x i32> {alignment = 8 : i64} : (i32) -> !llvm.ptr32 %memset_value = llvm.mlir.constant(42 : i8) : i833 // 16 bytes means it will span over the first 4 i32 entries.34 // CHECK: "llvm.intr.memset.inline"(%[[ALLOCA]], %[[MEMSET_VALUE]]) <{isVolatile = false, len = 4 : i64}>35 "llvm.intr.memset.inline"(%1, %memset_value) <{isVolatile = false, len = 16}> : (!llvm.ptr, i8) -> ()36 %2 = llvm.getelementptr %1[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<10 x i32>37 %3 = llvm.load %2 : !llvm.ptr -> i3238 llvm.return %3 : i3239}40 41// -----42 43// CHECK-LABEL: llvm.func @memset_partial44llvm.func @memset_partial() -> i32 {45 // CHECK-DAG: %[[ALLOCA_LEN:.*]] = llvm.mlir.constant(1 : i32) : i3246 // CHECK-DAG: %[[ALLOCA:.*]] = llvm.alloca %[[ALLOCA_LEN]] x i3247 // CHECK-DAG: %[[MEMSET_VALUE:.*]] = llvm.mlir.constant(42 : i8) : i848 // After SROA, only the second i32 will be actually used. As the memset writes up49 // to half of it, only 2 bytes will be set.50 // CHECK-DAG: %[[MEMSET_LEN:.*]] = llvm.mlir.constant(2 : i32) : i3251 %0 = llvm.mlir.constant(1 : i32) : i3252 %1 = llvm.alloca %0 x !llvm.array<10 x i32> {alignment = 8 : i64} : (i32) -> !llvm.ptr53 %memset_value = llvm.mlir.constant(42 : i8) : i854 // 6 bytes means it will span over the first i32 and half of the second i32.55 %memset_len = llvm.mlir.constant(6 : i32) : i3256 // CHECK: "llvm.intr.memset"(%[[ALLOCA]], %[[MEMSET_VALUE]], %[[MEMSET_LEN]]) <{isVolatile = false}>57 "llvm.intr.memset"(%1, %memset_value, %memset_len) <{isVolatile = false}> : (!llvm.ptr, i8, i32) -> ()58 %2 = llvm.getelementptr %1[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<10 x i32>59 %3 = llvm.load %2 : !llvm.ptr -> i3260 llvm.return %3 : i3261}62 63// -----64 65// CHECK-LABEL: llvm.func @memset_inline_partial66llvm.func @memset_inline_partial() -> i32 {67 // CHECK-DAG: %[[ALLOCA_LEN:.*]] = llvm.mlir.constant(1 : i32) : i3268 // CHECK-DAG: %[[ALLOCA:.*]] = llvm.alloca %[[ALLOCA_LEN]] x i3269 // CHECK-DAG: %[[MEMSET_VALUE:.*]] = llvm.mlir.constant(42 : i8) : i870 // After SROA, only the second i32 will be actually used. As the memset writes up71 // to half of it, only 2 bytes will be set.72 %0 = llvm.mlir.constant(1 : i32) : i3273 %1 = llvm.alloca %0 x !llvm.array<10 x i32> {alignment = 8 : i64} : (i32) -> !llvm.ptr74 %memset_value = llvm.mlir.constant(42 : i8) : i875 // 6 bytes means it will span over the first i32 and half of the second i32.76 // CHECK: "llvm.intr.memset.inline"(%[[ALLOCA]], %[[MEMSET_VALUE]]) <{isVolatile = false, len = 2 : i64}>77 "llvm.intr.memset.inline"(%1, %memset_value) <{isVolatile = false, len = 6}> : (!llvm.ptr, i8) -> ()78 %2 = llvm.getelementptr %1[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<10 x i32>79 %3 = llvm.load %2 : !llvm.ptr -> i3280 llvm.return %3 : i3281}82 83// -----84 85// CHECK-LABEL: llvm.func @memset_full86llvm.func @memset_full() -> i32 {87 // CHECK-DAG: %[[ALLOCA_LEN:.*]] = llvm.mlir.constant(1 : i32) : i3288 // CHECK-DAG: %[[ALLOCA:.*]] = llvm.alloca %[[ALLOCA_LEN]] x i3289 // CHECK-DAG: %[[MEMSET_VALUE:.*]] = llvm.mlir.constant(42 : i8) : i890 // After SROA, only one i32 will be actually used, so only 4 bytes will be set.91 // CHECK-DAG: %[[MEMSET_LEN:.*]] = llvm.mlir.constant(4 : i32) : i3292 %0 = llvm.mlir.constant(1 : i32) : i3293 %1 = llvm.alloca %0 x !llvm.array<10 x i32> {alignment = 8 : i64} : (i32) -> !llvm.ptr94 %memset_value = llvm.mlir.constant(42 : i8) : i895 // 40 bytes means it will span over the entire array96 %memset_len = llvm.mlir.constant(40 : i32) : i3297 // CHECK: "llvm.intr.memset"(%[[ALLOCA]], %[[MEMSET_VALUE]], %[[MEMSET_LEN]]) <{isVolatile = false}>98 "llvm.intr.memset"(%1, %memset_value, %memset_len) <{isVolatile = false}> : (!llvm.ptr, i8, i32) -> ()99 %2 = llvm.getelementptr %1[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<10 x i32>100 %3 = llvm.load %2 : !llvm.ptr -> i32101 llvm.return %3 : i32102}103 104// -----105 106// CHECK-LABEL: llvm.func @memset_inline_full107llvm.func @memset_inline_full() -> i32 {108 // CHECK-DAG: %[[ALLOCA_LEN:.*]] = llvm.mlir.constant(1 : i32) : i32109 // CHECK-DAG: %[[ALLOCA:.*]] = llvm.alloca %[[ALLOCA_LEN]] x i32110 // CHECK-DAG: %[[MEMSET_VALUE:.*]] = llvm.mlir.constant(42 : i8) : i8111 // After SROA, only one i32 will be actually used, so only 4 bytes will be set.112 %0 = llvm.mlir.constant(1 : i32) : i32113 %1 = llvm.alloca %0 x !llvm.array<10 x i32> {alignment = 8 : i64} : (i32) -> !llvm.ptr114 %memset_value = llvm.mlir.constant(42 : i8) : i8115 // 40 bytes means it will span over the entire array.116 // CHECK: "llvm.intr.memset.inline"(%[[ALLOCA]], %[[MEMSET_VALUE]]) <{isVolatile = false, len = 4 : i64}>117 "llvm.intr.memset.inline"(%1, %memset_value) <{isVolatile = false, len = 40}> : (!llvm.ptr, i8) -> ()118 %2 = llvm.getelementptr %1[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<10 x i32>119 %3 = llvm.load %2 : !llvm.ptr -> i32120 llvm.return %3 : i32121}122 123// -----124 125// CHECK-LABEL: llvm.func @memset_too_much126llvm.func @memset_too_much() -> i32 {127 // CHECK-DAG: %[[ALLOCA_LEN:.*]] = llvm.mlir.constant(1 : i32) : i32128 // CHECK-DAG: %[[ALLOCA:.*]] = llvm.alloca %[[ALLOCA_LEN]] x !llvm.array<10 x i32>129 // CHECK-DAG: %[[MEMSET_VALUE:.*]] = llvm.mlir.constant(42 : i8) : i8130 // CHECK-DAG: %[[MEMSET_LEN:.*]] = llvm.mlir.constant(41 : i32) : i32131 %0 = llvm.mlir.constant(1 : i32) : i32132 %1 = llvm.alloca %0 x !llvm.array<10 x i32> {alignment = 8 : i64} : (i32) -> !llvm.ptr133 %memset_value = llvm.mlir.constant(42 : i8) : i8134 // 41 bytes means it will span over the entire array, and then some135 %memset_len = llvm.mlir.constant(41 : i32) : i32136 // CHECK: "llvm.intr.memset"(%[[ALLOCA]], %[[MEMSET_VALUE]], %[[MEMSET_LEN]]) <{isVolatile = false}>137 "llvm.intr.memset"(%1, %memset_value, %memset_len) <{isVolatile = false}> : (!llvm.ptr, i8, i32) -> ()138 %2 = llvm.getelementptr %1[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<10 x i32>139 %3 = llvm.load %2 : !llvm.ptr -> i32140 llvm.return %3 : i32141}142 143// -----144 145// CHECK-LABEL: llvm.func @memset_inline_too_much146llvm.func @memset_inline_too_much() -> i32 {147 // CHECK-DAG: %[[ALLOCA_LEN:.*]] = llvm.mlir.constant(1 : i32) : i32148 // CHECK-DAG: %[[ALLOCA:.*]] = llvm.alloca %[[ALLOCA_LEN]] x !llvm.array<10 x i32>149 // CHECK-DAG: %[[MEMSET_VALUE:.*]] = llvm.mlir.constant(42 : i8) : i8150 %0 = llvm.mlir.constant(1 : i32) : i32151 %1 = llvm.alloca %0 x !llvm.array<10 x i32> {alignment = 8 : i64} : (i32) -> !llvm.ptr152 %memset_value = llvm.mlir.constant(42 : i8) : i8153 // 41 bytes means it will span over the entire array, and then some.154 // CHECK: "llvm.intr.memset.inline"(%[[ALLOCA]], %[[MEMSET_VALUE]]) <{isVolatile = false, len = 41 : i64}>155 "llvm.intr.memset.inline"(%1, %memset_value) <{isVolatile = false, len = 41}> : (!llvm.ptr, i8) -> ()156 %2 = llvm.getelementptr %1[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<10 x i32>157 %3 = llvm.load %2 : !llvm.ptr -> i32158 llvm.return %3 : i32159}160 161// -----162 163// CHECK-LABEL: llvm.func @memset_no_volatile164llvm.func @memset_no_volatile() -> i32 {165 // CHECK-DAG: %[[ALLOCA_LEN:.*]] = llvm.mlir.constant(1 : i32) : i32166 // CHECK-DAG: %[[ALLOCA:.*]] = llvm.alloca %[[ALLOCA_LEN]] x !llvm.array<10 x i32>167 // CHECK-DAG: %[[MEMSET_VALUE:.*]] = llvm.mlir.constant(42 : i8) : i8168 // CHECK-DAG: %[[MEMSET_LEN:.*]] = llvm.mlir.constant(16 : i32) : i32169 %0 = llvm.mlir.constant(1 : i32) : i32170 %1 = llvm.alloca %0 x !llvm.array<10 x i32> {alignment = 8 : i64} : (i32) -> !llvm.ptr171 %memset_value = llvm.mlir.constant(42 : i8) : i8172 %memset_len = llvm.mlir.constant(16 : i32) : i32173 // CHECK: "llvm.intr.memset"(%[[ALLOCA]], %[[MEMSET_VALUE]], %[[MEMSET_LEN]]) <{isVolatile = true}>174 "llvm.intr.memset"(%1, %memset_value, %memset_len) <{isVolatile = true}> : (!llvm.ptr, i8, i32) -> ()175 %2 = llvm.getelementptr %1[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<10 x i32>176 %3 = llvm.load %2 : !llvm.ptr -> i32177 llvm.return %3 : i32178}179 180// -----181 182// CHECK-LABEL: llvm.func @memset_inline_no_volatile183llvm.func @memset_inline_no_volatile() -> i32 {184 // CHECK-DAG: %[[ALLOCA_LEN:.*]] = llvm.mlir.constant(1 : i32) : i32185 // CHECK-DAG: %[[ALLOCA:.*]] = llvm.alloca %[[ALLOCA_LEN]] x !llvm.array<10 x i32>186 // CHECK-DAG: %[[MEMSET_VALUE:.*]] = llvm.mlir.constant(42 : i8) : i8187 %0 = llvm.mlir.constant(1 : i32) : i32188 %1 = llvm.alloca %0 x !llvm.array<10 x i32> {alignment = 8 : i64} : (i32) -> !llvm.ptr189 %memset_value = llvm.mlir.constant(42 : i8) : i8190 // CHECK: "llvm.intr.memset.inline"(%[[ALLOCA]], %[[MEMSET_VALUE]]) <{isVolatile = true, len = 16 : i64}>191 "llvm.intr.memset.inline"(%1, %memset_value) <{isVolatile = true, len = 16}> : (!llvm.ptr, i8) -> ()192 %2 = llvm.getelementptr %1[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<10 x i32>193 %3 = llvm.load %2 : !llvm.ptr -> i32194 llvm.return %3 : i32195}196 197// -----198 199// CHECK-LABEL: llvm.func @indirect_memset200llvm.func @indirect_memset() -> i32 {201 // CHECK-DAG: %[[ALLOCA_LEN:.*]] = llvm.mlir.constant(1 : i32) : i32202 // CHECK-DAG: %[[ALLOCA:.*]] = llvm.alloca %[[ALLOCA_LEN]] x i32203 // CHECK-DAG: %[[MEMSET_VALUE:.*]] = llvm.mlir.constant(42 : i8) : i8204 // CHECK-DAG: %[[MEMSET_LEN:.*]] = llvm.mlir.constant(4 : i32) : i32205 %0 = llvm.mlir.constant(1 : i32) : i32206 %1 = llvm.alloca %0 x !llvm.struct<"foo", (i32, i32)> : (i32) -> !llvm.ptr207 %memset_value = llvm.mlir.constant(42 : i8) : i8208 // This memset will only cover the selected element.209 %memset_len = llvm.mlir.constant(4 : i32) : i32210 %2 = llvm.getelementptr %1[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"foo", (i32, i32)>211 // CHECK: "llvm.intr.memset"(%[[ALLOCA]], %[[MEMSET_VALUE]], %[[MEMSET_LEN]]) <{isVolatile = false}>212 "llvm.intr.memset"(%2, %memset_value, %memset_len) <{isVolatile = false}> : (!llvm.ptr, i8, i32) -> ()213 %3 = llvm.load %2 : !llvm.ptr -> i32214 llvm.return %3 : i32215}216 217// -----218 219// CHECK-LABEL: llvm.func @indirect_memset_inline220llvm.func @indirect_memset_inline() -> i32 {221 // CHECK-DAG: %[[ALLOCA_LEN:.*]] = llvm.mlir.constant(1 : i32) : i32222 // CHECK-DAG: %[[ALLOCA:.*]] = llvm.alloca %[[ALLOCA_LEN]] x i32223 // CHECK-DAG: %[[MEMSET_VALUE:.*]] = llvm.mlir.constant(42 : i8) : i8224 %0 = llvm.mlir.constant(1 : i32) : i32225 %1 = llvm.alloca %0 x !llvm.struct<"foo", (i32, i32)> : (i32) -> !llvm.ptr226 %memset_value = llvm.mlir.constant(42 : i8) : i8227 // This memset will only cover the selected element.228 %2 = llvm.getelementptr %1[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"foo", (i32, i32)>229 // CHECK: "llvm.intr.memset.inline"(%[[ALLOCA]], %[[MEMSET_VALUE]]) <{isVolatile = false, len = 4 : i64}>230 "llvm.intr.memset.inline"(%2, %memset_value) <{isVolatile = false, len = 4}> : (!llvm.ptr, i8) -> ()231 %3 = llvm.load %2 : !llvm.ptr -> i32232 llvm.return %3 : i32233}234 235// -----236 237// CHECK-LABEL: llvm.func @invalid_indirect_memset238llvm.func @invalid_indirect_memset() -> i32 {239 // CHECK-DAG: %[[ALLOCA_LEN:.*]] = llvm.mlir.constant(1 : i32) : i32240 // CHECK-DAG: %[[ALLOCA:.*]] = llvm.alloca %[[ALLOCA_LEN]] x !llvm.struct<"foo", (i32, i32)>241 // CHECK-DAG: %[[MEMSET_VALUE:.*]] = llvm.mlir.constant(42 : i8) : i8242 // CHECK-DAG: %[[MEMSET_LEN:.*]] = llvm.mlir.constant(6 : i32) : i32243 %0 = llvm.mlir.constant(1 : i32) : i32244 %1 = llvm.alloca %0 x !llvm.struct<"foo", (i32, i32)> : (i32) -> !llvm.ptr245 %memset_value = llvm.mlir.constant(42 : i8) : i8246 // This memset will go slightly beyond one of the elements.247 %memset_len = llvm.mlir.constant(6 : i32) : i32248 // CHECK: %[[GEP:.*]] = llvm.getelementptr %[[ALLOCA]][0, 0]249 %2 = llvm.getelementptr %1[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"foo", (i32, i32)>250 // CHECK: "llvm.intr.memset"(%[[GEP]], %[[MEMSET_VALUE]], %[[MEMSET_LEN]]) <{isVolatile = false}>251 "llvm.intr.memset"(%2, %memset_value, %memset_len) <{isVolatile = false}> : (!llvm.ptr, i8, i32) -> ()252 %3 = llvm.load %2 : !llvm.ptr -> i32253 llvm.return %3 : i32254}255 256// -----257 258// CHECK-LABEL: llvm.func @invalid_indirect_memset_inline259llvm.func @invalid_indirect_memset_inline() -> i32 {260 // CHECK-DAG: %[[ALLOCA_LEN:.*]] = llvm.mlir.constant(1 : i32) : i32261 // CHECK-DAG: %[[ALLOCA:.*]] = llvm.alloca %[[ALLOCA_LEN]] x !llvm.struct<"foo", (i32, i32)>262 // CHECK-DAG: %[[MEMSET_VALUE:.*]] = llvm.mlir.constant(42 : i8) : i8263 %0 = llvm.mlir.constant(1 : i32) : i32264 %1 = llvm.alloca %0 x !llvm.struct<"foo", (i32, i32)> : (i32) -> !llvm.ptr265 %memset_value = llvm.mlir.constant(42 : i8) : i8266 // This memset will go slightly beyond one of the elements.267 // CHECK: %[[GEP:.*]] = llvm.getelementptr %[[ALLOCA]][0, 0]268 %2 = llvm.getelementptr %1[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"foo", (i32, i32)>269 // CHECK: "llvm.intr.memset.inline"(%[[GEP]], %[[MEMSET_VALUE]]) <{isVolatile = false, len = 6 : i64}>270 "llvm.intr.memset.inline"(%2, %memset_value) <{isVolatile = false, len = 6}> : (!llvm.ptr, i8) -> ()271 %3 = llvm.load %2 : !llvm.ptr -> i32272 llvm.return %3 : i32273}274 275// -----276 277// CHECK-LABEL: llvm.func @memset_double_use278llvm.func @memset_double_use() -> i32 {279 // CHECK: %[[ALLOCA_LEN:.*]] = llvm.mlir.constant(1 : i32) : i32280 // CHECK: %[[ALLOCA_FLOAT:.*]] = llvm.alloca %[[ALLOCA_LEN]] x f32281 // CHECK: %[[ALLOCA_INT:.*]] = llvm.alloca %[[ALLOCA_LEN]] x i32282 // CHECK: %[[MEMSET_VALUE:.*]] = llvm.mlir.constant(42 : i8) : i8283 %0 = llvm.mlir.constant(1 : i32) : i32284 %1 = llvm.alloca %0 x !llvm.struct<"foo", (i32, f32)> {alignment = 8 : i64} : (i32) -> !llvm.ptr285 %memset_value = llvm.mlir.constant(42 : i8) : i8286 // 8 bytes means it will span over the two i32 entries.287 %memset_len = llvm.mlir.constant(8 : i32) : i32288 // We expect two generated memset, one for each field.289 // CHECK-NOT: "llvm.intr.memset"290 // After SROA, only one i32 will be actually used, so only 4 bytes will be set.291 // CHECK: %[[MEMSET_LEN:.*]] = llvm.mlir.constant(4 : i32) : i32292 // CHECK: "llvm.intr.memset"(%[[ALLOCA_INT]], %[[MEMSET_VALUE]], %[[MEMSET_LEN]]) <{isVolatile = false}>293 // CHECK: %[[MEMSET_LEN:.*]] = llvm.mlir.constant(4 : i32) : i32294 // CHECK: "llvm.intr.memset"(%[[ALLOCA_FLOAT]], %[[MEMSET_VALUE]], %[[MEMSET_LEN]]) <{isVolatile = false}>295 // CHECK-NOT: "llvm.intr.memset"296 "llvm.intr.memset"(%1, %memset_value, %memset_len) <{isVolatile = false}> : (!llvm.ptr, i8, i32) -> ()297 %2 = llvm.getelementptr %1[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"foo", (i32, f32)>298 %3 = llvm.load %2 : !llvm.ptr -> i32299 %4 = llvm.getelementptr %1[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"foo", (i32, f32)>300 %5 = llvm.load %4 : !llvm.ptr -> f32301 // We use this exotic bitcast to use the f32 easily. Semantics do not matter here.302 %6 = llvm.bitcast %5 : f32 to i32303 %7 = llvm.add %3, %6 : i32304 llvm.return %7 : i32305}306 307// -----308 309// CHECK-LABEL: llvm.func @memset_inline_double_use310llvm.func @memset_inline_double_use() -> i32 {311 // CHECK: %[[ALLOCA_LEN:.*]] = llvm.mlir.constant(1 : i32) : i32312 // CHECK: %[[ALLOCA_FLOAT:.*]] = llvm.alloca %[[ALLOCA_LEN]] x f32313 // CHECK: %[[ALLOCA_INT:.*]] = llvm.alloca %[[ALLOCA_LEN]] x i32314 // CHECK: %[[MEMSET_VALUE:.*]] = llvm.mlir.constant(42 : i8) : i8315 %0 = llvm.mlir.constant(1 : i32) : i32316 %1 = llvm.alloca %0 x !llvm.struct<"foo", (i32, f32)> {alignment = 8 : i64} : (i32) -> !llvm.ptr317 %memset_value = llvm.mlir.constant(42 : i8) : i8318 // We expect two generated memset, one for each field.319 // CHECK-NOT: "llvm.intr.memset.inline"320 // After SROA, only one i32 will be actually used, so only 4 bytes will be set.321 // CHECK: "llvm.intr.memset.inline"(%[[ALLOCA_INT]], %[[MEMSET_VALUE]]) <{isVolatile = false, len = 4 : i64}>322 // CHECK: "llvm.intr.memset.inline"(%[[ALLOCA_FLOAT]], %[[MEMSET_VALUE]]) <{isVolatile = false, len = 4 : i64}>323 // CHECK-NOT: "llvm.intr.memset.inline"324 // 8 bytes means it will span over the two i32 entries.325 "llvm.intr.memset.inline"(%1, %memset_value) <{isVolatile = false, len = 8}> : (!llvm.ptr, i8) -> ()326 %2 = llvm.getelementptr %1[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"foo", (i32, f32)>327 %3 = llvm.load %2 : !llvm.ptr -> i32328 %4 = llvm.getelementptr %1[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"foo", (i32, f32)>329 %5 = llvm.load %4 : !llvm.ptr -> f32330 // We use this exotic bitcast to use the f32 easily. Semantics do not matter here.331 %6 = llvm.bitcast %5 : f32 to i32332 %7 = llvm.add %3, %6 : i32333 llvm.return %7 : i32334}335 336// -----337 338// CHECK-LABEL: llvm.func @memset_considers_alignment339llvm.func @memset_considers_alignment() -> i32 {340 // CHECK-DAG: %[[ALLOCA_LEN:.*]] = llvm.mlir.constant(1 : i32) : i32341 // CHECK-DAG: %[[ALLOCA_INT:.*]] = llvm.alloca %[[ALLOCA_LEN]] x i32342 // CHECK-DAG: %[[MEMSET_VALUE:.*]] = llvm.mlir.constant(42 : i8) : i8343 // After SROA, only 32-bit values will be actually used, so only 4 bytes will be set.344 // CHECK-DAG: %[[MEMSET_LEN:.*]] = llvm.mlir.constant(4 : i32) : i32345 %0 = llvm.mlir.constant(1 : i32) : i32346 %1 = llvm.alloca %0 x !llvm.struct<"foo", (i8, i32, f32)> {alignment = 8 : i64} : (i32) -> !llvm.ptr347 %memset_value = llvm.mlir.constant(42 : i8) : i8348 // 8 bytes means it will span over the i8 and the i32 entry.349 // Because of padding, the f32 entry will not be touched.350 %memset_len = llvm.mlir.constant(8 : i32) : i32351 // Even though the two i32 are used, only one memset should be generated,352 // as the second i32 is not touched by the initial memset.353 // CHECK-NOT: "llvm.intr.memset"354 // CHECK: "llvm.intr.memset"(%[[ALLOCA_INT]], %[[MEMSET_VALUE]], %[[MEMSET_LEN]]) <{isVolatile = false}>355 // CHECK-NOT: "llvm.intr.memset"356 "llvm.intr.memset"(%1, %memset_value, %memset_len) <{isVolatile = false}> : (!llvm.ptr, i8, i32) -> ()357 %2 = llvm.getelementptr %1[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"foo", (i8, i32, f32)>358 %3 = llvm.load %2 : !llvm.ptr -> i32359 %4 = llvm.getelementptr %1[0, 2] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"foo", (i8, i32, f32)>360 %5 = llvm.load %4 : !llvm.ptr -> f32361 // We use this exotic bitcast to use the f32 easily. Semantics do not matter here.362 %6 = llvm.bitcast %5 : f32 to i32363 %7 = llvm.add %3, %6 : i32364 llvm.return %7 : i32365}366 367// -----368 369// CHECK-LABEL: llvm.func @memset_inline_considers_alignment370llvm.func @memset_inline_considers_alignment() -> i32 {371 // CHECK-DAG: %[[ALLOCA_LEN:.*]] = llvm.mlir.constant(1 : i32) : i32372 // CHECK-DAG: %[[ALLOCA_INT:.*]] = llvm.alloca %[[ALLOCA_LEN]] x i32373 // CHECK-DAG: %[[MEMSET_VALUE:.*]] = llvm.mlir.constant(42 : i8) : i8374 // After SROA, only 32-bit values will be actually used, so only 4 bytes will be set.375 %0 = llvm.mlir.constant(1 : i32) : i32376 %1 = llvm.alloca %0 x !llvm.struct<"foo", (i8, i32, f32)> {alignment = 8 : i64} : (i32) -> !llvm.ptr377 %memset_value = llvm.mlir.constant(42 : i8) : i8378 // 8 bytes means it will span over the i8 and the i32 entry.379 // Because of padding, the f32 entry will not be touched.380 // Even though the two i32 are used, only one memset should be generated,381 // as the second i32 is not touched by the initial memset.382 // CHECK-NOT: "llvm.intr.memset.inline"383 // CHECK: "llvm.intr.memset.inline"(%[[ALLOCA_INT]], %[[MEMSET_VALUE]]) <{isVolatile = false, len = 4 : i64}>384 // CHECK-NOT: "llvm.intr.memset.inline"385 "llvm.intr.memset.inline"(%1, %memset_value) <{isVolatile = false, len = 8}> : (!llvm.ptr, i8) -> ()386 %2 = llvm.getelementptr %1[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"foo", (i8, i32, f32)>387 %3 = llvm.load %2 : !llvm.ptr -> i32388 %4 = llvm.getelementptr %1[0, 2] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"foo", (i8, i32, f32)>389 %5 = llvm.load %4 : !llvm.ptr -> f32390 // We use this exotic bitcast to use the f32 easily. Semantics do not matter here.391 %6 = llvm.bitcast %5 : f32 to i32392 %7 = llvm.add %3, %6 : i32393 llvm.return %7 : i32394}395 396// -----397 398// CHECK-LABEL: llvm.func @memset_considers_packing399llvm.func @memset_considers_packing() -> i32 {400 // CHECK: %[[ALLOCA_LEN:.*]] = llvm.mlir.constant(1 : i32) : i32401 // CHECK: %[[ALLOCA_FLOAT:.*]] = llvm.alloca %[[ALLOCA_LEN]] x f32402 // CHECK: %[[ALLOCA_INT:.*]] = llvm.alloca %[[ALLOCA_LEN]] x i32403 // CHECK: %[[MEMSET_VALUE:.*]] = llvm.mlir.constant(42 : i8) : i8404 %0 = llvm.mlir.constant(1 : i32) : i32405 %1 = llvm.alloca %0 x !llvm.struct<"foo", packed (i8, i32, f32)> {alignment = 8 : i64} : (i32) -> !llvm.ptr406 %memset_value = llvm.mlir.constant(42 : i8) : i8407 // 8 bytes means it will span over all the fields, because there is no padding as the struct is packed.408 %memset_len = llvm.mlir.constant(8 : i32) : i32409 // Now all fields are touched by the memset.410 // CHECK-NOT: "llvm.intr.memset"411 // After SROA, only 32-bit values will be actually used, so only 4 bytes will be set.412 // CHECK: %[[MEMSET_LEN_WHOLE:.*]] = llvm.mlir.constant(4 : i32) : i32413 // CHECK: "llvm.intr.memset"(%[[ALLOCA_INT]], %[[MEMSET_VALUE]], %[[MEMSET_LEN_WHOLE]]) <{isVolatile = false}>414 // CHECK: %[[MEMSET_LEN_PARTIAL:.*]] = llvm.mlir.constant(3 : i32) : i32415 // CHECK: "llvm.intr.memset"(%[[ALLOCA_FLOAT]], %[[MEMSET_VALUE]], %[[MEMSET_LEN_PARTIAL]]) <{isVolatile = false}>416 // CHECK-NOT: "llvm.intr.memset"417 "llvm.intr.memset"(%1, %memset_value, %memset_len) <{isVolatile = false}> : (!llvm.ptr, i8, i32) -> ()418 %2 = llvm.getelementptr %1[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"foo", packed (i8, i32, f32)>419 %3 = llvm.load %2 : !llvm.ptr -> i32420 %4 = llvm.getelementptr %1[0, 2] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"foo", packed (i8, i32, f32)>421 %5 = llvm.load %4 : !llvm.ptr -> f32422 // We use this exotic bitcast to use the f32 easily. Semantics do not matter here.423 %6 = llvm.bitcast %5 : f32 to i32424 %7 = llvm.add %3, %6 : i32425 llvm.return %7 : i32426}427 428// -----429 430// CHECK-LABEL: llvm.func @memset_inline_considers_packing431llvm.func @memset_inline_considers_packing() -> i32 {432 // CHECK: %[[ALLOCA_LEN:.*]] = llvm.mlir.constant(1 : i32) : i32433 // CHECK: %[[ALLOCA_FLOAT:.*]] = llvm.alloca %[[ALLOCA_LEN]] x f32434 // CHECK: %[[ALLOCA_INT:.*]] = llvm.alloca %[[ALLOCA_LEN]] x i32435 // CHECK: %[[MEMSET_VALUE:.*]] = llvm.mlir.constant(42 : i8) : i8436 %0 = llvm.mlir.constant(1 : i32) : i32437 %1 = llvm.alloca %0 x !llvm.struct<"foo", packed (i8, i32, f32)> {alignment = 8 : i64} : (i32) -> !llvm.ptr438 %memset_value = llvm.mlir.constant(42 : i8) : i8439 // Now all fields are touched by the memset.440 // CHECK-NOT: "llvm.intr.memset.inline"441 // After SROA, only 32-bit values will be actually used, so only 4 bytes will be set.442 // CHECK: "llvm.intr.memset.inline"(%[[ALLOCA_INT]], %[[MEMSET_VALUE]]) <{isVolatile = false, len = 4 : i64}>443 // CHECK: "llvm.intr.memset.inline"(%[[ALLOCA_FLOAT]], %[[MEMSET_VALUE]]) <{isVolatile = false, len = 3 : i64}>444 // CHECK-NOT: "llvm.intr.memset.inline"445 // 8 bytes means it will span over all the fields, because there is no padding as the struct is packed.446 "llvm.intr.memset.inline"(%1, %memset_value) <{isVolatile = false, len = 8}> : (!llvm.ptr, i8) -> ()447 %2 = llvm.getelementptr %1[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"foo", packed (i8, i32, f32)>448 %3 = llvm.load %2 : !llvm.ptr -> i32449 %4 = llvm.getelementptr %1[0, 2] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"foo", packed (i8, i32, f32)>450 %5 = llvm.load %4 : !llvm.ptr -> f32451 // We use this exotic bitcast to use the f32 easily. Semantics do not matter here.452 %6 = llvm.bitcast %5 : f32 to i32453 %7 = llvm.add %3, %6 : i32454 llvm.return %7 : i32455}456 457// -----458 459// CHECK-LABEL: llvm.func @memcpy_dest460// CHECK-SAME: (%[[OTHER_ARRAY:.*]]: !llvm.ptr)461llvm.func @memcpy_dest(%other_array: !llvm.ptr) -> i32 {462 // CHECK: %[[ALLOCA_LEN:.*]] = llvm.mlir.constant(1 : i32) : i32463 // CHECK: %[[ALLOCA:.*]] = llvm.alloca %[[ALLOCA_LEN]] x i32464 %0 = llvm.mlir.constant(1 : i32) : i32465 %1 = llvm.alloca %0 x !llvm.array<10 x i32> : (i32) -> !llvm.ptr466 %memcpy_len = llvm.mlir.constant(40 : i32) : i32467 // CHECK: %[[SLOT_IN_OTHER:.*]] = llvm.getelementptr %[[OTHER_ARRAY]][0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<10 x i32>468 // After SROA, only one i32 will be actually used, so only 4 bytes will be set.469 // CHECK: %[[MEMCPY_LEN:.*]] = llvm.mlir.constant(4 : i32) : i32470 // CHECK: "llvm.intr.memcpy"(%[[ALLOCA]], %[[SLOT_IN_OTHER]], %[[MEMCPY_LEN]]) <{isVolatile = false}>471 "llvm.intr.memcpy"(%1, %other_array, %memcpy_len) <{isVolatile = false}> : (!llvm.ptr, !llvm.ptr, i32) -> ()472 %2 = llvm.getelementptr %1[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<10 x i32>473 %3 = llvm.load %2 : !llvm.ptr -> i32474 llvm.return %3 : i32475}476 477// -----478 479// CHECK-LABEL: llvm.func @memcpy_src480// CHECK-SAME: (%[[OTHER_ARRAY:.*]]: !llvm.ptr)481llvm.func @memcpy_src(%other_array: !llvm.ptr) -> i32 {482 // CHECK: %[[ALLOCA_LEN:.*]] = llvm.mlir.constant(1 : i32) : i32483 // After SROA, only one i32 will be actually used, so only 4 bytes will be set.484 // CHECK-COUNT-4: = llvm.alloca %[[ALLOCA_LEN]] x i32485 %0 = llvm.mlir.constant(1 : i32) : i32486 %1 = llvm.alloca %0 x !llvm.array<4 x i32> : (i32) -> !llvm.ptr487 %memcpy_len = llvm.mlir.constant(16 : i32) : i32488 // Unfortunately because of FileCheck limitations it is not possible to check which slot gets read from.489 // We can only check that the amount of operations and allocated slots is correct, which should be sufficient490 // as unused slots are not generated.491 // CHECK: %[[SLOT_IN_OTHER:.*]] = llvm.getelementptr %[[OTHER_ARRAY]][0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<4 x i32>492 // CHECK: %[[MEMCPY_LEN:.*]] = llvm.mlir.constant(4 : i32) : i32493 // CHECK: "llvm.intr.memcpy"(%[[SLOT_IN_OTHER]], %{{.*}}, %[[MEMCPY_LEN]]) <{isVolatile = false}>494 // CHECK: %[[SLOT_IN_OTHER:.*]] = llvm.getelementptr %[[OTHER_ARRAY]][0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<4 x i32>495 // CHECK: %[[MEMCPY_LEN:.*]] = llvm.mlir.constant(4 : i32) : i32496 // CHECK: "llvm.intr.memcpy"(%[[SLOT_IN_OTHER]], %{{.*}}, %[[MEMCPY_LEN]]) <{isVolatile = false}>497 // CHECK: %[[SLOT_IN_OTHER:.*]] = llvm.getelementptr %[[OTHER_ARRAY]][0, 2] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<4 x i32>498 // CHECK: %[[MEMCPY_LEN:.*]] = llvm.mlir.constant(4 : i32) : i32499 // CHECK: "llvm.intr.memcpy"(%[[SLOT_IN_OTHER]], %{{.*}}, %[[MEMCPY_LEN]]) <{isVolatile = false}>500 // CHECK: %[[SLOT_IN_OTHER:.*]] = llvm.getelementptr %[[OTHER_ARRAY]][0, 3] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<4 x i32>501 // CHECK: %[[MEMCPY_LEN:.*]] = llvm.mlir.constant(4 : i32) : i32502 // CHECK: "llvm.intr.memcpy"(%[[SLOT_IN_OTHER]], %{{.*}}, %[[MEMCPY_LEN]]) <{isVolatile = false}>503 "llvm.intr.memcpy"(%other_array, %1, %memcpy_len) <{isVolatile = false}> : (!llvm.ptr, !llvm.ptr, i32) -> ()504 %2 = llvm.getelementptr %1[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<4 x i32>505 %3 = llvm.load %2 : !llvm.ptr -> i32506 llvm.return %3 : i32507}508 509// -----510 511// CHECK-LABEL: llvm.func @memcpy_double512llvm.func @memcpy_double() -> i32 {513 // CHECK: %[[ALLOCA_LEN:.*]] = llvm.mlir.constant(1 : i32) : i32514 %0 = llvm.mlir.constant(1 : i32) : i32515 // CHECK: = llvm.alloca %[[ALLOCA_LEN]] x i32516 // TODO: This should also disappear as a GEP with all zero indices should be517 // ignored.518 // CHECK: = llvm.alloca %[[ALLOCA_LEN]] x !llvm.array<1 x i32>519 %1 = llvm.alloca %0 x !llvm.array<1 x i32> : (i32) -> !llvm.ptr520 %2 = llvm.alloca %0 x !llvm.array<1 x i32> : (i32) -> !llvm.ptr521 // Match the dead constant, to avoid collision with the newly created one.522 // CHECK: llvm.mlir.constant523 %memcpy_len = llvm.mlir.constant(4 : i32) : i32524 // CHECK-NOT: "llvm.intr.memcpy"525 // CHECK: %[[MEMCPY_LEN:.*]] = llvm.mlir.constant(4 : i32) : i32526 // CHECK: "llvm.intr.memcpy"(%{{.*}}, %{{.*}}, %[[MEMCPY_LEN]]) <{isVolatile = false}>527 // CHECK-NOT: "llvm.intr.memcpy"528 "llvm.intr.memcpy"(%1, %2, %memcpy_len) <{isVolatile = false}> : (!llvm.ptr, !llvm.ptr, i32) -> ()529 %3 = llvm.getelementptr %1[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<1 x i32>530 %4 = llvm.load %3 : !llvm.ptr -> i32531 llvm.return %4 : i32532}533 534// -----535 536// CHECK-LABEL: llvm.func @memcpy_no_partial537// CHECK-SAME: (%[[OTHER_ARRAY:.*]]: !llvm.ptr)538llvm.func @memcpy_no_partial(%other_array: !llvm.ptr) -> i32 {539 // CHECK-DAG: %[[ALLOCA_LEN:.*]] = llvm.mlir.constant(1 : i32) : i32540 // CHECK-DAG: %[[ALLOCA:.*]] = llvm.alloca %[[ALLOCA_LEN]] x !llvm.array<10 x i32>541 // CHECK-DAG: %[[MEMCPY_LEN:.*]] = llvm.mlir.constant(21 : i32) : i32542 %0 = llvm.mlir.constant(1 : i32) : i32543 %1 = llvm.alloca %0 x !llvm.array<10 x i32> : (i32) -> !llvm.ptr544 %memcpy_len = llvm.mlir.constant(21 : i32) : i32545 // CHECK: "llvm.intr.memcpy"(%[[ALLOCA]], %[[OTHER_ARRAY]], %[[MEMCPY_LEN]]) <{isVolatile = false}>546 "llvm.intr.memcpy"(%1, %other_array, %memcpy_len) <{isVolatile = false}> : (!llvm.ptr, !llvm.ptr, i32) -> ()547 %2 = llvm.getelementptr %1[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<10 x i32>548 %3 = llvm.load %2 : !llvm.ptr -> i32549 llvm.return %3 : i32550}551 552// -----553 554// CHECK-LABEL: llvm.func @memcpy_no_volatile555// CHECK-SAME: (%[[OTHER_ARRAY:.*]]: !llvm.ptr)556llvm.func @memcpy_no_volatile(%other_array: !llvm.ptr) -> i32 {557 // CHECK-DAG: %[[ALLOCA_LEN:.*]] = llvm.mlir.constant(1 : i32) : i32558 // CHECK-DAG: %[[ALLOCA:.*]] = llvm.alloca %[[ALLOCA_LEN]] x !llvm.array<10 x i32>559 // CHECK-DAG: %[[MEMCPY_LEN:.*]] = llvm.mlir.constant(40 : i32) : i32560 %0 = llvm.mlir.constant(1 : i32) : i32561 %1 = llvm.alloca %0 x !llvm.array<10 x i32> : (i32) -> !llvm.ptr562 %memcpy_len = llvm.mlir.constant(40 : i32) : i32563 // CHECK: "llvm.intr.memcpy"(%[[ALLOCA]], %[[OTHER_ARRAY]], %[[MEMCPY_LEN]]) <{isVolatile = true}>564 "llvm.intr.memcpy"(%1, %other_array, %memcpy_len) <{isVolatile = true}> : (!llvm.ptr, !llvm.ptr, i32) -> ()565 %2 = llvm.getelementptr %1[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<10 x i32>566 %3 = llvm.load %2 : !llvm.ptr -> i32567 llvm.return %3 : i32568}569 570// -----571 572// CHECK-LABEL: llvm.func @memmove_dest573// CHECK-SAME: (%[[OTHER_ARRAY:.*]]: !llvm.ptr)574llvm.func @memmove_dest(%other_array: !llvm.ptr) -> i32 {575 // CHECK: %[[ALLOCA_LEN:.*]] = llvm.mlir.constant(1 : i32) : i32576 // CHECK: %[[ALLOCA:.*]] = llvm.alloca %[[ALLOCA_LEN]] x i32577 %0 = llvm.mlir.constant(1 : i32) : i32578 %1 = llvm.alloca %0 x !llvm.array<10 x i32> : (i32) -> !llvm.ptr579 %memmove_len = llvm.mlir.constant(40 : i32) : i32580 // CHECK: %[[SLOT_IN_OTHER:.*]] = llvm.getelementptr %[[OTHER_ARRAY]][0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<10 x i32>581 // After SROA, only one i32 will be actually used, so only 4 bytes will be set.582 // CHECK: %[[MEMMOVE_LEN:.*]] = llvm.mlir.constant(4 : i32) : i32583 // CHECK: "llvm.intr.memmove"(%[[ALLOCA]], %[[SLOT_IN_OTHER]], %[[MEMMOVE_LEN]]) <{isVolatile = false}>584 "llvm.intr.memmove"(%1, %other_array, %memmove_len) <{isVolatile = false}> : (!llvm.ptr, !llvm.ptr, i32) -> ()585 %2 = llvm.getelementptr %1[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<10 x i32>586 %3 = llvm.load %2 : !llvm.ptr -> i32587 llvm.return %3 : i32588}589 590// -----591 592// CHECK-LABEL: llvm.func @memmove_src593// CHECK-SAME: (%[[OTHER_ARRAY:.*]]: !llvm.ptr)594llvm.func @memmove_src(%other_array: !llvm.ptr) -> i32 {595 // CHECK: %[[ALLOCA_LEN:.*]] = llvm.mlir.constant(1 : i32) : i32596 // CHECK-COUNT-4: = llvm.alloca %[[ALLOCA_LEN]] x i32597 %0 = llvm.mlir.constant(1 : i32) : i32598 %1 = llvm.alloca %0 x !llvm.array<4 x i32> : (i32) -> !llvm.ptr599 %memmove_len = llvm.mlir.constant(16 : i32) : i32600 // Unfortunately because of FileCheck limitations it is not possible to check which slot gets read from.601 // We can only check that the amount of operations and allocated slots is correct, which should be sufficient602 // as unused slots are not generated.603 // CHECK: %[[SLOT_IN_OTHER:.*]] = llvm.getelementptr %[[OTHER_ARRAY]][0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<4 x i32>604 // CHECK: %[[MEMMOVE_LEN:.*]] = llvm.mlir.constant(4 : i32) : i32605 // CHECK: "llvm.intr.memmove"(%[[SLOT_IN_OTHER]], %{{.*}}, %[[MEMMOVE_LEN]]) <{isVolatile = false}>606 // CHECK: %[[SLOT_IN_OTHER:.*]] = llvm.getelementptr %[[OTHER_ARRAY]][0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<4 x i32>607 // CHECK: %[[MEMMOVE_LEN:.*]] = llvm.mlir.constant(4 : i32) : i32608 // CHECK: "llvm.intr.memmove"(%[[SLOT_IN_OTHER]], %{{.*}}, %[[MEMMOVE_LEN]]) <{isVolatile = false}>609 // CHECK: %[[SLOT_IN_OTHER:.*]] = llvm.getelementptr %[[OTHER_ARRAY]][0, 2] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<4 x i32>610 // CHECK: %[[MEMMOVE_LEN:.*]] = llvm.mlir.constant(4 : i32) : i32611 // CHECK: "llvm.intr.memmove"(%[[SLOT_IN_OTHER]], %{{.*}}, %[[MEMMOVE_LEN]]) <{isVolatile = false}>612 // CHECK: %[[SLOT_IN_OTHER:.*]] = llvm.getelementptr %[[OTHER_ARRAY]][0, 3] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<4 x i32>613 // CHECK: %[[MEMMOVE_LEN:.*]] = llvm.mlir.constant(4 : i32) : i32614 // CHECK: "llvm.intr.memmove"(%[[SLOT_IN_OTHER]], %{{.*}}, %[[MEMMOVE_LEN]]) <{isVolatile = false}>615 "llvm.intr.memmove"(%other_array, %1, %memmove_len) <{isVolatile = false}> : (!llvm.ptr, !llvm.ptr, i32) -> ()616 %2 = llvm.getelementptr %1[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<4 x i32>617 %3 = llvm.load %2 : !llvm.ptr -> i32618 llvm.return %3 : i32619}620 621// -----622 623// CHECK-LABEL: llvm.func @memcpy_inline_dest624// CHECK-SAME: (%[[OTHER_ARRAY:.*]]: !llvm.ptr)625llvm.func @memcpy_inline_dest(%other_array: !llvm.ptr) -> i32 {626 // CHECK-DAG: %[[ALLOCA_LEN:.*]] = llvm.mlir.constant(1 : i32) : i32627 // CHECK-DAG: %[[ALLOCA:.*]] = llvm.alloca %[[ALLOCA_LEN]] x i32628 // After SROA, only one i32 will be actually used, so only 4 bytes will be set.629 %0 = llvm.mlir.constant(1 : i32) : i32630 %1 = llvm.alloca %0 x !llvm.array<10 x i32> : (i32) -> !llvm.ptr631 // CHECK: %[[SLOT_IN_OTHER:.*]] = llvm.getelementptr %[[OTHER_ARRAY]][0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<10 x i32>632 // CHECK: "llvm.intr.memcpy.inline"(%[[ALLOCA]], %[[SLOT_IN_OTHER]]) <{isVolatile = false, len = 4 : i32}>633 "llvm.intr.memcpy.inline"(%1, %other_array) <{isVolatile = false, len = 40 : i32}> : (!llvm.ptr, !llvm.ptr) -> ()634 %2 = llvm.getelementptr %1[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<10 x i32>635 %3 = llvm.load %2 : !llvm.ptr -> i32636 llvm.return %3 : i32637}638 639// -----640 641// CHECK-LABEL: llvm.func @memcpy_inline_src642// CHECK-SAME: (%[[OTHER_ARRAY:.*]]: !llvm.ptr)643llvm.func @memcpy_inline_src(%other_array: !llvm.ptr) -> i32 {644 // CHECK-DAG: %[[ALLOCA_LEN:.*]] = llvm.mlir.constant(1 : i32) : i32645 // After SROA, only one i32 will be actually used, so only 4 bytes will be set.646 // CHECK-COUNT-4: = llvm.alloca %[[ALLOCA_LEN]] x i32647 %0 = llvm.mlir.constant(1 : i32) : i32648 %1 = llvm.alloca %0 x !llvm.array<4 x i32> : (i32) -> !llvm.ptr649 // Unfortunately because of FileCheck limitations it is not possible to check which slot gets read from.650 // We can only check that the amount of operations and allocated slots is correct, which should be sufficient651 // as unused slots are not generated.652 // CHECK-DAG: %[[SLOT_IN_OTHER:.*]] = llvm.getelementptr %[[OTHER_ARRAY]][0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<4 x i32>653 // CHECK-DAG: "llvm.intr.memcpy.inline"(%[[SLOT_IN_OTHER]], %{{.*}}) <{isVolatile = false, len = 4 : i32}>654 // CHECK-DAG: %[[SLOT_IN_OTHER:.*]] = llvm.getelementptr %[[OTHER_ARRAY]][0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<4 x i32>655 // CHECK-DAG: "llvm.intr.memcpy.inline"(%[[SLOT_IN_OTHER]], %{{.*}}) <{isVolatile = false, len = 4 : i32}>656 // CHECK-DAG: %[[SLOT_IN_OTHER:.*]] = llvm.getelementptr %[[OTHER_ARRAY]][0, 2] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<4 x i32>657 // CHECK-DAG: "llvm.intr.memcpy.inline"(%[[SLOT_IN_OTHER]], %{{.*}}) <{isVolatile = false, len = 4 : i32}>658 // CHECK-DAG: %[[SLOT_IN_OTHER:.*]] = llvm.getelementptr %[[OTHER_ARRAY]][0, 3] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<4 x i32>659 // CHECK-DAG: "llvm.intr.memcpy.inline"(%[[SLOT_IN_OTHER]], %{{.*}}) <{isVolatile = false, len = 4 : i32}>660 "llvm.intr.memcpy.inline"(%other_array, %1) <{isVolatile = false, len = 16 : i32}> : (!llvm.ptr, !llvm.ptr) -> ()661 %2 = llvm.getelementptr %1[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<4 x i32>662 %3 = llvm.load %2 : !llvm.ptr -> i32663 llvm.return %3 : i32664}665