Fix pr14893.
authorRafael Espindola <rafael.espindola@gmail.com>
Tue, 28 Jan 2014 16:56:46 +0000 (16:56 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Tue, 28 Jan 2014 16:56:46 +0000 (16:56 +0000)
When simplifycfg moves an instruction, it must drop metadata it doesn't know
is still valid with the preconditions changes. In particular, it must drop
the range and tbaa metadata.

The patch implements this with an utility function to drop all metadata not
in a white list.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@200322 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/IR/Instruction.h
lib/IR/Metadata.cpp
lib/Transforms/Utils/SimplifyCFG.cpp
test/Transforms/SimplifyCFG/basictest.ll

index 5721d8f2f3fb8e1c9eac0e7fe4b55ac4a579d949..0a245483ff762e3458acfaf14c8a49e88c6be17f 100644 (file)
@@ -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<unsigned> KnownIDs);
+  void dropUnknownMetadata() {
+    return dropUnknownMetadata(ArrayRef<unsigned>());
+  }
+  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; }
 
index a32d25c92ae926e892da75c18fa7bf99585276ec..ad943de88cc5a5e9ede7827b078bd67250e8f568 100644 (file)
@@ -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<unsigned> KnownIDs) {
+  SmallSet<unsigned, 5> 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<const Instruction *, LLVMContextImpl::MDMapTy> &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.
index 0401b9a7f7d841cb6423aca129515b9eae5e6b42..effc08edaa3900066006371230f9719d733f7df6 100644 (file)
@@ -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");
index 9c4edd68b800c9e0b17af6b971196bb1a7613c3d..d6958a9c111aed3a8e4b4735bacb75a5b08e34fa 100644 (file)
@@ -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}