Question: I have this 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

I have this 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 blockInfo; 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 worklist; 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(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; }); }}; }

When I run it 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, ptr %b, align 4 %1 = load i32, ptr %c, align 4 %add = add nsw i32 %0, %1 store i32 %add, ptr %e, align 4 %2 = load i32, ptr %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, ptr %a, align 4 store i32 %3, ptr %e, align 4 br label %if.end

if.else: ; preds = %entry %4 = load i32, ptr %b, align 4 %5 = load i32, ptr %c, align 4 %add1 = add nsw i32 %4, %5 store i32 %add1, ptr %a, align 4 br label %if.end

if.end: ; preds = %if.else, %if.then %6 = load i32, ptr %e, align 4 %7 = load i32, ptr %c, align 4 %add2 = add nsw i32 %6, %7 store i32 %add2, ptr %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"}

I get this output: -----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:

Step by Step Solution

There are 3 Steps involved in it

1 Expert Approved Answer
Step: 1 Unlock blur-text-image
Question Has Been Solved by an Expert!

Get step-by-step solutions from verified subject matter experts

Step: 2 Unlock
Step: 3 Unlock

Students Have Also Explored These Related Databases Questions!