Index: llvm/lib/Transforms/Scalar/EarlyCSE.cpp =================================================================== --- llvm/lib/Transforms/Scalar/EarlyCSE.cpp +++ llvm/lib/Transforms/Scalar/EarlyCSE.cpp @@ -1095,6 +1095,11 @@ if (!Inst->use_empty()) Inst->replaceAllUsesWith(Op); removeMSSA(Inst); + + if (auto OpInst = dyn_cast(Op)) { + combineMetadataForCSE(OpInst, Inst, true); + } + Inst->eraseFromParent(); Changed = true; ++NumCSELoad; @@ -1226,6 +1231,7 @@ LLVM_DEBUG(dbgs() << "Skipping due to debug counter\n"); } else { removeMSSA(LastStore); + combineMetadataForCSE(Inst, LastStore, false); LastStore->eraseFromParent(); Changed = true; ++NumDSE; Index: llvm/test/Transforms/EarlyCSE/aliasing.ll =================================================================== --- /dev/null +++ llvm/test/Transforms/EarlyCSE/aliasing.ll @@ -0,0 +1,75 @@ +; RUN: opt < %s -S -early-cse | FileCheck %s +; RUN: opt < %s -S -basicaa -early-cse-memssa | FileCheck %s +; RUN: opt < %s -S -passes=early-cse | FileCheck %s + +; CHECK-LABEL: @pre.load.alias.scope( +define i32 @pre.load.alias.scope(i32* %a) { + ; CHECK-NOT: !alias.scope + %non_alias_load = load i32, i32* %a, align 4, !alias.scope !0 + %aliased_load = load i32, i32* %a, align 4 + %add = add i32 %non_alias_load, %aliased_load + ret i32 %add +} + +; CHECK-LABEL: @post.load.alias.scope( +define i32 @post.load.alias.scope(i32* %a) { + ; CHECK-NOT: !alias.scope + %non_alias_load = load i32, i32* %a, align 4 + %aliased_load = load i32, i32* %a, align 4, !alias.scope !0 + %add = add i32 %non_alias_load, %aliased_load + ret i32 %add +} + +; CHECK-LABEL: @pre.load.noalias( +define i32 @pre.load.noalias(i32* %a) { + ; CHECK-NOT: !noalias + %non_alias_load = load i32, i32* %a, align 4, !noalias !0 + %aliased_load = load i32, i32* %a, align 4 + %add = add i32 %non_alias_load, %aliased_load + ret i32 %add +} + +; CHECK-LABEL: @post.load.noalias( +define i32 @post.load.noalias(i32* %a) { + ; CHECK-NOT: !noalias + %non_alias_load = load i32, i32* %a, align 4 + %aliased_load = load i32, i32* %a, align 4, !noalias !0 + %add = add i32 %non_alias_load, %aliased_load + ret i32 %add +} + +; CHECK-LABEL: @pre.store.alias.scope( +define void @pre.store.alias.scope(i32* %a) { + ; CHECK-NOT: !alias.scope + store i32 42, i32* %a, !alias.scope !0 + store i32 13, i32* %a + ret void +} + +; CHECK-LABEL: @post.store.alias.scope( +define void @post.store.alias.scope(i32* %a) { + ; CHECK-NOT: !alias.scope + store i32 42, i32* %a + store i32 13, i32* %a, !alias.scope !0 + ret void +} + +; CHECK-LABEL: @pre.store.noalias( +define void @pre.store.noalias(i32* %a) { + ; CHECK-NOT: !noalias + store i32 42, i32* %a, !noalias !0 + store i32 13, i32* %a + ret void +} + +; CHECK-LABEL: @post.store.noalias( +define void @post.store.noalias(i32* %a) { + ; CHECK-NOT: !noalias + store i32 42, i32* %a + store i32 13, i32* %a, !noalias !0 + ret void +} + +!0 = !{!1} +!1 = distinct !{!1, !2, !"called: argument 0"} +!2 = distinct !{!2, !"called"} Index: llvm/test/Transforms/EarlyCSE/invariant-loads.ll =================================================================== --- llvm/test/Transforms/EarlyCSE/invariant-loads.ll +++ llvm/test/Transforms/EarlyCSE/invariant-loads.ll @@ -1,6 +1,11 @@ ; RUN: opt -S -early-cse < %s | FileCheck %s ; RUN: opt -S -basicaa -early-cse-memssa < %s | FileCheck %s +; FIXME: D73342 fixes EarlyCSE to use combineMetadataForCSE, +; which does not propagate !invariant.load correctly among +; two loads where only one has !invariant.load. +; XFAIL: * + declare void @clobber_and_use(i32) define void @f_0(i32* %ptr) {