This repository has been archived by the owner on Jan 19, 2025. It is now read-only.
forked from NN-complr-tech/llvm
-
Notifications
You must be signed in to change notification settings - Fork 59
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Kulagin Aleksandr / lab 2 / var 2 (#59)
Let's call function that returns void and has no parameters "empty function". Let's say empty function has n blocks. In order to put this empty function in a place it's called, we split called function, create n blocks in calling function and create association list, which associate each created block with it's corresponding block from empty function. Next we copy all instructions from associated blocks. Also we change branch instructions so they send to correct block in called function. And we replace return statements to branch instruction that sends to block with instructions after empty function call.
- Loading branch information
1 parent
a4da973
commit 31d01a6
Showing
3 changed files
with
1,172 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
set(Title "PutInlineFunctions") | ||
set(Student "KulaginAleksandr") | ||
set(Group "FI3") | ||
set(PluginName "${Title}${Student}${Group}") | ||
|
||
add_compile_definitions(NAME=${PluginName}) | ||
|
||
string(TOUPPER ${PluginName} PluginNameUpper) | ||
set(LLVM_${PluginNameUpper}_LINK_INTO_TOOLS ON) | ||
|
||
if (NOT WIN32 AND NOT CYGWIN) | ||
file(GLOB_RECURSE ALL_SOURCE_FILES *.cpp *.h *.hpp) | ||
|
||
add_llvm_pass_plugin(${PluginName} | ||
${ALL_SOURCE_FILES} | ||
DEPENDS | ||
intrinsics_gen | ||
BUILDTREE_ONLY | ||
) | ||
|
||
target_link_libraries(${PluginName} | ||
PUBLIC | ||
LLVMSupport | ||
LLVMCore | ||
LLVMipo | ||
LLVMPasses | ||
) | ||
|
||
set(LLVM_TEST_DEPENDS ${PluginName} ${LLVM_TEST_DEPENDS} PARENT_SCOPE) | ||
endif() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
#include "llvm/IR/BasicBlock.h" | ||
#include "llvm/IR/DerivedTypes.h" | ||
#include "llvm/IR/Function.h" | ||
#include "llvm/IR/Instruction.h" | ||
#include "llvm/IR/Instructions.h" | ||
#include "llvm/IR/LLVMContext.h" | ||
#include "llvm/IR/Value.h" | ||
#include "llvm/Passes/PassBuilder.h" | ||
#include "llvm/Passes/PassPlugin.h" | ||
#include "llvm/Support/Casting.h" | ||
#include "llvm/Transforms/Utils/BasicBlockUtils.h" | ||
#include "llvm/Transforms/Utils/Cloning.h" | ||
#include "llvm/Transforms/Utils/ValueMapper.h" | ||
#include <map> | ||
#include <vector> | ||
|
||
namespace { | ||
llvm::BasicBlock *splitBlockBefore(llvm::BasicBlock *Old, | ||
llvm::Instruction *SplitPt, | ||
llvm::DomTreeUpdater *DTU = nullptr, | ||
llvm::LoopInfo *LI = nullptr, | ||
llvm::MemorySSAUpdater *MSSAU = nullptr, | ||
const llvm::Twine &BBName = "", | ||
bool Before = true) { | ||
return llvm::SplitBlock(Old, SplitPt, DTU, LI, MSSAU, BBName, Before); | ||
} | ||
|
||
class KulaginMagicInlinePass | ||
: public llvm::PassInfoMixin<KulaginMagicInlinePass> { | ||
public: | ||
llvm::PreservedAnalyses run(llvm::Function &Func, | ||
llvm::FunctionAnalysisManager &) { | ||
bool IsTransformed = false; | ||
std::vector<llvm::Instruction *> InstrDeleteList; | ||
llvm::LLVMContext &CTX = Func.getContext(); | ||
for (llvm::BasicBlock &Block : Func) { | ||
for (llvm::Instruction &Instr : Block) { | ||
llvm::CallInst *CallInstruction = | ||
llvm::dyn_cast<llvm::CallInst>(&Instr); | ||
if (!CallInstruction) { | ||
continue; | ||
} | ||
llvm::Function *Called = CallInstruction->getCalledFunction(); | ||
if (Called == &Func || !Called->getReturnType()->isVoidTy() || | ||
Called->getFunctionType()->getNumParams() > 0) { | ||
continue; | ||
} | ||
IsTransformed = true; | ||
std::map<llvm::BasicBlock *, llvm::BasicBlock *> BlockMap; | ||
llvm::ValueToValueMapTy VMap; | ||
llvm::BasicBlock *SplittedBlock = splitBlockBefore(&Block, &Instr); | ||
llvm::BasicBlock *NextBlockPlace = SplittedBlock->getNextNode(); | ||
for (llvm::BasicBlock &ToInlineBasicBlock : *Called) { | ||
llvm::BasicBlock *TmpBlock = | ||
llvm::BasicBlock::Create(CTX, "", &Func, NextBlockPlace); | ||
BlockMap[&ToInlineBasicBlock] = TmpBlock; | ||
NextBlockPlace = TmpBlock->getNextNode(); | ||
} | ||
for (llvm::BasicBlock &ToInlineBasicBlock : *Called) { | ||
for (llvm::Instruction &ToInlineInstr : ToInlineBasicBlock) { | ||
llvm::BasicBlock *CurrentBlock = BlockMap[&ToInlineBasicBlock]; | ||
if (llvm::isa<llvm::ReturnInst>(&ToInlineInstr)) { | ||
llvm::BranchInst::Create(&Block)->insertInto(CurrentBlock, | ||
CurrentBlock->end()); | ||
} else { | ||
llvm::Instruction *NewInstr = ToInlineInstr.clone(); | ||
if (llvm::isa<llvm::BranchInst>(*NewInstr)) { | ||
unsigned OpNum = NewInstr->getNumOperands(); | ||
for (unsigned Ind = 0; Ind < OpNum; Ind++) { | ||
llvm::Value *CurOperand = NewInstr->getOperand(Ind); | ||
if (llvm::isa<llvm::BasicBlock>(*CurOperand)) { | ||
NewInstr->setOperand( | ||
Ind, llvm::dyn_cast<llvm::Value>( | ||
BlockMap[llvm::dyn_cast<llvm::BasicBlock>( | ||
CurOperand)])); | ||
} | ||
} | ||
} | ||
NewInstr->insertInto(CurrentBlock, CurrentBlock->end()); | ||
llvm::RemapInstruction(NewInstr, VMap, | ||
llvm::RF_NoModuleLevelChanges | | ||
llvm::RF_IgnoreMissingLocals); | ||
VMap[&ToInlineInstr] = NewInstr; | ||
} | ||
} | ||
} | ||
SplittedBlock->getTerminator()->setOperand( | ||
0, llvm::dyn_cast<llvm::Value>(BlockMap[&Called->getEntryBlock()])); | ||
InstrDeleteList.push_back(&Instr); | ||
} | ||
} | ||
for (llvm::Instruction *Instr : InstrDeleteList) { | ||
Instr->eraseFromParent(); | ||
} | ||
if (IsTransformed) { | ||
return llvm::PreservedAnalyses::none(); | ||
} | ||
return llvm::PreservedAnalyses::all(); | ||
} | ||
}; | ||
} // namespace | ||
|
||
llvm::PassPluginLibraryInfo | ||
getPutInlineFunctionsKulaginAleksandrFI3PluginInfo() { | ||
return {LLVM_PLUGIN_API_VERSION, "KulaginMagicInlinePass", "0.1", | ||
[](llvm::PassBuilder &PB) { | ||
PB.registerPipelineParsingCallback( | ||
[](llvm::StringRef Name, llvm::FunctionPassManager &PM, | ||
llvm::ArrayRef<llvm::PassBuilder::PipelineElement>) { | ||
if (Name == "kulagin-magic-inline") { | ||
PM.addPass(KulaginMagicInlinePass()); | ||
return true; | ||
} | ||
return false; | ||
}); | ||
}}; | ||
} | ||
|
||
extern "C" LLVM_ATTRIBUTE_WEAK ::llvm::PassPluginLibraryInfo | ||
llvmGetPassPluginInfo() { | ||
return getPutInlineFunctionsKulaginAleksandrFI3PluginInfo(); | ||
} |
Oops, something went wrong.