Skip to content

Commit

Permalink
ugly
Browse files Browse the repository at this point in the history
  • Loading branch information
zhengyang92 committed Jan 15, 2020
1 parent d635639 commit 05a97b6
Show file tree
Hide file tree
Showing 6 changed files with 161 additions and 35 deletions.
13 changes: 10 additions & 3 deletions include/souper/Codegen/Codegen.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 <map>

Expand All @@ -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<Inst *, llvm::Value *> &ReplacedValues;


llvm::Value *getValueHelper(Inst *I, std::map<Inst *, llvm::Value *> &Cache, std::map<Block *, llvm::Value *> &BM);
bool GenControlFlow = false;
public:
Codegen(llvm::LLVMContext &Context_, llvm::Module *M_,
llvm::IRBuilder<> &Builder_, llvm::DominatorTree *DT_,
llvm::Instruction *ReplacedInst_,
const std::map<Inst *, llvm::Value *> &ReplacedValues_)
const std::map<Inst *, llvm::Value *> &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);
};

Expand Down
121 changes: 114 additions & 7 deletions lib/Codegen/Codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<Inst *, llvm::Value *> &C, std::map<Block *, llvm::Value *> &BM) {
const std::vector<Inst *> &Ops = I->orderedOps();
if (I->K == Inst::UntypedConst) {
// FIXME: We only get here because it is the second argument of
Expand All @@ -67,6 +67,43 @@ 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<BasicBlock *> Preds;
std::vector<Value *> Incomes;
BasicBlock *E = Builder.GetInsertBlock();
BasicBlock *NextBB = BasicBlock::Create(Context, "next", 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) {
Expand All @@ -89,7 +126,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;

Expand Down Expand Up @@ -135,7 +172,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) {
Expand Down Expand Up @@ -231,8 +268,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:
Expand Down Expand Up @@ -270,8 +307,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) {
Expand Down Expand Up @@ -302,4 +339,74 @@ llvm::Value *Codegen::getValue(Inst *I) {
Inst::getKindName(I->K) + " in Codegen::getValue()");
}

llvm::Value *Codegen::getValue(Inst *I) {
std::map<Inst *, llvm::Value *> C;
std::map<Block *, llvm::Value *> BM;
getValueHelper(I, C, BM);
}

static std::vector<llvm::Type *>
GetInputArgumentTypes(const InstContext &IC, llvm::LLVMContext &Context) {
const std::vector<Inst *> AllVariables = IC.getVariables();

std::vector<llvm::Type *> ArgTypes;
ArgTypes.reserve(AllVariables.size());
for (const Inst *const Var : AllVariables)
ArgTypes.emplace_back(Type::getIntNTy(Context, Var->Width));

return ArgTypes;
}

static std::map<Inst *, Value *> GetArgsMapping(const InstContext &IC,
Function *F) {
std::map<Inst *, Value *> Args;

const std::vector<Inst *> 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) {

auto PhiDet = M->getOrInsertFunction("phi_det",
FunctionType::getInt32Ty(Context));

std::vector<llvm::Type *> ArgTypes = GetInputArgumentTypes(IC, Context);
// phi determinism



const auto FT = llvm::FunctionType::get(
/*Result=*/GetInstReturnType(Context, I),
/*Params=*/ArgTypes, /*isVarArg=*/false);

F = llvm::Function::Create(FT, llvm::Function::ExternalLinkage, "fun", M);

const std::map<Inst *, Value *> Args = GetArgsMapping(IC, F);

//const std::map<Inst *, Value *> Args = GetArgsMapping(IC, F);

BasicBlock *BB = BasicBlock::Create(Context, "entry", F);


std::vector<Block *> Blocks = souper::getBlocksFromPhis(I);
std::map<Block *, llvm::Value *> BlockMap;

Builder.SetInsertPoint(BB);
for (int i = 0 ; i < Blocks.size(); i ++) {
Value *V = Builder.CreateCall(PhiDet, {});
BlockMap[Blocks[i]] = V;
}

std::map<Inst *, llvm::Value *> C;
Value *RetVal = getValueHelper(I, C, BlockMap);

Builder.CreateRet(RetVal);

return F;
}

} // namespace souper
3 changes: 0 additions & 3 deletions lib/Extractor/Candidates.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -501,9 +501,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];
Expand Down
5 changes: 3 additions & 2 deletions lib/Inst/Inst.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -768,6 +768,7 @@ std::vector<Inst *> 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());
}
}
Expand Down Expand Up @@ -1287,8 +1288,8 @@ std::vector<Block *> 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);
}

Expand Down
2 changes: 1 addition & 1 deletion lib/Pass/Pass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ struct SouperPass : public ModulePass {
std::map<Inst *, Value *> &ReplacedValues,
IRBuilder<> &Builder, Module *M) {
return Codegen(ReplacedInst->getContext(), M, Builder, &DT, ReplacedInst,
ReplacedValues)
ReplacedValues, false)
.getValue(I);
}

Expand Down
52 changes: 33 additions & 19 deletions tools/souper2llvm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ static cl::opt<std::string>
cl::desc("<input souper RHS (default=stdin)>"),
cl::init("-"));

static cl::opt<bool> GenCF("gen-cf",
cl::desc("Generate LLVM bitcode with control flow"),
cl::init(false));

static cl::opt<std::string> OutputFilename(
"o", cl::desc("<output destination for textual LLVM IR (default=stdout)>"),
cl::init("-"));
Expand Down Expand Up @@ -69,26 +73,36 @@ int Work(const MemoryBufferRef &MB) {

llvm::LLVMContext Context;
llvm::Module Module("souper.ll", Context);

const std::vector<llvm::Type *> 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);

const std::map<Inst *, Value *> 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);

Function *F;

if (GenCF) {
F = Codegen(Context, &Module, Builder, /*DT*/ nullptr,
/*ReplacedInst*/ nullptr, {}, true).getFunction(RepRHS.Mapping.RHS, IC);

} else {
const std::vector<llvm::Type *> ArgTypes = GetInputArgumentTypes(IC, Context);
const auto FT = llvm::FunctionType::get(
/*Result=*/Codegen::GetInstReturnType(Context, RepRHS.Mapping.RHS),
/*Params=*/ArgTypes, /*isVarArg=*/false);

F = Function::Create(FT, Function::ExternalLinkage, "fun", &Module);



BasicBlock *BB = BasicBlock::Create(Context, "entry", F);

llvm::IRBuilder<> Builder(Context);
Builder.SetInsertPoint(BB);
const std::map<Inst *, Value *> Args = GetArgsMapping(IC, F);

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()))
Expand Down

0 comments on commit 05a97b6

Please sign in to comment.