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
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
// Create a worklist of basic blocks to process, starting with the exit block queue
// 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
// 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
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
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
Get step-by-step solutions from verified subject matter experts
