268 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt -passes=dse -S %s | FileCheck %s3 4; Both the stores in %then and %else can be eliminated by translating %p5; through the phi.6define void @memoryphi_translate_1(i1 %c) {7; CHECK-LABEL: @memoryphi_translate_1(8; CHECK-NEXT: entry:9; CHECK-NEXT: [[A_1:%.*]] = alloca i8, align 110; CHECK-NEXT: [[A_2:%.*]] = alloca i8, align 111; CHECK-NEXT: br i1 [[C:%.*]], label [[THEN:%.*]], label [[ELSE:%.*]]12; CHECK: then:13; CHECK-NEXT: br label [[END:%.*]]14; CHECK: else:15; CHECK-NEXT: br label [[END]]16; CHECK: end:17; CHECK-NEXT: [[P:%.*]] = phi ptr [ [[A_1]], [[THEN]] ], [ [[A_2]], [[ELSE]] ]18; CHECK-NEXT: store i8 10, ptr [[P]], align 119; CHECK-NEXT: ret void20;21entry:22 %a.1 = alloca i823 %a.2 = alloca i824 br i1 %c, label %then, label %else25 26then:27 store i8 0, ptr %a.128 br label %end29 30else:31 store i8 9, ptr %a.232 br label %end33 34end:35 %p = phi ptr [ %a.1, %then ], [ %a.2, %else ]36 store i8 10, ptr %p37 ret void38}39 40; The store in %else can be eliminated by translating %p through the phi.41; The store in %then cannot be eliminated, because %a.1 is read before the final42; store.43define i8 @memoryphi_translate_2(i1 %c) {44; CHECK-LABEL: @memoryphi_translate_2(45; CHECK-NEXT: entry:46; CHECK-NEXT: [[A_1:%.*]] = alloca i8, align 147; CHECK-NEXT: [[A_2:%.*]] = alloca i8, align 148; CHECK-NEXT: br i1 [[C:%.*]], label [[THEN:%.*]], label [[ELSE:%.*]]49; CHECK: then:50; CHECK-NEXT: store i8 0, ptr [[A_1]], align 151; CHECK-NEXT: br label [[END:%.*]]52; CHECK: else:53; CHECK-NEXT: br label [[END]]54; CHECK: end:55; CHECK-NEXT: [[P:%.*]] = phi ptr [ [[A_1]], [[THEN]] ], [ [[A_2]], [[ELSE]] ]56; CHECK-NEXT: [[L:%.*]] = load i8, ptr [[A_1]], align 157; CHECK-NEXT: store i8 10, ptr [[P]], align 158; CHECK-NEXT: ret i8 [[L]]59;60entry:61 %a.1 = alloca i862 %a.2 = alloca i863 br i1 %c, label %then, label %else64 65then:66 store i8 0, ptr %a.167 br label %end68 69else:70 store i8 9, ptr %a.271 br label %end72 73end:74 %p = phi ptr [ %a.1, %then ], [ %a.2, %else ]75 %l = load i8, ptr %a.176 store i8 10, ptr %p77 ret i8 %l78}79 80; The store in %then can be eliminated by translating %p through the phi.81; The store in %else cannot be eliminated, because %a.2 is read before the final82; store.83define i8 @memoryphi_translate_3(i1 %c) {84; CHECK-LABEL: @memoryphi_translate_3(85; CHECK-NEXT: entry:86; CHECK-NEXT: [[A_1:%.*]] = alloca i8, align 187; CHECK-NEXT: [[A_2:%.*]] = alloca i8, align 188; CHECK-NEXT: br i1 [[C:%.*]], label [[THEN:%.*]], label [[ELSE:%.*]]89; CHECK: then:90; CHECK-NEXT: br label [[END:%.*]]91; CHECK: else:92; CHECK-NEXT: store i8 9, ptr [[A_2]], align 193; CHECK-NEXT: br label [[END]]94; CHECK: end:95; CHECK-NEXT: [[P:%.*]] = phi ptr [ [[A_1]], [[THEN]] ], [ [[A_2]], [[ELSE]] ]96; CHECK-NEXT: [[L:%.*]] = load i8, ptr [[A_2]], align 197; CHECK-NEXT: store i8 10, ptr [[P]], align 198; CHECK-NEXT: ret i8 [[L]]99;100entry:101 %a.1 = alloca i8102 %a.2 = alloca i8103 br i1 %c, label %then, label %else104 105then:106 store i8 0, ptr %a.1107 br label %end108 109else:110 store i8 9, ptr %a.2111 br label %end112 113end:114 %p = phi ptr [ %a.1, %then ], [ %a.2, %else ]115 %l = load i8, ptr %a.2116 store i8 10, ptr %p117 ret i8 %l118}119 120; No stores can be eliminated, because there's a load from the phi.121define i8 @memoryphi_translate_4(i1 %c) {122; CHECK-LABEL: @memoryphi_translate_4(123; CHECK-NEXT: entry:124; CHECK-NEXT: [[A_1:%.*]] = alloca i8, align 1125; CHECK-NEXT: [[A_2:%.*]] = alloca i8, align 1126; CHECK-NEXT: br i1 [[C:%.*]], label [[THEN:%.*]], label [[ELSE:%.*]]127; CHECK: then:128; CHECK-NEXT: store i8 0, ptr [[A_1]], align 1129; CHECK-NEXT: br label [[END:%.*]]130; CHECK: else:131; CHECK-NEXT: store i8 9, ptr [[A_2]], align 1132; CHECK-NEXT: br label [[END]]133; CHECK: end:134; CHECK-NEXT: [[P:%.*]] = phi ptr [ [[A_1]], [[THEN]] ], [ [[A_2]], [[ELSE]] ]135; CHECK-NEXT: [[L:%.*]] = load i8, ptr [[P]], align 1136; CHECK-NEXT: store i8 10, ptr [[P]], align 1137; CHECK-NEXT: ret i8 [[L]]138;139entry:140 %a.1 = alloca i8141 %a.2 = alloca i8142 br i1 %c, label %then, label %else143 144then:145 store i8 0, ptr %a.1146 br label %end147 148else:149 store i8 9, ptr %a.2150 br label %end151 152end:153 %p = phi ptr [ %a.1, %then ], [ %a.2, %else ]154 %l = load i8, ptr %p155 store i8 10, ptr %p156 ret i8 %l157}158 159; TODO: The store in %entry can be removed by translating %p through the phi.160define void @memoryphi_translate_5(i1 %cond) {161; CHECK-LABEL: @memoryphi_translate_5(162; CHECK-NEXT: entry:163; CHECK-NEXT: [[A:%.*]] = alloca i8, align 1164; CHECK-NEXT: [[B:%.*]] = alloca i8, align 1165; CHECK-NEXT: store i8 0, ptr [[A]], align 1166; CHECK-NEXT: br i1 [[COND:%.*]], label [[COND_TRUE:%.*]], label [[COND_END:%.*]]167; CHECK: cond.true:168; CHECK-NEXT: br label [[COND_END]]169; CHECK: cond.end:170; CHECK-NEXT: [[P:%.*]] = phi ptr [ [[B]], [[COND_TRUE]] ], [ [[A]], [[ENTRY:%.*]] ]171; CHECK-NEXT: store i8 0, ptr [[P]], align 1172; CHECK-NEXT: call void @use(ptr [[P]])173; CHECK-NEXT: ret void174;175entry:176 %a = alloca i8177 %b = alloca i8178 %c = alloca i8179 store i8 0, ptr %a180 br i1 %cond, label %cond.true, label %cond.end181 182cond.true:183 store i8 0, ptr %c184 br label %cond.end185 186cond.end:187 %p = phi ptr [ %b, %cond.true ], [ %a, %entry ]188 store i8 0, ptr %p189 call void @use(ptr %p)190 ret void191}192 193; TODO: The store in %entry can be removed by translating %p through the phi.194; Same as @memoryphi_translate_5, but without stores in %cond.true, so there195; is no MemoryPhi.196define void @translate_without_memoryphi_1(i1 %cond) {197; CHECK-LABEL: @translate_without_memoryphi_1(198; CHECK-NEXT: entry:199; CHECK-NEXT: [[A:%.*]] = alloca i8, align 1200; CHECK-NEXT: [[B:%.*]] = alloca i8, align 1201; CHECK-NEXT: store i8 0, ptr [[A]], align 1202; CHECK-NEXT: br i1 [[COND:%.*]], label [[COND_TRUE:%.*]], label [[COND_END:%.*]]203; CHECK: cond.true:204; CHECK-NEXT: br label [[COND_END]]205; CHECK: cond.end:206; CHECK-NEXT: [[P:%.*]] = phi ptr [ [[B]], [[COND_TRUE]] ], [ [[A]], [[ENTRY:%.*]] ]207; CHECK-NEXT: store i8 0, ptr [[P]], align 1208; CHECK-NEXT: call void @use(ptr [[P]])209; CHECK-NEXT: ret void210;211entry:212 %a = alloca i8213 %b = alloca i8214 store i8 0, ptr %a215 br i1 %cond, label %cond.true, label %cond.end216 217cond.true:218 br label %cond.end219 220cond.end:221 %p = phi ptr [ %b, %cond.true ], [ %a, %entry ]222 store i8 0, ptr %p223 call void @use(ptr %p)224 ret void225}226 227; In the test, translating through the phi results in a null address. Make sure228; this does not cause a crash.229define void @test_trans_null(i1 %c, ptr %ptr) {230; CHECK-LABEL: @test_trans_null(231; CHECK-NEXT: entry:232; CHECK-NEXT: br i1 [[C:%.*]], label [[THEN:%.*]], label [[ELSE:%.*]]233; CHECK: then:234; CHECK-NEXT: br label [[EXIT:%.*]]235; CHECK: else:236; CHECK-NEXT: call void @fn()237; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr inbounds i16, ptr undef, i64 2238; CHECK-NEXT: store i16 8, ptr [[GEP_1]], align 2239; CHECK-NEXT: br label [[EXIT]]240; CHECK: exit:241; CHECK-NEXT: [[P:%.*]] = phi ptr [ [[PTR:%.*]], [[THEN]] ], [ undef, [[ELSE]] ]242; CHECK-NEXT: [[GEP_2:%.*]] = getelementptr inbounds i16, ptr [[P]], i64 2243; CHECK-NEXT: store i16 8, ptr [[GEP_2]], align 2244; CHECK-NEXT: ret void245;246entry:247 br i1 %c, label %then, label %else248 249then:250 br label %exit251 252else:253 call void @fn()254 %gep.1 = getelementptr inbounds i16, ptr undef, i64 2255 store i16 8, ptr %gep.1, align 2256 br label %exit257 258exit:259 %p = phi ptr [ %ptr, %then ], [ undef, %else ]260 %gep.2 = getelementptr inbounds i16, ptr %p, i64 2261 store i16 8, ptr %gep.2, align 2262 ret void263}264 265 266declare void @use(ptr)267declare void @fn()268