Question
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
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
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
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
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
Get Instant Access to Expert-Tailored Solutions
See step-by-step solutions with expert insights and AI powered tools for academic success
Step: 2
Step: 3
Ace Your Homework with AI
Get the answers you need in no time with our AI-driven, step-by-step assistance
Get Started