Answered step by step
Verified Expert Solution
Link Copied!

Question

1 Approved Answer

This is my code: #include llvm/IR/LegacyPassManager.h #include llvm/Passes/PassPlugin.h #include llvm/Passes/PassBuilder.h #include llvm/IR/PassManager.h #include llvm/IR/Instructions.h #include llvm/ADT/BitVector.h #include #include using namespace std; using namespace llvm; namespace

This is my code: #include "llvm/IR/LegacyPassManager.h"

#include "llvm/Passes/PassPlugin.h"

#include "llvm/Passes/PassBuilder.h"

#include "llvm/IR/PassManager.h"

#include "llvm/IR/Instructions.h"

#include "llvm/ADT/BitVector.h"

#include

#include

using namespace std;

using namespace llvm;

namespace {

struct LivenessInfo {

BitVector liveIn;

BitVector liveOut;

};

// This method implements what the pass does

void visitor(Function &F){

string func_name = "main";

errs() << "Liveness analysis for function: " << F.getName() << " ";

// Process each basic block in the function and initialize the live-out and live-in sets

unordered_map blockInfo;

BitVector initialLiveOut(F.arg_size() + F.getBasicBlockList().size(), false);

for (auto& basic_block : F) {

LivenessInfo info;

info.liveOut = initialLiveOut;

info.liveIn.resize(F.arg_size() + F.getBasicBlockList().size(), false); // initialize live-in set to empty

blockInfo[&basic_block] = info;

}

// Creates a worklist of basic blocks to process, starting with the exit block

queue worklist;

auto exitBlock = &F.back();

auto& exitInfo = blockInfo[exitBlock];

worklist.push(exitBlock);

exitInfo.liveOut = BitVector(initialLiveOut.size(), false); // initialize live-out set for exit block to empty

// Compute the live-out set for each basic block

while (!worklist.empty()) {

auto block = worklist.front();

worklist.pop();

// Compute the live-out set by taking the union of the live-in sets of successors

auto& info = blockInfo[block];

for (auto it = succ_begin(block); it != succ_end(block); ++it) {

auto& succInfo = blockInfo[*it];

info.liveOut |= succInfo.liveIn;

}

// Compute the live-in set based on the live-out set and the instructions in the block

BitVector liveIn(info.liveOut);

for (auto it = block->rbegin(); it != block->rend(); ++it) {

auto inst = &*it;

// Remove variables defined by the instruction from the live-in set

if (auto store = dyn_cast(inst)) {

auto var = store->getPointerOperand();

size_t varIndex = F.arg_size() + var->getName().substr(1).getAsInteger(10, varIndex);

liveIn.reset(varIndex);

}

// Add variables used by the instruction to the live-in set

for (auto op = inst->op_begin(); op != inst->op_end(); ++op) {

if (auto var = dyn_cast(*op)) {

size_t varIndex = F.arg_size() + var->getName().substr(1).getAsInteger(10, varIndex);

liveIn.set(varIndex);

}

}

}

// Update the live-in set for the current block

info.liveIn = liveIn;

// Add the predecessors of the block to the worklist, if not already processed

for (auto it = pred_begin(block); it != pred_end(block); ++it) {

auto predBlock = *it;

if (blockInfo[predBlock].liveOut != liveIn) {

worklist.push(predBlock);

}

}

}

// Print the live-in and live-out sets for each basic block

for (auto& basic_block : F) {

errs() << "-----" << basic_block.getName() << "-----" << " ";

auto& info = blockInfo[&basic_block];

errs() << "UEVAR: ";

for (int i = 0; i < F.arg_size(); i++) {

if (info.liveIn[i]) {

auto arg = F.getArg(i);

errs() << arg->getName() << " ";

}

}

errs() << " VARKILL: ";

for (int i = 0; i < F.arg_size(); i++) {

if (info.liveOut[i] && info.liveIn[i]) {

auto arg = F.getArg(i);

errs() << arg->getName() << " ";

}

}

errs() << " LIVEOUT: ";

for (int i = 0; i < F.arg_size(); i++) {

if (info.liveOut[i]) {

auto arg = F.getArg(i);

errs() << arg->getName() << " ";

}

}

errs() << " ";

}

}

}

