338 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -passes='sroa<preserve-cfg>' -S | FileCheck %s --check-prefixes=CHECK,CHECK-PRESERVE-CFG3; RUN: opt < %s -passes='sroa<modify-cfg>' -S | FileCheck %s --check-prefixes=CHECK,CHECK-MODIFY-CFG4 5target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-n8:16:32:64"6 7; This test checks that SROA runs mem2reg on scalable vectors.8 9define <vscale x 16 x i1> @alloca_nxv16i1(<vscale x 16 x i1> %pg) {10; CHECK-LABEL: @alloca_nxv16i1(11; CHECK-NEXT: ret <vscale x 16 x i1> [[PG:%.*]]12;13 %pg.addr = alloca <vscale x 16 x i1>14 store <vscale x 16 x i1> %pg, ptr %pg.addr15 %1 = load <vscale x 16 x i1>, ptr %pg.addr16 ret <vscale x 16 x i1> %117}18 19define <vscale x 16 x i8> @alloca_nxv16i8(<vscale x 16 x i8> %vec) {20; CHECK-LABEL: @alloca_nxv16i8(21; CHECK-NEXT: ret <vscale x 16 x i8> [[VEC:%.*]]22;23 %vec.addr = alloca <vscale x 16 x i8>24 store <vscale x 16 x i8> %vec, ptr %vec.addr25 %1 = load <vscale x 16 x i8>, ptr %vec.addr26 ret <vscale x 16 x i8> %127}28 29; Test scalable alloca that can't be promoted. Mem2Reg only considers30; non-volatile loads and stores for promotion.31define <vscale x 16 x i8> @unpromotable_alloca(<vscale x 16 x i8> %vec) {32; CHECK-LABEL: @unpromotable_alloca(33; CHECK-NEXT: [[VEC_ADDR:%.*]] = alloca <vscale x 16 x i8>, align 1634; CHECK-NEXT: store volatile <vscale x 16 x i8> [[VEC:%.*]], ptr [[VEC_ADDR]], align 1635; CHECK-NEXT: [[TMP1:%.*]] = load volatile <vscale x 16 x i8>, ptr [[VEC_ADDR]], align 1636; CHECK-NEXT: ret <vscale x 16 x i8> [[TMP1]]37;38 %vec.addr = alloca <vscale x 16 x i8>39 store volatile <vscale x 16 x i8> %vec, ptr %vec.addr40 %1 = load volatile <vscale x 16 x i8>, ptr %vec.addr41 ret <vscale x 16 x i8> %142}43 44; Test we bail out when using an alloca of a fixed-length vector (VLS) that was45; bitcasted to a scalable vector.46define <vscale x 4 x i32> @cast_alloca_to_svint32_t(<vscale x 4 x i32> %type.coerce) {47; CHECK-LABEL: @cast_alloca_to_svint32_t(48; CHECK-NEXT: [[TYPE:%.*]] = alloca <16 x i32>, align 6449; CHECK-NEXT: [[TYPE_ADDR:%.*]] = alloca <16 x i32>, align 6450; CHECK-NEXT: store <vscale x 4 x i32> [[TYPE_COERCE:%.*]], ptr [[TYPE]], align 1651; CHECK-NEXT: [[TYPE1:%.*]] = load <16 x i32>, ptr [[TYPE]], align 6452; CHECK-NEXT: store <16 x i32> [[TYPE1]], ptr [[TYPE_ADDR]], align 6453; CHECK-NEXT: [[TMP1:%.*]] = load <16 x i32>, ptr [[TYPE_ADDR]], align 6454; CHECK-NEXT: [[TMP2:%.*]] = load <vscale x 4 x i32>, ptr [[TYPE_ADDR]], align 1655; CHECK-NEXT: ret <vscale x 4 x i32> [[TMP2]]56;57 %type = alloca <16 x i32>58 %type.addr = alloca <16 x i32>59 store <vscale x 4 x i32> %type.coerce, ptr %type60 %type1 = load <16 x i32>, ptr %type61 store <16 x i32> %type1, ptr %type.addr62 %1 = load <16 x i32>, ptr %type.addr63 %2 = load <vscale x 4 x i32>, ptr %type.addr64 ret <vscale x 4 x i32> %265}66 67; When casting from VLA to VLS via memory check we bail out when producing a68; GEP where the element type is a scalable vector.69define <vscale x 4 x i32> @cast_alloca_from_svint32_t() {70; CHECK-LABEL: @cast_alloca_from_svint32_t(71; CHECK-NEXT: [[RETVAL_COERCE:%.*]] = alloca <vscale x 4 x i32>, align 1672; CHECK-NEXT: store <16 x i32> zeroinitializer, ptr [[RETVAL_COERCE]], align 1673; CHECK-NEXT: [[TMP1:%.*]] = load <vscale x 4 x i32>, ptr [[RETVAL_COERCE]], align 1674; CHECK-NEXT: ret <vscale x 4 x i32> [[TMP1]]75;76 %retval = alloca <16 x i32>77 store <16 x i32> zeroinitializer, ptr %retval78 %retval.coerce = alloca <vscale x 4 x i32>79 call void @llvm.memcpy.p0.p0.i64(ptr align 16 %retval.coerce, ptr align 16 %retval, i64 64, i1 false)80 %1 = load <vscale x 4 x i32>, ptr %retval.coerce81 ret <vscale x 4 x i32> %182}83 84; Test we bail out when using an alloca of a fixed-length vector (VLS) that was85; bitcasted to a scalable vector.86define void @select_load_alloca_to_svdouble_t() {87; CHECK-LABEL: @select_load_alloca_to_svdouble_t(88; CHECK-NEXT: [[Z:%.*]] = alloca <16 x half>, align 3289; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 0, 090; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], ptr [[Z]], ptr null91; CHECK-NEXT: [[VAL:%.*]] = load <vscale x 2 x double>, ptr [[COND]], align 1692; CHECK-NEXT: ret void93;94 %z = alloca <16 x half>95 %cmp = icmp eq i32 0, 096 %cond = select i1 %cmp, ptr %z, ptr null97 %val = load <vscale x 2 x double>, ptr %cond, align 1698 ret void99}100 101define void @select_store_alloca_to_svdouble_t(<vscale x 2 x double> %val) {102; CHECK-LABEL: @select_store_alloca_to_svdouble_t(103; CHECK-NEXT: [[Z:%.*]] = alloca <16 x half>, align 32104; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 0, 0105; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], ptr [[Z]], ptr null106; CHECK-NEXT: store <vscale x 2 x double> [[VAL:%.*]], ptr [[COND]], align 16107; CHECK-NEXT: ret void108;109 %z = alloca <16 x half>110 %cmp = icmp eq i32 0, 0111 %cond = select i1 %cmp, ptr %z, ptr null112 store <vscale x 2 x double> %val, ptr %cond, align 16113 ret void114}115 116define <4 x i32> @fixed_alloca_fixed_from_scalable(<vscale x 4 x i32> %a) {117; CHECK-LABEL: @fixed_alloca_fixed_from_scalable(118; CHECK-NEXT: [[TMP:%.*]] = alloca <4 x i32>, align 16119; CHECK-NEXT: store <vscale x 4 x i32> [[A:%.*]], ptr [[TMP]], align 16120; CHECK-NEXT: [[TMP1:%.*]] = load <4 x i32>, ptr [[TMP]], align 16121; CHECK-NEXT: ret <4 x i32> [[TMP1]]122;123 %tmp = alloca <4 x i32>124 store <vscale x 4 x i32> %a, ptr %tmp125 %cast = load <4 x i32>, ptr %tmp126 ret <4 x i32> %cast127}128 129define <2 x i8> @fixed_alloca_fixed_from_scalable_requires_bitcast(<vscale x 16 x i1> %a) {130; CHECK-LABEL: @fixed_alloca_fixed_from_scalable_requires_bitcast(131; CHECK-NEXT: [[TMP:%.*]] = alloca <2 x i8>, align 2132; CHECK-NEXT: store <vscale x 16 x i1> [[A:%.*]], ptr [[TMP]], align 2133; CHECK-NEXT: [[TMP2:%.*]] = load <2 x i8>, ptr [[TMP]], align 2134; CHECK-NEXT: ret <2 x i8> [[TMP2]]135;136 %tmp = alloca <2 x i8>137 store <vscale x 16 x i1> %a, ptr %tmp138 %cast = load <2 x i8>, ptr %tmp139 ret <2 x i8> %cast140}141 142define <2 x ptr> @fixed_alloca_fixed_from_scalable_inttoptr(<vscale x 4 x i32> %a) {143; CHECK-LABEL: @fixed_alloca_fixed_from_scalable_inttoptr(144; CHECK-NEXT: [[TMP:%.*]] = alloca <4 x i32>, align 16145; CHECK-NEXT: store <vscale x 4 x i32> [[A:%.*]], ptr [[TMP]], align 16146; CHECK-NEXT: [[TMP2:%.*]] = load <2 x ptr>, ptr [[TMP]], align 16147; CHECK-NEXT: ret <2 x ptr> [[TMP2]]148;149 %tmp = alloca <4 x i32>150 store <vscale x 4 x i32> %a, ptr %tmp151 %cast = load <2 x ptr>, ptr %tmp152 ret <2 x ptr> %cast153}154 155define <4 x i32> @fixed_alloca_fixed_from_scalable_ptrtoint(<vscale x 2 x ptr> %a) {156; CHECK-LABEL: @fixed_alloca_fixed_from_scalable_ptrtoint(157; CHECK-NEXT: [[TMP:%.*]] = alloca <4 x i32>, align 16158; CHECK-NEXT: store <vscale x 2 x ptr> [[A:%.*]], ptr [[TMP]], align 16159; CHECK-NEXT: [[TMP_0_CAST:%.*]] = load <4 x i32>, ptr [[TMP]], align 16160; CHECK-NEXT: ret <4 x i32> [[TMP_0_CAST]]161;162 %tmp = alloca <4 x i32>163 store <vscale x 2 x ptr> %a, ptr %tmp164 %cast = load <4 x i32>, ptr %tmp165 ret <4 x i32> %cast166}167 168define <2 x ptr> @fixed_alloca_fixed_from_scalable_ptrtoptr(<vscale x 2 x ptr> %a) {169; CHECK-LABEL: @fixed_alloca_fixed_from_scalable_ptrtoptr(170; CHECK-NEXT: [[TMP:%.*]] = alloca <2 x ptr>, align 16171; CHECK-NEXT: store <vscale x 2 x ptr> [[A:%.*]], ptr [[TMP]], align 16172; CHECK-NEXT: [[CAST:%.*]] = load <2 x ptr>, ptr [[TMP]], align 16173; CHECK-NEXT: ret <2 x ptr> [[CAST]]174;175 %tmp = alloca <2 x ptr>176 store <vscale x 2 x ptr> %a, ptr %tmp177 %cast = load <2 x ptr>, ptr %tmp178 ret <2 x ptr> %cast179}180 181define <vscale x 4 x i32> @fixed_alloca_scalable_from_fixed(<4 x i32> %a) {182; CHECK-LABEL: @fixed_alloca_scalable_from_fixed(183; CHECK-NEXT: [[TMP:%.*]] = alloca <4 x i32>, align 16184; CHECK-NEXT: store <4 x i32> [[A:%.*]], ptr [[TMP]], align 16185; CHECK-NEXT: [[TMP1:%.*]] = load <vscale x 4 x i32>, ptr [[TMP]], align 16186; CHECK-NEXT: ret <vscale x 4 x i32> [[TMP1]]187;188 %tmp = alloca <4 x i32>189 store <4 x i32> %a, ptr %tmp190 %cast = load <vscale x 4 x i32>, ptr %tmp191 ret <vscale x 4 x i32> %cast192}193 194define <vscale x 16 x i1> @fixed_alloca_scalable_from_fixed_requires_bitcast(<2 x i8> %a) {195; CHECK-LABEL: @fixed_alloca_scalable_from_fixed_requires_bitcast(196; CHECK-NEXT: [[TMP:%.*]] = alloca <2 x i8>, align 2197; CHECK-NEXT: store <2 x i8> [[A:%.*]], ptr [[TMP]], align 2198; CHECK-NEXT: [[TMP2:%.*]] = load <vscale x 16 x i1>, ptr [[TMP]], align 2199; CHECK-NEXT: ret <vscale x 16 x i1> [[TMP2]]200;201 %tmp = alloca <2 x i8>202 store <2 x i8> %a, ptr %tmp203 %cast = load <vscale x 16 x i1>, ptr %tmp204 ret <vscale x 16 x i1> %cast205}206 207define <vscale x 2 x ptr> @fixed_alloca_scalable_from_fixed_inttoptr(<4 x i32> %a) {208; CHECK-LABEL: @fixed_alloca_scalable_from_fixed_inttoptr(209; CHECK-NEXT: [[TMP:%.*]] = alloca <4 x i32>, align 16210; CHECK-NEXT: store <4 x i32> [[A:%.*]], ptr [[TMP]], align 16211; CHECK-NEXT: [[TMP_0_CAST:%.*]] = load <vscale x 2 x ptr>, ptr [[TMP]], align 16212; CHECK-NEXT: ret <vscale x 2 x ptr> [[TMP_0_CAST]]213;214 %tmp = alloca <4 x i32>215 store <4 x i32> %a, ptr %tmp216 %cast = load <vscale x 2 x ptr>, ptr %tmp217 ret <vscale x 2 x ptr> %cast218}219 220define <vscale x 4 x i32> @fixed_alloca_scalable_from_fixed_ptrtoint(<2 x ptr> %a) {221; CHECK-LABEL: @fixed_alloca_scalable_from_fixed_ptrtoint(222; CHECK-NEXT: [[TMP:%.*]] = alloca <4 x i32>, align 16223; CHECK-NEXT: store <2 x ptr> [[A:%.*]], ptr [[TMP]], align 16224; CHECK-NEXT: [[TMP_0_CAST:%.*]] = load <vscale x 4 x i32>, ptr [[TMP]], align 16225; CHECK-NEXT: ret <vscale x 4 x i32> [[TMP_0_CAST]]226;227 %tmp = alloca <4 x i32>228 store <2 x ptr> %a, ptr %tmp229 %cast = load <vscale x 4 x i32>, ptr %tmp230 ret <vscale x 4 x i32> %cast231}232 233define <vscale x 2 x ptr> @fixed_alloca_scalable_from_fixed_ptrtoptr(<2 x ptr> %a) {234; CHECK-LABEL: @fixed_alloca_scalable_from_fixed_ptrtoptr(235; CHECK-NEXT: [[TMP:%.*]] = alloca <2 x ptr>, align 16236; CHECK-NEXT: store <2 x ptr> [[A:%.*]], ptr [[TMP]], align 16237; CHECK-NEXT: [[CAST:%.*]] = load <vscale x 2 x ptr>, ptr [[TMP]], align 16238; CHECK-NEXT: ret <vscale x 2 x ptr> [[CAST]]239;240 %tmp = alloca <2 x ptr>241 store <2 x ptr> %a, ptr %tmp242 %cast = load <vscale x 2 x ptr>, ptr %tmp243 ret <vscale x 2 x ptr> %cast244}245 246define <4 x i32> @scalable_alloca_fixed_from_scalable(<vscale x 4 x i32> %a) {247; CHECK-LABEL: @scalable_alloca_fixed_from_scalable(248; CHECK-NEXT: [[TMP:%.*]] = alloca <vscale x 4 x i32>, align 16249; CHECK-NEXT: store <vscale x 4 x i32> [[A:%.*]], ptr [[TMP]], align 16250; CHECK-NEXT: [[CAST:%.*]] = load <4 x i32>, ptr [[TMP]], align 16251; CHECK-NEXT: ret <4 x i32> [[CAST]]252;253 %tmp = alloca <vscale x 4 x i32>254 store <vscale x 4 x i32> %a, ptr %tmp255 %cast = load <4 x i32>, ptr %tmp256 ret <4 x i32> %cast257}258 259define <vscale x 4 x i32> @scalable_alloca_scalable_from_fixed(<4 x i32> %a) {260; CHECK-LABEL: @scalable_alloca_scalable_from_fixed(261; CHECK-NEXT: [[TMP:%.*]] = alloca <vscale x 4 x i32>, align 16262; CHECK-NEXT: store <4 x i32> [[A:%.*]], ptr [[TMP]], align 16263; CHECK-NEXT: [[CAST:%.*]] = load <vscale x 4 x i32>, ptr [[TMP]], align 16264; CHECK-NEXT: ret <vscale x 4 x i32> [[CAST]]265;266 %tmp = alloca <vscale x 4 x i32>267 store <4 x i32> %a, ptr %tmp268 %cast = load <vscale x 4 x i32>, ptr %tmp269 ret <vscale x 4 x i32> %cast270}271 272define i16 @scalar_alloca_scalar_from_scalable(<vscale x 16 x i1> %a) {273; CHECK-LABEL: @scalar_alloca_scalar_from_scalable(274; CHECK-NEXT: [[TMP:%.*]] = alloca i16, align 2275; CHECK-NEXT: store <vscale x 16 x i1> [[A:%.*]], ptr [[TMP]], align 2276; CHECK-NEXT: [[TMP_0_CAST:%.*]] = load i16, ptr [[TMP]], align 2277; CHECK-NEXT: ret i16 [[TMP_0_CAST]]278;279 %tmp = alloca i16280 store <vscale x 16 x i1> %a, ptr %tmp281 %cast = load i16, ptr %tmp282 ret i16 %cast283}284 285define <vscale x 16 x i1> @scalar_alloca_scalable_from_scalar(i16 %a) {286; CHECK-LABEL: @scalar_alloca_scalable_from_scalar(287; CHECK-NEXT: [[TMP:%.*]] = alloca i16, align 2288; CHECK-NEXT: store i16 [[A:%.*]], ptr [[TMP]], align 2289; CHECK-NEXT: [[TMP_0_CAST:%.*]] = load <vscale x 16 x i1>, ptr [[TMP]], align 2290; CHECK-NEXT: ret <vscale x 16 x i1> [[TMP_0_CAST]]291;292 %tmp = alloca i16293 store i16 %a, ptr %tmp294 %cast = load <vscale x 16 x i1>, ptr %tmp295 ret <vscale x 16 x i1> %cast296}297 298define { <2 x i32>, <2 x i32> } @fixed_struct_alloca_fixed_from_scalable(<vscale x 4 x i32> %a) {299; CHECK-LABEL: @fixed_struct_alloca_fixed_from_scalable(300; CHECK-NEXT: [[TMP:%.*]] = alloca { <2 x i32>, <2 x i32> }, align 8301; CHECK-NEXT: store <vscale x 4 x i32> [[A:%.*]], ptr [[TMP]], align 16302; CHECK-NEXT: [[CAST_FCA_0_GEP:%.*]] = getelementptr inbounds { <2 x i32>, <2 x i32> }, ptr [[TMP]], i32 0, i32 0303; CHECK-NEXT: [[TMP_0_CAST_FCA_0_LOAD:%.*]] = load <2 x i32>, ptr [[CAST_FCA_0_GEP]], align 8304; CHECK-NEXT: [[CAST_FCA_0_INSERT:%.*]] = insertvalue { <2 x i32>, <2 x i32> } poison, <2 x i32> [[TMP_0_CAST_FCA_0_LOAD]], 0305; CHECK-NEXT: [[TMP_8_CAST_FCA_1_GEP_SROA_IDX:%.*]] = getelementptr inbounds { <2 x i32>, <2 x i32> }, ptr [[TMP]], i32 0, i32 1306; CHECK-NEXT: [[TMP_8_CAST_FCA_1_LOAD:%.*]] = load <2 x i32>, ptr [[TMP_8_CAST_FCA_1_GEP_SROA_IDX]], align 8307; CHECK-NEXT: [[CAST_FCA_1_INSERT:%.*]] = insertvalue { <2 x i32>, <2 x i32> } [[CAST_FCA_0_INSERT]], <2 x i32> [[TMP_8_CAST_FCA_1_LOAD]], 1308; CHECK-NEXT: ret { <2 x i32>, <2 x i32> } [[CAST_FCA_1_INSERT]]309;310 %tmp = alloca { <2 x i32>, <2 x i32> }311 store <vscale x 4 x i32> %a, ptr %tmp312 %cast = load { <2 x i32>, <2 x i32> }, ptr %tmp313 ret { <2 x i32>, <2 x i32> } %cast314}315 316define <vscale x 4 x i64> @fixed_struct_alloca_scalable_from_fixed({ <2 x ptr>, <2 x ptr> } %a) {317; CHECK-LABEL: @fixed_struct_alloca_scalable_from_fixed(318; CHECK-NEXT: [[TMP:%.*]] = alloca { <2 x ptr>, <2 x ptr> }, align 16319; CHECK-NEXT: [[A_FCA_0_EXTRACT:%.*]] = extractvalue { <2 x ptr>, <2 x ptr> } [[A:%.*]], 0320; CHECK-NEXT: [[A_FCA_0_GEP:%.*]] = getelementptr inbounds { <2 x ptr>, <2 x ptr> }, ptr [[TMP]], i32 0, i32 0321; CHECK-NEXT: store <2 x ptr> [[A_FCA_0_EXTRACT]], ptr [[A_FCA_0_GEP]], align 16322; CHECK-NEXT: [[A_FCA_1_EXTRACT:%.*]] = extractvalue { <2 x ptr>, <2 x ptr> } [[A]], 1323; CHECK-NEXT: [[TMP_16_A_FCA_1_GEP_SROA_IDX:%.*]] = getelementptr inbounds { <2 x ptr>, <2 x ptr> }, ptr [[TMP]], i32 0, i32 1324; CHECK-NEXT: store <2 x ptr> [[A_FCA_1_EXTRACT]], ptr [[TMP_16_A_FCA_1_GEP_SROA_IDX]], align 16325; CHECK-NEXT: [[TMP_0_CAST:%.*]] = load <vscale x 4 x i64>, ptr [[TMP]], align 32326; CHECK-NEXT: ret <vscale x 4 x i64> [[TMP_0_CAST]]327;328 %tmp = alloca { <2 x ptr>, <2 x ptr> }329 store { <2 x ptr>, <2 x ptr> } %a, ptr %tmp330 %cast = load <vscale x 4 x i64>, ptr %tmp331 ret <vscale x 4 x i64> %cast332}333 334declare void @llvm.memcpy.p0.p0.i64(ptr nocapture, ptr nocapture, i64, i1) nounwind335;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:336; CHECK-MODIFY-CFG: {{.*}}337; CHECK-PRESERVE-CFG: {{.*}}338