Question: Here 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
Here 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 set
unordered_map
for (auto& basic_block : F) {
LivenessInfo info;
info.liveOut.resize(F.arg_size() + F.getBasicBlockList().size(), false);
blockInfo[&basic_block] = info;
}
// Create a worklist of basic blocks to process, starting with the exit block
queue
auto exitBlock = &F.back();
worklist.push(exitBlock);
// 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;
});
}};
}
Here is my 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"}
Here is my desire output: ----- 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:
How can my code be modified so I get my desire output when I run the pass?
Step by Step Solution
There are 3 Steps involved in it
Get step-by-step solutions from verified subject matter experts