struct ValueNumberingPass : public PassInfoMixin {

// The first argument of the run() function defines on what level

// of granularity your pass will run (e.g. Module, Function).

// The second argument is the corresponding AnalysisManager

// (e.g ModuleAnalysisManager, FunctionAnalysisManager)

PreservedAnalyses run(Function &F, FunctionAnalysisManager &) {

visitor(F);

return PreservedAnalyses::all();

}

static bool isRequired() { return true; }

};

//-----------------------------------------------------------------------------

// New PM Registration

//-----------------------------------------------------------------------------

extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK

llvmGetPassPluginInfo() {

return {

LLVM_PLUGIN_API_VERSION, "ValueNumberingPass", LLVM_VERSION_STRING,

[](PassBuilder &PB) {

PB.registerPipelineParsingCallback(

[](StringRef Name, FunctionPassManager &FPM,

ArrayRef) {

if (Name == "value-numbering") {

FPM.addPass(ValueNumberingPass());

return true;

}

return false;

});

}};

}

I am running the pass with this input file: ; ModuleID = 'test1.c'

source_filename = "test1.c"

target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"

target triple = "x86_64-apple-macosx12.0.0"

; Function Attrs: noinline nounwind optnone ssp uwtable

define void @test() #0 {

entry:

%a = alloca i32, align 4

%b = alloca i32, align 4

%c = alloca i32, align 4

%e = alloca i32, align 4

%0 = load i32, i32* %b, align 4

%1 = load i32, i32* %c, align 4

%add = add nsw i32 %0, %1

store i32 %add, i32* %e, align 4

%2 = load i32, i32* %e, align 4

%cmp = icmp sgt i32 %2, 0

br i1 %cmp, label %if.then, label %if.else

if.then: ; preds = %entry

%3 = load i32, i32* %a, align 4

store i32 %3, i32* %e, align 4

br label %if.end

if.else: ; preds = %entry

%4 = load i32, i32* %b, align 4

%5 = load i32, i32* %c, align 4

%add1 = add nsw i32 %4, %5

store i32 %add1, i32* %a, align 4

br label %if.end

if.end: ; preds = %if.else, %if.then

%6 = load i32, i32* %e, align 4

%7 = load i32, i32* %c, align 4

%add2 = add nsw i32 %6, %7

store i32 %add2, i32* %a, align 4

ret void

}

attributes #0 = { noinline nounwind optnone ssp uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="penryn" "target-features"="+cx16,+cx8,+fxsr,+mmx,+sahf,+sse,+sse2,+sse3,+sse4.1,+ssse3,+x87" "tune-cpu"="generic" }

!llvm.module.flags = !{!0, !1, !2, !3}

!llvm.ident = !{!4}

!0 = !{i32 1, !"wchar_size", i32 4}

!1 = !{i32 7, !"PIC Level", i32 2}

!2 = !{i32 7, !"uwtable", i32 2}

!3 = !{i32 7, !"frame-pointer", i32 2}

!4 = !{!"Homebrew clang version 15.0.7"}

My output is this: Liveness analysis for function: test

-----entry-----

UEVAR:

VARKILL:

LIVEOUT:

-----if.then-----

UEVAR:

VARKILL:

LIVEOUT:

-----if.else-----

UEVAR:

VARKILL:

LIVEOUT:

-----if.end-----

UEVAR:

VARKILL:

LIVEOUT: Instead of this:

----- entry -----

UEVAR: b c

VARKILL: e

LIVEOUT: a b c e

----- if.then -----

UEVAR: a

VARKILL: e

LIVEOUT: c e

----- if.else -----

UEVAR: b c

VARKILL: a

LIVEOUT: c e

----- if.end -----

UEVAR: c e

VARKILL: a

LIVEOUT:

What Am I doing wrong?

Step by Step Solution

There are 3 Steps involved in it

Step: 1

blur-text-image

Get Instant Access to Expert-Tailored Solutions

See step-by-step solutions with expert insights and AI powered tools for academic success

Step: 2

blur-text-image

Step: 3

blur-text-image

Ace Your Homework with AI

Get the answers you need in no time with our AI-driven, step-by-step assistance

Get Started

Recommended Textbook for

More Books

Students also viewed these Databases questions