Add support for phi nodes in the LLVM C API test
authorAmaury Sechet <deadalnix@gmail.com>
Thu, 11 Feb 2016 21:37:54 +0000 (21:37 +0000)
committerAmaury Sechet <deadalnix@gmail.com>
Thu, 11 Feb 2016 21:37:54 +0000 (21:37 +0000)
Summary: This required to add binding to Instruction::removeFromParent so that instruction can be forward declared and then moved at the right place.

Reviewers: bogner, chandlerc, echristo, dblaikie, joker.eph, Wallbraker

Subscribers: llvm-commits

Differential Revision: http://reviews.llvm.org/D17057

llvm-svn: 260597

llvm/include/llvm-c/Core.h
llvm/lib/IR/Core.cpp
llvm/test/Bindings/llvm-c/echo.ll
llvm/tools/llvm-c-test/echo.cpp

index 7224adf..fab975f 100644 (file)
@@ -2332,6 +2332,16 @@ LLVMValueRef LLVMGetPreviousInstruction(LLVMValueRef Inst);
  * Remove and delete an instruction.
  *
  * The instruction specified is removed from its containing building
+ * block but is kept alive.
+ *
+ * @see llvm::Instruction::removeFromParent()
+ */
+void LLVMInstructionRemoveFromParent(LLVMValueRef Inst);
+
+/**
+ * Remove and delete an instruction.
+ *
+ * The instruction specified is removed from its containing building
  * block and then deleted.
  *
  * @see llvm::Instruction::eraseFromParent()
index 8093bb5..d3abe0b 100644 (file)
@@ -2005,6 +2005,10 @@ LLVMValueRef LLVMGetPreviousInstruction(LLVMValueRef Inst) {
   return wrap(&*--I);
 }
 
+void LLVMInstructionRemoveFromParent(LLVMValueRef Inst) {
+  unwrap<Instruction>(Inst)->removeFromParent();
+}
+
 void LLVMInstructionEraseFromParent(LLVMValueRef Inst) {
   unwrap<Instruction>(Inst)->eraseFromParent();
 }
index d6c27ea..df6de85 100644 (file)
@@ -90,3 +90,19 @@ next8:
 next9:
   ret i32 0
 }
+
+define i32 @loop(i32 %i) {
+  br label %cond
+cond:
+  %c = phi i32 [ %i, %0 ], [ %j, %do ]
+  %p = phi i32 [ %r, %do ], [ 789, %0 ]
+  %1 = icmp eq i32 %c, 0
+  br i1 %1, label %do, label %done
+do:
+  %2 = sub i32 %p, 23
+  %j = sub i32 %i, 1
+  %r = mul i32 %2, 3
+  br label %cond
+done:
+  ret i32 %p
+}
index 47f366c..8d679b6 100644 (file)
@@ -206,24 +206,20 @@ struct FunCloner {
     }
 
     // Function argument should always be in the map already.
-    if (LLVMIsAArgument(Src)) {
-      auto i = VMap.find(Src);
-      if (i != VMap.end())
-        return i->second;
-    }
+    auto i = VMap.find(Src);
+    if (i != VMap.end())
+      return i->second;
 
-    if (LLVMIsAInstruction(Src)) {
-      auto Ctx = LLVMGetModuleContext(M);
-      auto Builder = LLVMCreateBuilderInContext(Ctx);
-      auto BB = DeclareBB(LLVMGetInstructionParent(Src));
-      LLVMPositionBuilderAtEnd(Builder, BB);
-      auto Dst = CloneInstruction(Src, Builder);
-      LLVMDisposeBuilder(Builder);
-      return Dst;
-    }
+    if (!LLVMIsAInstruction(Src))
+      report_fatal_error("Expected an instruction");
 
-    fprintf(stderr, "Could not determine the type of %s\n", Name);
-    exit(-1);
+    auto Ctx = LLVMGetModuleContext(M);
+    auto Builder = LLVMCreateBuilderInContext(Ctx);
+    auto BB = DeclareBB(LLVMGetInstructionParent(Src));
+    LLVMPositionBuilderAtEnd(Builder, BB);
+    auto Dst = CloneInstruction(Src, Builder);
+    LLVMDisposeBuilder(Builder);
+    return Dst;
   }
 
   LLVMValueRef CloneInstruction(LLVMValueRef Src, LLVMBuilderRef Builder) {
@@ -234,8 +230,15 @@ struct FunCloner {
     // Check if this is something we already computed.
     {
       auto i = VMap.find(Src);
-      if (i != VMap.end())
-        return i->second;
+      if (i != VMap.end()) {
+        // If we have a hit, it means we already generated the instruction
+        // as a dependancy to somethign else. We need to make sure
+        // it is ordered properly.
+        auto I = i->second;
+        LLVMInstructionRemoveFromParent(I);
+        LLVMInsertIntoBuilderWithName(Builder, I, Name);
+        return I;
+      }
     }
 
     // We tried everything, it must be an instruction
@@ -365,6 +368,22 @@ struct FunCloner {
         Dst = LLVMBuildICmp(Builder, Pred, LHS, RHS, Name);
         break;
       }
+      case LLVMPHI: {
+        // We need to agressively set things here because of loops.
+        VMap[Src] = Dst = LLVMBuildPhi(Builder, CloneType(Src), Name);
+
+        SmallVector<LLVMValueRef, 8> Values;
+        SmallVector<LLVMBasicBlockRef, 8> Blocks;
+
+        unsigned IncomingCount = LLVMCountIncoming(Src);
+        for (unsigned i = 0; i < IncomingCount; ++i) {
+          Blocks.push_back(DeclareBB(LLVMGetIncomingBlock(Src, i)));
+          Values.push_back(CloneValue(LLVMGetIncomingValue(Src, i)));
+        }
+
+        LLVMAddIncoming(Dst, Values.data(), Blocks.data(), IncomingCount);
+        return Dst;
+      }
       case LLVMCall: {
         SmallVector<LLVMValueRef, 8> Args;
         int ArgCount = LLVMGetNumArgOperands(Src);