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

Commit

Permalink
Ivanov Nikita. Lab 2. Var 3. (#61)
Browse files Browse the repository at this point in the history
Реализован плагин и тесты по задаче:
Найти все циклы внутри функции и обернуть их в вызовы loop_start()/loop_end(). Можно использовать Loop Analysis.
  • Loading branch information
Atikin-NT authored Apr 2, 2024
1 parent 31d01a6 commit c7dc20d
Show file tree
Hide file tree
Showing 3 changed files with 347 additions and 0 deletions.
14 changes: 14 additions & 0 deletions llvm/labs/lab2/ivanov_nikita/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
set(PluginName AtikinLoopPass)

file(GLOB_RECURSE ALL_SOURCE_FILES *.cpp *.h)

if (NOT WIN32 AND NOT CYGWIN)
add_llvm_pass_plugin(${PluginName}
${ALL_SOURCE_FILES}
DEPENDS
intrinsics_gen
BUILDTREE_ONLY
)

set(LLVM_TEST_DEPENDS ${PluginName} ${LLVM_TEST_DEPENDS} PARENT_SCOPE)
endif()
95 changes: 95 additions & 0 deletions llvm/labs/lab2/ivanov_nikita/ivanov.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/PassManager.h"
#include "llvm/Pass.h"
#include "llvm/Passes/PassBuilder.h"
#include "llvm/Passes/PassPlugin.h"

using namespace llvm;

class MyLoopPass : public PassInfoMixin<MyLoopPass> {
public:
PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM) {
auto *Ty = FunctionType::get(llvm::Type::getVoidTy(F.getContext()),
false); // get func type
auto *M = F.getParent();

auto LoopStartFunc = M->getOrInsertFunction("_Z10loop_startv",
Ty); // get or create func start
auto LoopEndFunc =
M->getOrInsertFunction("_Z8loop_endv", Ty); // get or create func end

auto &LI = FAM.getResult<LoopAnalysis>(F);

for (auto &L : LI) { // for by loop
auto *Preheader =
L->getLoopPreheader(); // get preheader block of the loop

SmallVector<BasicBlock *, 1> ExitBlocks;
L->getExitBlocks(ExitBlocks);

if (!Preheader || ExitBlocks.empty())
continue;

int loop_start_inside = 0;
int loop_end_inside = 0;

for (Instruction &Instr : *Preheader) {
if (CallInst *CI = dyn_cast<CallInst>(&Instr)) {
if (CI->getCalledFunction() &&
CI->getCalledFunction()->getName() == "_Z10loop_startv") {
loop_start_inside = 1;
break;
}
}
}

IRBuilder<> Builder(Preheader->getTerminator()); // api for basic block

if (!loop_start_inside)
Builder.CreateCall(LoopStartFunc); // paste loop_start

for (auto &ExitBlock : ExitBlocks) {
loop_end_inside = 0;
for (Instruction &Instr : *ExitBlock) {
if (CallInst *CI = dyn_cast<CallInst>(&Instr)) {
if (CI->getCalledFunction() &&
CI->getCalledFunction()->getName() == "_Z8loop_endv") {
loop_end_inside = 1;
break;
}
}
}
Builder.SetInsertPoint(
ExitBlock->getFirstNonPHI()); // set pointer to exit block

if (!loop_end_inside)
Builder.CreateCall(LoopEndFunc); // paste loop_start
}
}
return PreservedAnalyses::all();
}
};

/* New PM Registration */
llvm::PassPluginLibraryInfo getAtikinLoopPassPluginInfo() {
return {LLVM_PLUGIN_API_VERSION, "AtikinLoopPass", LLVM_VERSION_STRING,
[](llvm::PassBuilder &PB) {
PB.registerPipelineParsingCallback(
[](llvm::StringRef Name, llvm::FunctionPassManager &PM,
llvm::ArrayRef<llvm::PassBuilder::PipelineElement>) {
if (Name == "ivanov-loop-pass") {
PM.addPass(MyLoopPass());
return true;
}
return false;
});
}};
}

extern "C" LLVM_ATTRIBUTE_WEAK ::llvm::PassPluginLibraryInfo
llvmGetPassPluginInfo() {
return getAtikinLoopPassPluginInfo();
}
238 changes: 238 additions & 0 deletions llvm/test/lab2/ivanov_nikita/test.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,238 @@
; RUN: opt -load-pass-plugin=%llvmshlibdir/AtikinLoopPass%shlibext -passes=ivanov-loop-pass -S %s | FileCheck %s

; void foo(int n, int m) {
; int c0;
; int c1;
; for (c0 = n; c0 > 0; c0--) {
; c1++;
; }
; }

; void while_test(){
; int i = 0;
; while(i < 10){
; i++;
; }
; }

; void do_while_test(){
; int i = 0;
; do {
; i++;
; } while(i < 10);
; }

; void no_loop(){
; int a = 2;
; if (a > 0){
; a = 0;
; } else {
; a = 10;
; }
; }

; void loop_start();
; void loop_end();

; void with_lopps_func(){
; int i = 0;
; loop_start();
; while(i < 10){
; i++;
; }
; loop_end();
; }

; void LoopWithRet(int &a) {
; int i = 0;
; while(i < 100){
; i++;
; if (i > 10) {
; return;
; }
; a = a + i;
; }
; a *= i -1;
; return;
; }

