[llvm] r215805 - BitcodeReader: Only create one basic block for each blockaddress

Duncan P. N. Exon Smith dexonsmith at apple.com
Fri Aug 15 18:54:38 PDT 2014


Author: dexonsmith
Date: Fri Aug 15 20:54:37 2014
New Revision: 215805

URL: http://llvm.org/viewvc/llvm-project?rev=215805&view=rev
Log:
BitcodeReader: Only create one basic block for each blockaddress

Block address forward-references are implemented by creating a
`BasicBlock` ahead of time that gets inserted in the `Function` when
it's eventually encountered.

However, if the same blockaddress was used in two separate functions
that were parsed *before* the referenced function (and the blockaddress
was never used at global scope), two separate basic blocks would get
created, one of which would be forgotten creating invalid IR.

This commit changes the forward-reference logic to create only one basic
block (and always return the same blockaddress).

Modified:
    llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
    llvm/trunk/lib/Bitcode/Reader/BitcodeReader.h
    llvm/trunk/test/Bitcode/blockaddress.ll

Modified: llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp?rev=215805&r1=215804&r2=215805&view=diff
==============================================================================
--- llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp (original)
+++ llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp Fri Aug 15 20:54:37 2014
@@ -1635,11 +1635,14 @@ std::error_code BitcodeReader::ParseCons
       } else {
         // Otherwise insert a placeholder and remember it so it can be inserted
         // when the function is parsed.
-        BB = BasicBlock::Create(Context);
         auto &FwdBBs = BasicBlockFwdRefs[Fn];
         if (FwdBBs.empty())
           BasicBlockFwdRefQueue.push_back(Fn);
-        FwdBBs.emplace_back(BBID, BB);
+        if (FwdBBs.size() < BBID + 1)
+          FwdBBs.resize(BBID + 1);
+        if (!FwdBBs[BBID])
+          FwdBBs[BBID] = BasicBlock::Create(Context);
+        BB = FwdBBs[BBID];
       }
       V = BlockAddress::get(Fn, BB);
       break;
@@ -2392,24 +2395,19 @@ std::error_code BitcodeReader::ParseFunc
           FunctionBBs[i] = BasicBlock::Create(Context, "", F);
       } else {
         auto &BBRefs = BBFRI->second;
-        std::sort(BBRefs.begin(), BBRefs.end(),
-                  [](const std::pair<unsigned, BasicBlock *> &LHS,
-                     const std::pair<unsigned, BasicBlock *> &RHS) {
-          return LHS.first < RHS.first;
-        });
-        unsigned R = 0, RE = BBRefs.size();
-        for (unsigned I = 0, E = FunctionBBs.size(); I != E; ++I)
-          if (R != RE && BBRefs[R].first == I) {
-            assert(I != 0 && "Invalid reference to entry block");
-            BasicBlock *BB = BBRefs[R++].second;
-            BB->insertInto(F);
-            FunctionBBs[I] = BB;
+        // Check for invalid basic block references.
+        if (BBRefs.size() > FunctionBBs.size())
+          return Error(BitcodeError::InvalidID);
+        assert(!BBRefs.empty() && "Unexpected empty array");
+        assert(!BBRefs.front() && "Invalid reference to entry block");
+        for (unsigned I = 0, E = FunctionBBs.size(), RE = BBRefs.size(); I != E;
+             ++I)
+          if (I < RE && BBRefs[I]) {
+            BBRefs[I]->insertInto(F);
+            FunctionBBs[I] = BBRefs[I];
           } else {
             FunctionBBs[I] = BasicBlock::Create(Context, "", F);
           }
-        // Check for invalid basic block references.
-        if (R != RE)
-          return Error(BitcodeError::InvalidID);
 
         // Erase from the table.
         BasicBlockFwdRefs.erase(BBFRI);

Modified: llvm/trunk/lib/Bitcode/Reader/BitcodeReader.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Reader/BitcodeReader.h?rev=215805&r1=215804&r2=215805&view=diff
==============================================================================
--- llvm/trunk/lib/Bitcode/Reader/BitcodeReader.h (original)
+++ llvm/trunk/lib/Bitcode/Reader/BitcodeReader.h Fri Aug 15 20:54:37 2014
@@ -181,9 +181,9 @@ class BitcodeReader : public GVMateriali
   DenseMap<Function*, uint64_t> DeferredFunctionInfo;
 
   /// These are basic blocks forward-referenced by block addresses.  They are
-  /// inserted lazily into functions when they're loaded.
-  typedef std::pair<unsigned, BasicBlock *> BasicBlockRefTy;
-  DenseMap<Function *, std::vector<BasicBlockRefTy>> BasicBlockFwdRefs;
+  /// inserted lazily into functions when they're loaded.  The basic block ID is
+  /// its index into the vector.
+  DenseMap<Function *, std::vector<BasicBlock *>> BasicBlockFwdRefs;
   std::deque<Function *> BasicBlockFwdRefQueue;
 
   /// UseRelativeIDs - Indicates that we are using a new encoding for

Modified: llvm/trunk/test/Bitcode/blockaddress.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/blockaddress.ll?rev=215805&r1=215804&r2=215805&view=diff
==============================================================================
--- llvm/trunk/test/Bitcode/blockaddress.ll (original)
+++ llvm/trunk/test/Bitcode/blockaddress.ll Fri Aug 15 20:54:37 2014
@@ -44,3 +44,17 @@ here:
 end:
   ret void
 }
+
+; Check a blockaddress taken in two separate functions before the referenced
+; function.
+define i8* @take1() {
+  ret i8* blockaddress(@taken, %bb)
+}
+define i8* @take2() {
+  ret i8* blockaddress(@taken, %bb)
+}
+define void @taken() {
+  unreachable
+bb:
+  unreachable
+}





More information about the llvm-commits mailing list