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
This commit is contained in:
Richard Sandiford
2013-08-23 10:27:02 +00:00
parent 287c84a0b4
commit a8a7099c18
16 changed files with 109 additions and 55 deletions

View File

@@ -74,6 +74,9 @@ void LLVMAddLoopUnswitchPass(LLVMPassManagerRef PM);
/** See llvm::createMemCpyOptPass function. */ /** See llvm::createMemCpyOptPass function. */
void LLVMAddMemCpyOptPass(LLVMPassManagerRef PM); void LLVMAddMemCpyOptPass(LLVMPassManagerRef PM);
/** See llvm::createPartiallyInlineLibCallsPass function. */
void LLVMAddPartiallyInlineLibCallsPass(LLVMPassManagerRef PM);
/** See llvm::createPromoteMemoryToRegisterPass function. */ /** See llvm::createPromoteMemoryToRegisterPass function. */
void LLVMAddPromoteMemoryToRegisterPass(LLVMPassManagerRef PM); void LLVMAddPromoteMemoryToRegisterPass(LLVMPassManagerRef PM);

View File

@@ -262,6 +262,10 @@ public:
/// getPopcntSupport - Return hardware support for population count. /// getPopcntSupport - Return hardware support for population count.
virtual PopcntSupportKind getPopcntSupport(unsigned IntTyWidthInBit) const; virtual PopcntSupportKind getPopcntSupport(unsigned IntTyWidthInBit) const;
/// haveFastSqrt -- Return true if the hardware has a fast square-root
/// instruction.
virtual bool haveFastSqrt(Type *Ty) const;
/// getIntImmCost - Return the expected cost of materializing the given /// getIntImmCost - Return the expected cost of materializing the given
/// integer immediate of the specified type. /// integer immediate of the specified type.
virtual unsigned getIntImmCost(const APInt &Imm, Type *Ty) const; virtual unsigned getIntImmCost(const APInt &Imm, Type *Ty) const;

View File

@@ -205,6 +205,7 @@ void initializeObjCARCContractPass(PassRegistry&);
void initializeObjCARCOptPass(PassRegistry&); void initializeObjCARCOptPass(PassRegistry&);
void initializeOptimalEdgeProfilerPass(PassRegistry&); void initializeOptimalEdgeProfilerPass(PassRegistry&);
void initializeOptimizePHIsPass(PassRegistry&); void initializeOptimizePHIsPass(PassRegistry&);
void initializePartiallyInlineLibCallsPass(PassRegistry&);
void initializePEIPass(PassRegistry&); void initializePEIPass(PassRegistry&);
void initializePHIEliminationPass(PassRegistry&); void initializePHIEliminationPass(PassRegistry&);
void initializePartialInlinerPass(PassRegistry&); void initializePartialInlinerPass(PassRegistry&);

View File

@@ -163,6 +163,7 @@ namespace {
(void) llvm::createLoopVectorizePass(); (void) llvm::createLoopVectorizePass();
(void) llvm::createSLPVectorizerPass(); (void) llvm::createSLPVectorizerPass();
(void) llvm::createBBVectorizePass(); (void) llvm::createBBVectorizePass();
(void) llvm::createPartiallyInlineLibCallsPass();
(void)new llvm::IntervalPartition(); (void)new llvm::IntervalPartition();
(void)new llvm::FindUsedTypes(); (void)new llvm::FindUsedTypes();

View File

@@ -354,6 +354,13 @@ extern char &InstructionSimplifierID;
FunctionPass *createLowerExpectIntrinsicPass(); FunctionPass *createLowerExpectIntrinsicPass();
//===----------------------------------------------------------------------===//
//
// PartiallyInlineLibCalls - Tries to inline the fast path of library
// calls such as sqrt.
//
FunctionPass *createPartiallyInlineLibCallsPass();
} // End llvm namespace } // End llvm namespace
#endif #endif

View File

