diff --git a/include/llvm/IR/Instruction.h b/include/llvm/IR/Instruction.h index 5721d8f2f3f..0a245483ff7 100644 --- a/include/llvm/IR/Instruction.h +++ b/include/llvm/IR/Instruction.h @@ -15,6 +15,7 @@ #ifndef LLVM_IR_INSTRUCTION_H #define LLVM_IR_INSTRUCTION_H +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/ilist_node.h" #include "llvm/IR/User.h" #include "llvm/Support/DebugLoc.h" @@ -171,6 +172,21 @@ public: void setMetadata(unsigned KindID, MDNode *Node); void setMetadata(StringRef Kind, MDNode *Node); + /// \brief Drop unknown metadata. + /// Passes are required to drop metadata they don't understand. This is a + /// convenience method for passes to do so. + void dropUnknownMetadata(ArrayRef KnownIDs); + void dropUnknownMetadata() { + return dropUnknownMetadata(ArrayRef()); + } + void dropUnknownMetadata(unsigned ID1) { + return dropUnknownMetadata(makeArrayRef(ID1)); + } + void dropUnknownMetadata(unsigned ID1, unsigned ID2) { + unsigned IDs[] = {ID1, ID2}; + return dropUnknownMetadata(IDs); + } + /// setDebugLoc - Set the debug location information for this instruction. void setDebugLoc(const DebugLoc &Loc) { DbgLoc = Loc; } diff --git a/lib/IR/Metadata.cpp b/lib/IR/Metadata.cpp index a32d25c92ae..ad943de88cc 100644 --- a/lib/IR/Metadata.cpp +++ b/lib/IR/Metadata.cpp @@ -16,6 +16,7 @@ #include "SymbolTableListTraitsImpl.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringMap.h" #include "llvm/IR/Instruction.h" @@ -583,6 +584,50 @@ MDNode *Instruction::getMetadataImpl(StringRef Kind) const { return getMetadataImpl(getContext().getMDKindID(Kind)); } +void Instruction::dropUnknownMetadata(ArrayRef KnownIDs) { + SmallSet KnownSet; + KnownSet.insert(KnownIDs.begin(), KnownIDs.end()); + + // Drop debug if needed + if (KnownSet.erase(LLVMContext::MD_dbg)) + DbgLoc = DebugLoc(); + + if (!hasMetadataHashEntry()) + return; // Nothing to remove! + + DenseMap &MetadataStore = + getContext().pImpl->MetadataStore; + + if (KnownSet.empty()) { + // Just drop our entry at the store. + MetadataStore.erase(this); + setHasMetadataHashEntry(false); + return; + } + + LLVMContextImpl::MDMapTy &Info = MetadataStore[this]; + unsigned I; + unsigned E; + // Walk the array and drop any metadata we don't know. + for (I = 0, E = Info.size(); I != E;) { + if (KnownSet.count(Info[I].first)) { + ++I; + continue; + } + + Info[I] = Info.back(); + Info.pop_back(); + --E; + } + assert(E == Info.size()); + + if (E == 0) { + // Drop our entry at the store. + MetadataStore.erase(this); + setHasMetadataHashEntry(false); + } +} + /// setMetadata - Set the metadata of of the specified kind to the specified /// node. This updates/replaces metadata if already present, or removes it if /// Node is null. diff --git a/lib/Transforms/Utils/SimplifyCFG.cpp b/lib/Transforms/Utils/SimplifyCFG.cpp index 0401b9a7f7d..effc08edaa3 100644 --- a/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/lib/Transforms/Utils/SimplifyCFG.cpp @@ -2154,6 +2154,14 @@ bool llvm::FoldBranchToCommonDest(BranchInst *BI) { Instruction *NewBonus = 0; if (BonusInst) { NewBonus = BonusInst->clone(); + + // If we moved a load, we cannot any longer claim any knowledge about + // its potential value. The previous information might have been valid + // only given the branch precondition. + // For an analogous reason, we must also drop all the metadata whose + // semantics we don't understand. + NewBonus->dropUnknownMetadata(LLVMContext::MD_dbg); + PredBlock->getInstList().insert(PBI, NewBonus); NewBonus->takeName(BonusInst); BonusInst->setName(BonusInst->getName()+".old"); diff --git a/test/Transforms/SimplifyCFG/basictest.ll b/test/Transforms/SimplifyCFG/basictest.ll index 9c4edd68b80..d6958a9c111 100644 --- a/test/Transforms/SimplifyCFG/basictest.ll +++ b/test/Transforms/SimplifyCFG/basictest.ll @@ -41,3 +41,33 @@ return: ; preds = %entry ; CHECK-LABEL: @test5( ; CHECK-NEXT: ret void } + + +; PR14893 +define i8 @test6f() { +; CHECK-LABEL: @test6f +; CHECK: alloca i8, align 1 +; CHECK-NEXT: call i8 @test6g +; CHECK-NEXT: icmp eq i8 %tmp, 0 +; CHECK-NEXT: load i8* %r, align 1{{$}} + +bb0: + %r = alloca i8, align 1 + %tmp = call i8 @test6g(i8* %r) + %tmp1 = icmp eq i8 %tmp, 0 + br i1 %tmp1, label %bb2, label %bb1 +bb1: + %tmp3 = load i8* %r, align 1, !range !2, !tbaa !1 + %tmp4 = icmp eq i8 %tmp3, 1 + br i1 %tmp4, label %bb2, label %bb3 +bb2: + br label %bb3 +bb3: + %tmp6 = phi i8 [ 0, %bb2 ], [ 1, %bb1 ] + ret i8 %tmp6 +} +declare i8 @test6g(i8*) + +!0 = metadata !{metadata !1, metadata !1, i64 0} +!1 = metadata !{metadata !"foo"} +!2 = metadata !{i8 0, i8 2}