mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-14 00:32:55 +00:00
Fall back to selection DAG isel for calls to builtin functions.
Fast isel doesn't currently have support for translating builtin function calls to target instructions. For embedded environments where the library functions are not available, this is a matter of correctness and not just optimization. Most of this patch is just arranging to make the TargetLibraryInfo available in fast isel. <rdar://problem/12008746> git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@161232 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
d1e672e023
commit
d49edb7ab0
@ -34,6 +34,7 @@ class MachineFrameInfo;
|
|||||||
class MachineRegisterInfo;
|
class MachineRegisterInfo;
|
||||||
class TargetData;
|
class TargetData;
|
||||||
class TargetInstrInfo;
|
class TargetInstrInfo;
|
||||||
|
class TargetLibraryInfo;
|
||||||
class TargetLowering;
|
class TargetLowering;
|
||||||
class TargetMachine;
|
class TargetMachine;
|
||||||
class TargetRegisterClass;
|
class TargetRegisterClass;
|
||||||
@ -57,6 +58,7 @@ protected:
|
|||||||
const TargetInstrInfo &TII;
|
const TargetInstrInfo &TII;
|
||||||
const TargetLowering &TLI;
|
const TargetLowering &TLI;
|
||||||
const TargetRegisterInfo &TRI;
|
const TargetRegisterInfo &TRI;
|
||||||
|
const TargetLibraryInfo *LibInfo;
|
||||||
|
|
||||||
/// The position of the last instruction for materializing constants
|
/// The position of the last instruction for materializing constants
|
||||||
/// for use in the current block. It resets to EmitStartPt when it
|
/// for use in the current block. It resets to EmitStartPt when it
|
||||||
@ -144,7 +146,8 @@ public:
|
|||||||
virtual ~FastISel();
|
virtual ~FastISel();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
explicit FastISel(FunctionLoweringInfo &funcInfo);
|
explicit FastISel(FunctionLoweringInfo &funcInfo,
|
||||||
|
const TargetLibraryInfo *libInfo);
|
||||||
|
|
||||||
/// TargetSelectInstruction - This method is called by target-independent
|
/// TargetSelectInstruction - This method is called by target-independent
|
||||||
/// code when the normal FastISel process fails to select an instruction.
|
/// code when the normal FastISel process fails to select an instruction.
|
||||||
|
@ -51,6 +51,7 @@ namespace llvm {
|
|||||||
template<typename T> class SmallVectorImpl;
|
template<typename T> class SmallVectorImpl;
|
||||||
class TargetData;
|
class TargetData;
|
||||||
class TargetRegisterClass;
|
class TargetRegisterClass;
|
||||||
|
class TargetLibraryInfo;
|
||||||
class TargetLoweringObjectFile;
|
class TargetLoweringObjectFile;
|
||||||
class Value;
|
class Value;
|
||||||
|
|
||||||
@ -1413,7 +1414,8 @@ public:
|
|||||||
|
|
||||||
/// createFastISel - This method returns a target specific FastISel object,
|
/// createFastISel - This method returns a target specific FastISel object,
|
||||||
/// or null if the target does not support "fast" ISel.
|
/// or null if the target does not support "fast" ISel.
|
||||||
virtual FastISel *createFastISel(FunctionLoweringInfo &) const {
|
virtual FastISel *createFastISel(FunctionLoweringInfo &,
|
||||||
|
const TargetLibraryInfo *) const {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,6 +55,7 @@
|
|||||||
#include "llvm/Analysis/Loads.h"
|
#include "llvm/Analysis/Loads.h"
|
||||||
#include "llvm/Target/TargetData.h"
|
#include "llvm/Target/TargetData.h"
|
||||||
#include "llvm/Target/TargetInstrInfo.h"
|
#include "llvm/Target/TargetInstrInfo.h"
|
||||||
|
#include "llvm/Target/TargetLibraryInfo.h"
|
||||||
#include "llvm/Target/TargetLowering.h"
|
#include "llvm/Target/TargetLowering.h"
|
||||||
#include "llvm/Target/TargetMachine.h"
|
#include "llvm/Target/TargetMachine.h"
|
||||||
#include "llvm/Support/ErrorHandling.h"
|
#include "llvm/Support/ErrorHandling.h"
|
||||||
@ -789,6 +790,18 @@ FastISel::SelectInstruction(const Instruction *I) {
|
|||||||
|
|
||||||
MachineBasicBlock::iterator SavedInsertPt = FuncInfo.InsertPt;
|
MachineBasicBlock::iterator SavedInsertPt = FuncInfo.InsertPt;
|
||||||
|
|
||||||
|
// As a special case, don't even try to handle calls to builtin library
|
||||||
|
// functions so that calls to builtin functions get translated to
|
||||||
|
// instructions when supported by the target.
|
||||||
|
if (const CallInst *Call = dyn_cast<CallInst>(I)) {
|
||||||
|
const Function *F = Call->getCalledFunction();
|
||||||
|
LibFunc::Func Func;
|
||||||
|
if (F && !F->hasLocalLinkage() && F->hasName() &&
|
||||||
|
LibInfo->getLibFunc(F->getName(), Func) &&
|
||||||
|
LibInfo->has(Func))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// First, try doing target-independent selection.
|
// First, try doing target-independent selection.
|
||||||
if (SelectOperator(I, I->getOpcode())) {
|
if (SelectOperator(I, I->getOpcode())) {
|
||||||
++NumFastIselSuccessIndependent;
|
++NumFastIselSuccessIndependent;
|
||||||
@ -1040,7 +1053,8 @@ FastISel::SelectOperator(const User *I, unsigned Opcode) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FastISel::FastISel(FunctionLoweringInfo &funcInfo)
|
FastISel::FastISel(FunctionLoweringInfo &funcInfo,
|
||||||
|
const TargetLibraryInfo *libInfo)
|
||||||
: FuncInfo(funcInfo),
|
: FuncInfo(funcInfo),
|
||||||
MRI(FuncInfo.MF->getRegInfo()),
|
MRI(FuncInfo.MF->getRegInfo()),
|
||||||
MFI(*FuncInfo.MF->getFrameInfo()),
|
MFI(*FuncInfo.MF->getFrameInfo()),
|
||||||
@ -1049,7 +1063,8 @@ FastISel::FastISel(FunctionLoweringInfo &funcInfo)
|
|||||||
TD(*TM.getTargetData()),
|
TD(*TM.getTargetData()),
|
||||||
TII(*TM.getInstrInfo()),
|
TII(*TM.getInstrInfo()),
|
||||||
TLI(*TM.getTargetLowering()),
|
TLI(*TM.getTargetLowering()),
|
||||||
TRI(*TM.getRegisterInfo()) {
|
TRI(*TM.getRegisterInfo()),
|
||||||
|
LibInfo(libInfo) {
|
||||||
}
|
}
|
||||||
|
|
||||||
FastISel::~FastISel() {}
|
FastISel::~FastISel() {}
|
||||||
|
@ -979,7 +979,7 @@ void SelectionDAGISel::SelectAllBasicBlocks(const Function &Fn) {
|
|||||||
// Initialize the Fast-ISel state, if needed.
|
// Initialize the Fast-ISel state, if needed.
|
||||||
FastISel *FastIS = 0;
|
FastISel *FastIS = 0;
|
||||||
if (TM.Options.EnableFastISel)
|
if (TM.Options.EnableFastISel)
|
||||||
FastIS = TLI.createFastISel(*FuncInfo);
|
FastIS = TLI.createFastISel(*FuncInfo, LibInfo);
|
||||||
|
|
||||||
// Iterate over all basic blocks in the function.
|
// Iterate over all basic blocks in the function.
|
||||||
ReversePostOrderTraversal<const Function*> RPOT(&Fn);
|
ReversePostOrderTraversal<const Function*> RPOT(&Fn);
|
||||||
|
@ -87,8 +87,9 @@ class ARMFastISel : public FastISel {
|
|||||||
LLVMContext *Context;
|
LLVMContext *Context;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ARMFastISel(FunctionLoweringInfo &funcInfo)
|
explicit ARMFastISel(FunctionLoweringInfo &funcInfo,
|
||||||
: FastISel(funcInfo),
|
const TargetLibraryInfo *libInfo)
|
||||||
|
: FastISel(funcInfo, libInfo),
|
||||||
TM(funcInfo.MF->getTarget()),
|
TM(funcInfo.MF->getTarget()),
|
||||||
TII(*TM.getInstrInfo()),
|
TII(*TM.getInstrInfo()),
|
||||||
TLI(*TM.getTargetLowering()) {
|
TLI(*TM.getTargetLowering()) {
|
||||||
@ -2787,14 +2788,15 @@ bool ARMFastISel::TryToFoldLoad(MachineInstr *MI, unsigned OpNo,
|
|||||||
}
|
}
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
FastISel *ARM::createFastISel(FunctionLoweringInfo &funcInfo) {
|
FastISel *ARM::createFastISel(FunctionLoweringInfo &funcInfo,
|
||||||
|
const TargetLibraryInfo *libInfo) {
|
||||||
// Completely untested on non-iOS.
|
// Completely untested on non-iOS.
|
||||||
const TargetMachine &TM = funcInfo.MF->getTarget();
|
const TargetMachine &TM = funcInfo.MF->getTarget();
|
||||||
|
|
||||||
// Darwin and thumb1 only for now.
|
// Darwin and thumb1 only for now.
|
||||||
const ARMSubtarget *Subtarget = &TM.getSubtarget<ARMSubtarget>();
|
const ARMSubtarget *Subtarget = &TM.getSubtarget<ARMSubtarget>();
|
||||||
if (Subtarget->isTargetIOS() && !Subtarget->isThumb1Only())
|
if (Subtarget->isTargetIOS() && !Subtarget->isThumb1Only())
|
||||||
return new ARMFastISel(funcInfo);
|
return new ARMFastISel(funcInfo, libInfo);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1041,8 +1041,9 @@ const TargetRegisterClass *ARMTargetLowering::getRegClassFor(EVT VT) const {
|
|||||||
|
|
||||||
// Create a fast isel object.
|
// Create a fast isel object.
|
||||||
FastISel *
|
FastISel *
|
||||||
ARMTargetLowering::createFastISel(FunctionLoweringInfo &funcInfo) const {
|
ARMTargetLowering::createFastISel(FunctionLoweringInfo &funcInfo,
|
||||||
return ARM::createFastISel(funcInfo);
|
const TargetLibraryInfo *libInfo) const {
|
||||||
|
return ARM::createFastISel(funcInfo, libInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// getMaximalGlobalOffset - Returns the maximal possible offset which can
|
/// getMaximalGlobalOffset - Returns the maximal possible offset which can
|
||||||
|
@ -361,7 +361,8 @@ namespace llvm {
|
|||||||
|
|
||||||
/// createFastISel - This method returns a target specific FastISel object,
|
/// createFastISel - This method returns a target specific FastISel object,
|
||||||
/// or null if the target does not support "fast" ISel.
|
/// or null if the target does not support "fast" ISel.
|
||||||
virtual FastISel *createFastISel(FunctionLoweringInfo &funcInfo) const;
|
virtual FastISel *createFastISel(FunctionLoweringInfo &funcInfo,
|
||||||
|
const TargetLibraryInfo *libInfo) const;
|
||||||
|
|
||||||
Sched::Preference getSchedulingPreference(SDNode *N) const;
|
Sched::Preference getSchedulingPreference(SDNode *N) const;
|
||||||
|
|
||||||
@ -544,7 +545,8 @@ namespace llvm {
|
|||||||
|
|
||||||
|
|
||||||
namespace ARM {
|
namespace ARM {
|
||||||
FastISel *createFastISel(FunctionLoweringInfo &funcInfo);
|
FastISel *createFastISel(FunctionLoweringInfo &funcInfo,
|
||||||
|
const TargetLibraryInfo *libInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,7 +57,9 @@ class X86FastISel : public FastISel {
|
|||||||
bool X86ScalarSSEf32;
|
bool X86ScalarSSEf32;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit X86FastISel(FunctionLoweringInfo &funcInfo) : FastISel(funcInfo) {
|
explicit X86FastISel(FunctionLoweringInfo &funcInfo,
|
||||||
|
const TargetLibraryInfo *libInfo)
|
||||||
|
: FastISel(funcInfo, libInfo) {
|
||||||
Subtarget = &TM.getSubtarget<X86Subtarget>();
|
Subtarget = &TM.getSubtarget<X86Subtarget>();
|
||||||
StackPtr = Subtarget->is64Bit() ? X86::RSP : X86::ESP;
|
StackPtr = Subtarget->is64Bit() ? X86::RSP : X86::ESP;
|
||||||
X86ScalarSSEf64 = Subtarget->hasSSE2();
|
X86ScalarSSEf64 = Subtarget->hasSSE2();
|
||||||
@ -2199,7 +2201,8 @@ bool X86FastISel::TryToFoldLoad(MachineInstr *MI, unsigned OpNo,
|
|||||||
|
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
FastISel *X86::createFastISel(FunctionLoweringInfo &funcInfo) {
|
FastISel *X86::createFastISel(FunctionLoweringInfo &funcInfo,
|
||||||
return new X86FastISel(funcInfo);
|
const TargetLibraryInfo *libInfo) {
|
||||||
|
return new X86FastISel(funcInfo, libInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2896,8 +2896,9 @@ X86TargetLowering::IsEligibleForTailCallOptimization(SDValue Callee,
|
|||||||
}
|
}
|
||||||
|
|
||||||
FastISel *
|
FastISel *
|
||||||
X86TargetLowering::createFastISel(FunctionLoweringInfo &funcInfo) const {
|
X86TargetLowering::createFastISel(FunctionLoweringInfo &funcInfo,
|
||||||
return X86::createFastISel(funcInfo);
|
const TargetLibraryInfo *libInfo) const {
|
||||||
|
return X86::createFastISel(funcInfo, libInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -670,7 +670,8 @@ namespace llvm {
|
|||||||
|
|
||||||
/// createFastISel - This method returns a target specific FastISel object,
|
/// createFastISel - This method returns a target specific FastISel object,
|
||||||
/// or null if the target does not support "fast" ISel.
|
/// or null if the target does not support "fast" ISel.
|
||||||
virtual FastISel *createFastISel(FunctionLoweringInfo &funcInfo) const;
|
virtual FastISel *createFastISel(FunctionLoweringInfo &funcInfo,
|
||||||
|
const TargetLibraryInfo *libInfo) const;
|
||||||
|
|
||||||
/// getStackCookieLocation - Return true if the target stores stack
|
/// getStackCookieLocation - Return true if the target stores stack
|
||||||
/// protector cookies at a fixed offset in some non-standard address
|
/// protector cookies at a fixed offset in some non-standard address
|
||||||
@ -947,7 +948,8 @@ namespace llvm {
|
|||||||
};
|
};
|
||||||
|
|
||||||
namespace X86 {
|
namespace X86 {
|
||||||
FastISel *createFastISel(FunctionLoweringInfo &funcInfo);
|
FastISel *createFastISel(FunctionLoweringInfo &funcInfo,
|
||||||
|
const TargetLibraryInfo *libInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
; Make sure this testcase codegens to the fabs instruction, not a call to fabsf
|
; Make sure this testcase codegens to the fabs instruction, not a call to fabsf
|
||||||
; RUN: llc < %s -march=x86 -mattr=-sse2,-sse3,-sse | FileCheck %s
|
; RUN: llc < %s -march=x86 -mattr=-sse2,-sse3,-sse | FileCheck %s
|
||||||
; RUN: llc < %s -march=x86 -mattr=-sse,-sse2,-sse3 -enable-unsafe-fp-math -enable-no-nans-fp-math | FileCheck %s --check-prefix=UNSAFE
|
; RUN: llc < %s -march=x86 -mattr=-sse,-sse2,-sse3 -enable-unsafe-fp-math -enable-no-nans-fp-math | FileCheck %s --check-prefix=UNSAFE
|
||||||
|
; RUN: llc < %s -march=x86-64 -O0 | FileCheck %s --check-prefix=NOOPT
|
||||||
|
|
||||||
declare float @fabsf(float)
|
declare float @fabsf(float)
|
||||||
|
|
||||||
@ -8,6 +9,7 @@ declare x86_fp80 @fabsl(x86_fp80)
|
|||||||
|
|
||||||
; CHECK: test1:
|
; CHECK: test1:
|
||||||
; UNSAFE: test1:
|
; UNSAFE: test1:
|
||||||
|
; NOOPT: test1:
|
||||||
define float @test1(float %X) {
|
define float @test1(float %X) {
|
||||||
%Y = call float @fabsf(float %X)
|
%Y = call float @fabsf(float %X)
|
||||||
ret float %Y
|
ret float %Y
|
||||||
@ -17,9 +19,11 @@ define float @test1(float %X) {
|
|||||||
|
|
||||||
; CHECK-NOT: fabs
|
; CHECK-NOT: fabs
|
||||||
; UNSAFE-NOT: fabs
|
; UNSAFE-NOT: fabs
|
||||||
|
; NOOPT-NOT: fabsf
|
||||||
|
|
||||||
; CHECK: test2:
|
; CHECK: test2:
|
||||||
; UNSAFE: test2:
|
; UNSAFE: test2:
|
||||||
|
; NOOPT: test2:
|
||||||
define double @test2(double %X) {
|
define double @test2(double %X) {
|
||||||
%Y = fcmp oge double %X, -0.0
|
%Y = fcmp oge double %X, -0.0
|
||||||
%Z = fsub double -0.0, %X
|
%Z = fsub double -0.0, %X
|
||||||
@ -28,6 +32,7 @@ define double @test2(double %X) {
|
|||||||
}
|
}
|
||||||
; fabs is not used here.
|
; fabs is not used here.
|
||||||
; CHECK-NOT: fabs
|
; CHECK-NOT: fabs
|
||||||
|
; NOOPT-NOT: fabs
|
||||||
|
|
||||||
; UNSAFE: {{^[ \t]+fabs$}}
|
; UNSAFE: {{^[ \t]+fabs$}}
|
||||||
|
|
||||||
@ -35,12 +40,15 @@ define double @test2(double %X) {
|
|||||||
|
|
||||||
; CHECK: test3:
|
; CHECK: test3:
|
||||||
; UNSAFE: test3:
|
; UNSAFE: test3:
|
||||||
|
; NOOPT: test3:
|
||||||
define x86_fp80 @test3(x86_fp80 %X) {
|
define x86_fp80 @test3(x86_fp80 %X) {
|
||||||
%Y = call x86_fp80 @fabsl(x86_fp80 %X)
|
%Y = call x86_fp80 @fabsl(x86_fp80 %X)
|
||||||
ret x86_fp80 %Y
|
ret x86_fp80 %Y
|
||||||
}
|
}
|
||||||
; CHECK: {{^[ \t]+fabs$}}
|
; CHECK: {{^[ \t]+fabs$}}
|
||||||
; UNSAFE: {{^[ \t]+fabs$}}
|
; UNSAFE: {{^[ \t]+fabs$}}
|
||||||
|
; NOOPT: {{^[ \t]+fabs$}}
|
||||||
|
|
||||||
; CHECK-NOT: fabs
|
; CHECK-NOT: fabs
|
||||||
; UNSAFE-NOT: fabs
|
; UNSAFE-NOT: fabs
|
||||||
|
; NOOPT-NOT: fabs
|
||||||
|
Loading…
x
Reference in New Issue
Block a user