From 2f43208c9a5564fa9e13fe72082099322fd5e426 Mon Sep 17 00:00:00 2001 From: Amaury Sechet Date: Thu, 11 Feb 2016 21:37:54 +0000 Subject: [PATCH] Add support for phi nodes in the LLVM C API test 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 | 10 +++++++ llvm/lib/IR/Core.cpp | 4 +++ llvm/test/Bindings/llvm-c/echo.ll | 16 ++++++++++++ llvm/tools/llvm-c-test/echo.cpp | 55 ++++++++++++++++++++++++++------------- 4 files changed, 67 insertions(+), 18 deletions(-) diff --git a/llvm/include/llvm-c/Core.h b/llvm/include/llvm-c/Core.h index 7224adf..fab975f 100644 --- a/llvm/include/llvm-c/Core.h +++ b/llvm/include/llvm-c/Core.h @@ -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() diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp index 8093bb5..d3abe0b 100644 --- a/llvm/lib/IR/Core.cpp +++ b/llvm/lib/IR/Core.cpp @@ -2005,6 +2005,10 @@ LLVMValueRef LLVMGetPreviousInstruction(LLVMValueRef Inst) { return wrap(&*--I); } +void LLVMInstructionRemoveFromParent(LLVMValueRef Inst) { + unwrap(Inst)->removeFromParent(); +} + void LLVMInstructionEraseFromParent(LLVMValueRef Inst) { unwrap(Inst)->eraseFromParent(); } diff --git a/llvm/test/Bindings/llvm-c/echo.ll b/llvm/test/Bindings/llvm-c/echo.ll index d6c27ea..df6de85 100644 --- a/llvm/test/Bindings/llvm-c/echo.ll +++ b/llvm/test/Bindings/llvm-c/echo.ll @@ -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 +} diff --git a/llvm/tools/llvm-c-test/echo.cpp b/llvm/tools/llvm-c-test/echo.cpp index 47f366c..8d679b6 100644 --- a/llvm/tools/llvm-c-test/echo.cpp +++ b/llvm/tools/llvm-c-test/echo.cpp @@ -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 Values; + SmallVector 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 Args; int ArgCount = LLVMGetNumArgOperands(Src); -- 2.7.4