@@ -145,6 +145,10 @@ TargetTransformInfo::getPopcntSupport(unsigned IntTyWidthInBit) const {
return PrevTTI->getPopcntSupport(IntTyWidthInBit); return PrevTTI->getPopcntSupport(IntTyWidthInBit);
} }
bool TargetTransformInfo::haveFastSqrt(Type *Ty) const {
return PrevTTI->haveFastSqrt(Ty);
}
unsigned TargetTransformInfo::getIntImmCost(const APInt &Imm, Type *Ty) const { unsigned TargetTransformInfo::getIntImmCost(const APInt &Imm, Type *Ty) const {
return PrevTTI->getIntImmCost(Imm, Ty); return PrevTTI->getIntImmCost(Imm, Ty);
} }
@@ -505,6 +509,10 @@ struct NoTTI : ImmutablePass, TargetTransformInfo {
return PSK_Software; return PSK_Software;
} }
bool haveFastSqrt(Type *Ty) const {
return false;
}
unsigned getIntImmCost(const APInt &Imm, Type *Ty) const { unsigned getIntImmCost(const APInt &Imm, Type *Ty) const {
return 1; return 1;
} }

View File

@@ -83,6 +83,7 @@ public:
virtual unsigned getJumpBufAlignment() const; virtual unsigned getJumpBufAlignment() const;
virtual unsigned getJumpBufSize() const; virtual unsigned getJumpBufSize() const;
virtual bool shouldBuildLookupTables() const; virtual bool shouldBuildLookupTables() const;
virtual bool haveFastSqrt(Type *Ty) const;
/// @} /// @}
@@ -182,6 +183,12 @@ bool BasicTTI::shouldBuildLookupTables() const {
TLI->isOperationLegalOrCustom(ISD::BRIND, MVT::Other)); TLI->isOperationLegalOrCustom(ISD::BRIND, MVT::Other));
} }
bool BasicTTI::haveFastSqrt(Type *Ty) const {
const TargetLoweringBase *TLI = getTLI();
EVT VT = TLI->getValueType(Ty);
return TLI->isTypeLegal(VT) && TLI->isOperationLegalOrCustom(ISD::FSQRT, VT);
}
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// //
// Calls used by the vectorizers. // Calls used by the vectorizers.

View File

@@ -35,7 +35,6 @@ add_llvm_target(MipsCodeGen
MipsMachineFunction.cpp MipsMachineFunction.cpp
MipsModuleISelDAGToDAG.cpp MipsModuleISelDAGToDAG.cpp
MipsOs16.cpp MipsOs16.cpp
MipsOptimizeMathLibCalls.cpp
MipsRegisterInfo.cpp MipsRegisterInfo.cpp
MipsSEFrameLowering.cpp MipsSEFrameLowering.cpp
MipsSEInstrInfo.cpp MipsSEInstrInfo.cpp

View File

@@ -28,7 +28,6 @@ namespace llvm {
FunctionPass *createMipsJITCodeEmitterPass(MipsTargetMachine &TM, FunctionPass *createMipsJITCodeEmitterPass(MipsTargetMachine &TM,
JITCodeEmitter &JCE); JITCodeEmitter &JCE);
FunctionPass *createMipsConstantIslandPass(MipsTargetMachine &tm); FunctionPass *createMipsConstantIslandPass(MipsTargetMachine &tm);
FunctionPass *createMipsOptimizeMathLibCalls(MipsTargetMachine &TM);
} // end namespace llvm; } // end namespace llvm;
#endif #endif

View File

@@ -32,6 +32,7 @@
#include "llvm/Support/Debug.h" #include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h" #include "llvm/Support/raw_ostream.h"
#include "llvm/Support/TargetRegistry.h" #include "llvm/Support/TargetRegistry.h"
#include "llvm/Transforms/Scalar.h"
using namespace llvm; using namespace llvm;
@@ -160,7 +161,7 @@ void MipsPassConfig::addIRPasses() {
addPass(createMipsOs16(getMipsTargetMachine())); addPass(createMipsOs16(getMipsTargetMachine()));
if (getMipsSubtarget().inMips16HardFloat()) if (getMipsSubtarget().inMips16HardFloat())
addPass(createMips16HardFloat(getMipsTargetMachine())); addPass(createMips16HardFloat(getMipsTargetMachine()));
addPass(createMipsOptimizeMathLibCalls(getMipsTargetMachine())); addPass(createPartiallyInlineLibCallsPass());
} }
// Install an instruction selector pass using // Install an instruction selector pass using
// the ISelDag to gen Mips code. // the ISelDag to gen Mips code.

