Skip to content
This repository has been archived by the owner on Jan 19, 2025. It is now read-only.

Commit

Permalink
Kulagin Aleksandr / lab 2 / var 2 (#59)
Browse files Browse the repository at this point in the history
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
mahbhlddnhakkh authored Apr 1, 2024
1 parent a4da973 commit 31d01a6
Show file tree
Hide file tree
Showing 3 changed files with 1,172 additions and 0 deletions.
30 changes: 30 additions & 0 deletions llvm/labs/lab2/kulagin_aleksandr/CMakeLists.txt
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()
122 changes: 122 additions & 0 deletions llvm/labs/lab2/kulagin_aleksandr/magic_inline.cpp
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();
}
Loading

0 comments on commit 31d01a6

Please sign in to comment.