forked from OSchip/llvm-project
[FastISel][AArch64] Add lowering support for frem.
This lowers frem to a runtime libcall inside fast-isel. The test case also checks the CallLoweringInfo bug that was exposed by this change. This fixes rdar://problem/18342783. llvm-svn: 217833
This commit is contained in:
parent
3c5f180255
commit
afa034fb61
|
@ -141,8 +141,19 @@ public:
|
|||
RetTy = ResultTy;
|
||||
Callee = Target;
|
||||
CallConv = CC;
|
||||
NumFixedArgs = (FixedArgs == ~0U) ? Args.size() : FixedArgs;
|
||||
Args = std::move(ArgsList);
|
||||
NumFixedArgs = (FixedArgs == ~0U) ? Args.size() : FixedArgs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
CallLoweringInfo &setCallee(CallingConv::ID CC, Type *ResultTy,
|
||||
const char *Target, ArgListTy &&ArgsList,
|
||||
unsigned FixedArgs = ~0U) {
|
||||
RetTy = ResultTy;
|
||||
SymName = Target;
|
||||
CallConv = CC;
|
||||
Args = std::move(ArgsList);
|
||||
NumFixedArgs = (FixedArgs == ~0U) ? Args.size() : FixedArgs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
|
@ -132,6 +132,7 @@ private:
|
|||
bool SelectMul(const Instruction *I);
|
||||
bool SelectShift(const Instruction *I);
|
||||
bool SelectBitCast(const Instruction *I);
|
||||
bool selectFRem(const Instruction *I);
|
||||
|
||||
// Utility helper routines.
|
||||
bool isTypeLegal(Type *Ty, MVT &VT);
|
||||
|
@ -2322,6 +2323,9 @@ bool AArch64FastISel::fastLowerCall(CallLoweringInfo &CLI) {
|
|||
const Value *Callee = CLI.Callee;
|
||||
const char *SymName = CLI.SymName;
|
||||
|
||||
if (!Callee && !SymName)
|
||||
return false;
|
||||
|
||||
// Allow SelectionDAG isel to handle tail calls.
|
||||
if (IsTailCall)
|
||||
return false;
|
||||
|
@ -2368,7 +2372,7 @@ bool AArch64FastISel::fastLowerCall(CallLoweringInfo &CLI) {
|
|||
}
|
||||
|
||||
Address Addr;
|
||||
if (!ComputeCallAddress(Callee, Addr))
|
||||
if (Callee && !ComputeCallAddress(Callee, Addr))
|
||||
return false;
|
||||
|
||||
// Handle the arguments now that we've gotten them.
|
||||
|
@ -3624,6 +3628,43 @@ bool AArch64FastISel::SelectBitCast(const Instruction *I) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool AArch64FastISel::selectFRem(const Instruction *I) {
|
||||
MVT RetVT;
|
||||
if (!isTypeLegal(I->getType(), RetVT))
|
||||
return false;
|
||||
|
||||
RTLIB::Libcall LC;
|
||||
switch (RetVT.SimpleTy) {
|
||||
default:
|
||||
return false;
|
||||
case MVT::f32:
|
||||
LC = RTLIB::REM_F32;
|
||||
break;
|
||||
case MVT::f64:
|
||||
LC = RTLIB::REM_F64;
|
||||
break;
|
||||
}
|
||||
|
||||
ArgListTy Args;
|
||||
Args.reserve(I->getNumOperands());
|
||||
|
||||
// Populate the argument list.
|
||||
for (auto &Arg : I->operands()) {
|
||||
ArgListEntry Entry;
|
||||
Entry.Val = Arg;
|
||||
Entry.Ty = Arg->getType();
|
||||
Args.push_back(Entry);
|
||||
}
|
||||
|
||||
CallLoweringInfo CLI;
|
||||
CLI.setCallee(TLI.getLibcallCallingConv(LC), I->getType(),
|
||||
TLI.getLibcallName(LC), std::move(Args));
|
||||
if (!lowerCallTo(CLI))
|
||||
return false;
|
||||
updateValueMap(I, CLI.ResultReg);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AArch64FastISel::fastSelectInstruction(const Instruction *I) {
|
||||
switch (I->getOpcode()) {
|
||||
default:
|
||||
|
@ -3698,6 +3739,8 @@ bool AArch64FastISel::fastSelectInstruction(const Instruction *I) {
|
|||
return SelectSelect(I);
|
||||
case Instruction::Ret:
|
||||
return SelectRet(I);
|
||||
case Instruction::FRem:
|
||||
return selectFRem(I);
|
||||
}
|
||||
|
||||
// fall-back to target-independent instruction selection.
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
; RUN: llc -mtriple=aarch64-apple-darwin -fast-isel -fast-isel-abort -code-model=small -verify-machineinstrs < %s | FileCheck %s --check-prefix=SMALL
|
||||
; RUN: llc -mtriple=aarch64-apple-darwin -fast-isel -fast-isel-abort -code-model=large -verify-machineinstrs < %s | FileCheck %s --check-prefix=LARGE
|
||||
|
||||
define float @frem_f32(float %a, float %b) {
|
||||
; SMALL-LABEL: frem_f32
|
||||
; SMALL: bl _fmodf
|
||||
; LARGE-LABEL: frem_f32
|
||||
; LARGE: adrp [[REG:x[0-9]+]], _fmodf@GOTPAGE
|
||||
; LARGE: ldr [[REG]], {{\[}}[[REG]], _fmodf@GOTPAGEOFF{{\]}}
|
||||
; LARGE-NEXT: blr [[REG]]
|
||||
%1 = frem float %a, %b
|
||||
ret float %1
|
||||
}
|
||||
|
||||
define double @frem_f64(double %a, double %b) {
|
||||
; SMALL-LABEL: frem_f64
|
||||
; SMALL: bl _fmod
|
||||
; LARGE-LABEL: frem_f64
|
||||
; LARGE: adrp [[REG:x[0-9]+]], _fmod@GOTPAGE
|
||||
; LARGE: ldr [[REG]], {{\[}}[[REG]], _fmod@GOTPAGEOFF{{\]}}
|
||||
; LARGE-NEXT: blr [[REG]]
|
||||
%1 = frem double %a, %b
|
||||
ret double %1
|
||||
}
|
Loading…
Reference in New Issue