bool translateOverflowIntrinsic(const CallInst &CI, unsigned Op,
MachineIRBuilder &MIRBuilder);
- /// Helper function for translateSimpleUnaryIntrinsic.
+ /// Helper function for translateSimpleIntrinsic.
/// \return The generic opcode for \p IntrinsicID if \p IntrinsicID is a
- /// simple unary intrinsic (ceil, fabs, etc.). Otherwise, returns
+ /// simple intrinsic (ceil, fabs, etc.). Otherwise, returns
/// Intrinsic::not_intrinsic.
- unsigned getSimpleUnaryIntrinsicOpcode(Intrinsic::ID ID);
+ unsigned getSimpleIntrinsicOpcode(Intrinsic::ID ID);
- /// Translates the intrinsics defined in getSimpleUnaryIntrinsicOpcode.
+ /// Translates the intrinsics defined in getSimpleIntrinsicOpcode.
/// \return true if the translation succeeded.
- bool translateSimpleUnaryIntrinsic(const CallInst &CI, Intrinsic::ID ID,
- MachineIRBuilder &MIRBuilder);
+ bool translateSimpleIntrinsic(const CallInst &CI, Intrinsic::ID ID,
+ MachineIRBuilder &MIRBuilder);
bool translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID,
MachineIRBuilder &MIRBuilder);
return true;
}
-unsigned
-IRTranslator::getSimpleUnaryIntrinsicOpcode(Intrinsic::ID ID) {
+unsigned IRTranslator::getSimpleIntrinsicOpcode(Intrinsic::ID ID) {
switch (ID) {
default:
break;
return TargetOpcode::G_FCANONICALIZE;
case Intrinsic::floor:
return TargetOpcode::G_FFLOOR;
+ case Intrinsic::fma:
+ return TargetOpcode::G_FMA;
case Intrinsic::log:
return TargetOpcode::G_FLOG;
case Intrinsic::log2:
return TargetOpcode::G_FLOG2;
case Intrinsic::log10:
return TargetOpcode::G_FLOG10;
+ case Intrinsic::pow:
+ return TargetOpcode::G_FPOW;
case Intrinsic::round:
return TargetOpcode::G_INTRINSIC_ROUND;
case Intrinsic::sin:
return Intrinsic::not_intrinsic;
}
-bool IRTranslator::translateSimpleUnaryIntrinsic(
- const CallInst &CI, Intrinsic::ID ID, MachineIRBuilder &MIRBuilder) {
+bool IRTranslator::translateSimpleIntrinsic(const CallInst &CI,
+ Intrinsic::ID ID,
+ MachineIRBuilder &MIRBuilder) {
- unsigned Op = getSimpleUnaryIntrinsicOpcode(ID);
+ unsigned Op = getSimpleIntrinsicOpcode(ID);
- // Is this a simple unary intrinsic?
+ // Is this a simple intrinsic?
if (Op == Intrinsic::not_intrinsic)
return false;
// Yes. Let's translate it.
- MIRBuilder.buildInstr(Op, {getOrCreateVReg(CI)},
- {getOrCreateVReg(*CI.getArgOperand(0))},
+ SmallVector<llvm::SrcOp, 4> VRegs;
+ for (auto &Arg : CI.arg_operands())
+ VRegs.push_back(getOrCreateVReg(*Arg));
+
+ MIRBuilder.buildInstr(Op, {getOrCreateVReg(CI)}, VRegs,
MachineInstr::copyFlagsFromInstruction(CI));
return true;
}
bool IRTranslator::translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID,
MachineIRBuilder &MIRBuilder) {
- // If this is a simple unary intrinsic (that is, we just need to add a def of
- // a vreg, and a use of a vreg, then translate it.
- if (translateSimpleUnaryIntrinsic(CI, ID, MIRBuilder))
+ // If this is a simple intrinsic (that is, we just need to add a def of
+ // a vreg, and uses for each arg operand, then translate it.
+ if (translateSimpleIntrinsic(CI, ID, MIRBuilder))
return true;
switch (ID) {
return translateOverflowIntrinsic(CI, TargetOpcode::G_UMULO, MIRBuilder);
case Intrinsic::smul_with_overflow:
return translateOverflowIntrinsic(CI, TargetOpcode::G_SMULO, MIRBuilder);
- case Intrinsic::pow: {
- MIRBuilder.buildInstr(TargetOpcode::G_FPOW, {getOrCreateVReg(CI)},
- {getOrCreateVReg(*CI.getArgOperand(0)),
- getOrCreateVReg(*CI.getArgOperand(1))},
- MachineInstr::copyFlagsFromInstruction(CI));
- return true;
- }
- case Intrinsic::fma: {
- MIRBuilder.buildInstr(TargetOpcode::G_FMA, {getOrCreateVReg(CI)},
- {getOrCreateVReg(*CI.getArgOperand(0)),
- getOrCreateVReg(*CI.getArgOperand(1)),
- getOrCreateVReg(*CI.getArgOperand(2))},
- MachineInstr::copyFlagsFromInstruction(CI));
- return true;
- }
case Intrinsic::fmuladd: {
const TargetMachine &TM = MF->getTarget();
const TargetLowering &TLI = *MF->getSubtarget().getTargetLowering();