View File

@@ -10,6 +10,7 @@
#include "SystemZTargetMachine.h" #include "SystemZTargetMachine.h"
#include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/Passes.h"
#include "llvm/Support/TargetRegistry.h" #include "llvm/Support/TargetRegistry.h"
#include "llvm/Transforms/Scalar.h"
using namespace llvm; using namespace llvm;
@@ -47,12 +48,18 @@ public:
return getTM<SystemZTargetMachine>(); return getTM<SystemZTargetMachine>();
} }
virtual void addIRPasses() LLVM_OVERRIDE;
virtual bool addInstSelector() LLVM_OVERRIDE; virtual bool addInstSelector() LLVM_OVERRIDE;
virtual bool addPreSched2() LLVM_OVERRIDE; virtual bool addPreSched2() LLVM_OVERRIDE;
virtual bool addPreEmitPass() LLVM_OVERRIDE; virtual bool addPreEmitPass() LLVM_OVERRIDE;
}; };
} // end anonymous namespace } // end anonymous namespace
void SystemZPassConfig::addIRPasses() {
TargetPassConfig::addIRPasses();
addPass(createPartiallyInlineLibCallsPass());
}
bool SystemZPassConfig::addInstSelector() { bool SystemZPassConfig::addInstSelector() {
addPass(createSystemZISelDag(getSystemZTargetMachine(), getOptLevel())); addPass(createSystemZISelDag(getSystemZTargetMachine(), getOptLevel()));
return false; return false;

View File

@@ -21,6 +21,7 @@ add_llvm_library(LLVMScalarOpts
LoopUnswitch.cpp LoopUnswitch.cpp
LowerAtomic.cpp LowerAtomic.cpp
MemCpyOptimizer.cpp MemCpyOptimizer.cpp
PartiallyInlineLibCalls.cpp
Reassociate.cpp Reassociate.cpp
Reg2Mem.cpp Reg2Mem.cpp
SCCP.cpp SCCP.cpp

View File

@@ -1,4 +1,4 @@
//===---- MipsOptimizeMathLibCalls.cpp - Optimize math lib calls. ----===// //===--- PartiallyInlineLibCalls.cpp - Partially inline libcalls ----------===//
// //
// The LLVM Compiler Infrastructure // The LLVM Compiler Infrastructure
// //
@@ -7,76 +7,60 @@
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// //
// This pass does an IR transformation which enables the backend to emit native // This pass tries to partially inline the fast path of well-known library
// math instructions. // functions, such as using square-root instructions for cases where sqrt()
// does not need to set errno.
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "MipsTargetMachine.h" #define DEBUG_TYPE "partially-inline-libcalls"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/IR/IRBuilder.h" #include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Intrinsics.h" #include "llvm/IR/Intrinsics.h"
#include "llvm/Pass.h" #include "llvm/Pass.h"
#include "llvm/Support/CommandLine.h" #include "llvm/Support/CommandLine.h"
#include "llvm/Target/TargetLibraryInfo.h" #include "llvm/Target/TargetLibraryInfo.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h"
using namespace llvm; using namespace llvm;
static cl::opt<bool> DisableOpt("disable-mips-math-optimization",
cl::init(false),
cl::desc("MIPS: Disable math lib call "
"optimization."), cl::Hidden);
namespace { namespace {
class MipsOptimizeMathLibCalls : public FunctionPass { class PartiallyInlineLibCalls : public FunctionPass {
public: public:
static char ID; static char ID;
MipsOptimizeMathLibCalls(MipsTargetMachine &TM_) : PartiallyInlineLibCalls() :
FunctionPass(ID), TM(TM_) {} FunctionPass(ID) {
initializePartiallyInlineLibCallsPass(*PassRegistry::getPassRegistry());
virtual const char *getPassName() const {
return "MIPS: Optimize calls to math library functions.";
} }
virtual void getAnalysisUsage(AnalysisUsage &AU) const; virtual void getAnalysisUsage(AnalysisUsage &AU) const;
virtual bool runOnFunction(Function &F); virtual bool runOnFunction(Function &F);
private: private:
/// Optimize calls to sqrt. /// Optimize calls to sqrt.
bool optimizeSQRT(CallInst *Call, Function *CalledFunc, bool optimizeSQRT(CallInst *Call, Function *CalledFunc,
BasicBlock &CurrBB, BasicBlock &CurrBB, Function::iterator &BB);
Function::iterator &BB);
const TargetMachine &TM;
}; };
char MipsOptimizeMathLibCalls::ID = 0; char PartiallyInlineLibCalls::ID = 0;
} }
FunctionPass *llvm::createMipsOptimizeMathLibCalls(MipsTargetMachine &TM) { INITIALIZE_PASS(PartiallyInlineLibCalls, "partially-inline-libcalls",
return new MipsOptimizeMathLibCalls(TM); "Partially inline calls to library functions", false, false)
}
void MipsOptimizeMathLibCalls::getAnalysisUsage(AnalysisUsage &AU) const { void PartiallyInlineLibCalls::getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<TargetLibraryInfo>(); AU.addRequired<TargetLibraryInfo>();
AU.addRequired<TargetTransformInfo>();
FunctionPass::getAnalysisUsage(AU); FunctionPass::getAnalysisUsage(AU);
} }
bool MipsOptimizeMathLibCalls::runOnFunction(Function &F) { bool PartiallyInlineLibCalls::runOnFunction(Function &F) {
if (DisableOpt)
return false;
const MipsSubtarget &Subtarget = TM.getSubtarget<MipsSubtarget>();
if (Subtarget.inMips16Mode())
return false;
bool Changed = false; bool Changed = false;
Function::iterator CurrBB; Function::iterator CurrBB;
const TargetLibraryInfo *LibInfo = &getAnalysis<TargetLibraryInfo>(); TargetLibraryInfo *TLI = &getAnalysis<TargetLibraryInfo>();
const TargetTransformInfo *TTI = &getAnalysis<TargetTransformInfo>();
for (Function::iterator BB = F.begin(), BE = F.end(); BB != BE;) { for (Function::iterator BB = F.begin(), BE = F.end(); BB != BE;) {
CurrBB = BB++; CurrBB = BB++;
@@ -88,25 +72,18 @@ bool MipsOptimizeMathLibCalls::runOnFunction(Function &F) {
if (!Call || !(CalledFunc = Call->getCalledFunction())) if (!Call || !(CalledFunc = Call->getCalledFunction()))
continue; continue;
LibFunc::Func LibFunc;
Attribute A = CalledFunc->getAttributes()
.getAttribute(AttributeSet::FunctionIndex, "use-soft-float");
// Skip if function has "use-soft-float" attribute.
if ((A.isStringAttribute() && (A.getValueAsString() == "true")) ||
TM.Options.UseSoftFloat)
continue;
// Skip if function either has local linkage or is not a known library // Skip if function either has local linkage or is not a known library
// function. // function.
LibFunc::Func LibFunc;
if (CalledFunc->hasLocalLinkage() || !CalledFunc->hasName() || if (CalledFunc->hasLocalLinkage() || !CalledFunc->hasName() ||
!LibInfo->getLibFunc(CalledFunc->getName(), LibFunc)) !TLI->getLibFunc(CalledFunc->getName(), LibFunc))
continue; continue;
switch (LibFunc) { switch (LibFunc) {
case LibFunc::sqrtf: case LibFunc::sqrtf:
case LibFunc::sqrt: case LibFunc::sqrt:
if (optimizeSQRT(Call, CalledFunc, *CurrBB, BB)) if (TTI->haveFastSqrt(Call->getType()) &&
optimizeSQRT(Call, CalledFunc, *CurrBB, BB))
break; break;
continue; continue;
default: default:
@@ -121,10 +98,10 @@ bool MipsOptimizeMathLibCalls::runOnFunction(Function &F) {
return Changed; return Changed;
} }
bool MipsOptimizeMathLibCalls::optimizeSQRT(CallInst *Call, bool PartiallyInlineLibCalls::optimizeSQRT(CallInst *Call,
Function *CalledFunc, Function *CalledFunc,
BasicBlock &CurrBB, BasicBlock &CurrBB,
Function::iterator &BB) { Function::iterator &BB) {
// There is no need to change the IR, since backend will emit sqrt // There is no need to change the IR, since backend will emit sqrt
// instruction if the call has already been marked read-only. // instruction if the call has already been marked read-only.
if (Call->onlyReadsMemory()) if (Call->onlyReadsMemory())
@@ -173,3 +150,7 @@ bool MipsOptimizeMathLibCalls::optimizeSQRT(CallInst *Call,
BB = JoinBB; BB = JoinBB;
return true; return true;
} }
FunctionPass *llvm::createPartiallyInlineLibCallsPass() {
return new PartiallyInlineLibCalls();
}

View File

@@ -50,6 +50,7 @@ void llvm::initializeScalarOpts(PassRegistry &Registry) {
initializeLowerAtomicPass(Registry); initializeLowerAtomicPass(Registry);
initializeLowerExpectIntrinsicPass(Registry); initializeLowerExpectIntrinsicPass(Registry);
initializeMemCpyOptPass(Registry); initializeMemCpyOptPass(Registry);
initializePartiallyInlineLibCallsPass(Registry);
initializeReassociatePass(Registry); initializeReassociatePass(Registry);
initializeRegToMemPass(Registry); initializeRegToMemPass(Registry);
initializeSCCPPass(Registry); initializeSCCPPass(Registry);
@@ -123,6 +124,10 @@ void LLVMAddMemCpyOptPass(LLVMPassManagerRef PM) {
unwrap(PM)->add(createMemCpyOptPass()); unwrap(PM)->add(createMemCpyOptPass());
} }
void LLVMAddPartiallyInlineLibCallsPass(LLVMPassManagerRef PM) {
unwrap(PM)->add(createPartiallyInlineLibCallsPass());
}
void LLVMAddPromoteMemoryToRegisterPass(LLVMPassManagerRef PM) { void LLVMAddPromoteMemoryToRegisterPass(LLVMPassManagerRef PM) {
unwrap(PM)->add(createPromoteMemoryToRegisterPass()); unwrap(PM)->add(createPromoteMemoryToRegisterPass());
} }

View File

@@ -2,7 +2,8 @@
; ;
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s ; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
declare float @llvm.sqrt.f32(float %f) declare float @llvm.sqrt.f32(float)
declare float @sqrtf(float)
; Check register square root. ; Check register square root.
define float @f1(float %val) { define float @f1(float %val) {
@@ -152,3 +153,17 @@ define void @f7(float *%ptr) {
ret void ret void
} }
; Check that a call to the normal sqrtf function is lowered.
define float @f8(float %dummy, float %val) {
; CHECK-LABEL: f8:
; CHECK: sqebr %f0, %f2
; CHECK: cebr %f0, %f0
; CHECK: jo [[LABEL:\.L.*]]
; CHECK: br %r14
; CHECK: [[LABEL]]:
; CHECK: ler %f0, %f2
; CHECK: jg sqrtf@PLT
%res = tail call float @sqrtf(float %val)
ret float %res
}

View File

@@ -3,6 +3,7 @@
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s ; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
declare double @llvm.sqrt.f64(double %f) declare double @llvm.sqrt.f64(double %f)
declare double @sqrt(double)
; Check register square root. ; Check register square root.
define double @f1(double %val) { define double @f1(double %val) {
@@ -152,3 +153,17 @@ define void @f7(double *%ptr) {
ret void ret void
} }
; Check that a call to the normal sqrt function is lowered.
define double @f8(double %dummy, double %val) {
; CHECK-LABEL: f8:
; CHECK: sqdbr %f0, %f2
; CHECK: cdbr %f0, %f0
; CHECK: jo [[LABEL:\.L.*]]
; CHECK: br %r14
; CHECK: [[LABEL]]:
; CHECK: ldr %f0, %f2
; CHECK: jg sqrt@PLT
%res = tail call double @sqrt(double %val)
ret double %res
}