777 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt -S < %s -passes=newgvn,dce | FileCheck %s3 4; Analyze Load from clobbering Load.5 6define <vscale x 4 x i32> @load_store_clobber_load(ptr %p) {7; CHECK-LABEL: @load_store_clobber_load(8; CHECK-NEXT: [[LOAD1:%.*]] = load <vscale x 4 x i32>, ptr [[P:%.*]], align 169; CHECK-NEXT: store <vscale x 4 x i32> zeroinitializer, ptr undef, align 1610; CHECK-NEXT: [[ADD:%.*]] = add <vscale x 4 x i32> [[LOAD1]], [[LOAD1]]11; CHECK-NEXT: ret <vscale x 4 x i32> [[ADD]]12;13 %load1 = load <vscale x 4 x i32>, ptr %p14 store <vscale x 4 x i32> zeroinitializer, ptr undef15 %load2 = load <vscale x 4 x i32>, ptr %p ; <- load to be eliminated16 %add = add <vscale x 4 x i32> %load1, %load217 ret <vscale x 4 x i32> %add18}19 20define <vscale x 4 x i32> @load_store_clobber_load_mayalias(ptr %p, ptr %p2) {21; CHECK-LABEL: @load_store_clobber_load_mayalias(22; CHECK-NEXT: [[LOAD1:%.*]] = load <vscale x 4 x i32>, ptr [[P:%.*]], align 1623; CHECK-NEXT: store <vscale x 4 x i32> zeroinitializer, ptr [[P2:%.*]], align 1624; CHECK-NEXT: [[LOAD2:%.*]] = load <vscale x 4 x i32>, ptr [[P]], align 1625; CHECK-NEXT: [[SUB:%.*]] = sub <vscale x 4 x i32> [[LOAD1]], [[LOAD2]]26; CHECK-NEXT: ret <vscale x 4 x i32> [[SUB]]27;28 %load1 = load <vscale x 4 x i32>, ptr %p29 store <vscale x 4 x i32> zeroinitializer, ptr %p230 %load2 = load <vscale x 4 x i32>, ptr %p31 %sub = sub <vscale x 4 x i32> %load1, %load232 ret <vscale x 4 x i32> %sub33}34 35define <vscale x 4 x i32> @load_store_clobber_load_noalias(ptr noalias %p, ptr noalias %p2) {36; CHECK-LABEL: @load_store_clobber_load_noalias(37; CHECK-NEXT: [[LOAD1:%.*]] = load <vscale x 4 x i32>, ptr [[P:%.*]], align 1638; CHECK-NEXT: store <vscale x 4 x i32> zeroinitializer, ptr [[P2:%.*]], align 1639; CHECK-NEXT: [[ADD:%.*]] = add <vscale x 4 x i32> [[LOAD1]], [[LOAD1]]40; CHECK-NEXT: ret <vscale x 4 x i32> [[ADD]]41;42 %load1 = load <vscale x 4 x i32>, ptr %p43 store <vscale x 4 x i32> zeroinitializer, ptr %p244 %load2 = load <vscale x 4 x i32>, ptr %p ; <- load to be eliminated45 %add = add <vscale x 4 x i32> %load1, %load246 ret <vscale x 4 x i32> %add47}48 49; BasicAA return MayAlias for %gep1,%gep2, could improve as MustAlias.50define i32 @load_clobber_load_gep1(ptr %p) {51; CHECK-LABEL: @load_clobber_load_gep1(52; CHECK-NEXT: [[GEP1:%.*]] = getelementptr <vscale x 4 x i32>, ptr [[P:%.*]], i64 0, i64 153; CHECK-NEXT: [[LOAD1:%.*]] = load i32, ptr [[GEP1]], align 454; CHECK-NEXT: [[GEP2:%.*]] = getelementptr i32, ptr [[P]], i64 155; CHECK-NEXT: [[LOAD2:%.*]] = load i32, ptr [[GEP2]], align 456; CHECK-NEXT: [[ADD:%.*]] = add i32 [[LOAD1]], [[LOAD2]]57; CHECK-NEXT: ret i32 [[ADD]]58;59 %gep1 = getelementptr <vscale x 4 x i32>, ptr %p, i64 0, i64 160 %load1 = load i32, ptr %gep161 %gep2 = getelementptr i32, ptr %p, i64 162 %load2 = load i32, ptr %gep2 ; <- load could be eliminated63 %add = add i32 %load1, %load264 ret i32 %add65}66 67define i32 @load_clobber_load_gep2(ptr %p) {68; CHECK-LABEL: @load_clobber_load_gep2(69; CHECK-NEXT: [[GEP1:%.*]] = getelementptr <vscale x 4 x i32>, ptr [[P:%.*]], i64 1, i64 070; CHECK-NEXT: [[LOAD1:%.*]] = load i32, ptr [[GEP1]], align 471; CHECK-NEXT: [[GEP2:%.*]] = getelementptr i32, ptr [[P]], i64 472; CHECK-NEXT: [[LOAD2:%.*]] = load i32, ptr [[GEP2]], align 473; CHECK-NEXT: [[ADD:%.*]] = add i32 [[LOAD1]], [[LOAD2]]74; CHECK-NEXT: ret i32 [[ADD]]75;76 %gep1 = getelementptr <vscale x 4 x i32>, ptr %p, i64 1, i64 077 %load1 = load i32, ptr %gep178 %gep2 = getelementptr i32, ptr %p, i64 479 %load2 = load i32, ptr %gep2 ; <- can not determine at compile-time if %load1 and %load2 are same addr80 %add = add i32 %load1, %load281 ret i32 %add82}83 84; TODO: BasicAA return MayAlias for %gep1,%gep2, could improve as MustAlias.85define i32 @load_clobber_load_gep3(ptr %p) {86; CHECK-LABEL: @load_clobber_load_gep3(87; CHECK-NEXT: [[GEP1:%.*]] = getelementptr <vscale x 4 x i32>, ptr [[P:%.*]], i64 1, i64 088; CHECK-NEXT: [[LOAD1:%.*]] = load i32, ptr [[GEP1]], align 489; CHECK-NEXT: [[GEP2:%.*]] = getelementptr <vscale x 4 x float>, ptr [[P]], i64 1, i64 090; CHECK-NEXT: [[LOAD2:%.*]] = load float, ptr [[GEP2]], align 491; CHECK-NEXT: [[CAST:%.*]] = bitcast float [[LOAD2]] to i3292; CHECK-NEXT: [[ADD:%.*]] = add i32 [[LOAD1]], [[CAST]]93; CHECK-NEXT: ret i32 [[ADD]]94;95 %gep1 = getelementptr <vscale x 4 x i32>, ptr %p, i64 1, i64 096 %load1 = load i32, ptr %gep197 %gep2 = getelementptr <vscale x 4 x float>, ptr %p, i64 1, i64 098 %load2 = load float, ptr %gep2 ; <- load could be eliminated99 %cast = bitcast float %load2 to i32100 %add = add i32 %load1, %cast101 ret i32 %add102}103 104define <vscale x 4 x i32> @load_clobber_load_fence(ptr %p) {105; CHECK-LABEL: @load_clobber_load_fence(106; CHECK-NEXT: [[LOAD1:%.*]] = load <vscale x 4 x i32>, ptr [[P:%.*]], align 16107; CHECK-NEXT: call void asm "", "~{memory}"()108; CHECK-NEXT: [[LOAD2:%.*]] = load <vscale x 4 x i32>, ptr [[P]], align 16109; CHECK-NEXT: [[SUB:%.*]] = sub <vscale x 4 x i32> [[LOAD1]], [[LOAD2]]110; CHECK-NEXT: ret <vscale x 4 x i32> [[SUB]]111;112 %load1 = load <vscale x 4 x i32>, ptr %p113 call void asm "", "~{memory}"()114 %load2 = load <vscale x 4 x i32>, ptr %p115 %sub = sub <vscale x 4 x i32> %load1, %load2116 ret <vscale x 4 x i32> %sub117}118 119define <vscale x 4 x i32> @load_clobber_load_sideeffect(ptr %p) {120; CHECK-LABEL: @load_clobber_load_sideeffect(121; CHECK-NEXT: [[LOAD1:%.*]] = load <vscale x 4 x i32>, ptr [[P:%.*]], align 16122; CHECK-NEXT: call void asm sideeffect "", ""()123; CHECK-NEXT: [[LOAD2:%.*]] = load <vscale x 4 x i32>, ptr [[P]], align 16124; CHECK-NEXT: [[ADD:%.*]] = add <vscale x 4 x i32> [[LOAD1]], [[LOAD2]]125; CHECK-NEXT: ret <vscale x 4 x i32> [[ADD]]126;127 %load1 = load <vscale x 4 x i32>, ptr %p128 call void asm sideeffect "", ""()129 %load2 = load <vscale x 4 x i32>, ptr %p130 %add = add <vscale x 4 x i32> %load1, %load2131 ret <vscale x 4 x i32> %add132}133 134; Analyze Load from clobbering Store.135 136define <vscale x 4 x i32> @store_forward_to_load(ptr %p) {137; CHECK-LABEL: @store_forward_to_load(138; CHECK-NEXT: store <vscale x 4 x i32> zeroinitializer, ptr [[P:%.*]], align 16139; CHECK-NEXT: ret <vscale x 4 x i32> zeroinitializer140;141 store <vscale x 4 x i32> zeroinitializer, ptr %p142 %load = load <vscale x 4 x i32>, ptr %p143 ret <vscale x 4 x i32> %load144}145 146define <vscale x 4 x i32> @store_forward_to_load_sideeffect(ptr %p) {147; CHECK-LABEL: @store_forward_to_load_sideeffect(148; CHECK-NEXT: store <vscale x 4 x i32> zeroinitializer, ptr [[P:%.*]], align 16149; CHECK-NEXT: call void asm sideeffect "", ""()150; CHECK-NEXT: [[LOAD:%.*]] = load <vscale x 4 x i32>, ptr [[P]], align 16151; CHECK-NEXT: ret <vscale x 4 x i32> [[LOAD]]152;153 store <vscale x 4 x i32> zeroinitializer, ptr %p154 call void asm sideeffect "", ""()155 %load = load <vscale x 4 x i32>, ptr %p156 ret <vscale x 4 x i32> %load157}158 159define i32 @store_clobber_load() {160; CHECK-LABEL: @store_clobber_load(161; CHECK-NEXT: [[ALLOC:%.*]] = alloca <vscale x 4 x i32>, align 16162; CHECK-NEXT: store <vscale x 4 x i32> undef, ptr [[ALLOC]], align 16163; CHECK-NEXT: [[PTR:%.*]] = getelementptr <vscale x 4 x i32>, ptr [[ALLOC]], i32 0, i32 1164; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[PTR]], align 4165; CHECK-NEXT: ret i32 [[LOAD]]166;167 %alloc = alloca <vscale x 4 x i32>168 store <vscale x 4 x i32> undef, ptr %alloc169 %ptr = getelementptr <vscale x 4 x i32>, ptr %alloc, i32 0, i32 1170 %load = load i32, ptr %ptr171 ret i32 %load172}173 174; Analyze Load from clobbering MemInst.175 176declare void @llvm.memset.p0.i64(ptr nocapture, i8, i64, i1)177 178define i32 @memset_clobber_load(ptr %p) {179; CHECK-LABEL: @memset_clobber_load(180; CHECK-NEXT: tail call void @llvm.memset.p0.i64(ptr [[P:%.*]], i8 1, i64 200, i1 false)181; CHECK-NEXT: ret i32 16843009182;183 tail call void @llvm.memset.p0.i64(ptr %p, i8 1, i64 200, i1 false)184 %gep = getelementptr <vscale x 4 x i32>, ptr %p, i64 0, i64 5185 %load = load i32, ptr %gep186 ret i32 %load187}188 189define i32 @memset_clobber_load_vscaled_base(ptr %p) {190; CHECK-LABEL: @memset_clobber_load_vscaled_base(191; CHECK-NEXT: tail call void @llvm.memset.p0.i64(ptr [[P:%.*]], i8 1, i64 200, i1 false)192; CHECK-NEXT: [[GEP:%.*]] = getelementptr <vscale x 4 x i32>, ptr [[P]], i64 1, i64 1193; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[GEP]], align 4194; CHECK-NEXT: ret i32 [[LOAD]]195;196 tail call void @llvm.memset.p0.i64(ptr %p, i8 1, i64 200, i1 false)197 %gep = getelementptr <vscale x 4 x i32>, ptr %p, i64 1, i64 1198 %load = load i32, ptr %gep199 ret i32 %load200}201 202define i32 @memset_clobber_load_nonconst_index(ptr %p, i64 %idx1, i64 %idx2) {203; CHECK-LABEL: @memset_clobber_load_nonconst_index(204; CHECK-NEXT: tail call void @llvm.memset.p0.i64(ptr [[P:%.*]], i8 1, i64 200, i1 false)205; CHECK-NEXT: [[GEP:%.*]] = getelementptr <vscale x 4 x i32>, ptr [[P]], i64 [[IDX1:%.*]], i64 [[IDX2:%.*]]206; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[GEP]], align 4207; CHECK-NEXT: ret i32 [[LOAD]]208;209 tail call void @llvm.memset.p0.i64(ptr %p, i8 1, i64 200, i1 false)210 %gep = getelementptr <vscale x 4 x i32>, ptr %p, i64 %idx1, i64 %idx2211 %load = load i32, ptr %gep212 ret i32 %load213}214 215 216; Load elimination across BBs217 218define ptr @load_from_alloc_replaced_with_undef() {219; CHECK-LABEL: @load_from_alloc_replaced_with_undef(220; CHECK-NEXT: entry:221; CHECK-NEXT: [[A:%.*]] = alloca <vscale x 4 x i32>, align 16222; CHECK-NEXT: [[GEP:%.*]] = getelementptr <vscale x 4 x i32>, ptr [[A]], i64 0, i64 1223; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[GEP]], align 4224; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[LOAD]], 0225; CHECK-NEXT: br i1 [[TOBOOL]], label [[IF_END:%.*]], label [[IF_THEN:%.*]]226; CHECK: if.then:227; CHECK-NEXT: store <vscale x 4 x i32> zeroinitializer, ptr [[A]], align 16228; CHECK-NEXT: br label [[IF_END]]229; CHECK: if.end:230; CHECK-NEXT: ret ptr [[A]]231;232entry:233 %a = alloca <vscale x 4 x i32>234 %gep = getelementptr <vscale x 4 x i32>, ptr %a, i64 0, i64 1235 %load = load i32, ptr %gep ; <- load to be eliminated236 %tobool = icmp eq i32 %load, 0 ; <- icmp to be eliminated237 br i1 %tobool, label %if.end, label %if.then238 239if.then:240 store <vscale x 4 x i32> zeroinitializer, ptr %a241 br label %if.end242 243if.end:244 ret ptr %a245}246 247define i32 @redundant_load_elimination_1(ptr %p) {248; CHECK-LABEL: @redundant_load_elimination_1(249; CHECK-NEXT: entry:250; CHECK-NEXT: [[GEP:%.*]] = getelementptr <vscale x 4 x i32>, ptr [[P:%.*]], i64 1, i64 1251; CHECK-NEXT: [[LOAD1:%.*]] = load i32, ptr [[GEP]], align 4252; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[LOAD1]], 0253; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]254; CHECK: if.then:255; CHECK-NEXT: br label [[IF_END]]256; CHECK: if.end:257; CHECK-NEXT: ret i32 [[LOAD1]]258;259entry:260 %gep = getelementptr <vscale x 4 x i32>, ptr %p, i64 1, i64 1261 %load1 = load i32, ptr %gep262 %cmp = icmp eq i32 %load1, 0263 br i1 %cmp, label %if.then, label %if.end264 265if.then:266 %load2 = load i32, ptr %gep ; <- load to be eliminated267 %add = add i32 %load1, %load2268 br label %if.end269 270if.end:271 %result = phi i32 [ %add, %if.then ], [ %load1, %entry ]272 ret i32 %result273}274 275; TODO: BasicAA return MayAlias for %gep1,%gep2, could improve as NoAlias.276define void @redundant_load_elimination_2(i1 %c, ptr %p, ptr %q) {277; CHECK-LABEL: @redundant_load_elimination_2(278; CHECK-NEXT: entry:279; CHECK-NEXT: [[GEP1:%.*]] = getelementptr <vscale x 4 x i32>, ptr [[P:%.*]], i64 1, i64 1280; CHECK-NEXT: store i32 0, ptr [[GEP1]], align 4281; CHECK-NEXT: [[GEP2:%.*]] = getelementptr <vscale x 4 x i32>, ptr [[P]], i64 1, i64 0282; CHECK-NEXT: store i32 1, ptr [[GEP2]], align 4283; CHECK-NEXT: br i1 [[C:%.*]], label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]]284; CHECK: if.then:285; CHECK-NEXT: [[T:%.*]] = load i32, ptr [[GEP1]], align 4286; CHECK-NEXT: store i32 [[T]], ptr [[Q:%.*]], align 4287; CHECK-NEXT: ret void288; CHECK: if.else:289; CHECK-NEXT: ret void290;291entry:292 %gep1 = getelementptr <vscale x 4 x i32>, ptr %p, i64 1, i64 1293 store i32 0, ptr %gep1294 %gep2 = getelementptr <vscale x 4 x i32>, ptr %p, i64 1, i64 0295 store i32 1, ptr %gep2296 br i1 %c, label %if.else, label %if.then297 298if.then:299 %t = load i32, ptr %gep1 ; <- load could be eliminated300 store i32 %t, ptr %q301 ret void302 303if.else:304 ret void305}306 307define void @redundant_load_elimination_zero_index(i1 %c, ptr %p, ptr %q) {308; CHECK-LABEL: @redundant_load_elimination_zero_index(309; CHECK-NEXT: entry:310; CHECK-NEXT: [[GEP1:%.*]] = getelementptr <vscale x 4 x i32>, ptr [[P:%.*]], i64 0, i64 1311; CHECK-NEXT: store i32 0, ptr [[GEP1]], align 4312; CHECK-NEXT: store i32 1, ptr [[P]], align 4313; CHECK-NEXT: br i1 [[C:%.*]], label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]]314; CHECK: if.then:315; CHECK-NEXT: store i32 0, ptr [[Q:%.*]], align 4316; CHECK-NEXT: ret void317; CHECK: if.else:318; CHECK-NEXT: ret void319;320entry:321 %gep1 = getelementptr <vscale x 4 x i32>, ptr %p, i64 0, i64 1322 store i32 0, ptr %gep1323 store i32 1, ptr %p324 br i1 %c, label %if.else, label %if.then325 326if.then:327 %t = load i32, ptr %gep1 ; <- load could be eliminated328 store i32 %t, ptr %q329 ret void330 331if.else:332 ret void333}334 335define void @redundant_load_elimination_zero_index_1(i1 %c, ptr %p, ptr %q, i64 %i) {336; CHECK-LABEL: @redundant_load_elimination_zero_index_1(337; CHECK-NEXT: entry:338; CHECK-NEXT: [[J:%.*]] = add i64 [[I:%.*]], 1339; CHECK-NEXT: [[GEP1:%.*]] = getelementptr <vscale x 4 x i32>, ptr [[P:%.*]], i64 0, i64 [[J]]340; CHECK-NEXT: store i32 0, ptr [[GEP1]], align 4341; CHECK-NEXT: [[GEP2:%.*]] = getelementptr <vscale x 4 x i32>, ptr [[P]], i64 0, i64 [[I]]342; CHECK-NEXT: store i32 1, ptr [[GEP2]], align 4343; CHECK-NEXT: br i1 [[C:%.*]], label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]]344; CHECK: if.then:345; CHECK-NEXT: store i32 0, ptr [[Q:%.*]], align 4346; CHECK-NEXT: ret void347; CHECK: if.else:348; CHECK-NEXT: ret void349;350entry:351 %j = add i64 %i, 1352 %gep1 = getelementptr <vscale x 4 x i32>, ptr %p, i64 0, i64 %j353 store i32 0, ptr %gep1354 %gep2 = getelementptr <vscale x 4 x i32>, ptr %p, i64 0, i64 %i355 store i32 1, ptr %gep2356 br i1 %c, label %if.else, label %if.then357 358if.then:359 %t = load i32, ptr %gep1 ; <- load could be eliminated360 store i32 %t, ptr %q361 ret void362 363if.else:364 ret void365}366; TODO: load in if.then could have been eliminated367define void @missing_load_elimination(i1 %c, ptr %p, ptr %q, <vscale x 4 x i32> %v) {368; CHECK-LABEL: @missing_load_elimination(369; CHECK-NEXT: entry:370; CHECK-NEXT: store <vscale x 4 x i32> zeroinitializer, ptr [[P:%.*]], align 16371; CHECK-NEXT: [[P1:%.*]] = getelementptr <vscale x 4 x i32>, ptr [[P]], i64 1372; CHECK-NEXT: store <vscale x 4 x i32> [[V:%.*]], ptr [[P1]], align 16373; CHECK-NEXT: br i1 [[C:%.*]], label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]]374; CHECK: if.then:375; CHECK-NEXT: [[T:%.*]] = load <vscale x 4 x i32>, ptr [[P]], align 16376; CHECK-NEXT: store <vscale x 4 x i32> [[T]], ptr [[Q:%.*]], align 16377; CHECK-NEXT: ret void378; CHECK: if.else:379; CHECK-NEXT: ret void380;381entry:382 store <vscale x 4 x i32> zeroinitializer, ptr %p383 %p1 = getelementptr <vscale x 4 x i32>, ptr %p, i64 1384 store <vscale x 4 x i32> %v, ptr %p1385 br i1 %c, label %if.else, label %if.then386 387if.then:388 %t = load <vscale x 4 x i32>, ptr %p ; load could be eliminated389 store <vscale x 4 x i32> %t, ptr %q390 ret void391 392if.else:393 ret void394}395 396; Different sizes / types397 398define <vscale x 16 x i8> @load_v16i8_store_v4i32_forward_load(ptr %p, <vscale x 4 x i32> %x) {399; CHECK-LABEL: @load_v16i8_store_v4i32_forward_load(400; CHECK-NEXT: store <vscale x 4 x i32> [[X:%.*]], ptr [[P:%.*]], align 16401; CHECK-NEXT: [[LOAD:%.*]] = load <vscale x 16 x i8>, ptr [[P]], align 16402; CHECK-NEXT: ret <vscale x 16 x i8> [[LOAD]]403;404 store <vscale x 4 x i32> %x, ptr %p405 %load = load <vscale x 16 x i8>, ptr %p406 ret <vscale x 16 x i8> %load407}408 409define <vscale x 4 x float> @load_v4f32_store_v4i32_forward_load(ptr %p, <vscale x 4 x i32> %x) {410; CHECK-LABEL: @load_v4f32_store_v4i32_forward_load(411; CHECK-NEXT: store <vscale x 4 x i32> [[X:%.*]], ptr [[P:%.*]], align 16412; CHECK-NEXT: [[LOAD:%.*]] = load <vscale x 4 x float>, ptr [[P]], align 16413; CHECK-NEXT: ret <vscale x 4 x float> [[LOAD]]414;415 store <vscale x 4 x i32> %x, ptr %p416 %load = load <vscale x 4 x float>, ptr %p417 ret <vscale x 4 x float> %load418}419 420define <vscale x 4 x float> @load_v4f32_store_v16i8_forward_load(ptr %p, <vscale x 16 x i8> %x) {421; CHECK-LABEL: @load_v4f32_store_v16i8_forward_load(422; CHECK-NEXT: store <vscale x 16 x i8> [[X:%.*]], ptr [[P:%.*]], align 16423; CHECK-NEXT: [[LOAD:%.*]] = load <vscale x 4 x float>, ptr [[P]], align 16424; CHECK-NEXT: ret <vscale x 4 x float> [[LOAD]]425;426 store <vscale x 16 x i8> %x, ptr %p427 %load = load <vscale x 4 x float>, ptr %p428 ret <vscale x 4 x float> %load429}430 431define <vscale x 4 x i32> @load_v4i32_store_v4f32_forward_load(ptr %p, <vscale x 4 x float> %x) {432; CHECK-LABEL: @load_v4i32_store_v4f32_forward_load(433; CHECK-NEXT: store <vscale x 4 x float> [[X:%.*]], ptr [[P:%.*]], align 16434; CHECK-NEXT: [[LOAD:%.*]] = load <vscale x 4 x i32>, ptr [[P]], align 16435; CHECK-NEXT: ret <vscale x 4 x i32> [[LOAD]]436;437 store <vscale x 4 x float> %x, ptr %p438 %load = load <vscale x 4 x i32>, ptr %p439 ret <vscale x 4 x i32> %load440}441 442define <vscale x 4 x i32> @load_v4i32_store_v4i64_forward_load(ptr %p, <vscale x 4 x i64> %x) {443; CHECK-LABEL: @load_v4i32_store_v4i64_forward_load(444; CHECK-NEXT: store <vscale x 4 x i64> [[X:%.*]], ptr [[P:%.*]], align 32445; CHECK-NEXT: [[LOAD:%.*]] = load <vscale x 4 x i32>, ptr [[P]], align 16446; CHECK-NEXT: ret <vscale x 4 x i32> [[LOAD]]447;448 store <vscale x 4 x i64> %x, ptr %p449 %load = load <vscale x 4 x i32>, ptr %p450 ret <vscale x 4 x i32> %load451}452 453define <vscale x 4 x i64> @load_v4i64_store_v4i32_forward_load(ptr %p, <vscale x 4 x i32> %x) {454; CHECK-LABEL: @load_v4i64_store_v4i32_forward_load(455; CHECK-NEXT: store <vscale x 4 x i32> [[X:%.*]], ptr [[P:%.*]], align 16456; CHECK-NEXT: [[LOAD:%.*]] = load <vscale x 4 x i64>, ptr [[P]], align 32457; CHECK-NEXT: ret <vscale x 4 x i64> [[LOAD]]458;459 store <vscale x 4 x i32> %x, ptr %p460 %load = load <vscale x 4 x i64>, ptr %p461 ret <vscale x 4 x i64> %load462}463 464define <vscale x 2 x i32> @load_v2i32_store_v4i32_forward_load(ptr %p, <vscale x 4 x i32> %x) {465; CHECK-LABEL: @load_v2i32_store_v4i32_forward_load(466; CHECK-NEXT: store <vscale x 4 x i32> [[X:%.*]], ptr [[P:%.*]], align 16467; CHECK-NEXT: [[LOAD:%.*]] = load <vscale x 2 x i32>, ptr [[P]], align 8468; CHECK-NEXT: ret <vscale x 2 x i32> [[LOAD]]469;470 store <vscale x 4 x i32> %x, ptr %p471 %load = load <vscale x 2 x i32>, ptr %p472 ret <vscale x 2 x i32> %load473}474 475define <vscale x 2 x i32> @load_v2i32_store_v4i32_forward_load_offsets(ptr %p, <vscale x 4 x i32> %x) {476; CHECK-LABEL: @load_v2i32_store_v4i32_forward_load_offsets(477; CHECK-NEXT: store <vscale x 4 x i32> [[X:%.*]], ptr [[P:%.*]], align 16478; CHECK-NEXT: [[Q:%.*]] = getelementptr <vscale x 2 x i32>, ptr [[P]], i64 1479; CHECK-NEXT: [[LOAD:%.*]] = load <vscale x 2 x i32>, ptr [[Q]], align 8480; CHECK-NEXT: ret <vscale x 2 x i32> [[LOAD]]481;482 store <vscale x 4 x i32> %x, ptr %p483 %q = getelementptr <vscale x 2 x i32>, ptr %p, i64 1484 %load = load <vscale x 2 x i32>, ptr %q485 ret <vscale x 2 x i32> %load486}487 488define <vscale x 2 x i32> @load_v2i32_store_v4i32_forward_load_offsetc(ptr %p, <vscale x 4 x i32> %x) {489; CHECK-LABEL: @load_v2i32_store_v4i32_forward_load_offsetc(490; CHECK-NEXT: store <vscale x 4 x i32> [[X:%.*]], ptr [[P:%.*]], align 16491; CHECK-NEXT: [[Q:%.*]] = getelementptr <2 x i32>, ptr [[P]], i64 1492; CHECK-NEXT: [[LOAD:%.*]] = load <vscale x 2 x i32>, ptr [[Q]], align 8493; CHECK-NEXT: ret <vscale x 2 x i32> [[LOAD]]494;495 store <vscale x 4 x i32> %x, ptr %p496 %q = getelementptr <2 x i32>, ptr %p, i64 1497 %load = load <vscale x 2 x i32>, ptr %q498 ret <vscale x 2 x i32> %load499}500 501define <vscale x 2 x ptr> @load_v2p0_store_v4i32_forward_load(ptr %p, <vscale x 4 x i32> %x) {502; CHECK-LABEL: @load_v2p0_store_v4i32_forward_load(503; CHECK-NEXT: store <vscale x 4 x i32> [[X:%.*]], ptr [[P:%.*]], align 16504; CHECK-NEXT: [[LOAD:%.*]] = load <vscale x 2 x ptr>, ptr [[P]], align 16505; CHECK-NEXT: ret <vscale x 2 x ptr> [[LOAD]]506;507 store <vscale x 4 x i32> %x, ptr %p508 %load = load <vscale x 2 x ptr>, ptr %p509 ret <vscale x 2 x ptr> %load510}511 512define <vscale x 2 x i64> @load_v2i64_store_v2p0_forward_load(ptr %p, <vscale x 2 x ptr> %x) {513; CHECK-LABEL: @load_v2i64_store_v2p0_forward_load(514; CHECK-NEXT: store <vscale x 2 x ptr> [[X:%.*]], ptr [[P:%.*]], align 16515; CHECK-NEXT: [[LOAD:%.*]] = load <vscale x 2 x i64>, ptr [[P]], align 16516; CHECK-NEXT: ret <vscale x 2 x i64> [[LOAD]]517;518 store <vscale x 2 x ptr> %x, ptr %p519 %load = load <vscale x 2 x i64>, ptr %p520 ret <vscale x 2 x i64> %load521}522 523define <vscale x 16 x i8> @load_nxv16i8_store_v4i32_forward_load(ptr %p, <4 x i32> %x) {524; CHECK-LABEL: @load_nxv16i8_store_v4i32_forward_load(525; CHECK-NEXT: store <4 x i32> [[X:%.*]], ptr [[P:%.*]], align 16526; CHECK-NEXT: [[LOAD:%.*]] = load <vscale x 16 x i8>, ptr [[P]], align 16527; CHECK-NEXT: ret <vscale x 16 x i8> [[LOAD]]528;529 store <4 x i32> %x, ptr %p530 %load = load <vscale x 16 x i8>, ptr %p531 ret <vscale x 16 x i8> %load532}533 534define <16 x i8> @load_v16i8_store_nxv4i32_forward_load(ptr %p, <vscale x 4 x i32> %x) {535; CHECK-LABEL: @load_v16i8_store_nxv4i32_forward_load(536; CHECK-NEXT: store <vscale x 4 x i32> [[X:%.*]], ptr [[P:%.*]], align 16537; CHECK-NEXT: [[LOAD:%.*]] = load <16 x i8>, ptr [[P]], align 16538; CHECK-NEXT: ret <16 x i8> [[LOAD]]539;540 store <vscale x 4 x i32> %x, ptr %p541 %load = load <16 x i8>, ptr %p542 ret <16 x i8> %load543}544 545define <vscale x 16 x i8> @load_v16i8_store_v4i32_forward_constant(ptr %p) {546; CHECK-LABEL: @load_v16i8_store_v4i32_forward_constant(547; CHECK-NEXT: store <vscale x 4 x i32> splat (i32 4), ptr [[P:%.*]], align 16548; CHECK-NEXT: [[LOAD:%.*]] = load <vscale x 16 x i8>, ptr [[P]], align 16549; CHECK-NEXT: ret <vscale x 16 x i8> [[LOAD]]550;551 store <vscale x 4 x i32> splat (i32 4), ptr %p552 %load = load <vscale x 16 x i8>, ptr %p553 ret <vscale x 16 x i8> %load554}555 556define <vscale x 16 x i8> @load_v16i8_struct_store_v4i32_forward_load(ptr %p, { <vscale x 4 x i32> } %x) {557; CHECK-LABEL: @load_v16i8_struct_store_v4i32_forward_load(558; CHECK-NEXT: store { <vscale x 4 x i32> } [[X:%.*]], ptr [[P:%.*]], align 16559; CHECK-NEXT: [[LOAD:%.*]] = load <vscale x 16 x i8>, ptr [[P]], align 16560; CHECK-NEXT: ret <vscale x 16 x i8> [[LOAD]]561;562 store { <vscale x 4 x i32> } %x, ptr %p563 %load = load <vscale x 16 x i8>, ptr %p564 ret <vscale x 16 x i8> %load565}566 567define {<vscale x 16 x i8>} @load_v16i8_store_v4i32_struct_forward_load(ptr %p, <vscale x 4 x i32> %x) {568; CHECK-LABEL: @load_v16i8_store_v4i32_struct_forward_load(569; CHECK-NEXT: store <vscale x 4 x i32> [[X:%.*]], ptr [[P:%.*]], align 16570; CHECK-NEXT: [[LOAD:%.*]] = load { <vscale x 16 x i8> }, ptr [[P]], align 16571; CHECK-NEXT: ret { <vscale x 16 x i8> } [[LOAD]]572;573 store <vscale x 4 x i32> %x, ptr %p574 %load = load { <vscale x 16 x i8> }, ptr %p575 ret { <vscale x 16 x i8> } %load576}577 578define { <vscale x 16 x i8>, <vscale x 16 x i8>, <vscale x 16 x i8>, <vscale x 16 x i8> } @bigexample({ <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32> } %a) vscale_range(1,16) {579; CHECK-LABEL: @bigexample(580; CHECK-NEXT: entry:581; CHECK-NEXT: [[REF_TMP:%.*]] = alloca { <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32> }, align 16582; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr nonnull [[REF_TMP]])583; CHECK-NEXT: [[A_ELT:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32> } [[A:%.*]], 0584; CHECK-NEXT: store <vscale x 4 x i32> [[A_ELT]], ptr [[REF_TMP]], align 16585; CHECK-NEXT: [[TMP0:%.*]] = call i64 @llvm.vscale.i64()586; CHECK-NEXT: [[TMP1:%.*]] = shl i64 [[TMP0]], 4587; CHECK-NEXT: [[REF_TMP_REPACK1:%.*]] = getelementptr inbounds i8, ptr [[REF_TMP]], i64 [[TMP1]]588; CHECK-NEXT: [[A_ELT2:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32> } [[A]], 1589; CHECK-NEXT: store <vscale x 4 x i32> [[A_ELT2]], ptr [[REF_TMP_REPACK1]], align 16590; CHECK-NEXT: [[TMP3:%.*]] = shl i64 [[TMP0]], 5591; CHECK-NEXT: [[REF_TMP_REPACK3:%.*]] = getelementptr inbounds i8, ptr [[REF_TMP]], i64 [[TMP3]]592; CHECK-NEXT: [[A_ELT4:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32> } [[A]], 2593; CHECK-NEXT: store <vscale x 4 x i32> [[A_ELT4]], ptr [[REF_TMP_REPACK3]], align 16594; CHECK-NEXT: [[TMP5:%.*]] = mul i64 [[TMP0]], 48595; CHECK-NEXT: [[REF_TMP_REPACK5:%.*]] = getelementptr inbounds i8, ptr [[REF_TMP]], i64 [[TMP5]]596; CHECK-NEXT: [[A_ELT6:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32> } [[A]], 3597; CHECK-NEXT: store <vscale x 4 x i32> [[A_ELT6]], ptr [[REF_TMP_REPACK5]], align 16598; CHECK-NEXT: [[DOTUNPACK:%.*]] = load <vscale x 16 x i8>, ptr [[REF_TMP]], align 16599; CHECK-NEXT: [[TMP6:%.*]] = insertvalue { <vscale x 16 x i8>, <vscale x 16 x i8>, <vscale x 16 x i8>, <vscale x 16 x i8> } poison, <vscale x 16 x i8> [[DOTUNPACK]], 0600; CHECK-NEXT: [[DOTUNPACK8:%.*]] = load <vscale x 16 x i8>, ptr [[REF_TMP_REPACK1]], align 16601; CHECK-NEXT: [[TMP9:%.*]] = insertvalue { <vscale x 16 x i8>, <vscale x 16 x i8>, <vscale x 16 x i8>, <vscale x 16 x i8> } [[TMP6]], <vscale x 16 x i8> [[DOTUNPACK8]], 1602; CHECK-NEXT: [[DOTUNPACK10:%.*]] = load <vscale x 16 x i8>, ptr [[REF_TMP_REPACK3]], align 16603; CHECK-NEXT: [[TMP12:%.*]] = insertvalue { <vscale x 16 x i8>, <vscale x 16 x i8>, <vscale x 16 x i8>, <vscale x 16 x i8> } [[TMP9]], <vscale x 16 x i8> [[DOTUNPACK10]], 2604; CHECK-NEXT: [[DOTUNPACK12:%.*]] = load <vscale x 16 x i8>, ptr [[REF_TMP_REPACK5]], align 16605; CHECK-NEXT: [[TMP15:%.*]] = insertvalue { <vscale x 16 x i8>, <vscale x 16 x i8>, <vscale x 16 x i8>, <vscale x 16 x i8> } [[TMP12]], <vscale x 16 x i8> [[DOTUNPACK12]], 3606; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr nonnull [[REF_TMP]])607; CHECK-NEXT: ret { <vscale x 16 x i8>, <vscale x 16 x i8>, <vscale x 16 x i8>, <vscale x 16 x i8> } [[TMP15]]608;609entry:610 %ref.tmp = alloca { <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32> }, align 16611 call void @llvm.lifetime.start.p0(ptr nonnull %ref.tmp)612 %a.elt = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32> } %a, 0613 store <vscale x 4 x i32> %a.elt, ptr %ref.tmp, align 16614 %0 = call i64 @llvm.vscale.i64()615 %1 = shl i64 %0, 4616 %ref.tmp.repack1 = getelementptr inbounds i8, ptr %ref.tmp, i64 %1617 %a.elt2 = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32> } %a, 1618 store <vscale x 4 x i32> %a.elt2, ptr %ref.tmp.repack1, align 16619 %2 = call i64 @llvm.vscale.i64()620 %3 = shl i64 %2, 5621 %ref.tmp.repack3 = getelementptr inbounds i8, ptr %ref.tmp, i64 %3622 %a.elt4 = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32> } %a, 2623 store <vscale x 4 x i32> %a.elt4, ptr %ref.tmp.repack3, align 16624 %4 = call i64 @llvm.vscale.i64()625 %5 = mul i64 %4, 48626 %ref.tmp.repack5 = getelementptr inbounds i8, ptr %ref.tmp, i64 %5627 %a.elt6 = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32> } %a, 3628 store <vscale x 4 x i32> %a.elt6, ptr %ref.tmp.repack5, align 16629 %.unpack = load <vscale x 16 x i8>, ptr %ref.tmp, align 16630 %6 = insertvalue { <vscale x 16 x i8>, <vscale x 16 x i8>, <vscale x 16 x i8>, <vscale x 16 x i8> } poison, <vscale x 16 x i8> %.unpack, 0631 %7 = call i64 @llvm.vscale.i64()632 %8 = shl i64 %7, 4633 %.elt7 = getelementptr inbounds i8, ptr %ref.tmp, i64 %8634 %.unpack8 = load <vscale x 16 x i8>, ptr %.elt7, align 16635 %9 = insertvalue { <vscale x 16 x i8>, <vscale x 16 x i8>, <vscale x 16 x i8>, <vscale x 16 x i8> } %6, <vscale x 16 x i8> %.unpack8, 1636 %10 = call i64 @llvm.vscale.i64()637 %11 = shl i64 %10, 5638 %.elt9 = getelementptr inbounds i8, ptr %ref.tmp, i64 %11639 %.unpack10 = load <vscale x 16 x i8>, ptr %.elt9, align 16640 %12 = insertvalue { <vscale x 16 x i8>, <vscale x 16 x i8>, <vscale x 16 x i8>, <vscale x 16 x i8> } %9, <vscale x 16 x i8> %.unpack10, 2641 %13 = call i64 @llvm.vscale.i64()642 %14 = mul i64 %13, 48643 %.elt11 = getelementptr inbounds i8, ptr %ref.tmp, i64 %14644 %.unpack12 = load <vscale x 16 x i8>, ptr %.elt11, align 16645 %15 = insertvalue { <vscale x 16 x i8>, <vscale x 16 x i8>, <vscale x 16 x i8>, <vscale x 16 x i8> } %12, <vscale x 16 x i8> %.unpack12, 3646 call void @llvm.lifetime.end.p0(ptr nonnull %ref.tmp)647 ret { <vscale x 16 x i8>, <vscale x 16 x i8>, <vscale x 16 x i8>, <vscale x 16 x i8> } %15648}649 650define <vscale x 4 x float> @scalable_store_to_fixed_load(<vscale x 4 x float> %.coerce) vscale_range(4,4) {651; CHECK-LABEL: @scalable_store_to_fixed_load(652; CHECK-NEXT: entry:653; CHECK-NEXT: [[RETVAL:%.*]] = alloca { <16 x float> }, align 64654; CHECK-NEXT: [[TMP0:%.*]] = fadd <vscale x 4 x float> [[DOTCOERCE:%.*]], [[DOTCOERCE]]655; CHECK-NEXT: store <vscale x 4 x float> [[TMP0]], ptr [[RETVAL]], align 16656; CHECK-NEXT: [[TMP1:%.*]] = load <16 x float>, ptr [[RETVAL]], align 64657; CHECK-NEXT: [[CAST_SCALABLE:%.*]] = tail call <vscale x 4 x float> @llvm.vector.insert.nxv4f32.v16f32(<vscale x 4 x float> poison, <16 x float> [[TMP1]], i64 0)658; CHECK-NEXT: ret <vscale x 4 x float> [[CAST_SCALABLE]]659;660entry:661 %retval = alloca { <16 x float> }662 %0 = fadd <vscale x 4 x float> %.coerce, %.coerce663 store <vscale x 4 x float> %0, ptr %retval664 %1 = load <16 x float>, ptr %retval665 %cast.scalable = tail call <vscale x 4 x float> @llvm.vector.insert.nxv4f32.v16f32(<vscale x 4 x float> poison, <16 x float> %1, i64 0)666 ret <vscale x 4 x float> %cast.scalable667}668 669; Here, only the lower bound for the vscale is known, but this is enough to allow a forward to a load to 16 elements.670define <vscale x 4 x float> @scalable_store_to_fixed_load_only_lower_bound(<vscale x 4 x float> %a) vscale_range(4) {671; CHECK-LABEL: @scalable_store_to_fixed_load_only_lower_bound(672; CHECK-NEXT: entry:673; CHECK-NEXT: [[RETVAL:%.*]] = alloca { <vscale x 4 x float> }, align 16674; CHECK-NEXT: store <vscale x 4 x float> [[A:%.*]], ptr [[RETVAL]], align 16675; CHECK-NEXT: [[TMP0:%.*]] = load <16 x float>, ptr [[RETVAL]], align 64676; CHECK-NEXT: [[CAST_SCALABLE:%.*]] = tail call <vscale x 4 x float> @llvm.vector.insert.nxv4f32.v16f32(<vscale x 4 x float> poison, <16 x float> [[TMP0]], i64 0)677; CHECK-NEXT: ret <vscale x 4 x float> [[CAST_SCALABLE]]678;679entry:680 %retval = alloca { <vscale x 4 x float> }681 store <vscale x 4 x float> %a, ptr %retval682 %1 = load <16 x float>, ptr %retval683 %cast.scalable = tail call <vscale x 4 x float> @llvm.vector.insert.nxv4f32.v16f32(<vscale x 4 x float> poison, <16 x float> %1, i64 0)684 ret <vscale x 4 x float> %cast.scalable685}686 687define <vscale x 4 x float> @scalable_store_to_fixed_load_with_offset(<vscale x 4 x float> %a) vscale_range(4,4) {688; CHECK-LABEL: @scalable_store_to_fixed_load_with_offset(689; CHECK-NEXT: entry:690; CHECK-NEXT: [[PTR:%.*]] = alloca { <32 x float> }, align 128691; CHECK-NEXT: store <vscale x 4 x float> [[A:%.*]], ptr [[PTR]], align 16692; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 8693; CHECK-NEXT: [[TMP0:%.*]] = load <16 x float>, ptr [[GEP]], align 64694; CHECK-NEXT: [[CAST_SCALABLE:%.*]] = tail call <vscale x 4 x float> @llvm.vector.insert.nxv4f32.v16f32(<vscale x 4 x float> poison, <16 x float> [[TMP0]], i64 0)695; CHECK-NEXT: ret <vscale x 4 x float> [[CAST_SCALABLE]]696;697entry:698 %ptr = alloca { <32 x float> }699 store <vscale x 4 x float> %a, ptr %ptr700 %gep = getelementptr inbounds i8, ptr %ptr, i64 8701 %1 = load <16 x float>, ptr %gep702 %cast.scalable = tail call <vscale x 4 x float> @llvm.vector.insert.nxv4f32.v16f32(<vscale x 4 x float> poison, <16 x float> %1, i64 0)703 ret <vscale x 4 x float> %cast.scalable704}705 706define <vscale x 4 x float> @scalable_store_to_fixed_load_unknown_vscale(<vscale x 4 x float> %.coerce) {707; CHECK-LABEL: @scalable_store_to_fixed_load_unknown_vscale(708; CHECK-NEXT: entry:709; CHECK-NEXT: [[RETVAL:%.*]] = alloca { <16 x float> }, align 64710; CHECK-NEXT: [[TMP0:%.*]] = fadd <vscale x 4 x float> [[DOTCOERCE:%.*]], [[DOTCOERCE]]711; CHECK-NEXT: store <vscale x 4 x float> [[TMP0]], ptr [[RETVAL]], align 16712; CHECK-NEXT: [[TMP1:%.*]] = load <16 x float>, ptr [[RETVAL]], align 64713; CHECK-NEXT: [[CAST_SCALABLE:%.*]] = tail call <vscale x 4 x float> @llvm.vector.insert.nxv4f32.v16f32(<vscale x 4 x float> poison, <16 x float> [[TMP1]], i64 0)714; CHECK-NEXT: ret <vscale x 4 x float> [[CAST_SCALABLE]]715;716entry:717 %retval = alloca { <16 x float> }718 %0 = fadd <vscale x 4 x float> %.coerce, %.coerce719 store <vscale x 4 x float> %0, ptr %retval720 %1 = load <16 x float>, ptr %retval721 %cast.scalable = tail call <vscale x 4 x float> @llvm.vector.insert.nxv4f32.v16f32(<vscale x 4 x float> poison, <16 x float> %1, i64 0)722 ret <vscale x 4 x float> %cast.scalable723}724 725define <vscale x 4 x float> @scalable_store_to_fixed_load_size_missmatch(<vscale x 4 x float> %.coerce) vscale_range(4,4) {726; CHECK-LABEL: @scalable_store_to_fixed_load_size_missmatch(727; CHECK-NEXT: entry:728; CHECK-NEXT: [[RETVAL:%.*]] = alloca { <32 x float> }, align 128729; CHECK-NEXT: [[TMP0:%.*]] = fadd <vscale x 4 x float> [[DOTCOERCE:%.*]], [[DOTCOERCE]]730; CHECK-NEXT: store <vscale x 4 x float> [[TMP0]], ptr [[RETVAL]], align 16731; CHECK-NEXT: [[TMP1:%.*]] = load <32 x float>, ptr [[RETVAL]], align 128732; CHECK-NEXT: [[CAST_SCALABLE:%.*]] = tail call <vscale x 4 x float> @llvm.vector.insert.nxv4f32.v32f32(<vscale x 4 x float> poison, <32 x float> [[TMP1]], i64 0)733; CHECK-NEXT: ret <vscale x 4 x float> [[CAST_SCALABLE]]734;735entry:736 %retval = alloca { <32 x float> }737 %0 = fadd <vscale x 4 x float> %.coerce, %.coerce738 store <vscale x 4 x float> %0, ptr %retval739 %1 = load <32 x float>, ptr %retval740 %cast.scalable = tail call <vscale x 4 x float> @llvm.vector.insert.nxv4f32.v32f32(<vscale x 4 x float> poison, <32 x float> %1, i64 0)741 ret <vscale x 4 x float> %cast.scalable742}743 744define <vscale x 4 x i32> @scalable_store_to_fixed_load_different_types(<vscale x 4 x float> %a) vscale_range(4,4) {745; CHECK-LABEL: @scalable_store_to_fixed_load_different_types(746; CHECK-NEXT: entry:747; CHECK-NEXT: [[PTR:%.*]] = alloca { <16 x float> }, align 64748; CHECK-NEXT: store <vscale x 4 x float> [[A:%.*]], ptr [[PTR]], align 16749; CHECK-NEXT: [[TMP0:%.*]] = load <16 x i32>, ptr [[PTR]], align 64750; CHECK-NEXT: [[CAST_SCALABLE:%.*]] = tail call <vscale x 4 x i32> @llvm.vector.insert.nxv4i32.v16i32(<vscale x 4 x i32> poison, <16 x i32> [[TMP0]], i64 0)751; CHECK-NEXT: ret <vscale x 4 x i32> [[CAST_SCALABLE]]752;753entry:754 %ptr = alloca { <16 x float> }755 store <vscale x 4 x float> %a, ptr %ptr756 %1 = load <16 x i32>, ptr %ptr757 %cast.scalable = tail call <vscale x 4 x i32> @llvm.vector.insert.nxv4i32.v16i32(<vscale x 4 x i32> poison, <16 x i32> %1, i64 0)758 ret <vscale x 4 x i32> %cast.scalable759}760 761; This function does not have a fixed vscale, but the loaded vector is still known762; to be smaller or equal in size compared to the stored vector.763define <4 x float> @scalable_store_to_small_fixed_load(<vscale x 4 x float> %a) {764; CHECK-LABEL: @scalable_store_to_small_fixed_load(765; CHECK-NEXT: entry:766; CHECK-NEXT: [[PTR:%.*]] = alloca <vscale x 4 x float>, align 16767; CHECK-NEXT: store <vscale x 4 x float> [[A:%.*]], ptr [[PTR]], align 16768; CHECK-NEXT: [[TMP0:%.*]] = load <4 x float>, ptr [[PTR]], align 16769; CHECK-NEXT: ret <4 x float> [[TMP0]]770;771entry:772 %ptr = alloca <vscale x 4 x float>773 store <vscale x 4 x float> %a, ptr %ptr774 %1 = load <4 x float>, ptr %ptr775 ret <4 x float> %1776}777