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

Ivanov Nikita. Lab 2. Var 3. #61

Merged
merged 24 commits into from
Apr 2, 2024
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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()
89 changes: 89 additions & 0 deletions llvm/labs/lab2/ivanov_nikita/ivanov.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
#include "llvm/ADT/ArrayRef.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
auto *ExitBlock = L->getExitBlock(); // end exit block of the loop

if (!Preheader || !ExitBlock)
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;
}
}
}

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

IRBuilder<> Builder(Preheader->getTerminator()); // api for basic block
if (!loop_start_inside)
Builder.CreateCall(LoopStartFunc); // paste loop_start

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();
}
174 changes: 174 additions & 0 deletions llvm/test/lab2/ivanov_nikita/test.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
; 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();
; }

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()
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
}

declare dso_local void @_Z10loop_startv()

declare dso_local void @_Z8loop_endv()
Loading