brintos

brintos / llvm-project-archived public Read only

0
0
Text · 36.4 KiB · 6dc8a97 Raw
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