451 lines · plain
1// RUN: mlir-opt %s --pass-pipeline="builtin.module(llvm.func(sroa))" --split-input-file | FileCheck %s2 3// CHECK-LABEL: llvm.func @basic_struct4llvm.func @basic_struct() -> i32 {5 // CHECK: %[[SIZE:.*]] = llvm.mlir.constant(1 : i32)6 %0 = llvm.mlir.constant(1 : i32) : i327 // CHECK: %[[ALLOCA:.*]] = llvm.alloca %[[SIZE]] x i328 %1 = llvm.alloca %0 x !llvm.struct<"foo", (i32, f64, i32)> {alignment = 8 : i64} : (i32) -> !llvm.ptr9 %2 = llvm.getelementptr inbounds %1[0, 2] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"foo", (i32, f64, i32)>10 // CHECK: %[[RES:.*]] = llvm.load %[[ALLOCA]]11 %3 = llvm.load %2 : !llvm.ptr -> i3212 // CHECK: llvm.return %[[RES]] : i3213 llvm.return %3 : i3214}15 16// -----17 18// CHECK-LABEL: llvm.func @basic_array19llvm.func @basic_array() -> i32 {20 // CHECK: %[[SIZE:.*]] = llvm.mlir.constant(1 : i32)21 %0 = llvm.mlir.constant(1 : i32) : i3222 // CHECK: %[[ALLOCA:.*]] = llvm.alloca %[[SIZE]] x i3223 %1 = llvm.alloca %0 x !llvm.array<10 x i32> {alignment = 8 : i64} : (i32) -> !llvm.ptr24 %2 = llvm.getelementptr inbounds %1[0, 2] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<10 x i32>25 // CHECK: %[[RES:.*]] = llvm.load %[[ALLOCA]]26 %3 = llvm.load %2 : !llvm.ptr -> i3227 // CHECK: llvm.return %[[RES]] : i3228 llvm.return %3 : i3229}30 31// -----32 33// CHECK-LABEL: llvm.func @multi_level_direct34llvm.func @multi_level_direct() -> i32 {35 // CHECK: %[[SIZE:.*]] = llvm.mlir.constant(1 : i32)36 %0 = llvm.mlir.constant(1 : i32) : i3237 // CHECK: %[[ALLOCA:.*]] = llvm.alloca %[[SIZE]] x i3238 %1 = llvm.alloca %0 x !llvm.struct<"foo", (i32, f64, struct<"bar", (i8, array<10 x array<10 x i32>>, i8)>)> {alignment = 8 : i64} : (i32) -> !llvm.ptr39 %2 = llvm.getelementptr inbounds %1[0, 2, 1, 5, 8] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"foo", (i32, f64, struct<"bar", (i8, array<10 x array<10 x i32>>, i8)>)>40 // CHECK: %[[RES:.*]] = llvm.load %[[ALLOCA]]41 %3 = llvm.load %2 : !llvm.ptr -> i3242 // CHECK: llvm.return %[[RES]] : i3243 llvm.return %3 : i3244}45 46// -----47 48// The first application of SROA would generate a GEP with indices [0, 0]. This49// test ensures this GEP is not eliminated during the first application. Even50// though doing it would be correct, it would prevent the second application51// of SROA to eliminate the array. GEPs should be eliminated only when they are52// truly trivial (with indices [0]).53 54// CHECK-LABEL: llvm.func @multi_level_direct_two_applications55llvm.func @multi_level_direct_two_applications() -> i32 {56 // CHECK: %[[SIZE:.*]] = llvm.mlir.constant(1 : i32)57 %0 = llvm.mlir.constant(1 : i32) : i3258 // CHECK: %[[ALLOCA:.*]] = llvm.alloca %[[SIZE]] x i3259 %1 = llvm.alloca %0 x !llvm.struct<"foo", (i32, f64, array<10 x i32>, i8)> {alignment = 8 : i64} : (i32) -> !llvm.ptr60 %2 = llvm.getelementptr inbounds %1[0, 2, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"foo", (i32, f64, array<10 x i32>, i8)>61 // CHECK: %[[RES:.*]] = llvm.load %[[ALLOCA]]62 %3 = llvm.load %2 : !llvm.ptr -> i3263 // CHECK: llvm.return %[[RES]] : i3264 llvm.return %3 : i3265}66 67// -----68 69// CHECK-LABEL: llvm.func @multi_level_indirect70llvm.func @multi_level_indirect() -> i32 {71 // CHECK: %[[SIZE:.*]] = llvm.mlir.constant(1 : i32)72 %0 = llvm.mlir.constant(1 : i32) : i3273 // CHECK: %[[ALLOCA:.*]] = llvm.alloca %[[SIZE]] x i3274 %1 = llvm.alloca %0 x !llvm.struct<"foo", (i32, f64, struct<"bar", (i8, array<10 x array<10 x i32>>, i8)>)> {alignment = 8 : i64} : (i32) -> !llvm.ptr75 %2 = llvm.getelementptr inbounds %1[0, 2, 1, 5] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"foo", (i32, f64, struct<"bar", (i8, array<10 x array<10 x i32>>, i8)>)>76 %3 = llvm.getelementptr inbounds %2[0, 8] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<10 x i32>77 // CHECK: %[[RES:.*]] = llvm.load %[[ALLOCA]]78 %4 = llvm.load %3 : !llvm.ptr -> i3279 // CHECK: llvm.return %[[RES]] : i3280 llvm.return %4 : i3281}82 83// -----84 85// This verifies that a nested GEP's users are checked properly. In this case86// the load goes over the bounds of the memory slot and thus should block the87// splitting of the alloca.88 89// CHECK-LABEL: llvm.func @nested_access_over_slot_bound90llvm.func @nested_access_over_slot_bound() -> i64 {91 %0 = llvm.mlir.constant(1 : i32) : i3292 // CHECK: %[[ALLOCA:.*]] = llvm.alloca %{{.*}} x !llvm.struct<(i32, struct<(93 %1 = llvm.alloca %0 x !llvm.struct<(i32, struct<(array<10 x i32>)>, i32)> {alignment = 8 : i64} : (i32) -> !llvm.ptr94 // CHECK: %[[GEP0:.*]] = llvm.getelementptr inbounds %[[ALLOCA]]95 %2 = llvm.getelementptr inbounds %1[0, 1, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i32, struct<(array<10 x i32>)>, i32)>96 // CHECK: %[[GEP1:.*]] = llvm.getelementptr inbounds %[[GEP0]]97 %3 = llvm.getelementptr inbounds %2[0, 9] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<10 x i32>98 // CHECK: %[[RES:.*]] = llvm.load %[[GEP1]]99 %4 = llvm.load %3 : !llvm.ptr -> i64100 // CHECK: llvm.return %[[RES]] : i64101 llvm.return %4 : i64102}103 104// -----105 106// CHECK-LABEL: llvm.func @resolve_alias107// CHECK-SAME: (%[[ARG:.*]]: i32)108llvm.func @resolve_alias(%arg: i32) -> i32 {109 // CHECK: %[[SIZE:.*]] = llvm.mlir.constant(1 : i32)110 %0 = llvm.mlir.constant(1 : i32) : i32111 // CHECK: %[[ALLOCA:.*]] = llvm.alloca %[[SIZE]] x i32112 %1 = llvm.alloca %0 x !llvm.struct<"foo", (i32, f64, i32)> {alignment = 8 : i64} : (i32) -> !llvm.ptr113 %2 = llvm.getelementptr %1[0, 2] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"foo", (i32, f64, i32)>114 %3 = llvm.getelementptr inbounds %1[0, 2] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"foo", (i32, f64, i32)>115 // CHECK: llvm.store %[[ARG]], %[[ALLOCA]]116 llvm.store %arg, %2 : i32, !llvm.ptr117 // CHECK: %[[RES:.*]] = llvm.load %[[ALLOCA]]118 %4 = llvm.load %3 : !llvm.ptr -> i32119 // CHECK: llvm.return %[[RES]] : i32120 llvm.return %4 : i32121}122 123// -----124 125// CHECK-LABEL: llvm.func @no_non_single_support126llvm.func @no_non_single_support() -> i32 {127 // CHECK: %[[SIZE:.*]] = llvm.mlir.constant128 %0 = llvm.mlir.constant(2 : i32) : i32129 // CHECK: %[[ALLOCA:.*]] = llvm.alloca %[[SIZE]] x !llvm.struct<"foo", (i32, f64, i32)> {alignment = 8 : i64} : (i32) -> !llvm.ptr130 %1 = llvm.alloca %0 x !llvm.struct<"foo", (i32, f64, i32)> {alignment = 8 : i64} : (i32) -> !llvm.ptr131 // CHECK-NOT: = llvm.alloca132 %2 = llvm.getelementptr inbounds %1[0, 2] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"foo", (i32, f64, i32)>133 %3 = llvm.load %2 : !llvm.ptr -> i32134 llvm.return %3 : i32135}136 137// -----138 139// CHECK-LABEL: llvm.func @no_pointer_indexing140llvm.func @no_pointer_indexing() -> i32 {141 // CHECK: %[[SIZE:.*]] = llvm.mlir.constant(1 : i32)142 %0 = llvm.mlir.constant(1 : i32) : i32143 // CHECK: %[[ALLOCA:.*]] = llvm.alloca %[[SIZE]] x !llvm.struct<"foo", (i32, f64, i32)> {alignment = 8 : i64} : (i32) -> !llvm.ptr144 %1 = llvm.alloca %0 x !llvm.struct<"foo", (i32, f64, i32)> {alignment = 8 : i64} : (i32) -> !llvm.ptr145 // CHECK-NOT: = llvm.alloca146 %2 = llvm.getelementptr %1[1, 2] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"foo", (i32, f64, i32)>147 %3 = llvm.load %2 : !llvm.ptr -> i32148 llvm.return %3 : i32149}150 151// -----152 153// CHECK-LABEL: llvm.func @no_direct_use154llvm.func @no_direct_use() -> i32 {155 // CHECK: %[[SIZE:.*]] = llvm.mlir.constant(1 : i32)156 %0 = llvm.mlir.constant(1 : i32) : i32157 // CHECK: %[[ALLOCA:.*]] = llvm.alloca %[[SIZE]] x !llvm.struct<"foo", (i32, f64, i32)> {alignment = 8 : i64} : (i32) -> !llvm.ptr158 %1 = llvm.alloca %0 x !llvm.struct<"foo", (i32, f64, i32)> {alignment = 8 : i64} : (i32) -> !llvm.ptr159 // CHECK-NOT: = llvm.alloca160 %2 = llvm.getelementptr %1[0, 2] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"foo", (i32, f64, i32)>161 %3 = llvm.load %2 : !llvm.ptr -> i32162 llvm.call @use(%1) : (!llvm.ptr) -> ()163 llvm.return %3 : i32164}165 166llvm.func @use(!llvm.ptr)167 168// -----169 170// CHECK-LABEL: llvm.func @direct_promotable_use_is_fine171llvm.func @direct_promotable_use_is_fine() -> i32 {172 // CHECK: %[[SIZE:.*]] = llvm.mlir.constant(1 : i32)173 %0 = llvm.mlir.constant(1 : i32) : i32174 // CHECK: %[[ALLOCA:.*]] = llvm.alloca %[[SIZE]] x i32175 %1 = llvm.alloca %0 x !llvm.struct<"foo", (i32, f64, i32)> {alignment = 8 : i64} : (i32) -> !llvm.ptr176 %2 = llvm.getelementptr %1[0, 2] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"foo", (i32, f64, i32)>177 // CHECK: %[[RES:.*]] = llvm.load %[[ALLOCA]]178 %3 = llvm.load %2 : !llvm.ptr -> i32179 // This is a direct use of the slot but it can be removed because it implements PromotableOpInterface.180 llvm.intr.lifetime.start %1 : !llvm.ptr181 // CHECK: llvm.return %[[RES]] : i32182 llvm.return %3 : i32183}184 185// -----186 187// CHECK-LABEL: llvm.func @direct_promotable_use_is_fine_on_accessor188llvm.func @direct_promotable_use_is_fine_on_accessor() -> i32 {189 // CHECK: %[[SIZE:.*]] = llvm.mlir.constant(1 : i32)190 %0 = llvm.mlir.constant(1 : i32) : i32191 // CHECK: %[[ALLOCA:.*]] = llvm.alloca %[[SIZE]] x i32192 %1 = llvm.alloca %0 x !llvm.struct<"foo", (i32, f64, i32)> {alignment = 8 : i64} : (i32) -> !llvm.ptr193 %2 = llvm.getelementptr %1[0, 2] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"foo", (i32, f64, i32)>194 // This does not provide side-effect info but it can be removed because it implements PromotableOpInterface.195 %3 = llvm.intr.invariant.start 2, %2 : !llvm.ptr196 // CHECK: %[[RES:.*]] = llvm.load %[[ALLOCA]]197 %4 = llvm.load %2 : !llvm.ptr -> i32198 // This does not provide side-effect info but it can be removed because it implements PromotableOpInterface.199 llvm.intr.invariant.end %3, 2, %2 : !llvm.ptr200 // CHECK: llvm.return %[[RES]] : i32201 llvm.return %4 : i32202}203 204// -----205 206// CHECK-LABEL: llvm.func @no_dynamic_indexing207// CHECK-SAME: (%[[ARG:.*]]: i32)208llvm.func @no_dynamic_indexing(%arg: i32) -> i32 {209 // CHECK: %[[SIZE:.*]] = llvm.mlir.constant(1 : i32)210 %0 = llvm.mlir.constant(1 : i32) : i32211 // CHECK: %[[ALLOCA:.*]] = llvm.alloca %[[SIZE]] x !llvm.array<10 x i32> {alignment = 8 : i64} : (i32) -> !llvm.ptr212 %1 = llvm.alloca %0 x !llvm.array<10 x i32> {alignment = 8 : i64} : (i32) -> !llvm.ptr213 // CHECK-NOT: = llvm.alloca214 // CHECK: %[[GEP:.*]] = llvm.getelementptr %[[ALLOCA]][0, %[[ARG]]]215 %2 = llvm.getelementptr %1[0, %arg] : (!llvm.ptr, i32) -> !llvm.ptr, !llvm.array<10 x i32>216 // CHECK: %[[RES:.*]] = llvm.load %[[GEP]]217 %3 = llvm.load %2 : !llvm.ptr -> i32218 // CHECK: llvm.return %[[RES]] : i32219 llvm.return %3 : i32220}221 222// -----223 224// CHECK-LABEL: llvm.func @no_nested_dynamic_indexing225// CHECK-SAME: (%[[ARG:.*]]: i32)226llvm.func @no_nested_dynamic_indexing(%arg: i32) -> i32 {227 // CHECK: %[[SIZE:.*]] = llvm.mlir.constant(1 : i32)228 %0 = llvm.mlir.constant(1 : i32) : i32229 // CHECK: %[[ALLOCA:.*]] = llvm.alloca %[[SIZE]] x !llvm.struct<(array<10 x i32>, i32)> {alignment = 8 : i64} : (i32) -> !llvm.ptr230 %1 = llvm.alloca %0 x !llvm.struct<(array<10 x i32>, i32)> {alignment = 8 : i64} : (i32) -> !llvm.ptr231 // CHECK-NOT: = llvm.alloca232 // CHECK: %[[GEP:.*]] = llvm.getelementptr %[[ALLOCA]][0, 0, %[[ARG]]]233 %2 = llvm.getelementptr %1[0, 0, %arg] : (!llvm.ptr, i32) -> !llvm.ptr, !llvm.struct<(array<10 x i32>, i32)>234 // CHECK: %[[RES:.*]] = llvm.load %[[GEP]]235 %3 = llvm.load %2 : !llvm.ptr -> i32236 // CHECK: llvm.return %[[RES]] : i32237 llvm.return %3 : i32238}239 240// -----241 242// CHECK-LABEL: llvm.func @store_first_field243llvm.func @store_first_field(%arg: i32) {244 %0 = llvm.mlir.constant(1 : i32) : i32245 // CHECK: %[[ALLOCA:.*]] = llvm.alloca %{{.*}} x i32246 %1 = llvm.alloca %0 x !llvm.struct<"foo", (i32, i32, i32)> : (i32) -> !llvm.ptr247 // CHECK-NEXT: llvm.store %{{.*}}, %[[ALLOCA]] : i32248 llvm.store %arg, %1 : i32, !llvm.ptr249 llvm.return250}251 252// -----253 254// CHECK-LABEL: llvm.func @store_first_field_different_type255// CHECK-SAME: (%[[ARG:.*]]: f32)256llvm.func @store_first_field_different_type(%arg: f32) {257 %0 = llvm.mlir.constant(1 : i32) : i32258 // CHECK: %[[ALLOCA:.*]] = llvm.alloca %{{.*}} x i32259 %1 = llvm.alloca %0 x !llvm.struct<"foo", (i32, i32, i32)> : (i32) -> !llvm.ptr260 // CHECK-NEXT: llvm.store %[[ARG]], %[[ALLOCA]] : f32261 llvm.store %arg, %1 : f32, !llvm.ptr262 llvm.return263}264 265// -----266 267// CHECK-LABEL: llvm.func @store_sub_field268// CHECK-SAME: (%[[ARG:.*]]: f32)269llvm.func @store_sub_field(%arg: f32) {270 %0 = llvm.mlir.constant(1 : i32) : i32271 // CHECK: %[[ALLOCA:.*]] = llvm.alloca %{{.*}} x i64272 %1 = llvm.alloca %0 x !llvm.struct<"foo", (i64, i32)> : (i32) -> !llvm.ptr273 // CHECK-NEXT: llvm.store %[[ARG]], %[[ALLOCA]] : f32274 llvm.store %arg, %1 : f32, !llvm.ptr275 llvm.return276}277 278// -----279 280// CHECK-LABEL: llvm.func @load_first_field281llvm.func @load_first_field() -> i32 {282 %0 = llvm.mlir.constant(1 : i32) : i32283 // CHECK: %[[ALLOCA:.*]] = llvm.alloca %{{.*}} x i32284 %1 = llvm.alloca %0 x !llvm.struct<"foo", (i32, i32, i32)> : (i32) -> !llvm.ptr285 // CHECK-NEXT: %[[RES:.*]] = llvm.load %[[ALLOCA]] : !llvm.ptr -> i32286 %2 = llvm.load %1 : !llvm.ptr -> i32287 // CHECK: llvm.return %[[RES]] : i32288 llvm.return %2 : i32289}290 291// -----292 293// CHECK-LABEL: llvm.func @load_first_field_different_type294llvm.func @load_first_field_different_type() -> f32 {295 %0 = llvm.mlir.constant(1 : i32) : i32296 // CHECK: %[[ALLOCA:.*]] = llvm.alloca %{{.*}} x i32297 %1 = llvm.alloca %0 x !llvm.struct<"foo", (i32, i32, i32)> : (i32) -> !llvm.ptr298 // CHECK-NEXT: %[[RES:.*]] = llvm.load %[[ALLOCA]] : !llvm.ptr -> f32299 %2 = llvm.load %1 : !llvm.ptr -> f32300 // CHECK: llvm.return %[[RES]] : f32301 llvm.return %2 : f32302}303 304// -----305 306// CHECK-LABEL: llvm.func @load_sub_field307llvm.func @load_sub_field() -> i32 {308 %0 = llvm.mlir.constant(1 : i32) : i32309 // CHECK: %[[ALLOCA:.*]] = llvm.alloca %{{.*}} x i64 : (i32) -> !llvm.ptr310 %1 = llvm.alloca %0 x !llvm.struct<(i64, i32)> : (i32) -> !llvm.ptr311 // CHECK-NEXT: %[[RES:.*]] = llvm.load %[[ALLOCA]]312 %res = llvm.load %1 : !llvm.ptr -> i32313 // CHECK: llvm.return %[[RES]] : i32314 llvm.return %res : i32315}316 317// -----318 319// CHECK-LABEL: llvm.func @vector_store_type_mismatch320// CHECK-SAME: %[[ARG:.*]]: vector<4xi32>321llvm.func @vector_store_type_mismatch(%arg: vector<4xi32>) {322 %0 = llvm.mlir.constant(1 : i32) : i32323 // CHECK: %[[ALLOCA:.*]] = llvm.alloca %{{.*}} x vector<4xf32>324 %1 = llvm.alloca %0 x !llvm.struct<"foo", (vector<4xf32>)> : (i32) -> !llvm.ptr325 // CHECK-NEXT: llvm.store %[[ARG]], %[[ALLOCA]]326 llvm.store %arg, %1 : vector<4xi32>, !llvm.ptr327 llvm.return328}329 330// -----331 332// CHECK-LABEL: llvm.func @store_to_memory333// CHECK-SAME: %[[ARG:.*]]: !llvm.ptr334llvm.func @store_to_memory(%arg: !llvm.ptr) {335 %0 = llvm.mlir.constant(1 : i32) : i32336 // CHECK: %[[ALLOCA:.*]] = llvm.alloca %{{.*}} x !llvm.struct<337 %1 = llvm.alloca %0 x !llvm.struct<"foo", (vector<4xf32>)> : (i32) -> !llvm.ptr338 // CHECK-NEXT: llvm.store %[[ALLOCA]], %[[ARG]]339 llvm.store %1, %arg : !llvm.ptr, !llvm.ptr340 llvm.return341}342 343// -----344 345// CHECK-LABEL: llvm.func @type_mismatch_array_access346// CHECK-SAME: %[[ARG:.*]]: i32347llvm.func @type_mismatch_array_access(%arg: i32) {348 %0 = llvm.mlir.constant(1 : i32) : i32349 // CHECK: %[[ALLOCA:.*]] = llvm.alloca %{{.*}} x i32350 %1 = llvm.alloca %0 x !llvm.struct<(i32, i32, i32)> : (i32) -> !llvm.ptr351 %2 = llvm.getelementptr %1[8] : (!llvm.ptr) -> !llvm.ptr, i8352 // CHECK-NEXT: llvm.store %[[ARG]], %[[ALLOCA]]353 llvm.store %arg, %2 : i32, !llvm.ptr354 llvm.return355}356 357// -----358 359// CHECK-LABEL: llvm.func @type_mismatch_struct_access360// CHECK-SAME: %[[ARG:.*]]: i32361llvm.func @type_mismatch_struct_access(%arg: i32) {362 %0 = llvm.mlir.constant(1 : i32) : i32363 // CHECK: %[[ALLOCA:.*]] = llvm.alloca %{{.*}} x i32364 %1 = llvm.alloca %0 x !llvm.struct<(i32, i32, i32)> : (i32) -> !llvm.ptr365 %2 = llvm.getelementptr %1[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i32, i32)>366 // CHECK-NEXT: llvm.store %[[ARG]], %[[ALLOCA]]367 llvm.store %arg, %2 : i32, !llvm.ptr368 llvm.return369}370 371// -----372 373// CHECK-LABEL: llvm.func @index_in_final_padding374llvm.func @index_in_final_padding(%arg: i32) {375 %0 = llvm.mlir.constant(1 : i32) : i32376 // CHECK: %[[ALLOCA:.*]] = llvm.alloca %{{.*}} x !llvm.struct<"foo", (i32, i8)>377 %1 = llvm.alloca %0 x !llvm.struct<"foo", (i32, i8)> : (i32) -> !llvm.ptr378 // CHECK: = llvm.getelementptr %[[ALLOCA]][7] : (!llvm.ptr) -> !llvm.ptr, i8379 %2 = llvm.getelementptr %1[7] : (!llvm.ptr) -> !llvm.ptr, i8380 llvm.store %arg, %2 : i32, !llvm.ptr381 llvm.return382}383 384// -----385 386// CHECK-LABEL: llvm.func @index_out_of_bounds387llvm.func @index_out_of_bounds(%arg: i32) {388 %0 = llvm.mlir.constant(1 : i32) : i32389 // CHECK: %[[ALLOCA:.*]] = llvm.alloca %{{.*}} x !llvm.struct<"foo", (i32, i32)>390 %1 = llvm.alloca %0 x !llvm.struct<"foo", (i32, i32)> : (i32) -> !llvm.ptr391 // CHECK: = llvm.getelementptr %[[ALLOCA]][9] : (!llvm.ptr) -> !llvm.ptr, i8392 %2 = llvm.getelementptr %1[9] : (!llvm.ptr) -> !llvm.ptr, i8393 llvm.store %arg, %2 : i32, !llvm.ptr394 llvm.return395}396 397// -----398 399// CHECK-LABEL: llvm.func @index_in_padding400llvm.func @index_in_padding(%arg: i16) {401 %0 = llvm.mlir.constant(1 : i32) : i32402 // CHECK: %[[ALLOCA:.*]] = llvm.alloca %{{.*}} x !llvm.struct<"foo", (i16, i32)>403 %1 = llvm.alloca %0 x !llvm.struct<"foo", (i16, i32)> : (i32) -> !llvm.ptr404 // CHECK: = llvm.getelementptr %[[ALLOCA]][2] : (!llvm.ptr) -> !llvm.ptr, i8405 %2 = llvm.getelementptr %1[2] : (!llvm.ptr) -> !llvm.ptr, i8406 llvm.store %arg, %2 : i16, !llvm.ptr407 llvm.return408}409 410// -----411 412// CHECK-LABEL: llvm.func @index_not_in_padding_because_packed413// CHECK-SAME: %[[ARG:.*]]: i16414llvm.func @index_not_in_padding_because_packed(%arg: i16) {415 %0 = llvm.mlir.constant(1 : i32) : i32416 // CHECK: %[[ALLOCA:.*]] = llvm.alloca %{{.*}} x i32417 %1 = llvm.alloca %0 x !llvm.struct<"foo", packed (i16, i32)> : (i32) -> !llvm.ptr418 %2 = llvm.getelementptr %1[2] : (!llvm.ptr) -> !llvm.ptr, i8419 // CHECK-NEXT: llvm.store %[[ARG]], %[[ALLOCA]]420 llvm.store %arg, %2 : i16, !llvm.ptr421 llvm.return422}423 424// -----425 426// CHECK-LABEL: llvm.func @no_crash_on_negative_gep_index427// CHECK-SAME: %[[ARG:.*]]: f16428llvm.func @no_crash_on_negative_gep_index(%arg: f16) {429 %0 = llvm.mlir.constant(1 : i32) : i32430 // CHECK: %[[ALLOCA:.*]] = llvm.alloca %{{.*}} x !llvm.struct<"foo", (i32, i32, i32)>431 %1 = llvm.alloca %0 x !llvm.struct<"foo", (i32, i32, i32)> : (i32) -> !llvm.ptr432 // CHECK: llvm.getelementptr %[[ALLOCA]][-1] : (!llvm.ptr) -> !llvm.ptr, f32433 %2 = llvm.getelementptr %1[-1] : (!llvm.ptr) -> !llvm.ptr, f32434 llvm.store %arg, %2 : f16, !llvm.ptr435 llvm.return436}437 438// -----439 440// CHECK-LABEL: llvm.func @out_of_bound_gep_array_access441// CHECK-SAME: %[[ARG:.*]]: i32442llvm.func @out_of_bound_gep_array_access(%arg: i32) {443 %0 = llvm.mlir.constant(1 : i32) : i32444 // CHECK: %[[ALLOCA:.*]] = llvm.alloca %{{.*}} x i32445 %1 = llvm.alloca %0 x !llvm.struct<"foo", (i32, i32)> : (i32) -> !llvm.ptr446 %2 = llvm.getelementptr %1[0, 4] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<4 x i8>447 // CHECK-NEXT: llvm.store %[[ARG]], %[[ALLOCA]]448 llvm.store %arg, %2 : i32, !llvm.ptr449 llvm.return450}451