393 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt -passes=gvn -S < %s | FileCheck %s3 4target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128-ni:4:5"5 6define void @f0(i1 %alwaysFalse, i64 %val, ptr %loc) {7; CHECK-LABEL: @f0(8; CHECK-NEXT: entry:9; CHECK-NEXT: store i64 [[VAL:%.*]], ptr [[LOC:%.*]], align 810; CHECK-NEXT: br i1 [[ALWAYSFALSE:%.*]], label [[NEVERTAKEN:%.*]], label [[ALWAYSTAKEN:%.*]]11; CHECK: neverTaken:12; CHECK-NEXT: [[PTR:%.*]] = load ptr addrspace(4), ptr [[LOC]], align 813; CHECK-NEXT: store i8 5, ptr addrspace(4) [[PTR]], align 114; CHECK-NEXT: ret void15; CHECK: alwaysTaken:16; CHECK-NEXT: ret void17;18 entry:19 store i64 %val, ptr %loc20 br i1 %alwaysFalse, label %neverTaken, label %alwaysTaken21 22 neverTaken:23 %ptr = load ptr addrspace(4), ptr %loc24 store i8 5, ptr addrspace(4) %ptr25 ret void26 27 alwaysTaken:28 ret void29}30 31define i64 @f1(i1 %alwaysFalse, ptr addrspace(4) %val, ptr %loc) {32; CHECK-LABEL: @f1(33; CHECK-NEXT: entry:34; CHECK-NEXT: store ptr addrspace(4) [[VAL:%.*]], ptr [[LOC:%.*]], align 835; CHECK-NEXT: br i1 [[ALWAYSFALSE:%.*]], label [[NEVERTAKEN:%.*]], label [[ALWAYSTAKEN:%.*]]36; CHECK: neverTaken:37; CHECK-NEXT: [[INT:%.*]] = load i64, ptr [[LOC]], align 838; CHECK-NEXT: ret i64 [[INT]]39; CHECK: alwaysTaken:40; CHECK-NEXT: ret i64 4241;42 entry:43 store ptr addrspace(4) %val, ptr %loc44 br i1 %alwaysFalse, label %neverTaken, label %alwaysTaken45 46 neverTaken:47 %int = load i64, ptr %loc48 ret i64 %int49 50 alwaysTaken:51 ret i64 4252}53 54;; Note: For terseness, we stop using the %alwaysfalse trick for the55;; tests below and just exercise the bits of forwarding logic directly.56 57declare void @llvm.memset.p4.i64(ptr addrspace(4) nocapture, i8, i64, i1) nounwind58 59; Can't forward as the load might be dead. (Pretend we wrote out the alwaysfalse idiom above.)60define ptr addrspace(4) @neg_forward_memset(ptr addrspace(4) %loc) {61; CHECK-LABEL: @neg_forward_memset(62; CHECK-NEXT: entry:63; CHECK-NEXT: call void @llvm.memset.p4.i64(ptr addrspace(4) align 4 [[LOC:%.*]], i8 7, i64 8, i1 false)64; CHECK-NEXT: [[REF:%.*]] = load ptr addrspace(4), ptr addrspace(4) [[LOC]], align 865; CHECK-NEXT: ret ptr addrspace(4) [[REF]]66;67 entry:68 call void @llvm.memset.p4.i64(ptr addrspace(4) align 4 %loc, i8 7, i64 8, i1 false)69 %ref = load ptr addrspace(4), ptr addrspace(4) %loc70 ret ptr addrspace(4) %ref71}72 73define <1 x ptr addrspace(4)> @neg_forward_memset_vload(ptr addrspace(4) %loc) {74; CHECK-LABEL: @neg_forward_memset_vload(75; CHECK-NEXT: entry:76; CHECK-NEXT: call void @llvm.memset.p4.i64(ptr addrspace(4) align 4 [[LOC:%.*]], i8 7, i64 8, i1 false)77; CHECK-NEXT: [[REF:%.*]] = load <1 x ptr addrspace(4)>, ptr addrspace(4) [[LOC]], align 878; CHECK-NEXT: ret <1 x ptr addrspace(4)> [[REF]]79;80 entry:81 call void @llvm.memset.p4.i64(ptr addrspace(4) align 4 %loc, i8 7, i64 8, i1 false)82 %ref = load <1 x ptr addrspace(4)>, ptr addrspace(4) %loc83 ret <1 x ptr addrspace(4)> %ref84}85 86 87; Can forward since we can do so w/o breaking types88define ptr addrspace(4) @forward_memset_zero(ptr addrspace(4) %loc) {89; CHECK-LABEL: @forward_memset_zero(90; CHECK-NEXT: entry:91; CHECK-NEXT: call void @llvm.memset.p4.i64(ptr addrspace(4) align 4 [[LOC:%.*]], i8 0, i64 8, i1 false)92; CHECK-NEXT: ret ptr addrspace(4) null93;94 entry:95 call void @llvm.memset.p4.i64(ptr addrspace(4) align 4 %loc, i8 0, i64 8, i1 false)96 %ref = load ptr addrspace(4), ptr addrspace(4) %loc97 ret ptr addrspace(4) %ref98}99 100; Can't forward as the load might be dead. (Pretend we wrote out the alwaysfalse idiom above.)101define ptr addrspace(4) @neg_forward_store(ptr addrspace(4) %loc) {102; CHECK-LABEL: @neg_forward_store(103; CHECK-NEXT: entry:104; CHECK-NEXT: store i64 5, ptr addrspace(4) [[LOC:%.*]], align 8105; CHECK-NEXT: [[REF:%.*]] = load ptr addrspace(4), ptr addrspace(4) [[LOC]], align 8106; CHECK-NEXT: ret ptr addrspace(4) [[REF]]107;108 entry:109 store i64 5, ptr addrspace(4) %loc110 %ref = load ptr addrspace(4), ptr addrspace(4) %loc111 ret ptr addrspace(4) %ref112}113 114define <1 x ptr addrspace(4)> @neg_forward_store_vload(ptr addrspace(4) %loc) {115; CHECK-LABEL: @neg_forward_store_vload(116; CHECK-NEXT: entry:117; CHECK-NEXT: store i64 5, ptr addrspace(4) [[LOC:%.*]], align 8118; CHECK-NEXT: [[REF:%.*]] = load <1 x ptr addrspace(4)>, ptr addrspace(4) [[LOC]], align 8119; CHECK-NEXT: ret <1 x ptr addrspace(4)> [[REF]]120;121 entry:122 store i64 5, ptr addrspace(4) %loc123 %ref = load <1 x ptr addrspace(4)>, ptr addrspace(4) %loc124 ret <1 x ptr addrspace(4)> %ref125}126 127; Nulls have known bit patterns, so we can forward128define ptr addrspace(4) @forward_store_zero(ptr addrspace(4) %loc) {129; CHECK-LABEL: @forward_store_zero(130; CHECK-NEXT: entry:131; CHECK-NEXT: store i64 0, ptr addrspace(4) [[LOC:%.*]], align 8132; CHECK-NEXT: ret ptr addrspace(4) null133;134 entry:135 store i64 0, ptr addrspace(4) %loc136 %ref = load ptr addrspace(4), ptr addrspace(4) %loc137 ret ptr addrspace(4) %ref138}139 140; Nulls have known bit patterns, so we can forward141define ptr addrspace(4) @forward_store_zero2(ptr addrspace(4) %loc) {142; CHECK-LABEL: @forward_store_zero2(143; CHECK-NEXT: entry:144; CHECK-NEXT: store <2 x i32> zeroinitializer, ptr addrspace(4) [[LOC:%.*]], align 8145; CHECK-NEXT: ret ptr addrspace(4) null146;147 entry:148 store <2 x i32> zeroinitializer, ptr addrspace(4) %loc149 %ref = load ptr addrspace(4), ptr addrspace(4) %loc150 ret ptr addrspace(4) %ref151}152 153 154 155@NonZeroConstant = constant <4 x i64> <i64 3, i64 3, i64 3, i64 3>156@NonZeroConstant2 = constant <4 x ptr addrspace(4)> <157 ptr addrspace(4) getelementptr (i64, ptr addrspace(4) null, i32 3),158 ptr addrspace(4) getelementptr (i64, ptr addrspace(4) null, i32 3),159 ptr addrspace(4) getelementptr (i64, ptr addrspace(4) null, i32 3),160 ptr addrspace(4) getelementptr (i64, ptr addrspace(4) null, i32 3)>161@ZeroConstant = constant <4 x i64> zeroinitializer162 163 164; Can't forward as the load might be dead. (Pretend we wrote out the alwaysfalse idiom above.)165define ptr addrspace(4) @neg_forward_memcopy(ptr addrspace(4) %loc) {166; CHECK-LABEL: @neg_forward_memcopy(167; CHECK-NEXT: entry:168; CHECK-NEXT: call void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) align 4 [[LOC:%.*]], ptr @NonZeroConstant, i64 8, i1 false)169; CHECK-NEXT: [[REF:%.*]] = load ptr addrspace(4), ptr addrspace(4) [[LOC]], align 8170; CHECK-NEXT: ret ptr addrspace(4) [[REF]]171;172entry:173 call void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) align 4 %loc, ptr @NonZeroConstant, i64 8, i1 false)174 %ref = load ptr addrspace(4), ptr addrspace(4) %loc175 ret ptr addrspace(4) %ref176}177 178define ptr addrspace(4) @neg_forward_memcopy2(ptr addrspace(4) %loc) {179; CHECK-LABEL: @neg_forward_memcopy2(180; CHECK-NEXT: entry:181; CHECK-NEXT: call void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) align 4 [[LOC:%.*]], ptr @NonZeroConstant, i64 8, i1 false)182; CHECK-NEXT: [[REF:%.*]] = load ptr addrspace(4), ptr addrspace(4) [[LOC]], align 8183; CHECK-NEXT: ret ptr addrspace(4) [[REF]]184;185entry:186 call void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) align 4 %loc, ptr @NonZeroConstant, i64 8, i1 false)187 %ref = load ptr addrspace(4), ptr addrspace(4) %loc188 ret ptr addrspace(4) %ref189}190 191define ptr addrspace(4) @forward_memcopy(ptr addrspace(4) %loc) {192; CHECK-LABEL: @forward_memcopy(193; CHECK-NEXT: entry:194; CHECK-NEXT: call void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) align 4 [[LOC:%.*]], ptr @NonZeroConstant2, i64 8, i1 false)195; CHECK-NEXT: ret ptr addrspace(4) getelementptr (i64, ptr addrspace(4) null, i32 3)196;197entry:198 call void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) align 4 %loc, ptr @NonZeroConstant2, i64 8, i1 false)199 %ref = load ptr addrspace(4), ptr addrspace(4) %loc200 ret ptr addrspace(4) %ref201}202 203define ptr addrspace(4) @forward_memcopy2(ptr addrspace(4) %loc) {204; CHECK-LABEL: @forward_memcopy2(205; CHECK-NEXT: entry:206; CHECK-NEXT: call void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) align 4 [[LOC:%.*]], ptr @NonZeroConstant2, i64 8, i1 false)207; CHECK-NEXT: ret ptr addrspace(4) getelementptr (i64, ptr addrspace(4) null, i32 3)208;209entry:210 call void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) align 4 %loc, ptr @NonZeroConstant2, i64 8, i1 false)211 %ref = load ptr addrspace(4), ptr addrspace(4) %loc212 ret ptr addrspace(4) %ref213}214 215define <1 x ptr addrspace(4)> @neg_forward_memcpy_vload(ptr addrspace(4) %loc) {216; CHECK-LABEL: @neg_forward_memcpy_vload(217; CHECK-NEXT: entry:218; CHECK-NEXT: call void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) align 4 [[LOC:%.*]], ptr @NonZeroConstant, i64 8, i1 false)219; CHECK-NEXT: [[REF:%.*]] = load <1 x ptr addrspace(4)>, ptr addrspace(4) [[LOC]], align 8220; CHECK-NEXT: ret <1 x ptr addrspace(4)> [[REF]]221;222entry:223 call void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) align 4 %loc, ptr @NonZeroConstant, i64 8, i1 false)224 %ref = load <1 x ptr addrspace(4)>, ptr addrspace(4) %loc225 ret <1 x ptr addrspace(4)> %ref226}227 228define <4 x ptr addrspace(4)> @neg_forward_memcpy_vload2(ptr addrspace(4) %loc) {229; CHECK-LABEL: @neg_forward_memcpy_vload2(230; CHECK-NEXT: entry:231; CHECK-NEXT: call void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) align 4 [[LOC:%.*]], ptr @NonZeroConstant, i64 32, i1 false)232; CHECK-NEXT: [[REF:%.*]] = load <4 x ptr addrspace(4)>, ptr addrspace(4) [[LOC]], align 32233; CHECK-NEXT: ret <4 x ptr addrspace(4)> [[REF]]234;235entry:236 call void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) align 4 %loc, ptr @NonZeroConstant, i64 32, i1 false)237 %ref = load <4 x ptr addrspace(4)>, ptr addrspace(4) %loc238 ret <4 x ptr addrspace(4)> %ref239}240 241define <4 x i64> @neg_forward_memcpy_vload3(ptr addrspace(4) %loc) {242; CHECK-LABEL: @neg_forward_memcpy_vload3(243; CHECK-NEXT: entry:244; CHECK-NEXT: call void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) align 4 [[LOC:%.*]], ptr @NonZeroConstant2, i64 32, i1 false)245; CHECK-NEXT: [[REF:%.*]] = load <4 x i64>, ptr addrspace(4) [[LOC]], align 32246; CHECK-NEXT: ret <4 x i64> [[REF]]247;248entry:249 call void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) align 4 %loc, ptr @NonZeroConstant2, i64 32, i1 false)250 %ref = load <4 x i64>, ptr addrspace(4) %loc251 ret <4 x i64> %ref252}253 254define <1 x ptr addrspace(4)> @forward_memcpy_vload3(ptr addrspace(4) %loc) {255; CHECK-LABEL: @forward_memcpy_vload3(256; CHECK-NEXT: entry:257; CHECK-NEXT: call void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) align 4 [[LOC:%.*]], ptr @NonZeroConstant2, i64 32, i1 false)258; CHECK-NEXT: ret <1 x ptr addrspace(4)> <ptr addrspace(4) getelementptr (i64, ptr addrspace(4) null, i32 3)>259;260entry:261 call void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) align 4 %loc, ptr @NonZeroConstant2, i64 32, i1 false)262 %ref = load <4 x ptr addrspace(4)>, ptr addrspace(4) %loc263 %val = extractelement <4 x ptr addrspace(4)> %ref, i32 0264 %ret = insertelement <1 x ptr addrspace(4)> undef, ptr addrspace(4) %val, i32 0265 ret <1 x ptr addrspace(4)> %ret266}267 268; Can forward since we can do so w/o breaking types269define ptr addrspace(4) @forward_memcpy_zero(ptr addrspace(4) %loc) {270; CHECK-LABEL: @forward_memcpy_zero(271; CHECK-NEXT: entry:272; CHECK-NEXT: call void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) align 4 [[LOC:%.*]], ptr @ZeroConstant, i64 8, i1 false)273; CHECK-NEXT: ret ptr addrspace(4) null274;275entry:276 call void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) align 4 %loc, ptr @ZeroConstant, i64 8, i1 false)277 %ref = load ptr addrspace(4), ptr addrspace(4) %loc278 ret ptr addrspace(4) %ref279}280 281declare void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) nocapture, ptr nocapture, i64, i1) nounwind282 283 284; Same as the neg_forward_store cases, but for non defs.285; (Pretend we wrote out the alwaysfalse idiom above.)286define ptr addrspace(4) @neg_store_clobber(ptr addrspace(4) %loc) {287; CHECK-LABEL: @neg_store_clobber(288; CHECK-NEXT: entry:289; CHECK-NEXT: store <2 x i64> splat (i64 4), ptr addrspace(4) [[LOC:%.*]], align 16290; CHECK-NEXT: [[LOC_OFF:%.*]] = getelementptr ptr addrspace(4), ptr addrspace(4) [[LOC]], i64 1291; CHECK-NEXT: [[REF:%.*]] = load ptr addrspace(4), ptr addrspace(4) [[LOC_OFF]], align 8292; CHECK-NEXT: ret ptr addrspace(4) [[REF]]293;294entry:295 store <2 x i64> <i64 4, i64 4>, ptr addrspace(4) %loc296 %loc.off = getelementptr ptr addrspace(4), ptr addrspace(4) %loc, i64 1297 %ref = load ptr addrspace(4), ptr addrspace(4) %loc.off298 ret ptr addrspace(4) %ref299}300 301declare void @use(<2 x i64>) inaccessiblememonly302 303; Same as the neg_forward_store cases, but for non defs.304; (Pretend we wrote out the alwaysfalse idiom above.)305define ptr addrspace(4) @neg_load_clobber(ptr addrspace(4) %loc) {306; CHECK-LABEL: @neg_load_clobber(307; CHECK-NEXT: entry:308; CHECK-NEXT: [[V:%.*]] = load <2 x i64>, ptr addrspace(4) [[LOC:%.*]], align 16309; CHECK-NEXT: call void @use(<2 x i64> [[V]])310; CHECK-NEXT: [[LOC_OFF:%.*]] = getelementptr ptr addrspace(4), ptr addrspace(4) [[LOC]], i64 1311; CHECK-NEXT: [[REF:%.*]] = load ptr addrspace(4), ptr addrspace(4) [[LOC_OFF]], align 8312; CHECK-NEXT: ret ptr addrspace(4) [[REF]]313;314entry:315 %v = load <2 x i64>, ptr addrspace(4) %loc316 call void @use(<2 x i64> %v)317 %loc.off = getelementptr ptr addrspace(4), ptr addrspace(4) %loc, i64 1318 %ref = load ptr addrspace(4), ptr addrspace(4) %loc.off319 ret ptr addrspace(4) %ref320}321 322define ptr addrspace(4) @store_clobber_zero(ptr addrspace(4) %loc) {323; CHECK-LABEL: @store_clobber_zero(324; CHECK-NEXT: entry:325; CHECK-NEXT: store <2 x i64> zeroinitializer, ptr addrspace(4) [[LOC:%.*]], align 16326; CHECK-NEXT: [[LOC_OFF:%.*]] = getelementptr ptr addrspace(4), ptr addrspace(4) [[LOC]], i64 1327; CHECK-NEXT: ret ptr addrspace(4) null328;329entry:330 store <2 x i64> zeroinitializer, ptr addrspace(4) %loc331 %loc.off = getelementptr ptr addrspace(4), ptr addrspace(4) %loc, i64 1332 %ref = load ptr addrspace(4), ptr addrspace(4) %loc.off333 ret ptr addrspace(4) %ref334}335 336 337define void @smaller_vector(ptr %p) {338; CHECK-LABEL: @smaller_vector(339; CHECK-NEXT: entry:340; CHECK-NEXT: [[V4:%.*]] = load <4 x ptr addrspace(4)>, ptr [[P:%.*]], align 32341; CHECK-NEXT: [[V2:%.*]] = load <2 x ptr addrspace(4)>, ptr [[P]], align 32342; CHECK-NEXT: call void @use.v2(<2 x ptr addrspace(4)> [[V2]])343; CHECK-NEXT: call void @use.v4(<4 x ptr addrspace(4)> [[V4]])344; CHECK-NEXT: ret void345;346entry:347 %v4 = load <4 x ptr addrspace(4)>, ptr %p, align 32348 %v2 = load <2 x ptr addrspace(4)>, ptr %p, align 32349 call void @use.v2(<2 x ptr addrspace(4)> %v2)350 call void @use.v4(<4 x ptr addrspace(4)> %v4)351 ret void352}353 354define ptr addrspace(4) @vector_extract(ptr %p) {355; CHECK-LABEL: @vector_extract(356; CHECK-NEXT: entry:357; CHECK-NEXT: [[V4:%.*]] = load <4 x ptr addrspace(4)>, ptr [[P:%.*]], align 32358; CHECK-NEXT: [[RES:%.*]] = load ptr addrspace(4), ptr [[P]], align 32359; CHECK-NEXT: call void @use.v4(<4 x ptr addrspace(4)> [[V4]])360; CHECK-NEXT: ret ptr addrspace(4) [[RES]]361;362entry:363 %v4 = load <4 x ptr addrspace(4)>, ptr %p, align 32364 %res = load ptr addrspace(4), ptr %p, align 32365 call void @use.v4(<4 x ptr addrspace(4)> %v4)366 ret ptr addrspace(4) %res367}368 369declare void @use.v2(<2 x ptr addrspace(4)>)370declare void @use.v4(<4 x ptr addrspace(4)>)371define ptr addrspace(5) @multini(i1 %alwaysFalse, ptr addrspace(4) %val, ptr %loc) {372; CHECK-LABEL: @multini(373; CHECK-NEXT: entry:374; CHECK-NEXT: store ptr addrspace(4) [[VAL:%.*]], ptr [[LOC:%.*]], align 8375; CHECK-NEXT: br i1 [[ALWAYSFALSE:%.*]], label [[NEVERTAKEN:%.*]], label [[ALWAYSTAKEN:%.*]]376; CHECK: neverTaken:377; CHECK-NEXT: [[DIFFERENTAS:%.*]] = load ptr addrspace(5), ptr [[LOC]], align 8378; CHECK-NEXT: ret ptr addrspace(5) [[DIFFERENTAS]]379; CHECK: alwaysTaken:380; CHECK-NEXT: ret ptr addrspace(5) null381;382entry:383 store ptr addrspace(4) %val, ptr %loc384 br i1 %alwaysFalse, label %neverTaken, label %alwaysTaken385 386neverTaken:387 %differentas = load ptr addrspace(5), ptr %loc388 ret ptr addrspace(5) %differentas389 390alwaysTaken:391 ret ptr addrspace(5) null392}393