Pawan Nirpal
Pawan Nirpal

Reputation: 622

LLVM opt unable to print instructions from a specific function, But it does for the rest of the functions in the IR

I am new to llvm framework and was able to run a basic pass to iterate over instructions in a simple IR function with only entry basic block, but to expand upon that I got an .ll file from clang for a simple c function ( don't mind the correctness of the function I don't care about it for the sake of learning llvm at least for now ).

// fact.c 

int fact(int n){
  int t =1; 
  for(int i = 2;i<=n;i++){
    t = t*i;  
  }
  return t;
}

I was able to get a fact.ll file for this function, given below, and there are 3 functions in the fact.ll which I hand coded into the IR. foo , add and bar. And I attempt to run a simple pass which will iterate over each BasicBlock and gather it's inst opcodes and simply print them at the end, My issue is the opt tool is able to do it for foo, add and bar functions but not for the fact function.

Pass file :

#include "llvm/Transforms/Utils/MyHello.h"
#include <string>
using namespace llvm;

PreservedAnalyses MyHelloPass::run(Function &F,FunctionAnalysisManager &AM) {
  std::string output; 
  errs()<<F.getName()<<"\n";
  for(Function::iterator BB = F.begin();BB!=F.end();BB++){
    for(BasicBlock::iterator I = BB->begin();I!=BB->end();I++){
        output+=(I->getOpcodeName());
        output+='\n';
    }
  }
  errs()<<output<<'\n';
  return PreservedAnalyses::all();
}

fact.ll

; ModuleID = 'fact.c'
source_filename = "fact.c"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

; Function Attrs: noinline nounwind optnone uwtable
define dso_local i32 @fact(i32 noundef %n) #0 {
entry:
  %n.addr = alloca i32, align 4
  %t = alloca i32, align 4
  %i = alloca i32, align 4
  store i32 %n, i32* %n.addr, align 4
  store i32 1, i32* %t, align 4
  store i32 2, i32* %i, align 4
  br label %for.cond

for.cond:                                         ; preds = %for.inc, %entry
  %0 = load i32, i32* %i, align 4
  %1 = load i32, i32* %n.addr, align 4
  %cmp = icmp sle i32 %0, %1
  br i1 %cmp, label %for.body, label %for.end

for.body:                                         ; preds = %for.cond
  %2 = load i32, i32* %t, align 4
  %3 = load i32, i32* %i, align 4
  %mul = mul nsw i32 %2, %3
  store i32 %mul, i32* %t, align 4
  br label %for.inc

for.inc:                                          ; preds = %for.body
  %4 = load i32, i32* %i, align 4
  %inc = add nsw i32 %4, 1
  store i32 %inc, i32* %i, align 4
  br label %for.cond, !llvm.loop !6

for.end:                                          ; preds = %for.cond
  %5 = load i32, i32* %t, align 4
  ret i32 %5
}

define i32 @foo(){
  %a = add i32 2,3
  ret i32 %a
}

define i32 @add(i32 %a,i32 %b){
  %c = add i32 %a,%b 
  %d = add i32 %c,%c 
  %e = sub i32 %c, %d 
  %f = mul i32 %d, %e
  ret i32 %f
}

define void @bar(){
  ret void
}


attributes #0 = { noinline nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }

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

!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{i32 7, !"PIC Level", i32 2}
!2 = !{i32 7, !"PIE Level", i32 2}
!3 = !{i32 7, !"uwtable", i32 2}
!4 = !{i32 7, !"frame-pointer", i32 2}
!5 = !{!"AMD\C2\A0\C2\A0-DCLANG_REPOSITORY_STRING=CLANG: clang version 15.0.0 (CLANG: Jenkins CPUPC_Mirror_To_Staging_Merge-Build#892) (based on LLVM Mirror.Version.14.0.0)"}
!6 = distinct !{!6, !7}
!7 = !{!"llvm.loop.mustprogress"}

run command : opt -disable-output fact.ll -passes="myhello"

Ouput :

foo
add
ret

add
add
add
sub
mul
ret

bar
ret

Upvotes: 1

Views: 740

Answers (1)

Nick Lewycky
Nick Lewycky

Reputation: 1342

See the optnone in:

; Function Attrs: noinline nounwind optnone uwtable
define dso_local i32 @fact(i32 noundef %n) #0 {

That means that this function is opting out of optimizations, hence your pass will not be run on that function.

You can manually remove the optnone from the definition of #0 at the bottom (note: the ; Function Attrs: ... line is merely a comment, changing it has no effect) or you can build your LLVM IR with "clang -O2". You may want to also add -mllvm -disable-llvm-optzns if you want clang to produce IR that could be optimized but hasn't been run through LLVM passes.

Upvotes: 2

Related Questions