From cdb4bf651ddf09ba3cc59457a9b7c7dd710d7375 Mon Sep 17 00:00:00 2001 From: Zhengyang Liu Date: Wed, 15 Jan 2020 06:39:23 +0000 Subject: [PATCH] ugly foo --- include/souper/Codegen/Codegen.h | 13 +++- lib/Codegen/Codegen.cpp | 104 ++++++++++++++++++++++++++++--- lib/Extractor/Candidates.cpp | 3 - lib/Inst/Inst.cpp | 5 +- lib/Pass/Pass.cpp | 2 +- tools/souper2llvm.cpp | 33 ++++++---- 6 files changed, 132 insertions(+), 28 deletions(-) diff --git a/include/souper/Codegen/Codegen.h b/include/souper/Codegen/Codegen.h index ed8a88d18..79ff1768d 100644 --- a/include/souper/Codegen/Codegen.h +++ b/include/souper/Codegen/Codegen.h @@ -20,6 +20,7 @@ #include "llvm/IR/IRBuilder.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" +#include "llvm/IR/Function.h" #include "llvm/IR/Value.h" #include @@ -28,22 +29,28 @@ namespace souper { class Codegen { llvm::LLVMContext &Context; llvm::Module *M; + llvm::Function *F; llvm::IRBuilder<> &Builder; llvm::DominatorTree *DT; llvm::Instruction *ReplacedInst; const std::map &ReplacedValues; - + + llvm::Value *getValueHelper(Inst *I, std::map &Cache, std::map &BM); + bool GenControlFlow = false; public: Codegen(llvm::LLVMContext &Context_, llvm::Module *M_, llvm::IRBuilder<> &Builder_, llvm::DominatorTree *DT_, llvm::Instruction *ReplacedInst_, - const std::map &ReplacedValues_) + const std::map &ReplacedValues_, + bool GenControlFlow_) : Context(Context_), M(M_), Builder(Builder_), DT(DT_), - ReplacedInst(ReplacedInst_), ReplacedValues(ReplacedValues_) {} + ReplacedInst(ReplacedInst_), ReplacedValues(ReplacedValues_), + GenControlFlow(GenControlFlow_) {} static llvm::Type *GetInstReturnType(llvm::LLVMContext &Context, Inst *I); + llvm::Function *getFunction(Inst *I, const InstContext &IC); llvm::Value *getValue(Inst *I); }; diff --git a/lib/Codegen/Codegen.cpp b/lib/Codegen/Codegen.cpp index 42459cfe7..7ff79bd1d 100644 --- a/lib/Codegen/Codegen.cpp +++ b/lib/Codegen/Codegen.cpp @@ -48,7 +48,7 @@ llvm::Type *Codegen::GetInstReturnType(llvm::LLVMContext &Context, Inst *I) { } } -llvm::Value *Codegen::getValue(Inst *I) { +llvm::Value *Codegen::getValueHelper(Inst *I, std::map &C, std::map &BM) { const std::vector &Ops = I->orderedOps(); if (I->K == Inst::UntypedConst) { // FIXME: We only get here because it is the second argument of @@ -67,6 +67,44 @@ llvm::Value *Codegen::getValue(Inst *I) { if (ReplacedValues.find(I) != ReplacedValues.end()) return ReplacedValues.at(I); + if (C.find(I) != C.end()) + return C.at(I); + + if (GenControlFlow && I->K == Inst::Phi) { + std::vector Preds; + std::vector Incomes; + BasicBlock *E = Builder.GetInsertBlock(); + BasicBlock *NextBB = BasicBlock::Create(Context, "cont", F); + + BasicBlock *DefaultNextBB; + for (int i = 0 ; i < I->Ops.size(); i ++) { + BasicBlock *BB = BasicBlock::Create(Context, "phi", F); + Builder.SetInsertPoint(BB); + Value *V0 = Codegen::getValueHelper(Ops[i], C, BM); + Builder.CreateBr(NextBB); + Preds.emplace_back(BB); + Incomes.emplace_back(V0); + if (i == 0) DefaultNextBB = BB; + } + + + Builder.SetInsertPoint(E); + Value *D = BM[I->B]; + SwitchInst *SI = Builder.CreateSwitch(D, DefaultNextBB); + + for (int i = 1 ; i < I->Ops.size(); i ++) { + SI->addCase(ConstantInt::get(Type::getIntNTy(Context, 32), i), Preds[i]); + } + + Builder.SetInsertPoint(NextBB); + PHINode *Phi = Builder.CreatePHI(GetInstReturnType(Context, I), 1); + for (int i = 0 ; i < Preds.size() ; i ++) { + Phi->addIncoming(Incomes[i], Preds[i]); + } + C[I] = Phi; + return Phi; + } + if (I->Origins.size() > 0) { // if there's an Origin, we're connecting to existing code for (auto V : I->Origins) { @@ -89,7 +127,7 @@ llvm::Value *Codegen::getValue(Inst *I) { } // otherwise, recursively generate code - Value *V0 = Codegen::getValue(Ops[0]); + Value *V0 = Codegen::getValueHelper(Ops[0], C, BM); if (!V0) return nullptr; @@ -137,7 +175,7 @@ llvm::Value *Codegen::getValue(Inst *I) { break; } case 2: { - Value *V1 = Codegen::getValue(Ops[1]); + Value *V1 = Codegen::getValueHelper(Ops[1], C, BM); if (!V1) return nullptr; switch (I->K) { @@ -233,8 +271,8 @@ llvm::Value *Codegen::getValue(Inst *I) { report_fatal_error( "Inst::*WithOverflow with non-identical args unsupported."); } - V0 = Codegen::getValue(Ops[0]->orderedOps()[0]); - V1 = Codegen::getValue(Ops[0]->orderedOps()[1]); + V0 = Codegen::getValueHelper(Ops[0]->orderedOps()[0], C, BM); + V1 = Codegen::getValueHelper(Ops[0]->orderedOps()[1], C, BM); Intrinsic::ID ID = [K = I->K]() { switch (K) { case Inst::SAddWithOverflow: @@ -272,8 +310,8 @@ llvm::Value *Codegen::getValue(Inst *I) { break; } case 3: { - Value *V1 = Codegen::getValue(Ops[1]); - Value *V2 = Codegen::getValue(Ops[2]); + Value *V1 = Codegen::getValueHelper(Ops[1], C, BM); + Value *V2 = Codegen::getValueHelper(Ops[2], C, BM); if (!V1 || !V2) return nullptr; switch (I->K) { @@ -304,4 +342,56 @@ llvm::Value *Codegen::getValue(Inst *I) { Inst::getKindName(I->K) + " in Codegen::getValue()"); } +llvm::Value *Codegen::getValue(Inst *I) { + std::map C; + std::map BM; + getValueHelper(I, C, BM); +} + +static std::vector +GetInputArgumentTypes(const InstContext &IC, llvm::LLVMContext &Context) { + const std::vector AllVariables = IC.getVariables(); + + std::vector ArgTypes; + ArgTypes.reserve(AllVariables.size()); + for (const Inst *const Var : AllVariables) + ArgTypes.emplace_back(Type::getIntNTy(Context, Var->Width)); + + return ArgTypes; +} + +static std::map GetArgsMapping(const InstContext &IC, + Function *F) { + std::map Args; + + const std::vector AllVariables = IC.getVariables(); + for (auto zz : llvm::zip(AllVariables, F->args())) + Args[std::get<0>(zz)] = &(std::get<1>(zz)); + + return Args; +}; + + +llvm::Function *Codegen::getFunction(Inst *I, const InstContext &IC) { + F = Builder.GetInsertBlock()->getParent(); + auto PhiDet = M->getOrInsertFunction("phi_det", + FunctionType::getInt32Ty(Context)); + + + std::vector Blocks = souper::getBlocksFromPhis(I); + std::map BlockMap; + + for (int i = 0 ; i < Blocks.size(); i ++) { + Value *V = Builder.CreateCall(PhiDet, {}); + BlockMap[Blocks[i]] = V; + } + + std::map C; + Value *RetVal = getValueHelper(I, C, BlockMap); + + Builder.CreateRet(RetVal); + + return F; +} + } // namespace souper diff --git a/lib/Extractor/Candidates.cpp b/lib/Extractor/Candidates.cpp index 73ea3613b..4c4a2ef5e 100644 --- a/lib/Extractor/Candidates.cpp +++ b/lib/Extractor/Candidates.cpp @@ -504,9 +504,6 @@ Inst *ExprBuilder::buildHelper(Value *V) { // TODO: In principle we could track loop iterations and maybe even maintain // a separate set of values for each iteration (as in bounded model // checking). - if (UseAlive) { // FIXME: Remove this after alive supports phi - return makeArrayRead(V); - } if (!isLoopEntryPoint(Phi)) { BasicBlock *BB = Phi->getParent(); BlockInfo &BI = EBC.BlockMap[BB]; diff --git a/lib/Inst/Inst.cpp b/lib/Inst/Inst.cpp index d29f4290d..0116abdf1 100644 --- a/lib/Inst/Inst.cpp +++ b/lib/Inst/Inst.cpp @@ -771,6 +771,7 @@ std::vector InstContext::getVariables() const { for (const auto &OuterIter : VarInstsByWidth) { for (const auto &InnerIter : OuterIter.getSecond()) { assert(InnerIter->K == Inst::Kind::Var); + if (InnerIter->Name == "blockpred") continue; AllVariables.emplace_back(InnerIter.get()); } } @@ -1303,8 +1304,8 @@ std::vector souper::getBlocksFromPhis(Inst *I) { Q.pop(); if (I->K == Inst::Phi) Result.push_back(I->B); - if (Visited.insert(I).second) - for (auto Op : I->orderedOps()) + for (auto Op : I->orderedOps()) + if (Visited.insert(Op).second) Q.push(Op); } diff --git a/lib/Pass/Pass.cpp b/lib/Pass/Pass.cpp index 9c4aae580..b2e98be55 100644 --- a/lib/Pass/Pass.cpp +++ b/lib/Pass/Pass.cpp @@ -186,7 +186,7 @@ struct SouperPass : public ModulePass { std::map &ReplacedValues, IRBuilder<> &Builder, Module *M) { return Codegen(ReplacedInst->getContext(), M, Builder, &DT, ReplacedInst, - ReplacedValues) + ReplacedValues, false) .getValue(I); } diff --git a/tools/souper2llvm.cpp b/tools/souper2llvm.cpp index 0d1d0a036..d32bb6fc5 100644 --- a/tools/souper2llvm.cpp +++ b/tools/souper2llvm.cpp @@ -28,6 +28,10 @@ static cl::opt cl::desc(""), cl::init("-")); +static cl::opt GenCF("gen-cf", + cl::desc("Generate LLVM bitcode with control flow"), + cl::init(false)); + static cl::opt OutputFilename( "o", cl::desc(""), cl::init("-")); @@ -70,26 +74,31 @@ int Work(const MemoryBufferRef &MB) { llvm::LLVMContext Context; llvm::Module Module("souper.ll", Context); - + Function *F; const std::vector ArgTypes = GetInputArgumentTypes(IC, Context); const auto FT = llvm::FunctionType::get( - /*Result=*/Codegen::GetInstReturnType(Context, RepRHS.Mapping.RHS), - /*Params=*/ArgTypes, /*isVarArg=*/false); - - Function *F = Function::Create(FT, Function::ExternalLinkage, "fun", &Module); - + /*Result=*/Codegen::GetInstReturnType(Context, RepRHS.Mapping.RHS), + /*Params=*/ArgTypes, /*isVarArg=*/false); + + F = Function::Create(FT, Function::ExternalLinkage, "fun", &Module); const std::map Args = GetArgsMapping(IC, F); - + BasicBlock *BB = BasicBlock::Create(Context, "entry", F); llvm::IRBuilder<> Builder(Context); Builder.SetInsertPoint(BB); - Value *RetVal = Codegen(Context, &Module, Builder, /*DT*/ nullptr, - /*ReplacedInst*/ nullptr, Args) - .getValue(RepRHS.Mapping.RHS); - - Builder.CreateRet(RetVal); + if (GenCF) { + F = Codegen(Context, &Module, Builder, /*DT*/ nullptr, nullptr, + /*ReplacedInst*/ Args, true) + .getFunction(RepRHS.Mapping.RHS, IC); + } else { + Value *RetVal = Codegen(Context, &Module, Builder, /*DT*/ nullptr, + /*ReplacedInst*/ nullptr, Args, false) + .getValue(RepRHS.Mapping.RHS); + + Builder.CreateRet(RetVal); + } // Validate the generated code, checking for consistency. if (verifyFunction(*F, &llvm::errs()))