[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:
Juergen Ributzka 2014-09-15 22:07:49 +00:00
parent 3c5f180255
commit afa034fb61
3 changed files with 80 additions and 2 deletions

View File

@ -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;
}

View File

@ -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.

View File

@ -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
}