Index: llvm/lib/Transforms/Scalar/EarlyCSE.cpp =================================================================== --- llvm/lib/Transforms/Scalar/EarlyCSE.cpp +++ llvm/lib/Transforms/Scalar/EarlyCSE.cpp @@ -1095,6 +1095,14 @@ if (!Inst->use_empty()) Inst->replaceAllUsesWith(Op); removeMSSA(Inst); + + if (auto OpInst = dyn_cast(Op)) { + AAMDNodes AAMD; + Inst->getAAMetadata(AAMD); + OpInst->getAAMetadata(AAMD, true); + OpInst->setAAMetadata(AAMD); + } + Inst->eraseFromParent(); Changed = true; ++NumCSELoad; @@ -1226,6 +1234,10 @@ LLVM_DEBUG(dbgs() << "Skipping due to debug counter\n"); } else { removeMSSA(LastStore); + AAMDNodes AAMD; + LastStore->getAAMetadata(AAMD); + Inst->getAAMetadata(AAMD, true); + Inst->setAAMetadata(AAMD); 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: !alias.scope + 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"}