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);
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;
}
Address Addr;
- if (!ComputeCallAddress(Callee, Addr))
+ if (Callee && !ComputeCallAddress(Callee, Addr))
return false;
// Handle the arguments now that we've gotten them.
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:
return SelectSelect(I);
case Instruction::Ret:
return SelectRet(I);
+ case Instruction::FRem:
+ return selectFRem(I);
}
// fall-back to target-independent instruction selection.