Index: lib/Transforms/Scalar/EarlyCSE.cpp =================================================================== --- lib/Transforms/Scalar/EarlyCSE.cpp +++ lib/Transforms/Scalar/EarlyCSE.cpp @@ -487,9 +487,10 @@ // Skip assume intrinsics, they don't really have side effects (although // they're marked as such to ensure preservation of control dependencies), // and this pass will not disturb any of the assumption's control - // dependencies. - if (match(Inst, m_Intrinsic())) { - DEBUG(dbgs() << "EarlyCSE skipping assumption: " << *Inst << '\n'); + // dependencies. Likewise, noalias intrinsics don't actually write. + if (match(Inst, m_CombineOr(m_Intrinsic(), + m_Intrinsic()))) { + DEBUG(dbgs() << "EarlyCSE skipping intrinsic: " << *Inst << '\n'); continue; } Index: test/Transforms/EarlyCSE/basic.ll =================================================================== --- test/Transforms/EarlyCSE/basic.ll +++ test/Transforms/EarlyCSE/basic.ll @@ -54,6 +54,16 @@ ; CHECK: ret i32 0 } +; CHECK-LABEL: @test2b( +define i32 @test2b(i32 *%P, i1 %b) { + %V1 = load i32, i32* %P + call i8* @llvm.noalias.p0i8(i8* undef, metadata !1) + %V2 = load i32, i32* %P + %Diff = sub i32 %V1, %V2 + ret i32 %Diff + ; CHECK: ret i32 0 +} + ;; Cross block load value numbering. ; CHECK-LABEL: @test3( define i32 @test3(i32 *%P, i1 %Cond) { @@ -134,6 +144,15 @@ ; CHECK: ret i32 42 } +; CHECK-LABEL: @test6b( +define i32 @test6b(i32 *%P, i1 %b) { + store i32 42, i32* %P + call i8* @llvm.noalias.p0i8(i8* undef, metadata !1) + %V1 = load i32, i32* %P + ret i32 %V1 + ; CHECK: ret i32 42 +} + ;; Trivial dead store elimination. ; CHECK-LABEL: @test7( define void @test7(i32 *%P) { @@ -203,3 +222,9 @@ ; CHECK: load i32, i32* %P1 ; CHECK: load i32, i32* %P1 } + +declare i8* @llvm.noalias.p0i8(i8*, metadata) nounwind + +!0 = !{!0, !"some domain"} +!1 = !{!1, !0, !"some scope"} +