define dso_local void @_Z3fooii(i32 noundef %n, i32 noundef %m) {
entry:
%n.addr = alloca i32, align 4
%m.addr = alloca i32, align 4
%c0 = alloca i32, align 4
%c1 = alloca i32, align 4
store i32 %n, ptr %n.addr, align 4
store i32 %m, ptr %m.addr, align 4
%0 = load i32, ptr %n.addr, align 4
store i32 %0, ptr %c0, align 4
; CHECK: call void @_Z10loop_startv()
br label %for.cond

for.cond:
%1 = load i32, ptr %c0, align 4
%cmp = icmp sgt i32 %1, 0
br i1 %cmp, label %for.body, label %for.end

for.body:
%2 = load i32, ptr %c1, align 4
%inc = add nsw i32 %2, 1
store i32 %inc, ptr %c1, align 4
br label %for.inc

for.inc:
%3 = load i32, ptr %c0, align 4
%dec = add nsw i32 %3, -1
store i32 %dec, ptr %c0, align 4
br label %for.cond

for.end:
; CHECK: call void @_Z8loop_endv()
ret void
}

define dso_local void @_Z10while_testv() {
entry:
%i = alloca i32, align 4
store i32 0, ptr %i, align 4
; CHECK: call void @_Z10loop_startv()
br label %while.cond

while.cond:
%0 = load i32, ptr %i, align 4
%cmp = icmp slt i32 %0, 10
br i1 %cmp, label %while.body, label %while.end

while.body:
%1 = load i32, ptr %i, align 4
%inc = add nsw i32 %1, 1
store i32 %inc, ptr %i, align 4
br label %while.cond

while.end:
; CHECK: call void @_Z8loop_endv()
ret void
}

define dso_local void @_Z13do_while_testv() {
entry:
%i = alloca i32, align 4
store i32 0, ptr %i, align 4
; CHECK: call void @_Z10loop_startv()
br label %do.body

do.body:
%0 = load i32, ptr %i, align 4
%inc = add nsw i32 %0, 1
store i32 %inc, ptr %i, align 4
br label %do.cond

do.cond:
%1 = load i32, ptr %i, align 4
%cmp = icmp slt i32 %1, 10
br i1 %cmp, label %do.body, label %do.end

do.end:
; CHECK: call void @_Z8loop_endv()
ret void
}

define dso_local void @_Z7no_loopv() {
entry:
%a = alloca i32, align 4
store i32 2, ptr %a, align 4
%0 = load i32, ptr %a, align 4
; CHECK-NOT: call void @_Z10loop_startv()
%cmp = icmp sgt i32 %0, 0
br i1 %cmp, label %if.then, label %if.else

if.then:
store i32 0, ptr %a, align 4
br label %if.end

if.else:
store i32 10, ptr %a, align 4
br label %if.end

if.end:
; CHECK-NOT: call void @_Z8loop_endv()
ret void
}

define dso_local void @_Z15with_lopps_funcv() {
entry:
%i = alloca i32, align 4
store i32 0, ptr %i, align 4
; CHECK: call void @_Z10loop_startv()
; CHECK-NOT: call void @_Z10loop_startv()
br label %while.cond

while.cond:
%0 = load i32, ptr %i, align 4
%cmp = icmp slt i32 %0, 10
br i1 %cmp, label %while.body, label %while.end

while.body:
%1 = load i32, ptr %i, align 4
%inc = add nsw i32 %1, 1
store i32 %inc, ptr %i, align 4
br label %while.cond

while.end:
; CHECK: call void @_Z8loop_endv()
; CHECK-NOT: call void @_Z8loop_endv()
ret void
}

declare dso_local void @_Z10loop_startv()

declare dso_local void @_Z8loop_endv()

define dso_local void @_Z11LoopWithRetRi(ptr noundef nonnull align 4 dereferenceable(4) %a) {
entry:
%a.addr = alloca ptr, align 8
%i = alloca i32, align 4
store ptr %a, ptr %a.addr, align 8
store i32 0, ptr %i, align 4
; CHECK: call void @_Z10loop_startv()
br label %while.cond

while.cond:
%0 = load i32, ptr %i, align 4
%cmp = icmp slt i32 %0, 100
br i1 %cmp, label %while.body, label %while.end

while.body:
%1 = load i32, ptr %i, align 4
%inc = add nsw i32 %1, 1
store i32 %inc, ptr %i, align 4
%2 = load i32, ptr %i, align 4
%cmp1 = icmp sgt i32 %2, 10
br i1 %cmp1, label %if.then, label %if.end

if.then:
; CHECK: call void @_Z8loop_endv()
br label %return

if.end:
%3 = load ptr, ptr %a.addr, align 8
%4 = load i32, ptr %3, align 4
%5 = load i32, ptr %i, align 4
%add = add nsw i32 %4, %5
%6 = load ptr, ptr %a.addr, align 8
store i32 %add, ptr %6, align 4
br label %while.cond

while.end:
; CHECK: call void @_Z8loop_endv()
%7 = load i32, ptr %i, align 4
%sub = sub nsw i32 %7, 1
%8 = load ptr, ptr %a.addr, align 8
%9 = load i32, ptr %8, align 4
%mul = mul nsw i32 %9, %sub
store i32 %mul, ptr %8, align 4
br label %return

return:
ret void
}

0 comments on commit c7dc20d

Please sign in to comment.