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/Compiler.h"
26 #include "llvm/Support/Debug.h"
27 #include "llvm/Config/config.h"
31 /// This pass optimizes well half_powr function calls.
33 class VISIBILITY_HIDDEN SimplifyHalfPowrLibCalls
: public FunctionPass
{
36 static char ID
; // Pass identification
37 SimplifyHalfPowrLibCalls() : FunctionPass(&ID
) {}
39 bool runOnFunction(Function
&F
);
41 virtual void getAnalysisUsage(AnalysisUsage
&AU
) const {
42 AU
.addRequired
<TargetData
>();
46 InlineHalfPowrs(const std::vector
<Instruction
*> &HalfPowrs
,
47 Instruction
*InsertPt
);
49 char SimplifyHalfPowrLibCalls::ID
= 0;
50 } // end anonymous namespace.
52 static RegisterPass
<SimplifyHalfPowrLibCalls
>
53 X("simplify-libcalls-halfpowr", "Simplify half_powr library calls");
55 // Public interface to the Simplify HalfPowr LibCalls pass.
56 FunctionPass
*llvm::createSimplifyHalfPowrLibCallsPass() {
57 return new SimplifyHalfPowrLibCalls();
60 /// InlineHalfPowrs - Inline a sequence of adjacent half_powr calls, rearranging
61 /// their control flow to better facilitate subsequent optimization.
63 SimplifyHalfPowrLibCalls::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 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
= next(BasicBlock::iterator(Call
));
95 // Inline the call, taking care of what code ends up where.
96 NewBlock
= SplitBlock(NextInst
->getParent(), NextInst
, this);
98 bool B
= InlineFunction(Call
, 0, TD
);
99 assert(B
&& "half_powr didn't inline?"); B
=B
;
101 BasicBlock
*NewBody
= NewBlock
->getSinglePredecessor();
103 Bodies
.push_back(NewBody
);
109 // Put the code for all the bodies into one block, to facilitate
110 // subsequent optimization.
111 (void)SplitEdge(NewBlock
->getSinglePredecessor(), NewBlock
, this);
112 for (unsigned i
= 0, e
= Bodies
.size(); i
!= e
; ++i
) {
113 BasicBlock
*Body
= Bodies
[i
];
114 Instruction
*FNP
= Body
->getFirstNonPHI();
115 // Splice the insts from body into NewBlock.
116 NewBlock
->getInstList().splice(NewBlock
->begin(), Body
->getInstList(),
117 FNP
, Body
->getTerminator());
120 return NewBlock
->begin();
123 /// runOnFunction - Top level algorithm.
125 bool SimplifyHalfPowrLibCalls::runOnFunction(Function
&F
) {
126 TD
= &getAnalysis
<TargetData
>();
128 bool Changed
= false;
129 std::vector
<Instruction
*> HalfPowrs
;
130 for (Function::iterator BB
= F
.begin(), E
= F
.end(); BB
!= E
; ++BB
) {
131 for (BasicBlock::iterator I
= BB
->begin(), E
= BB
->end(); I
!= E
; ++I
) {
133 bool IsHalfPowr
= false;
134 if (CallInst
*CI
= dyn_cast
<CallInst
>(I
)) {
135 // Look for direct calls and calls to non-external functions.
136 Function
*Callee
= CI
->getCalledFunction();
137 if (Callee
&& Callee
->hasExternalLinkage()) {
138 // Look for calls with well-known names.
139 const char *CalleeName
= Callee
->getNameStart();
140 if (strcmp(CalleeName
, "__half_powrf4") == 0)
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!");