1 //===- SimplifyHalfPowrLibCalls.cpp - Optimize specific half_powr calls ---===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file implements a simple pass that applies an experimental
11 // transformation on calls to specific functions.
13 //===----------------------------------------------------------------------===//
15 #define DEBUG_TYPE "simplify-libcalls-halfpowr"
16 #include "llvm/Transforms/Scalar.h"
17 #include "llvm/Instructions.h"
18 #include "llvm/Intrinsics.h"
19 #include "llvm/Module.h"
20 #include "llvm/Pass.h"
21 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
22 #include "llvm/Transforms/Utils/Cloning.h"
23 #include "llvm/Target/TargetData.h"
24 #include "llvm/ADT/STLExtras.h"
25 #include "llvm/Support/Debug.h"
29 /// This pass optimizes well half_powr function calls.
31 class SimplifyHalfPowrLibCalls
: public FunctionPass
{
34 static char ID
; // Pass identification
35 SimplifyHalfPowrLibCalls() : FunctionPass(ID
) {
36 initializeSimplifyHalfPowrLibCallsPass(*PassRegistry::getPassRegistry());
39 bool runOnFunction(Function
&F
);
41 virtual void getAnalysisUsage(AnalysisUsage
&AU
) const {
45 InlineHalfPowrs(const std::vector
<Instruction
*> &HalfPowrs
,
46 Instruction
*InsertPt
);
48 char SimplifyHalfPowrLibCalls::ID
= 0;
49 } // end anonymous namespace.
51 INITIALIZE_PASS(SimplifyHalfPowrLibCalls
, "simplify-libcalls-halfpowr",
52 "Simplify half_powr library calls", false, false)
54 // Public interface to the Simplify HalfPowr LibCalls pass.
55 FunctionPass
*llvm::createSimplifyHalfPowrLibCallsPass() {
56 return new SimplifyHalfPowrLibCalls();
59 /// InlineHalfPowrs - Inline a sequence of adjacent half_powr calls, rearranging
60 /// their control flow to better facilitate subsequent optimization.
62 SimplifyHalfPowrLibCalls::
63 InlineHalfPowrs(const std::vector
<Instruction
*> &HalfPowrs
,
64 Instruction
*InsertPt
) {
65 std::vector
<BasicBlock
*> Bodies
;
66 BasicBlock
*NewBlock
= 0;
68 for (unsigned i
= 0, e
= HalfPowrs
.size(); i
!= e
; ++i
) {
69 CallInst
*Call
= cast
<CallInst
>(HalfPowrs
[i
]);
70 Function
*Callee
= Call
->getCalledFunction();
72 // Minimally sanity-check the CFG of half_powr to ensure that it contains
73 // the kind of code we expect. If we're running this pass, we have
74 // reason to believe it will be what we expect.
75 Function::iterator I
= Callee
->begin();
76 BasicBlock
*Prologue
= I
++;
77 if (I
== Callee
->end()) break;
78 BasicBlock
*SubnormalHandling
= I
++;
79 if (I
== Callee
->end()) break;
80 BasicBlock
*Body
= I
++;
81 if (I
!= Callee
->end()) break;
82 if (SubnormalHandling
->getSinglePredecessor() != Prologue
)
84 BranchInst
*PBI
= dyn_cast
<BranchInst
>(Prologue
->getTerminator());
85 if (!PBI
|| !PBI
->isConditional())
87 BranchInst
*SNBI
= dyn_cast
<BranchInst
>(SubnormalHandling
->getTerminator());
88 if (!SNBI
|| SNBI
->isConditional())
90 if (!isa
<ReturnInst
>(Body
->getTerminator()))
93 Instruction
*NextInst
= llvm::next(BasicBlock::iterator(Call
));
95 // Inline the call, taking care of what code ends up where.
96 NewBlock
= SplitBlock(NextInst
->getParent(), NextInst
, this);
98 InlineFunctionInfo
IFI(0, TD
);
99 bool B
= InlineFunction(Call
, IFI
);
100 assert(B
&& "half_powr didn't inline?"); B
=B
;
102 BasicBlock
*NewBody
= NewBlock
->getSinglePredecessor();
104 Bodies
.push_back(NewBody
);
110 // Put the code for all the bodies into one block, to facilitate
111 // subsequent optimization.
112 (void)SplitEdge(NewBlock
->getSinglePredecessor(), NewBlock
, this);
113 for (unsigned i
= 0, e
= Bodies
.size(); i
!= e
; ++i
) {
114 BasicBlock
*Body
= Bodies
[i
];
115 Instruction
*FNP
= Body
->getFirstNonPHI();
116 // Splice the insts from body into NewBlock.
117 NewBlock
->getInstList().splice(NewBlock
->begin(), Body
->getInstList(),
118 FNP
, Body
->getTerminator());
121 return NewBlock
->begin();
124 /// runOnFunction - Top level algorithm.
126 bool SimplifyHalfPowrLibCalls::runOnFunction(Function
&F
) {
127 TD
= getAnalysisIfAvailable
<TargetData
>();
129 bool Changed
= false;
130 std::vector
<Instruction
*> HalfPowrs
;
131 for (Function::iterator BB
= F
.begin(), E
= F
.end(); BB
!= E
; ++BB
) {
132 for (BasicBlock::iterator I
= BB
->begin(), E
= BB
->end(); I
!= E
; ++I
) {
134 bool IsHalfPowr
= false;
135 if (CallInst
*CI
= dyn_cast
<CallInst
>(I
)) {
136 // Look for direct calls and calls to non-external functions.
137 Function
*Callee
= CI
->getCalledFunction();
138 if (Callee
&& Callee
->hasExternalLinkage()) {
139 // Look for calls with well-known names.
140 if (Callee
->getName() == "__half_powrf4")
145 HalfPowrs
.push_back(I
);
146 // We're looking for sequences of up to three such calls, which we'll
147 // simplify as a group.
148 if ((!IsHalfPowr
&& !HalfPowrs
.empty()) || HalfPowrs
.size() == 3) {
149 I
= InlineHalfPowrs(HalfPowrs
, I
);
150 E
= I
->getParent()->end();
155 assert(HalfPowrs
.empty() && "Block had no terminator!");