WRITING AN LLVM PASS · -x86-asm-syntax - Choose style of code to emit: =att - Emit AT&T-style...
Transcript of WRITING AN LLVM PASS · -x86-asm-syntax - Choose style of code to emit: =att - Emit AT&T-style...
![Page 1: WRITING AN LLVM PASS · -x86-asm-syntax - Choose style of code to emit: =att - Emit AT&T-style assembly =intel - Emit Intel-style assembly The command sta%c RegisterPass](https://reader030.fdocuments.in/reader030/viewer/2022041121/5f35b5e65b4d6b0a422e05dc/html5/thumbnails/1.jpg)
DCC888
UniversidadeFederaldeMinasGerais–DepartmentofComputerScience–ProgrammingLanguagesLaboratory
WRITINGANLLVMPASS
![Page 2: WRITING AN LLVM PASS · -x86-asm-syntax - Choose style of code to emit: =att - Emit AT&T-style assembly =intel - Emit Intel-style assembly The command sta%c RegisterPass](https://reader030.fdocuments.in/reader030/viewer/2022041121/5f35b5e65b4d6b0a422e05dc/html5/thumbnails/2.jpg)
Passes
• LLVMappliesachainofanalysesandtransformaAonsonthetarget
program.
• EachoftheseanalysesortransformaAonsiscalledapass.
• Wehaveseenafewpassesalready:mem2reg,early-cseand
constprop,forinstance.
• Somepasses,whicharemachineindependent,areinvokedbyopt.
• Otherpasses,whicharemachinedependent,areinvokedbyllc.
• ApassmayrequireinformaAonprovidedbyotherpasses.Such
dependenciesmustbeexplicitlystated.
– Forinstance:acommonpaMernisatransformaAonpass
requiringananalysispass.
![Page 3: WRITING AN LLVM PASS · -x86-asm-syntax - Choose style of code to emit: =att - Emit AT&T-style assembly =intel - Emit Intel-style assembly The command sta%c RegisterPass](https://reader030.fdocuments.in/reader030/viewer/2022041121/5f35b5e65b4d6b0a422e05dc/html5/thumbnails/3.jpg)
DifferentTypesofPasses
• ApassisaninstanceoftheLLVMclassPass.
• Therearemanykindsofpasses.
Pass
FunctionPass
ModulePass LoopPass
BasicBlockPass
CallGraphSCCPassRegionPass
InthislessonwewillfocusonFuncAon
Passes,whichanalyzewholefuncAons.
Canyouguess
whattheotherpasses
aregoodfor?
![Page 4: WRITING AN LLVM PASS · -x86-asm-syntax - Choose style of code to emit: =att - Emit AT&T-style assembly =intel - Emit Intel-style assembly The command sta%c RegisterPass](https://reader030.fdocuments.in/reader030/viewer/2022041121/5f35b5e65b4d6b0a422e05dc/html5/thumbnails/4.jpg)
CounAngNumberofOpcodesinPrograms
Let'swriteapassthatcountsthenumberofAmesthateach
opcodeappearsinagivenfuncAon.Thispassmustprint,for
eachfuncAon,alistwithalltheinstrucAonsthatshowedupinitscode,followedbythenumberofAmeseachoftheseopcodes
hasbeenused.
Function foo
add: 4
alloca: 5
br: 8
icmp: 3
load: 11
ret: 1
select: 1
store: 9
int foo(int n, int m) {
int sum = 0;
int c0; for (c0 = n; c0 > 0; c0--) {
int c1 = m;
for (; c1 > 0; c1--) {
sum += c0 > c1 ? 1 : 0;
} }
return sum;
}
!"#$!%$&$'(()*'$+,-.$'(+/0$1$!-$&$'(()*'$+,-.$'(+/0$1$!234$&$'(()*'$+,-.$'(+/0$1$!*"$&$'(()*'$+,-.$'(+/0$1$!*%$&$'(()*'$+,-.$'(+/0$1$25)67$+,-$!0.$+,-8$!%.$'(+/0$1$25)67$+,-$!4.$+,-8$!-.$'(+/0$1$25)67$+,-$".$+,-8$!234.$'(+/0$1$!,$&$()'9$+,-8$!%.$'(+/0$1$25)67$+,-$!,.$+,-8$!*".$'(+/0$1$:6$(':7($!1
!1#
$!;$&$()'9$+,-8$!*".$'(+/0$1$!<$&$+*4=$2/5$+,-$!;.$"$:6$+%$!<.$(':7($!>.$(':7($!-<
? @
!>#
$!A$&$()'9$+,-8$!-.$'(+/0$1$25)67$+,-$!A.$+,-8$!*%.$'(+/0$1$:6$(':7($!B
!-<#
$!->$&$()'9$+,-8$C*)30576.$'(+/0$1$!-A$&$'99$02D$+,-$!->.$%$25)67$+,-$!-A.$+,-8$C*)30576.$'(+/0$1$!-B$&$()'9$+,-8$!234.$'(+/0$1$675$+,-$!-B
!B#
$!%"$&$()'9$+,-8$!*%.$'(+/0$1$!%%$&$+*4=$2/5$+,-$!%".$"$:6$+%$!%%.$(':7($!%-.$(':7($!--
? @
!%-#
$!%,$&$()'9$+,-8$!*".$'(+/0$1$!%1$&$()'9$+,-8$!*%.$'(+/0$1$!%;$&$+*4=$2/5$+,-$!%,.$!%1$!%<$&$27(7*5$+%$!%;.$+,-$%.$+,-$"$!%>$&$()'9$+,-8$!234.$'(+/0$1$!%A$&$'99$02D$+,-$!%>.$!%<$25)67$+,-$!%A.$+,-8$!234.$'(+/0$1$:6$(':7($!%B
!--#
$:6$(':7($!-,
!%B#
$!-"$&$()'9$+,-8$!*%.$'(+/0$1$!-%$&$'99$02D$+,-$!-".$E%$25)67$+,-$!-%.$+,-8$!*%.$'(+/0$1$:6$(':7($!B
!-,#
$!-1$&$()'9$+,-8$!*".$'(+/0$1$!-;$&$'99$02D$+,-$!-1.$E%$25)67$+,-$!-;.$+,-8$!*".$'(+/0$1$:6$(':7($!1
![Page 5: WRITING AN LLVM PASS · -x86-asm-syntax - Choose style of code to emit: =att - Emit AT&T-style assembly =intel - Emit Intel-style assembly The command sta%c RegisterPass](https://reader030.fdocuments.in/reader030/viewer/2022041121/5f35b5e65b4d6b0a422e05dc/html5/thumbnails/5.jpg)
CounAngNumberofOpcodesinPrograms
#define DEBUG_TYPE "opCounter"
#include "llvm/Pass.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/raw_ostream.h"
#include <map>
using namespace llvm;
namespace {
struct CountOp : public FunctionPass {
std::map<std::string, int> opCounter;
static char ID;
CountOp() : FunctionPass(ID) {}
virtual bool runOnFunction(Function &F) {
errs() << "Function " << F.getName() << '\n';
for (Function::iterator bb = F.begin(), e = F.end(); bb != e; ++bb) {
for (BasicBlock::iterator i = bb->begin(), e = bb->end(); i != e; ++i) {
if(opCounter.find(i->getOpcodeName()) == opCounter.end()) {
opCounter[i->getOpcodeName()] = 1;
} else {
opCounter[i->getOpcodeName()] += 1;
}
}
}
std::map <std::string, int>::iterator i = opCounter.begin();
std::map <std::string, int>::iterator e = opCounter.end();
while (i != e) {
errs() << i->first << ": " << i->second << "\n";
i++;
}
errs() << "\n";
opCounter.clear();
return false;
}
};
}
char CountOp::ID = 0;
static RegisterPass<CountOp> X("opCounter", "Counts opcodes per functions");
Thislinedefinesthenameof
thepass,inthecommandline,e.g.,opCounter,andthehelp
stringthatoptprovidestotheuseraboutthepass.
Ourpassrunsonceforeach
funcAonintheprogram;therefore,itisaFunctionPass.Ifwehadto
seethewholeprogram,thenwewouldimplementaModulePass.
Whatare
anonymousnamespaces?
Count_Opcodes.cpp
![Page 6: WRITING AN LLVM PASS · -x86-asm-syntax - Choose style of code to emit: =att - Emit AT&T-style assembly =intel - Emit Intel-style assembly The command sta%c RegisterPass](https://reader030.fdocuments.in/reader030/viewer/2022041121/5f35b5e65b4d6b0a422e05dc/html5/thumbnails/6.jpg)
ACloserLookintoourPass struct CountOp : public FunctionPass {
std::map<std::string, int> opCounter;
static char ID; CountOp() : FunctionPass(ID) {}
virtual bool runOnFunction(Function &F) {
errs() << "Function " << F.getName() << '\n';
for (Function::iterator bb = F.begin(), e = F.end(); bb != e; ++bb) {
for (BasicBlock::iterator i = bb->begin(), e = bb->end(); i != e; ++i) { if(opCounter.find(i->getOpcodeName()) == opCounter.end()) {
opCounter[i->getOpcodeName()] = 1;
} else {
opCounter[i->getOpcodeName()] += 1;
} }
}
std::map <std::string, int>::iterator i = opCounter.begin();
std::map <std::string, int>::iterator e = opCounter.end();
while (i != e) { errs() << i->first << ": " << i->second << "\n";
i++;
}
errs() << "\n";
opCounter.clear(); return false;
}
};
}
Wewillberecordingthe
numberofeachopcodeinthismap,thatbindsopcode
namestointegernumbers.
Thiscodecollectsthe
opcodes.Wewilllookintoitmorecloselysoon.
Thiscodeprintsourresults.Itisastandardloopon
anSTLdatastructure.Weuseiteratorstogooverthemap.Eachelementinamapisapair,wherethe
firstelementisthekey,andthesecondisthevalue.
Count_Opcodes.cpp
![Page 7: WRITING AN LLVM PASS · -x86-asm-syntax - Choose style of code to emit: =att - Emit AT&T-style assembly =intel - Emit Intel-style assembly The command sta%c RegisterPass](https://reader030.fdocuments.in/reader030/viewer/2022041121/5f35b5e65b4d6b0a422e05dc/html5/thumbnails/7.jpg)
IteraAngThroughFuncAons,BlocksandInsts
for(Function::iterator bb = F.begin(), e = F.end(); bb != e; ++bb) {
for(BasicBlock::iterator i = bb->begin(), e = bb->end(); i != e; ++i) {
if(opCounter.find(i->getOpcodeName()) == opCounter.end()) {
opCounter[i->getOpcodeName()] = 1;
} else {
opCounter[i->getOpcodeName()] += 1;
}
}
}WegooverLLVMdatastructuresthroughiterators.
• AniteratoroveraModulegivesusalistofFuncAons.
• AniteratoroveraFunc@ongivesusalistofbasicblocks.
• AniteratoroveraBlockgivesusalistofinstrucAons.
• AndwecaniterateovertheoperandsoftheinstrucAontoo.
for (User::op_iterator O = I.op_begin(), E = I.op_end(); O != E; ++O);
for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F);
![Page 8: WRITING AN LLVM PASS · -x86-asm-syntax - Choose style of code to emit: =att - Emit AT&T-style assembly =intel - Emit Intel-style assembly The command sta%c RegisterPass](https://reader030.fdocuments.in/reader030/viewer/2022041121/5f35b5e65b4d6b0a422e05dc/html5/thumbnails/8.jpg)
CompilingthePass
• ToCompilethepass,wecanfollowthesetwosteps:
1. Wemaysavethepassinto�
llvm/lib/Transforms/
DirectoryName,where
DirectoryNamecanbe,
forinstance,CountOp.
2. WebuildaMakefilefortheproject.IfweinvoketheLLVM
standardMakefile,wesave
someAme.
#PathtotoplevelofLLVMhierarchy
LEVEL=../../..
#NameofthelibrarytobuildLIBRARYNAME=CountOp
#Makethesharedlibrarybecomea#loadablemodulesothetoolscan
#dlopen/dlsymontheresulAnglibrary.LOADABLE_MODULE=1
#IncludethemakefileimplementaAoninclude$(LEVEL)/Makefile.common
�:Well,giventhatthispassdoesnotchangethesourceprogram,wecouldsaveitinthe
Analysesfolder.FormoreinfoontheLLVMstructure,seehMp://llvm.org/docs/Projects.html
Makefile
![Page 9: WRITING AN LLVM PASS · -x86-asm-syntax - Choose style of code to emit: =att - Emit AT&T-style assembly =intel - Emit Intel-style assembly The command sta%c RegisterPass](https://reader030.fdocuments.in/reader030/viewer/2022041121/5f35b5e65b4d6b0a422e05dc/html5/thumbnails/9.jpg)
RunningthePass
• Ourpassisnowasharedlibrary,inllvm/Debug/lib1.
• Wecaninvokeitusingtheopttool:
$> clang –c –emit-llvm file.c –o file.bc
$> opt -load CountOp.dylib -opCounter -disable-output t.bc
• Remember,ifwearerunningonLinux,thenourshared
libraryhastheextension".so",insteadof".dylib",as
intheMacOS.
Justtoavoid
prinAngthebinaryt.bcfile
1:Actually,thetruelocaAonofthenewlibrarydependsonyoursystemsetup.IfyouhavecompiledLLVM
withthe–DebugdirecAve,forinstance,thenyourbinarieswillbeinllvm/Release/lib.
![Page 10: WRITING AN LLVM PASS · -x86-asm-syntax - Choose style of code to emit: =att - Emit AT&T-style assembly =intel - Emit Intel-style assembly The command sta%c RegisterPass](https://reader030.fdocuments.in/reader030/viewer/2022041121/5f35b5e65b4d6b0a422e05dc/html5/thumbnails/10.jpg)
RegisteringthePass
$> opt -load CountOp.dylib -help
OVERVIEW: llvm .bc -> .bc modular optimizer and analysis printer
USAGE: opt [options] <input bitcode file>
OPTIONS: -O1 - Optimization level 1.
-O2 - Optimization level 2.
...
Optimizations available:
... -objc-arc-contract - ObjC ARC contraction
-objc-arc-expand - ObjC ARC expansion
-opCounter - Counts opcodes per functions
-partial-inliner - Partial Inliner
... -x86-asm-syntax - Choose style of code to emit:
=att - Emit AT&T-style assembly
=intel - Emit Intel-style assembly
Thecommandsta%cRegisterPass<CountOp>X("opCounter","Countsopcodes
perfunc%ons");registersthepassintheLLVM'spassmanager:
![Page 11: WRITING AN LLVM PASS · -x86-asm-syntax - Choose style of code to emit: =att - Emit AT&T-style assembly =intel - Emit Intel-style assembly The command sta%c RegisterPass](https://reader030.fdocuments.in/reader030/viewer/2022041121/5f35b5e65b4d6b0a422e05dc/html5/thumbnails/11.jpg)
TimingthePass
$> opt -load CountOp.dylib -opCounter -disable-output -time-passes f.bc
Function main add: 6
br: 17 call: 1 icmp: 5
ret: 1
===-------------------------------------------------------------------------=== ... Pass execution timing report ... ===-------------------------------------------------------------------------===
Total Execution Time: 0.0010 seconds (0.0011 wall clock)
---User Time--- --System Time-- --User+System-- ---Wall Time--- --- Name --- 0.0002 ( 30.6%) 0.0002 ( 57.7%) 0.0004 ( 37.7%) 0.0004 ( 39.2%) Counts opcodes per functions
0.0003 ( 33.6%) 0.0001 ( 21.1%) 0.0003 ( 30.3%) 0.0003 ( 29.3%) Module Verifier
0.0003 ( 34.6%) 0.0001 ( 18.9%) 0.0003 ( 30.5%) 0.0003 ( 29.2%) Dominator Tree Construction 0.0000 ( 1.2%) 0.0000 ( 2.3%) 0.0000 ( 1.5%) 0.0000 ( 2.3%) Preliminary
verification 0.0008 (100.0%) 0.0003 (100.0%) 0.0010 (100.0%) 0.0011 (100.0%) Total
ThepassmanagerprovidestheAme‐passesdirecAve,thatletsusgetthe
runAmeofeachpassthatwerun.Thatisusefulduringbenchmarking.
Canyouguess
whattheseotherpassesaredoing?
![Page 12: WRITING AN LLVM PASS · -x86-asm-syntax - Choose style of code to emit: =att - Emit AT&T-style assembly =intel - Emit Intel-style assembly The command sta%c RegisterPass](https://reader030.fdocuments.in/reader030/viewer/2022041121/5f35b5e65b4d6b0a422e05dc/html5/thumbnails/12.jpg)
ChainingPasses
• Apassmayinvokeanother.
– Totransformtheprogram,e.g.,BreakCriAcalEdges
– ToobtaininformaAonabouttheprogram,e.g.,
AliasAnalysis
• Ifapassinvokesanother,thenitmustsayitexplicitly,
throughthegetAnalysisUsagemethod,intheclass
FunctionPass.
• Torecoverthedata‐structurescreatedbythepass,we
canusethegetAnalysismethod.
![Page 13: WRITING AN LLVM PASS · -x86-asm-syntax - Choose style of code to emit: =att - Emit AT&T-style assembly =intel - Emit Intel-style assembly The command sta%c RegisterPass](https://reader030.fdocuments.in/reader030/viewer/2022041121/5f35b5e65b4d6b0a422e05dc/html5/thumbnails/13.jpg)
CounAngtheNumberofBasicBlocksinLoops
Inordertodemonstrate
howtoinvokeapassfrom
anotherpass,wewillcreateatooltocountthenumber
ofbasicblocksinsidealoop.
!"#$%&'($!#)*+','*++-.*'/012'*+/3"'4'(*$3.5*66$','*++-.*'/012'*+/3"'4'(*$3)5*66$','*++-.*'/7882'*+/3"'4'(/','*++-.*'/012'*+/3"'4'(9','*++-.*'/012'*+/3"'4'(#','*++-.*'/012'*+/3"'4':#-$!'/01';2'/018'($!#)*+':#-$!'/01'(*$3.2'/018'(*$3.5*66$2'*+/3"'4':#-$!'/788'(*$3)2'/7888'(*$3)5*66$2'*+/3"'4':#-$!'/01';2'/018'(#2'*+/3"'4':#-$!'/01';2'/018'(/2'*+/3"'4'<$'+*<!+'(=-$5.-"6
=-$5.-"6&''(;','+-*6'/018'(/2'*+/3"'4'(.>?','/.>?':+#'/01'(;2'@;'<$'/@'(.>?2'+*<!+'(=-$5<-6%2'+*<!+'(=-$5!"67
A B
=-$5<-6%&'':#-$!'/01';2'/018'(92'*+/3"'4'<$'+*<!+'(=-$5.-"6@
=-$5!"67&''(C','+-*6'/018'(#2'*+/3"'4'(.*++','D?$/"#=E555F'$!#'/01';
=-$5.-"6@&''(@','+-*6'/018'(92'*+/3"'4'(.>?1','/.>?':+#'/01'(@2'@;'<$'/@'(.>?12'+*<!+'(=-$5<-6%02'+*<!+'(=-$5!"6
A B
=-$5<-6%0&''(1','+-*6'/018'(/2'*+/3"'4'(0','+-*6'/018'(92'*+/3"'4'(*66','*66'":G'/01'(12'(0'($!>',':$!>'/01'(*662'C'(.>?4','/.>?'!H'/01'($!>2';'<$'/@'(.>?42'+*<!+'(/=5#I!"2'+*<!+'(/=5!+:!
A B
=-$5!"6&''<$'+*<!+'(=-$5/".J
/=5#I!"&''<$'+*<!+'(=-$5!"6
/=5!+:!&''(4','+-*6'/018'(#2'*+/3"'4'(/".','*66'":G'/01'(42'@':#-$!'/01'(/".2'/018'(#2'*+/3"'4'<$'+*<!+'(/=5!"6
=-$5/".J&''(J','+-*6'/018'(/2'*+/3"'4'(/".C','*66'":G'/01'(J2'@':#-$!'/01'(/".C2'/018'(/2'*+/3"'4'<$'+*<!+'(=-$5.-"6
/=5!"6&''<$'+*<!+'(=-$5/".
=-$5/".&''(K','+-*6'/018'(92'*+/3"'4'(/".K','*66'":G'/01'(K2'@':#-$!'/01'(/".K2'/018'(92'*+/3"'4'<$'+*<!+'(=-$5.-"6@
1) Howmanyloopsdowe
haveintheprogramontheright?
2) HowtoidenAfyaloop?
3) Howmanybasicblocksdowehaveinthe
smallestloop?
![Page 14: WRITING AN LLVM PASS · -x86-asm-syntax - Choose style of code to emit: =att - Emit AT&T-style assembly =intel - Emit Intel-style assembly The command sta%c RegisterPass](https://reader030.fdocuments.in/reader030/viewer/2022041121/5f35b5e65b4d6b0a422e05dc/html5/thumbnails/14.jpg)
DealingwithLoops
Inordertodemonstrate
howtoinvokeapassfrom
anotherpass,wewillcreateatooltocountthenumber
ofbasicblocksinsidealoop.
1) Howmanyloopsdowe
haveintheprogramontheright?
2) HowtoidenAfyaloop?
3) Howmanybasicblocksdowehaveinthe
smallestloop?
• Wecouldimplement
somefuncAonaliAesto
dealwithallthequesAonsonthelej.
• However,LLVMalready
hasapassthathandles
loops.
• Wecanusethispassto
obtainthenumberof
basicblocksperloops.
![Page 15: WRITING AN LLVM PASS · -x86-asm-syntax - Choose style of code to emit: =att - Emit AT&T-style assembly =intel - Emit Intel-style assembly The command sta%c RegisterPass](https://reader030.fdocuments.in/reader030/viewer/2022041121/5f35b5e65b4d6b0a422e05dc/html5/thumbnails/15.jpg)
TheSkeletonofourPass
namespace{
structBBinLoops:publicFunc@onPass{staAccharID;
BBinLoops():FuncAonPass(ID){}
voidgetAnalysisUsage(AnalysisUsage&AU)const{
…}
virtualboolrunOnFuncAon(FuncAon&F){
…
return(false);}
};}
charBBinLoops::ID=0;staAcRegisterPass<BBinLoops>X("bbloop",
"CountthenumberofBBsinsideeachloop");
1) Wewillbegoingover
funcAons;hence,weimplementaFunc@onPass.
2) Apass,inLLVM,is
implementedasaclass(ora
struct,astheyarealmostthesameinC++).
3) ThismethodtellsLLVMwhich
otherpassesweneedto
executeproperly.
4) Ourpassisnotchangingtheprogram,thuswereturn
false.Wereweapplyingany
changeontheprogram,thenourrunOnFuncAonmethod
shouldreturntrue.
Whatisthedifference
betweenstructsandclassesinC++?
Count_Blocks_In_Loops.cpp
![Page 16: WRITING AN LLVM PASS · -x86-asm-syntax - Choose style of code to emit: =att - Emit AT&T-style assembly =intel - Emit Intel-style assembly The command sta%c RegisterPass](https://reader030.fdocuments.in/reader030/viewer/2022041121/5f35b5e65b4d6b0a422e05dc/html5/thumbnails/16.jpg)
WhichAnalysesdoyouNeed?
• AnLLVMpassmustdeclarewhichotherpassesit
requirestoexecuteproperly.
– ThisdeclaraAonisdoneinthegetAnalysisUsage
method.
voidgetAnalysisUsage(AnalysisUsage&AU)const{
AU.addRequired<LoopInfo>();AU.setPreservesAll();
}
Inourexample,wearesayingthatLoopInfo–anLLVMpass–is
requiredbyouranalysis.Wearealsosayingthatwedonot
changetheprograminanywaythatwouldinvalidatetheresultscomputedbyotherpasses.Ifanotherpass,lateron,also
requiresLoopInfo,thentheinformaAonstoredinLoopInfowill
notneedtoberecomputed,forinstance.
![Page 17: WRITING AN LLVM PASS · -x86-asm-syntax - Choose style of code to emit: =att - Emit AT&T-style assembly =intel - Emit Intel-style assembly The command sta%c RegisterPass](https://reader030.fdocuments.in/reader030/viewer/2022041121/5f35b5e65b4d6b0a422e05dc/html5/thumbnails/17.jpg)
TheBasicBlockCounter
virtualboolrunOnFuncAon(FuncAon&F){
LoopInfo&LI=getAnalysis<LoopInfo>();
intloopCounter=0;
errs()<<F.getName()+"\n";for(LoopInfo::iteratori=LI.begin(),e=LI.end();i!=e;++i){
Loop*L=*i;
intbbCounter=0;loopCounter++;
for(Loop::block_iteratorbb=L‐>block_begin();bb!=L‐>block_end();++bb){bbCounter+=1;
}
errs()<<"Loop";errs()<<loopCounter;
errs()<<":#BBs=";errs()<<bbCounter;
errs()<<"\n";
}return(false);
}
Weareusingadata‐structurecalled
LoopInfo,whichisproducedbyapass
withthesamename.WeobtainapointertothispassviagetgetAnalysis
method,whichisparameterizedbya
type,e.g.,theclassnameLoopInfo.
Whatdowe
getwiththeseiterators?
Count_Blocks_In_Loops.cpp
![Page 18: WRITING AN LLVM PASS · -x86-asm-syntax - Choose style of code to emit: =att - Emit AT&T-style assembly =intel - Emit Intel-style assembly The command sta%c RegisterPass](https://reader030.fdocuments.in/reader030/viewer/2022041121/5f35b5e65b4d6b0a422e05dc/html5/thumbnails/18.jpg)
UsingLoopInfo
virtualboolrunOnFuncAon(FuncAon&F){
LoopInfo&LI=getAnalysis<LoopInfo>();intloopCounter=0;
errs()<<F.getName()+"\n";for(LoopInfo::iteratori=LI.begin(),e=LI.end();i!=e;++i){
Loop*L=*i;
intbbCounter=0;loopCounter++;
for(Loop::block_iteratorbb=L‐>block_begin();bb!=L‐>block_end();++bb){
bbCounter+=1;
}
errs()<<"Loop";errs()<<loopCounter;
errs()<<":#BBs=";errs()<<bbCounter;
errs()<<"\n";
}
return(false);
}
AniteratoronLoopInfogivesusa
collecAonofloops.AniteratoronaLoop
givesusacollecAonofbasicblocksthatconsAtutethatloop.
Count_Blocks_In_Loops.cpp
![Page 19: WRITING AN LLVM PASS · -x86-asm-syntax - Choose style of code to emit: =att - Emit AT&T-style assembly =intel - Emit Intel-style assembly The command sta%c RegisterPass](https://reader030.fdocuments.in/reader030/viewer/2022041121/5f35b5e65b4d6b0a422e05dc/html5/thumbnails/19.jpg)
IteraAngonLoops
for(LoopInfo::iteratori=LI.begin(),e=LI.end();i!=e;++i){
…
}
{entry: %retval = alloca i32, align 4 %argc.addr = alloca i32, align 4 %argv.addr = alloca i8**, align 4 %i = alloca i32, align 4 %j = alloca i32, align 4 %t = alloca i32, align 4 store i32 0, i32* %retval store i32 %argc, i32* %argc.addr, align 4 store i8** %argv, i8*** %argv.addr, align 4 store i32 0, i32* %t, align 4 store i32 0, i32* %i, align 4 br label %for.cond}
{for.cond: %0 = load i32* %i, align 4 %cmp = icmp slt i32 %0, 10 br i1 %cmp, label %for.body, label %for.end8|{<s0>T|<s1>F}}
{for.body: store i32 0, i32* %j, align 4 br label %for.cond1}
{for.end8: %7 = load i32* %t, align 4 %call = @printf(...) ret i32 0}
{for.cond1: %1 = load i32* %j, align 4 %cmp2 = icmp slt i32 %1, 10 br i1 %cmp2, label %for.body3, label %for.end|{<s0>T|<s1>F}}
{for.body3: %2 = load i32* %i, align 4 %3 = load i32* %j, align 4 %add = add nsw i32 %2, %3 %rem = srem i32 %add, 7 %cmp4 = icmp eq i32 %rem, 0 br i1 %cmp4, label %if.then, label %if.else|{<s0>T|<s1>F}}
{for.end: br label %for.inc6}
{if.then: br label %for.end}
{if.else: %4 = load i32* %t, align 4 %inc = add nsw i32 %4, 1 store i32 %inc, i32* %t, align 4 br label %if.end}
{if.end: br label %for.inc}
{for.inc: %5 = load i32* %j, align 4 %inc5 = add nsw i32 %5, 1 store i32 %inc5, i32* %j, align 4 br label %for.cond1}
{for.inc6: %6 = load i32* %i, align 4 %inc7 = add nsw i32 %6, 1 store i32 %inc7, i32* %i, align 4 br label %for.cond}
intmain(intargc,char**argv){
inti,j,t=0;for(i=0;i<10;i++){
for(j=0;j<10;j++){
if((i+j)%7==0)
break;
else
t++;
}
}
prinx("%d\n",t);
return0;}
![Page 20: WRITING AN LLVM PASS · -x86-asm-syntax - Choose style of code to emit: =att - Emit AT&T-style assembly =intel - Emit Intel-style assembly The command sta%c RegisterPass](https://reader030.fdocuments.in/reader030/viewer/2022041121/5f35b5e65b4d6b0a422e05dc/html5/thumbnails/20.jpg)
IteraAngonBlocksinsideLoops
for(LoopInfo::iteratori=LI.begin(),e=LI.end();i!=e;++i){
Loop*L=*i;
for(Loop::block_iteratorbb=L‐>block_begin();bb!=L‐>block_end();++bb){}
}
{entry: %retval = alloca i32, align 4 %argc.addr = alloca i32, align 4 %argv.addr = alloca i8**, align 4 %i = alloca i32, align 4 %j = alloca i32, align 4 %t = alloca i32, align 4 store i32 0, i32* %retval store i32 %argc, i32* %argc.addr, align 4 store i8** %argv, i8*** %argv.addr, align 4 store i32 0, i32* %t, align 4 store i32 0, i32* %i, align 4 br label %for.cond}
{for.cond: %0 = load i32* %i, align 4 %cmp = icmp slt i32 %0, 10 br i1 %cmp, label %for.body, label %for.end8|{<s0>T|<s1>F}}
{for.body: store i32 0, i32* %j, align 4 br label %for.cond1}
{for.end8: %7 = load i32* %t, align 4 %call = @printf(...) ret i32 0}
{for.cond1: %1 = load i32* %j, align 4 %cmp2 = icmp slt i32 %1, 10 br i1 %cmp2, label %for.body3, label %for.end|{<s0>T|<s1>F}}
{for.body3: %2 = load i32* %i, align 4 %3 = load i32* %j, align 4 %add = add nsw i32 %2, %3 %rem = srem i32 %add, 7 %cmp4 = icmp eq i32 %rem, 0 br i1 %cmp4, label %if.then, label %if.else|{<s0>T|<s1>F}}
{for.end: br label %for.inc6}
{if.then: br label %for.end}
{if.else: %4 = load i32* %t, align 4 %inc = add nsw i32 %4, 1 store i32 %inc, i32* %t, align 4 br label %if.end}
{if.end: br label %for.inc}
{for.inc: %5 = load i32* %j, align 4 %inc5 = add nsw i32 %5, 1 store i32 %inc5, i32* %j, align 4 br label %for.cond1}
{for.inc6: %6 = load i32* %i, align 4 %inc7 = add nsw i32 %6, 1 store i32 %inc7, i32* %i, align 4 br label %for.cond}
intmain(intargc,char**argv){
inti,j,t=0;for(i=0;i<10;i++){
for(j=0;j<10;j++){
if((i+j)%7==0)
break;
else
t++;
}
}
prinx("%d\n",t);
return0;}
![Page 21: WRITING AN LLVM PASS · -x86-asm-syntax - Choose style of code to emit: =att - Emit AT&T-style assembly =intel - Emit Intel-style assembly The command sta%c RegisterPass](https://reader030.fdocuments.in/reader030/viewer/2022041121/5f35b5e65b4d6b0a422e05dc/html5/thumbnails/21.jpg)
RunningtheCounter
• Again,oncewecompilethispass,wecaninvokeitusing
theopttool,likewedidbefore:
$> clang –c –emit-llvm file.c –o file.bc
$> opt -load dcc888.dylib -bbloop -disable-output file.bc
Theresultsofourpasswillbeprinted
inthestandarderroroutput,aswe
areusingtheerrs()channeltooutputresults.
Function main
Loop 1: #BBs = 10
Ouf,nowwait:we
havetwoloops.Whathappenedto
thesecondone?
![Page 22: WRITING AN LLVM PASS · -x86-asm-syntax - Choose style of code to emit: =att - Emit AT&T-style assembly =intel - Emit Intel-style assembly The command sta%c RegisterPass](https://reader030.fdocuments.in/reader030/viewer/2022041121/5f35b5e65b4d6b0a422e05dc/html5/thumbnails/22.jpg)
FixingtheLoopCounter
virtualboolrunOnFuncAon(FuncAon&F){
LoopInfo&LI=getAnalysis<LoopInfo>();intloopCounter=0;
errs()<<F.getName()+"\n";for(LoopInfo::iteratori=LI.begin(),e=LI.end();i!=e;++i){
Loop*L=*i;
intbbCounter=0;loopCounter++;
for(Loop::block_iteratorbb=L‐>block_begin();bb!=L‐>block_end();++bb){bbCounter+=1;
}
errs()<<"Loop";errs()<<loopCounter;
errs()<<":#BBs=";errs()<<bbCounter;
errs()<<"\n";
}return(false);
}
Thiscodeonlygoesover
theoutermostloopsofa
funcAon.Itdoesnot
reallyvisitnestedloops.
Anyideaon
howcouldwefixit?
Count_Blocks_In_Loops.cpp
![Page 23: WRITING AN LLVM PASS · -x86-asm-syntax - Choose style of code to emit: =att - Emit AT&T-style assembly =intel - Emit Intel-style assembly The command sta%c RegisterPass](https://reader030.fdocuments.in/reader030/viewer/2022041121/5f35b5e65b4d6b0a422e05dc/html5/thumbnails/23.jpg)
RecursivelyNavigaAngThroughLoops
voidcountBlocksInLoop(Loop*L,unsignednesAng){
unsignednumBlocks=0;Loop::block_iteratorbb;
for(bb=L‐>block_begin();bb!=L‐>block_end();++bb)numBlocks++;
errs()<<"Looplevel"<<nesAng<<"has"<<numBlocks<<"blocks\n";
vector<Loop*>subLoops=L‐>getSubLoops();Loop::iteratorj,f;
for(j=subLoops.begin(),f=subLoops.end();j!=f;++j)countBlocksInLoop(*j,nesAng+1);
}
virtualboolrunOnFuncAon(FuncAon&F){
LoopInfo&LI=getAnalysis<LoopInfo>();errs()<<"FuncAon"<<F.getName()+"\n";
for(LoopInfo::iteratori=LI.begin(),e=LI.end();i!=e;++i)
countBlocksInLoop(*i,0);return(false);
}
Count_Blocks_In_Loops2.cpp
Wecanusethe
getSubLoopmethod
toobtainahandlefor
thenestedloops.
Areyousure
thisrecursionterminates?
![Page 24: WRITING AN LLVM PASS · -x86-asm-syntax - Choose style of code to emit: =att - Emit AT&T-style assembly =intel - Emit Intel-style assembly The command sta%c RegisterPass](https://reader030.fdocuments.in/reader030/viewer/2022041121/5f35b5e65b4d6b0a422e05dc/html5/thumbnails/24.jpg)
TheFixinAcAon
intmain(intargc,char**argv){
inti,j,k,t=0;
for(i=0;i<10;i++){
for(j=0;j<10;j++){
for(k=0;k<10;k++){
t++;
}
}
for(j=0;j<10;j++){
t++;
}
}
for(i=0;i<20;i++){
for(j=0;j<20;j++){
t++;
}
for(j=0;j<20;j++){
t++;
}
}
returnt;
}
$>opt‐loaddcc888.dylib‐bbloop‐disable‐outputex.bc
FuncAonmain
Looplevel0has11blocks
Looplevel1has3blocks
Looplevel1has3blocks
Looplevel0has15blocks
Looplevel1has7blocks
Looplevel2has3blocks
Looplevel1has3blocks
0
1 1
0
1
2
1
![Page 25: WRITING AN LLVM PASS · -x86-asm-syntax - Choose style of code to emit: =att - Emit AT&T-style assembly =intel - Emit Intel-style assembly The command sta%c RegisterPass](https://reader030.fdocuments.in/reader030/viewer/2022041121/5f35b5e65b4d6b0a422e05dc/html5/thumbnails/25.jpg)
WhichPassesdoIInvoke?
• TheLLVM'spassmanagerprovidesadebug‐passopAon
thatgivesusthechancetoseewhichpassesinteract
withouranalysesandopAmizaAons:
$> opt -load dcc888.dylib -bbloop -disable-output --debug-
pass=Structure file.bc
Target Library Information
Data Layout
No target information Target independent code generator's TTI
X86 Target Transform Info
ModulePass Manager
FunctionPass Manager
Dominator Tree Construction Natural Loop Information
Count the number of BBs inside each loop
Preliminary module verification
Module Verifier
Thereareother
opAonsthatwecan
usewithdebug‐pass:
‐ Arguments
‐ Details
‐ Disabled
‐ ExecuAons
‐ Structure
![Page 26: WRITING AN LLVM PASS · -x86-asm-syntax - Choose style of code to emit: =att - Emit AT&T-style assembly =intel - Emit Intel-style assembly The command sta%c RegisterPass](https://reader030.fdocuments.in/reader030/viewer/2022041121/5f35b5e65b4d6b0a422e05dc/html5/thumbnails/26.jpg)
FinalRemarks
• LLVMprovidesuserswithastringofanalysesand
opAmizaAonswhicharecalledpasses.
• Userscanchainnewpassesintothispipeline.
• Thepassmanagerordersthepassesinsuchaawayto
saAsfiesthedependencies.
• Passesareorganizedaccordingtotheirgranularity,e.g.,
module,funcAon,loop,basicblock,etc.