From 323445f7066f023e22e0eeb3c3572bd44565451f Mon Sep 17 00:00:00 2001 From: Juergen Ributzka Date: Mon, 15 Sep 2014 22:07:49 +0000 Subject: [PATCH] [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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@217833 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/CodeGen/FastISel.h | 11 +++++++++ lib/Target/AArch64/AArch64FastISel.cpp | 45 +++++++++++++++++++++++++++++++++- test/CodeGen/AArch64/fast-isel-frem.ll | 24 ++++++++++++++++++ 3 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 test/CodeGen/AArch64/fast-isel-frem.ll diff --git a/include/llvm/CodeGen/FastISel.h b/include/llvm/CodeGen/FastISel.h index 80b3a40017d..b5405f97d4c 100644 --- a/include/llvm/CodeGen/FastISel.h +++ b/include/llvm/CodeGen/FastISel.h @@ -141,8 +141,19 @@ public: RetTy = ResultTy; Callee = Target; CallConv = CC; + 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; } diff --git a/lib/Target/AArch64/AArch64FastISel.cpp b/lib/Target/AArch64/AArch64FastISel.cpp index 0ea99d442bb..9658834b750 100644 --- a/lib/Target/AArch64/AArch64FastISel.cpp +++ b/lib/Target/AArch64/AArch64FastISel.cpp @@ -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. diff --git a/test/CodeGen/AArch64/fast-isel-frem.ll b/test/CodeGen/AArch64/fast-isel-frem.ll new file mode 100644 index 00000000000..3907fd3003c --- /dev/null +++ b/test/CodeGen/AArch64/fast-isel-frem.ll @@ -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 +} -- 2.11.0