llvm.org GIT mirror llvm / a8a7099
Turn MipsOptimizeMathLibCalls into a target-independent scalar transform ...so that it can be used for z too. Most of the code is the same. The only real change is to use TargetTransformInfo to test when a sqrt instruction is available. The pass is opt-in because at the moment it only handles sqrt. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@189097 91177308-0d34-0410-b5e6-96231b3b80d8 Richard Sandiford 6 years ago
17 changed file(s) with 233 addition(s) and 179 deletion(s). Raw diff Collapse all Expand all
261261 /// getPopcntSupport - Return hardware support for population count.
262262 virtual PopcntSupportKind getPopcntSupport(unsigned IntTyWidthInBit) const;
263263
264 /// haveFastSqrt -- Return true if the hardware has a fast square-root
265 /// instruction.
266 virtual bool haveFastSqrt(Type *Ty) const;
267
264268 /// getIntImmCost - Return the expected cost of materializing the given
265269 /// integer immediate of the specified type.
266270 virtual unsigned getIntImmCost(const APInt &Imm, Type *Ty) const;
204204 void initializeObjCARCOptPass(PassRegistry&);
205205 void initializeOptimalEdgeProfilerPass(PassRegistry&);
206206 void initializeOptimizePHIsPass(PassRegistry&);
207 void initializePartiallyInlineLibCallsPass(PassRegistry&);
207208 void initializePEIPass(PassRegistry&);
208209 void initializePHIEliminationPass(PassRegistry&);
209210 void initializePartialInlinerPass(PassRegistry&);
162162 (void) llvm::createLoopVectorizePass();
163163 (void) llvm::createSLPVectorizerPass();
164164 (void) llvm::createBBVectorizePass();
165 (void) llvm::createPartiallyInlineLibCallsPass();
165166
166167 (void)new llvm::IntervalPartition();
167168 (void)new llvm::FindUsedTypes();
353353 FunctionPass *createLowerExpectIntrinsicPass();
354354
355355
356 //===----------------------------------------------------------------------===//
357 //
358 // PartiallyInlineLibCalls - Tries to inline the fast path of library
359 // calls such as sqrt.
360 //
361 FunctionPass *createPartiallyInlineLibCallsPass();
362
356363 } // End llvm namespace
357364
358365 #endif
7373 /** See llvm::createMemCpyOptPass function. */
7474 void LLVMAddMemCpyOptPass(LLVMPassManagerRef PM);
7575
76 /** See llvm::createPartiallyInlineLibCallsPass function. */
77 void LLVMAddPartiallyInlineLibCallsPass(LLVMPassManagerRef PM);
78
7679 /** See llvm::createPromoteMemoryToRegisterPass function. */
7780 void LLVMAddPromoteMemoryToRegisterPass(LLVMPassManagerRef PM);
7881
142142 TargetTransformInfo::PopcntSupportKind
143143 TargetTransformInfo::getPopcntSupport(unsigned IntTyWidthInBit) const {
144144 return PrevTTI->getPopcntSupport(IntTyWidthInBit);
145 }
146
147 bool TargetTransformInfo::haveFastSqrt(Type *Ty) const {
148 return PrevTTI->haveFastSqrt(Ty);
145149 }
146150
147151 unsigned TargetTransformInfo::getIntImmCost(const APInt &Imm, Type *Ty) const {
504508 return PSK_Software;
505509 }
506510
511 bool haveFastSqrt(Type *Ty) const {
512 return false;
513 }
514
507515 unsigned getIntImmCost(const APInt &Imm, Type *Ty) const {
508516 return 1;
509517 }
8282 virtual unsigned getJumpBufAlignment() const;
8383 virtual unsigned getJumpBufSize() const;
8484 virtual bool shouldBuildLookupTables() const;
85 virtual bool haveFastSqrt(Type *Ty) const;
8586
8687 /// @}
8788
179180 return TLI->supportJumpTables() &&
180181 (TLI->isOperationLegalOrCustom(ISD::BR_JT, MVT::Other) ||
181182 TLI->isOperationLegalOrCustom(ISD::BRIND, MVT::Other));
183 }
184
185 bool BasicTTI::haveFastSqrt(Type *Ty) const {
186 const TargetLoweringBase *TLI = getTLI();
187 EVT VT = TLI->getValueType(Ty);
188 return TLI->isTypeLegal(VT) && TLI->isOperationLegalOrCustom(ISD::FSQRT, VT);
182189 }
183190
184191 //===----------------------------------------------------------------------===//
3434 MipsMachineFunction.cpp
3535 MipsModuleISelDAGToDAG.cpp
3636 MipsOs16.cpp
37 MipsOptimizeMathLibCalls.cpp
3837 MipsRegisterInfo.cpp
3938 MipsSEFrameLowering.cpp
4039 MipsSEInstrInfo.cpp
2727 FunctionPass *createMipsJITCodeEmitterPass(MipsTargetMachine &TM,
2828 JITCodeEmitter &JCE);
2929 FunctionPass *createMipsConstantIslandPass(MipsTargetMachine &tm);
30 FunctionPass *createMipsOptimizeMathLibCalls(MipsTargetMachine &TM);
3130 } // end namespace llvm;
3231
3332 #endif
+0
-175
lib/Target/Mips/MipsOptimizeMathLibCalls.cpp less more
None //===---- MipsOptimizeMathLibCalls.cpp - Optimize math lib calls. ----===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This pass does an IR transformation which enables the backend to emit native
10 // math instructions.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "MipsTargetMachine.h"
15 #include "llvm/IR/IRBuilder.h"
16 #include "llvm/IR/Intrinsics.h"
17 #include "llvm/Pass.h"
18 #include "llvm/Support/CommandLine.h"
19 #include "llvm/Target/TargetLibraryInfo.h"
20 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
21
22 using namespace llvm;
23
24 static cl::opt DisableOpt("disable-mips-math-optimization",
25 cl::init(false),
26 cl::desc("MIPS: Disable math lib call "
27 "optimization."), cl::Hidden);
28
29 namespace {
30 class MipsOptimizeMathLibCalls : public FunctionPass {
31 public:
32 static char ID;
33
34 MipsOptimizeMathLibCalls(MipsTargetMachine &TM_) :
35 FunctionPass(ID), TM(TM_) {}
36
37 virtual const char *getPassName() const {
38 return "MIPS: Optimize calls to math library functions.";
39 }
40
41 virtual void getAnalysisUsage(AnalysisUsage &AU) const;
42
43 virtual bool runOnFunction(Function &F);
44
45 private:
46 /// Optimize calls to sqrt.
47 bool optimizeSQRT(CallInst *Call, Function *CalledFunc,
48 BasicBlock &CurrBB,
49 Function::iterator &BB);
50
51 const TargetMachine &TM;
52 };
53
54 char MipsOptimizeMathLibCalls::ID = 0;
55 }
56
57 FunctionPass *llvm::createMipsOptimizeMathLibCalls(MipsTargetMachine &TM) {
58 return new MipsOptimizeMathLibCalls(TM);
59 }
60
61 void MipsOptimizeMathLibCalls::getAnalysisUsage(AnalysisUsage &AU) const {
62 AU.addRequired();
63 FunctionPass::getAnalysisUsage(AU);
64 }
65
66 bool MipsOptimizeMathLibCalls::runOnFunction(Function &F) {
67 if (DisableOpt)
68 return false;
69
70 const MipsSubtarget &Subtarget = TM.getSubtarget();
71
72 if (Subtarget.inMips16Mode())
73 return false;
74
75 bool Changed = false;
76 Function::iterator CurrBB;
77 const TargetLibraryInfo *LibInfo = &getAnalysis();
78
79 for (Function::iterator BB = F.begin(), BE = F.end(); BB != BE;) {
80 CurrBB = BB++;
81
82 for (BasicBlock::iterator II = CurrBB->begin(), IE = CurrBB->end();
83 II != IE; ++II) {
84 CallInst *Call = dyn_cast(&*II);
85 Function *CalledFunc;
86
87 if (!Call || !(CalledFunc = Call->getCalledFunction()))
88 continue;
89
90 LibFunc::Func LibFunc;
91 Attribute A = CalledFunc->getAttributes()
92 .getAttribute(AttributeSet::FunctionIndex, "use-soft-float");
93
94 // Skip if function has "use-soft-float" attribute.
95 if ((A.isStringAttribute() && (A.getValueAsString() == "true")) ||
96 TM.Options.UseSoftFloat)
97 continue;
98
99 // Skip if function either has local linkage or is not a known library
100 // function.
101 if (CalledFunc->hasLocalLinkage() || !CalledFunc->hasName() ||
102 !LibInfo->getLibFunc(CalledFunc->getName(), LibFunc))
103 continue;
104
105 switch (LibFunc) {
106 case LibFunc::sqrtf:
107 case LibFunc::sqrt:
108 if (optimizeSQRT(Call, CalledFunc, *CurrBB, BB))
109 break;
110 continue;
111 default:
112 continue;
113 }
114
115 Changed = true;
116 break;
117 }
118 }
119
120 return Changed;
121 }
122
123 bool MipsOptimizeMathLibCalls::optimizeSQRT(CallInst *Call,
124 Function *CalledFunc,
125 BasicBlock &CurrBB,
126 Function::iterator &BB) {
127 // There is no need to change the IR, since backend will emit sqrt
128 // instruction if the call has already been marked read-only.
129 if (Call->onlyReadsMemory())
130 return false;
131
132 // Do the following transformation:
133 //
134 // (before)
135 // dst = sqrt(src)
136 //
137 // (after)
138 // v0 = sqrt_noreadmem(src) # native sqrt instruction.
139 // if (v0 is a NaN)
140 // v1 = sqrt(src) # library call.
141 // dst = phi(v0, v1)
142 //
143
144 // Move all instructions following Call to newly created block JoinBB.
145 // Create phi and replace all uses.
146 BasicBlock *JoinBB = llvm::SplitBlock(&CurrBB, Call->getNextNode(), this);
147 IRBuilder<> Builder(JoinBB, JoinBB->begin());
148 PHINode *Phi = Builder.CreatePHI(Call->getType(), 2);
149 Call->replaceAllUsesWith(Phi);
150
151 // Create basic block LibCallBB and insert a call to library function sqrt.
152 BasicBlock *LibCallBB = BasicBlock::Create(CurrBB.getContext(), "call.sqrt",
153 CurrBB.getParent(), JoinBB);
154 Builder.SetInsertPoint(LibCallBB);
155 Instruction *LibCall = Call->clone();
156 Builder.Insert(LibCall);
157 Builder.CreateBr(JoinBB);
158
159 // Add attribute "readnone" so that backend can use a native sqrt instruction
160 // for this call. Insert a FP compare instruction and a conditional branch
161 // at the end of CurrBB.
162 Call->addAttribute(AttributeSet::FunctionIndex, Attribute::ReadNone);
163 CurrBB.getTerminator()->eraseFromParent();
164 Builder.SetInsertPoint(&CurrBB);
165 Value *FCmp = Builder.CreateFCmpOEQ(Call, Call);
166 Builder.CreateCondBr(FCmp, JoinBB, LibCallBB);
167
168 // Add phi operands.
169 Phi->addIncoming(Call, &CurrBB);
170 Phi->addIncoming(LibCall, LibCallBB);
171
172 BB = JoinBB;
173 return true;
174 }
3131 #include "llvm/Support/Debug.h"
3232 #include "llvm/Support/raw_ostream.h"
3333 #include "llvm/Support/TargetRegistry.h"
34 #include "llvm/Transforms/Scalar.h"
3435 using namespace llvm;
3536
3637
159160 addPass(createMipsOs16(getMipsTargetMachine()));
160161 if (getMipsSubtarget().inMips16HardFloat())
161162 addPass(createMips16HardFloat(getMipsTargetMachine()));
162 addPass(createMipsOptimizeMathLibCalls(getMipsTargetMachine()));
163 addPass(createPartiallyInlineLibCallsPass());
163164 }
164165 // Install an instruction selector pass using
165166 // the ISelDag to gen Mips code.
99 #include "SystemZTargetMachine.h"
1010 #include "llvm/CodeGen/Passes.h"
1111 #include "llvm/Support/TargetRegistry.h"
12 #include "llvm/Transforms/Scalar.h"
1213
1314 using namespace llvm;
1415
4647 return getTM();
4748 }
4849
50 virtual void addIRPasses() LLVM_OVERRIDE;
4951 virtual bool addInstSelector() LLVM_OVERRIDE;
5052 virtual bool addPreSched2() LLVM_OVERRIDE;
5153 virtual bool addPreEmitPass() LLVM_OVERRIDE;
5254 };
5355 } // end anonymous namespace
56
57 void SystemZPassConfig::addIRPasses() {
58 TargetPassConfig::addIRPasses();
59 addPass(createPartiallyInlineLibCallsPass());
60 }
5461
5562 bool SystemZPassConfig::addInstSelector() {
5663 addPass(createSystemZISelDag(getSystemZTargetMachine(), getOptLevel()));
2020 LoopUnswitch.cpp
2121 LowerAtomic.cpp
2222 MemCpyOptimizer.cpp
23 PartiallyInlineLibCalls.cpp
2324 Reassociate.cpp
2425 Reg2Mem.cpp
2526 SCCP.cpp
0 //===--- PartiallyInlineLibCalls.cpp - Partially inline libcalls ----------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This pass tries to partially inline the fast path of well-known library
10 // functions, such as using square-root instructions for cases where sqrt()
11 // does not need to set errno.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #define DEBUG_TYPE "partially-inline-libcalls"
16 #include "llvm/Analysis/TargetTransformInfo.h"
17 #include "llvm/IR/IRBuilder.h"
18 #include "llvm/IR/Intrinsics.h"
19 #include "llvm/Pass.h"
20 #include "llvm/Support/CommandLine.h"
21 #include "llvm/Target/TargetLibraryInfo.h"
22 #include "llvm/Transforms/Scalar.h"
23 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
24
25 using namespace llvm;
26
27 namespace {
28 class PartiallyInlineLibCalls : public FunctionPass {
29 public:
30 static char ID;
31
32 PartiallyInlineLibCalls() :
33 FunctionPass(ID) {
34 initializePartiallyInlineLibCallsPass(*PassRegistry::getPassRegistry());
35 }
36
37 virtual void getAnalysisUsage(AnalysisUsage &AU) const;
38 virtual bool runOnFunction(Function &F);
39
40 private:
41 /// Optimize calls to sqrt.
42 bool optimizeSQRT(CallInst *Call, Function *CalledFunc,
43 BasicBlock &CurrBB, Function::iterator &BB);
44 };
45
46 char PartiallyInlineLibCalls::ID = 0;
47 }
48
49 INITIALIZE_PASS(PartiallyInlineLibCalls, "partially-inline-libcalls",
50 "Partially inline calls to library functions", false, false)
51
52 void PartiallyInlineLibCalls::getAnalysisUsage(AnalysisUsage &AU) const {
53 AU.addRequired();
54 AU.addRequired();
55 FunctionPass::getAnalysisUsage(AU);
56 }
57
58 bool PartiallyInlineLibCalls::runOnFunction(Function &F) {
59 bool Changed = false;
60 Function::iterator CurrBB;
61 TargetLibraryInfo *TLI = &getAnalysis();
62 const TargetTransformInfo *TTI = &getAnalysis();
63 for (Function::iterator BB = F.begin(), BE = F.end(); BB != BE;) {
64 CurrBB = BB++;
65
66 for (BasicBlock::iterator II = CurrBB->begin(), IE = CurrBB->end();
67 II != IE; ++II) {
68 CallInst *Call = dyn_cast(&*II);
69 Function *CalledFunc;
70
71 if (!Call || !(CalledFunc = Call->getCalledFunction()))
72 continue;
73
74 // Skip if function either has local linkage or is not a known library
75 // function.
76 LibFunc::Func LibFunc;
77 if (CalledFunc->hasLocalLinkage() || !CalledFunc->hasName() ||
78 !TLI->getLibFunc(CalledFunc->getName(), LibFunc))
79 continue;
80
81 switch (LibFunc) {
82 case LibFunc::sqrtf:
83 case LibFunc::sqrt:
84 if (TTI->haveFastSqrt(Call->getType()) &&
85 optimizeSQRT(Call, CalledFunc, *CurrBB, BB))
86 break;
87 continue;
88 default:
89 continue;
90 }
91
92 Changed = true;
93 break;
94 }
95 }
96
97 return Changed;
98 }
99
100 bool PartiallyInlineLibCalls::optimizeSQRT(CallInst *Call,
101 Function *CalledFunc,
102 BasicBlock &CurrBB,
103 Function::iterator &BB) {
104 // There is no need to change the IR, since backend will emit sqrt
105 // instruction if the call has already been marked read-only.
106 if (Call->onlyReadsMemory())
107 return false;
108
109 // Do the following transformation:
110 //
111 // (before)
112 // dst = sqrt(src)
113 //
114 // (after)
115 // v0 = sqrt_noreadmem(src) # native sqrt instruction.
116 // if (v0 is a NaN)
117 // v1 = sqrt(src) # library call.
118 // dst = phi(v0, v1)
119 //
120
121 // Move all instructions following Call to newly created block JoinBB.
122 // Create phi and replace all uses.
123 BasicBlock *JoinBB = llvm::SplitBlock(&CurrBB, Call->getNextNode(), this);
124 IRBuilder<> Builder(JoinBB, JoinBB->begin());
125 PHINode *Phi = Builder.CreatePHI(Call->getType(), 2);
126 Call->replaceAllUsesWith(Phi);
127
128 // Create basic block LibCallBB and insert a call to library function sqrt.
129 BasicBlock *LibCallBB = BasicBlock::Create(CurrBB.getContext(), "call.sqrt",
130 CurrBB.getParent(), JoinBB);
131 Builder.SetInsertPoint(LibCallBB);
132 Instruction *LibCall = Call->clone();
133 Builder.Insert(LibCall);
134 Builder.CreateBr(JoinBB);
135
136 // Add attribute "readnone" so that backend can use a native sqrt instruction
137 // for this call. Insert a FP compare instruction and a conditional branch
138 // at the end of CurrBB.
139 Call->addAttribute(AttributeSet::FunctionIndex, Attribute::ReadNone);
140 CurrBB.getTerminator()->eraseFromParent();
141 Builder.SetInsertPoint(&CurrBB);
142 Value *FCmp = Builder.CreateFCmpOEQ(Call, Call);
143 Builder.CreateCondBr(FCmp, JoinBB, LibCallBB);
144
145 // Add phi operands.
146 Phi->addIncoming(Call, &CurrBB);
147 Phi->addIncoming(LibCall, LibCallBB);
148
149 BB = JoinBB;
150 return true;
151 }
152
153 FunctionPass *llvm::createPartiallyInlineLibCallsPass() {
154 return new PartiallyInlineLibCalls();
155 }
4949 initializeLowerAtomicPass(Registry);
5050 initializeLowerExpectIntrinsicPass(Registry);
5151 initializeMemCpyOptPass(Registry);
52 initializePartiallyInlineLibCallsPass(Registry);
5253 initializeReassociatePass(Registry);
5354 initializeRegToMemPass(Registry);
5455 initializeSCCPPass(Registry);
122123 unwrap(PM)->add(createMemCpyOptPass());
123124 }
124125
126 void LLVMAddPartiallyInlineLibCallsPass(LLVMPassManagerRef PM) {
127 unwrap(PM)->add(createPartiallyInlineLibCallsPass());
128 }
129
125130 void LLVMAddPromoteMemoryToRegisterPass(LLVMPassManagerRef PM) {
126131 unwrap(PM)->add(createPromoteMemoryToRegisterPass());
127132 }
11 ;
22 ; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
33
4 declare float @llvm.sqrt.f32(float %f)
4 declare float @llvm.sqrt.f32(float)
5 declare float @sqrtf(float)
56
67 ; Check register square root.
78 define float @f1(float %val) {
151152
152153 ret void
153154 }
155
156 ; Check that a call to the normal sqrtf function is lowered.
157 define float @f8(float %dummy, float %val) {
158 ; CHECK-LABEL: f8:
159 ; CHECK: sqebr %f0, %f2
160 ; CHECK: cebr %f0, %f0
161 ; CHECK: jo [[LABEL:\.L.*]]
162 ; CHECK: br %r14
163 ; CHECK: [[LABEL]]:
164 ; CHECK: ler %f0, %f2
165 ; CHECK: jg sqrtf@PLT
166 %res = tail call float @sqrtf(float %val)
167 ret float %res
168 }
22 ; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
33
44 declare double @llvm.sqrt.f64(double %f)
5 declare double @sqrt(double)
56
67 ; Check register square root.
78 define double @f1(double %val) {
151152
152153 ret void
153154 }
155
156 ; Check that a call to the normal sqrt function is lowered.
157 define double @f8(double %dummy, double %val) {
158 ; CHECK-LABEL: f8:
159 ; CHECK: sqdbr %f0, %f2
160 ; CHECK: cdbr %f0, %f0
161 ; CHECK: jo [[LABEL:\.L.*]]
162 ; CHECK: br %r14
163 ; CHECK: [[LABEL]]:
164 ; CHECK: ldr %f0, %f2
165 ; CHECK: jg sqrt@PLT
166 %res = tail call double @sqrt(double %val)
167 ret double %res
168 }