394 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"5target triple = "x86_64-unknown-linux-gnu"6 7define void @f0(i1 %alwaysFalse, i64 %val, ptr %loc) {8; CHECK-LABEL: @f0(9; CHECK-NEXT: entry:10; CHECK-NEXT: store i64 [[VAL:%.*]], ptr [[LOC:%.*]], align 811; CHECK-NEXT: br i1 [[ALWAYSFALSE:%.*]], label [[NEVERTAKEN:%.*]], label [[ALWAYSTAKEN:%.*]]12; CHECK: neverTaken:13; CHECK-NEXT: [[PTR:%.*]] = load ptr addrspace(4), ptr [[LOC]], align 814; CHECK-NEXT: store i8 5, ptr addrspace(4) [[PTR]], align 115; CHECK-NEXT: ret void16; CHECK: alwaysTaken:17; CHECK-NEXT: ret void18;19 entry:20 store i64 %val, ptr %loc21 br i1 %alwaysFalse, label %neverTaken, label %alwaysTaken22 23 neverTaken:24 %ptr = load ptr addrspace(4), ptr %loc25 store i8 5, ptr addrspace(4) %ptr26 ret void27 28 alwaysTaken:29 ret void30}31 32define i64 @f1(i1 %alwaysFalse, ptr addrspace(4) %val, ptr %loc) {33; CHECK-LABEL: @f1(34; CHECK-NEXT: entry:35; CHECK-NEXT: store ptr addrspace(4) [[VAL:%.*]], ptr [[LOC:%.*]], align 836; CHECK-NEXT: br i1 [[ALWAYSFALSE:%.*]], label [[NEVERTAKEN:%.*]], label [[ALWAYSTAKEN:%.*]]37; CHECK: neverTaken:38; CHECK-NEXT: [[INT:%.*]] = load i64, ptr [[LOC]], align 839; CHECK-NEXT: ret i64 [[INT]]40; CHECK: alwaysTaken:41; CHECK-NEXT: ret i64 4242;43 entry:44 store ptr addrspace(4) %val, ptr %loc45 br i1 %alwaysFalse, label %neverTaken, label %alwaysTaken46 47 neverTaken:48 %int = load i64, ptr %loc49 ret i64 %int50 51 alwaysTaken:52 ret i64 4253}54 55;; Note: For terseness, we stop using the %alwaysfalse trick for the56;; tests below and just exercise the bits of forwarding logic directly.57 58declare void @llvm.memset.p4.i64(ptr addrspace(4) nocapture, i8, i64, i1) nounwind59 60; Can't forward as the load might be dead. (Pretend we wrote out the alwaysfalse idiom above.)61define ptr addrspace(4) @neg_forward_memset(ptr addrspace(4) %loc) {62; CHECK-LABEL: @neg_forward_memset(63; CHECK-NEXT: entry:64; CHECK-NEXT: call void @llvm.memset.p4.i64(ptr addrspace(4) align 4 [[LOC:%.*]], i8 7, i64 8, i1 false)65; CHECK-NEXT: [[REF:%.*]] = load ptr addrspace(4), ptr addrspace(4) [[LOC]], align 866; CHECK-NEXT: ret ptr addrspace(4) [[REF]]67;68 entry:69 call void @llvm.memset.p4.i64(ptr addrspace(4) align 4 %loc, i8 7, i64 8, i1 false)70 %ref = load ptr addrspace(4), ptr addrspace(4) %loc71 ret ptr addrspace(4) %ref72}73 74define <1 x ptr addrspace(4)> @neg_forward_memset_vload(ptr addrspace(4) %loc) {75; CHECK-LABEL: @neg_forward_memset_vload(76; CHECK-NEXT: entry:77; CHECK-NEXT: call void @llvm.memset.p4.i64(ptr addrspace(4) align 4 [[LOC:%.*]], i8 7, i64 8, i1 false)78; CHECK-NEXT: [[REF:%.*]] = load <1 x ptr addrspace(4)>, ptr addrspace(4) [[LOC]], align 879; CHECK-NEXT: ret <1 x ptr addrspace(4)> [[REF]]80;81 entry:82 call void @llvm.memset.p4.i64(ptr addrspace(4) align 4 %loc, i8 7, i64 8, i1 false)83 %ref = load <1 x ptr addrspace(4)>, ptr addrspace(4) %loc84 ret <1 x ptr addrspace(4)> %ref85}86 87 88; Can forward since we can do so w/o breaking types89define ptr addrspace(4) @forward_memset_zero(ptr addrspace(4) %loc) {90; CHECK-LABEL: @forward_memset_zero(91; CHECK-NEXT: entry:92; CHECK-NEXT: call void @llvm.memset.p4.i64(ptr addrspace(4) align 4 [[LOC:%.*]], i8 0, i64 8, i1 false)93; CHECK-NEXT: ret ptr addrspace(4) null94;95 entry:96 call void @llvm.memset.p4.i64(ptr addrspace(4) align 4 %loc, i8 0, i64 8, i1 false)97 %ref = load ptr addrspace(4), ptr addrspace(4) %loc98 ret ptr addrspace(4) %ref99}100 101; Can't forward as the load might be dead. (Pretend we wrote out the alwaysfalse idiom above.)102define ptr addrspace(4) @neg_forward_store(ptr addrspace(4) %loc) {103; CHECK-LABEL: @neg_forward_store(104; CHECK-NEXT: entry:105; CHECK-NEXT: store i64 5, ptr addrspace(4) [[LOC:%.*]], align 8106; CHECK-NEXT: [[REF:%.*]] = load ptr addrspace(4), ptr addrspace(4) [[LOC]], align 8107; CHECK-NEXT: ret ptr addrspace(4) [[REF]]108;109 entry:110 store i64 5, ptr addrspace(4) %loc111 %ref = load ptr addrspace(4), ptr addrspace(4) %loc112 ret ptr addrspace(4) %ref113}114 115define <1 x ptr addrspace(4)> @neg_forward_store_vload(ptr addrspace(4) %loc) {116; CHECK-LABEL: @neg_forward_store_vload(117; CHECK-NEXT: entry:118; CHECK-NEXT: store i64 5, ptr addrspace(4) [[LOC:%.*]], align 8119; CHECK-NEXT: [[REF:%.*]] = load <1 x ptr addrspace(4)>, ptr addrspace(4) [[LOC]], align 8120; CHECK-NEXT: ret <1 x ptr addrspace(4)> [[REF]]121;122 entry:123 store i64 5, ptr addrspace(4) %loc124 %ref = load <1 x ptr addrspace(4)>, ptr addrspace(4) %loc125 ret <1 x ptr addrspace(4)> %ref126}127 128; Nulls have known bit patterns, so we can forward129define ptr addrspace(4) @forward_store_zero(ptr addrspace(4) %loc) {130; CHECK-LABEL: @forward_store_zero(131; CHECK-NEXT: entry:132; CHECK-NEXT: store i64 0, ptr addrspace(4) [[LOC:%.*]], align 8133; CHECK-NEXT: ret ptr addrspace(4) null134;135 entry:136 store i64 0, ptr addrspace(4) %loc137 %ref = load ptr addrspace(4), ptr addrspace(4) %loc138 ret ptr addrspace(4) %ref139}140 141; Nulls have known bit patterns, so we can forward142define ptr addrspace(4) @forward_store_zero2(ptr addrspace(4) %loc) {143; CHECK-LABEL: @forward_store_zero2(144; CHECK-NEXT: entry:145; CHECK-NEXT: store <2 x i32> zeroinitializer, ptr addrspace(4) [[LOC:%.*]], align 8146; CHECK-NEXT: ret ptr addrspace(4) null147;148 entry:149 store <2 x i32> zeroinitializer, ptr addrspace(4) %loc150 %ref = load ptr addrspace(4), ptr addrspace(4) %loc151 ret ptr addrspace(4) %ref152}153 154 155 156@NonZeroConstant = constant <4 x i64> <i64 3, i64 3, i64 3, i64 3>157@NonZeroConstant2 = constant <4 x ptr addrspace(4)> <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 ptr addrspace(4) getelementptr (i64, ptr addrspace(4) null, i32 3)>162@ZeroConstant = constant <4 x i64> zeroinitializer163 164 165; Can't forward as the load might be dead. (Pretend we wrote out the alwaysfalse idiom above.)166define ptr addrspace(4) @neg_forward_memcopy(ptr addrspace(4) %loc) {167; CHECK-LABEL: @neg_forward_memcopy(168; CHECK-NEXT: entry:169; CHECK-NEXT: call void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) align 4 [[LOC:%.*]], ptr @NonZeroConstant, i64 8, i1 false)170; CHECK-NEXT: [[REF:%.*]] = load ptr addrspace(4), ptr addrspace(4) [[LOC]], align 8171; CHECK-NEXT: ret ptr addrspace(4) [[REF]]172;173entry:174 call void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) align 4 %loc, ptr @NonZeroConstant, i64 8, i1 false)175 %ref = load ptr addrspace(4), ptr addrspace(4) %loc176 ret ptr addrspace(4) %ref177}178 179define ptr addrspace(4) @neg_forward_memcopy2(ptr addrspace(4) %loc) {180; CHECK-LABEL: @neg_forward_memcopy2(181; CHECK-NEXT: entry:182; CHECK-NEXT: call void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) align 4 [[LOC:%.*]], ptr @NonZeroConstant, i64 8, i1 false)183; CHECK-NEXT: [[REF:%.*]] = load ptr addrspace(4), ptr addrspace(4) [[LOC]], align 8184; CHECK-NEXT: ret ptr addrspace(4) [[REF]]185;186entry:187 call void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) align 4 %loc, ptr @NonZeroConstant, i64 8, i1 false)188 %ref = load ptr addrspace(4), ptr addrspace(4) %loc189 ret ptr addrspace(4) %ref190}191 192define ptr addrspace(4) @forward_memcopy(ptr addrspace(4) %loc) {193; CHECK-LABEL: @forward_memcopy(194; CHECK-NEXT: entry:195; CHECK-NEXT: call void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) align 4 [[LOC:%.*]], ptr @NonZeroConstant2, i64 8, i1 false)196; CHECK-NEXT: ret ptr addrspace(4) getelementptr (i64, ptr addrspace(4) null, i32 3)197;198entry:199 call void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) align 4 %loc, ptr @NonZeroConstant2, i64 8, i1 false)200 %ref = load ptr addrspace(4), ptr addrspace(4) %loc201 ret ptr addrspace(4) %ref202}203 204define ptr addrspace(4) @forward_memcopy2(ptr addrspace(4) %loc) {205; CHECK-LABEL: @forward_memcopy2(206; CHECK-NEXT: entry:207; CHECK-NEXT: call void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) align 4 [[LOC:%.*]], ptr @NonZeroConstant2, i64 8, i1 false)208; CHECK-NEXT: ret ptr addrspace(4) getelementptr (i64, ptr addrspace(4) null, i32 3)209;210entry:211 call void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) align 4 %loc, ptr @NonZeroConstant2, i64 8, i1 false)212 %ref = load ptr addrspace(4), ptr addrspace(4) %loc213 ret ptr addrspace(4) %ref214}215 216define <1 x ptr addrspace(4)> @neg_forward_memcpy_vload(ptr addrspace(4) %loc) {217; CHECK-LABEL: @neg_forward_memcpy_vload(218; CHECK-NEXT: entry:219; CHECK-NEXT: call void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) align 4 [[LOC:%.*]], ptr @NonZeroConstant, i64 8, i1 false)220; CHECK-NEXT: [[REF:%.*]] = load <1 x ptr addrspace(4)>, ptr addrspace(4) [[LOC]], align 8221; CHECK-NEXT: ret <1 x ptr addrspace(4)> [[REF]]222;223entry:224 call void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) align 4 %loc, ptr @NonZeroConstant, i64 8, i1 false)225 %ref = load <1 x ptr addrspace(4)>, ptr addrspace(4) %loc226 ret <1 x ptr addrspace(4)> %ref227}228 229define <4 x ptr addrspace(4)> @neg_forward_memcpy_vload2(ptr addrspace(4) %loc) {230; CHECK-LABEL: @neg_forward_memcpy_vload2(231; CHECK-NEXT: entry:232; CHECK-NEXT: call void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) align 4 [[LOC:%.*]], ptr @NonZeroConstant, i64 32, i1 false)233; CHECK-NEXT: [[REF:%.*]] = load <4 x ptr addrspace(4)>, ptr addrspace(4) [[LOC]], align 32234; CHECK-NEXT: ret <4 x ptr addrspace(4)> [[REF]]235;236entry:237 call void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) align 4 %loc, ptr @NonZeroConstant, i64 32, i1 false)238 %ref = load <4 x ptr addrspace(4)>, ptr addrspace(4) %loc239 ret <4 x ptr addrspace(4)> %ref240}241 242define <4 x i64> @neg_forward_memcpy_vload3(ptr addrspace(4) %loc) {243; CHECK-LABEL: @neg_forward_memcpy_vload3(244; CHECK-NEXT: entry:245; CHECK-NEXT: call void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) align 4 [[LOC:%.*]], ptr @NonZeroConstant2, i64 32, i1 false)246; CHECK-NEXT: [[REF:%.*]] = load <4 x i64>, ptr addrspace(4) [[LOC]], align 32247; CHECK-NEXT: ret <4 x i64> [[REF]]248;249entry:250 call void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) align 4 %loc, ptr @NonZeroConstant2, i64 32, i1 false)251 %ref = load <4 x i64>, ptr addrspace(4) %loc252 ret <4 x i64> %ref253}254 255define <1 x ptr addrspace(4)> @forward_memcpy_vload3(ptr addrspace(4) %loc) {256; CHECK-LABEL: @forward_memcpy_vload3(257; CHECK-NEXT: entry:258; CHECK-NEXT: call void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) align 4 [[LOC:%.*]], ptr @NonZeroConstant2, i64 32, i1 false)259; CHECK-NEXT: ret <1 x ptr addrspace(4)> <ptr addrspace(4) getelementptr (i64, ptr addrspace(4) null, i32 3)>260;261entry:262 call void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) align 4 %loc, ptr @NonZeroConstant2, i64 32, i1 false)263 %ref = load <4 x ptr addrspace(4)>, ptr addrspace(4) %loc264 %val = extractelement <4 x ptr addrspace(4)> %ref, i32 0265 %ret = insertelement <1 x ptr addrspace(4)> poison, ptr addrspace(4) %val, i32 0266 ret <1 x ptr addrspace(4)> %ret267}268 269; Can forward since we can do so w/o breaking types270define ptr addrspace(4) @forward_memcpy_zero(ptr addrspace(4) %loc) {271; CHECK-LABEL: @forward_memcpy_zero(272; CHECK-NEXT: entry:273; CHECK-NEXT: call void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) align 4 [[LOC:%.*]], ptr @ZeroConstant, i64 8, i1 false)274; CHECK-NEXT: ret ptr addrspace(4) null275;276entry:277 call void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) align 4 %loc, ptr @ZeroConstant, i64 8, i1 false)278 %ref = load ptr addrspace(4), ptr addrspace(4) %loc279 ret ptr addrspace(4) %ref280}281 282declare void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) nocapture, ptr nocapture, i64, i1) nounwind283 284 285; Same as the neg_forward_store cases, but for non defs.286; (Pretend we wrote out the alwaysfalse idiom above.)287define ptr addrspace(4) @neg_store_clobber(ptr addrspace(4) %loc) {288; CHECK-LABEL: @neg_store_clobber(289; CHECK-NEXT: entry:290; CHECK-NEXT: store <2 x i64> splat (i64 4), ptr addrspace(4) [[LOC:%.*]], align 16291; CHECK-NEXT: [[LOC_OFF:%.*]] = getelementptr ptr addrspace(4), ptr addrspace(4) [[LOC]], i64 1292; CHECK-NEXT: [[REF:%.*]] = load ptr addrspace(4), ptr addrspace(4) [[LOC_OFF]], align 8293; CHECK-NEXT: ret ptr addrspace(4) [[REF]]294;295entry:296 store <2 x i64> <i64 4, i64 4>, ptr addrspace(4) %loc297 %loc.off = getelementptr ptr addrspace(4), ptr addrspace(4) %loc, i64 1298 %ref = load ptr addrspace(4), ptr addrspace(4) %loc.off299 ret ptr addrspace(4) %ref300}301 302declare void @use(<2 x i64>) inaccessiblememonly303 304; Same as the neg_forward_store cases, but for non defs.305; (Pretend we wrote out the alwaysfalse idiom above.)306define ptr addrspace(4) @neg_load_clobber(ptr addrspace(4) %loc) {307; CHECK-LABEL: @neg_load_clobber(308; CHECK-NEXT: entry:309; CHECK-NEXT: [[V:%.*]] = load <2 x i64>, ptr addrspace(4) [[LOC:%.*]], align 16310; CHECK-NEXT: call void @use(<2 x i64> [[V]])311; CHECK-NEXT: [[LOC_OFF:%.*]] = getelementptr ptr addrspace(4), ptr addrspace(4) [[LOC]], i64 1312; CHECK-NEXT: [[REF:%.*]] = load ptr addrspace(4), ptr addrspace(4) [[LOC_OFF]], align 8313; CHECK-NEXT: ret ptr addrspace(4) [[REF]]314;315entry:316 %v = load <2 x i64>, ptr addrspace(4) %loc317 call void @use(<2 x i64> %v)318 %loc.off = getelementptr ptr addrspace(4), ptr addrspace(4) %loc, i64 1319 %ref = load ptr addrspace(4), ptr addrspace(4) %loc.off320 ret ptr addrspace(4) %ref321}322 323define ptr addrspace(4) @store_clobber_zero(ptr addrspace(4) %loc) {324; CHECK-LABEL: @store_clobber_zero(325; CHECK-NEXT: entry:326; CHECK-NEXT: store <2 x i64> zeroinitializer, ptr addrspace(4) [[LOC:%.*]], align 16327; CHECK-NEXT: [[LOC_OFF:%.*]] = getelementptr ptr addrspace(4), ptr addrspace(4) [[LOC]], i64 1328; CHECK-NEXT: ret ptr addrspace(4) null329;330entry:331 store <2 x i64> zeroinitializer, ptr addrspace(4) %loc332 %loc.off = getelementptr ptr addrspace(4), ptr addrspace(4) %loc, i64 1333 %ref = load ptr addrspace(4), ptr addrspace(4) %loc.off334 ret ptr addrspace(4) %ref335}336 337 338define void @smaller_vector(ptr %p) {339; CHECK-LABEL: @smaller_vector(340; CHECK-NEXT: entry:341; CHECK-NEXT: [[V4:%.*]] = load <4 x ptr addrspace(4)>, ptr [[P:%.*]], align 32342; CHECK-NEXT: [[V2:%.*]] = load <2 x ptr addrspace(4)>, ptr [[P]], align 32343; CHECK-NEXT: call void @use.v2(<2 x ptr addrspace(4)> [[V2]])344; CHECK-NEXT: call void @use.v4(<4 x ptr addrspace(4)> [[V4]])345; CHECK-NEXT: ret void346;347entry:348 %v4 = load <4 x ptr addrspace(4)>, ptr %p, align 32349 %v2 = load <2 x ptr addrspace(4)>, ptr %p, align 32350 call void @use.v2(<2 x ptr addrspace(4)> %v2)351 call void @use.v4(<4 x ptr addrspace(4)> %v4)352 ret void353}354 355define ptr addrspace(4) @vector_extract(ptr %p) {356; CHECK-LABEL: @vector_extract(357; CHECK-NEXT: entry:358; CHECK-NEXT: [[V4:%.*]] = load <4 x ptr addrspace(4)>, ptr [[P:%.*]], align 32359; CHECK-NEXT: [[RES:%.*]] = load ptr addrspace(4), ptr [[P]], align 32360; CHECK-NEXT: call void @use.v4(<4 x ptr addrspace(4)> [[V4]])361; CHECK-NEXT: ret ptr addrspace(4) [[RES]]362;363entry:364 %v4 = load <4 x ptr addrspace(4)>, ptr %p, align 32365 %res = load ptr addrspace(4), ptr %p, align 32366 call void @use.v4(<4 x ptr addrspace(4)> %v4)367 ret ptr addrspace(4) %res368}369 370declare void @use.v2(<2 x ptr addrspace(4)>)371declare void @use.v4(<4 x ptr addrspace(4)>)372 define ptr addrspace(5) @multini(i1 %alwaysFalse, ptr addrspace(4) %val, ptr %loc) {373; CHECK-LABEL: @multini(374; CHECK-NEXT: entry:375; CHECK-NEXT: store ptr addrspace(4) [[VAL:%.*]], ptr [[LOC:%.*]], align 8376; CHECK-NEXT: br i1 [[ALWAYSFALSE:%.*]], label [[NEVERTAKEN:%.*]], label [[ALWAYSTAKEN:%.*]]377; CHECK: neverTaken:378; CHECK-NEXT: [[DIFFERENTAS:%.*]] = load ptr addrspace(5), ptr [[LOC]], align 8379; CHECK-NEXT: ret ptr addrspace(5) [[DIFFERENTAS]]380; CHECK: alwaysTaken:381; CHECK-NEXT: ret ptr addrspace(5) null382;383 entry:384 store ptr addrspace(4) %val, ptr %loc385 br i1 %alwaysFalse, label %neverTaken, label %alwaysTaken386 387 neverTaken:388 %differentas = load ptr addrspace(5), ptr %loc389 ret ptr addrspace(5) %differentas390 391 alwaysTaken:392 ret ptr addrspace(5) null393 }394