Add minnum / maxnum codegen

llvm-svn: 220342
This commit is contained in:
Matt Arsenault 2014-10-21 23:01:01 +00:00
parent 74dd906076
commit 2257f6b589
26 changed files with 1065 additions and 6 deletions

View File

@ -485,7 +485,8 @@ namespace ISD {
FNEG, FABS, FSQRT, FSIN, FCOS, FPOWI, FPOW,
FLOG, FLOG2, FLOG10, FEXP, FEXP2,
FCEIL, FTRUNC, FRINT, FNEARBYINT, FROUND, FFLOOR,
FMINNUM, FMAXNUM,
/// FSINCOS - Compute both fsin and fcos as a single operation.
FSINCOS,

View File

@ -203,6 +203,16 @@ namespace RTLIB {
COPYSIGN_F80,
COPYSIGN_F128,
COPYSIGN_PPCF128,
FMIN_F32,
FMIN_F64,
FMIN_F80,
FMIN_F128,
FMIN_PPCF128,
FMAX_F32,
FMAX_F64,
FMAX_F80,
FMAX_F128,
FMAX_PPCF128,
// CONVERSION
FPEXT_F64_F128,

View File

@ -1067,7 +1067,10 @@ public:
case ISD::SADDO:
case ISD::UADDO:
case ISD::ADDC:
case ISD::ADDE: return true;
case ISD::ADDE:
case ISD::FMINNUM:
case ISD::FMAXNUM:
return true;
default: return false;
}
}

View File

@ -565,6 +565,8 @@ unsigned BasicTTI::getIntrinsicInstrCost(Intrinsic::ID IID, Type *RetTy,
case Intrinsic::log10: ISD = ISD::FLOG10; break;
case Intrinsic::log2: ISD = ISD::FLOG2; break;
case Intrinsic::fabs: ISD = ISD::FABS; break;
case Intrinsic::minnum: ISD = ISD::FMINNUM; break;
case Intrinsic::maxnum: ISD = ISD::FMAXNUM; break;
case Intrinsic::copysign: ISD = ISD::FCOPYSIGN; break;
case Intrinsic::floor: ISD = ISD::FFLOOR; break;
case Intrinsic::ceil: ISD = ISD::FCEIL; break;

View File

@ -290,6 +290,8 @@ namespace {
SDValue visitFCEIL(SDNode *N);
SDValue visitFTRUNC(SDNode *N);
SDValue visitFFLOOR(SDNode *N);
SDValue visitFMINNUM(SDNode *N);
SDValue visitFMAXNUM(SDNode *N);
SDValue visitBRCOND(SDNode *N);
SDValue visitBR_CC(SDNode *N);
SDValue visitLOAD(SDNode *N);
@ -1321,6 +1323,8 @@ SDValue DAGCombiner::visit(SDNode *N) {
case ISD::FNEG: return visitFNEG(N);
case ISD::FABS: return visitFABS(N);
case ISD::FFLOOR: return visitFFLOOR(N);
case ISD::FMINNUM: return visitFMINNUM(N);
case ISD::FMAXNUM: return visitFMAXNUM(N);
case ISD::FCEIL: return visitFCEIL(N);
case ISD::FTRUNC: return visitFTRUNC(N);
case ISD::BRCOND: return visitBRCOND(N);
@ -7493,6 +7497,48 @@ SDValue DAGCombiner::visitFNEG(SDNode *N) {
return SDValue();
}
SDValue DAGCombiner::visitFMINNUM(SDNode *N) {
SDValue N0 = N->getOperand(0);
SDValue N1 = N->getOperand(1);
const ConstantFPSDNode *N0CFP = dyn_cast<ConstantFPSDNode>(N0);
const ConstantFPSDNode *N1CFP = dyn_cast<ConstantFPSDNode>(N1);
if (N0CFP && N1CFP) {
const APFloat &C0 = N0CFP->getValueAPF();
const APFloat &C1 = N1CFP->getValueAPF();
return DAG.getConstantFP(minnum(C0, C1), N->getValueType(0));
}
if (N0CFP) {
EVT VT = N->getValueType(0);
// Canonicalize to constant on RHS.
return DAG.getNode(ISD::FMINNUM, SDLoc(N), VT, N1, N0);
}
return SDValue();
}
SDValue DAGCombiner::visitFMAXNUM(SDNode *N) {
SDValue N0 = N->getOperand(0);
SDValue N1 = N->getOperand(1);
const ConstantFPSDNode *N0CFP = dyn_cast<ConstantFPSDNode>(N0);
const ConstantFPSDNode *N1CFP = dyn_cast<ConstantFPSDNode>(N1);
if (N0CFP && N1CFP) {
const APFloat &C0 = N0CFP->getValueAPF();
const APFloat &C1 = N1CFP->getValueAPF();
return DAG.getConstantFP(maxnum(C0, C1), N->getValueType(0));
}
if (N0CFP) {
EVT VT = N->getValueType(0);
// Canonicalize to constant on RHS.
return DAG.getNode(ISD::FMAXNUM, SDLoc(N), VT, N1, N0);
}
return SDValue();
}
SDValue DAGCombiner::visitFABS(SDNode *N) {
SDValue N0 = N->getOperand(0);
EVT VT = N->getValueType(0);

View File

@ -3400,6 +3400,16 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node) {
Results.push_back(Tmp1);
break;
}
case ISD::FMINNUM:
Results.push_back(ExpandFPLibCall(Node, RTLIB::FMIN_F32, RTLIB::FMIN_F64,
RTLIB::FMIN_F80, RTLIB::FMIN_F128,
RTLIB::FMIN_PPCF128));
break;
case ISD::FMAXNUM:
Results.push_back(ExpandFPLibCall(Node, RTLIB::FMAX_F32, RTLIB::FMAX_F64,
RTLIB::FMAX_F80, RTLIB::FMAX_F128,
RTLIB::FMAX_PPCF128));
break;
case ISD::FSQRT:
Results.push_back(ExpandFPLibCall(Node, RTLIB::SQRT_F32, RTLIB::SQRT_F64,
RTLIB::SQRT_F80, RTLIB::SQRT_F128,

View File

@ -68,6 +68,8 @@ void DAGTypeLegalizer::SoftenFloatResult(SDNode *N, unsigned ResNo) {
case ISD::EXTRACT_VECTOR_ELT:
R = SoftenFloatRes_EXTRACT_VECTOR_ELT(N); break;
case ISD::FABS: R = SoftenFloatRes_FABS(N); break;
case ISD::FMINNUM: R = SoftenFloatRes_FMINNUM(N); break;
case ISD::FMAXNUM: R = SoftenFloatRes_FMAXNUM(N); break;
case ISD::FADD: R = SoftenFloatRes_FADD(N); break;
case ISD::FCEIL: R = SoftenFloatRes_FCEIL(N); break;
case ISD::FCOPYSIGN: R = SoftenFloatRes_FCOPYSIGN(N); break;
@ -153,6 +155,32 @@ SDValue DAGTypeLegalizer::SoftenFloatRes_FABS(SDNode *N) {
return DAG.getNode(ISD::AND, SDLoc(N), NVT, Op, Mask);
}
SDValue DAGTypeLegalizer::SoftenFloatRes_FMINNUM(SDNode *N) {
EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
SDValue Ops[2] = { GetSoftenedFloat(N->getOperand(0)),
GetSoftenedFloat(N->getOperand(1)) };
return TLI.makeLibCall(DAG, GetFPLibCall(N->getValueType(0),
RTLIB::FMIN_F32,
RTLIB::FMIN_F64,
RTLIB::FMIN_F80,
RTLIB::FMIN_F128,
RTLIB::FMIN_PPCF128),
NVT, Ops, 2, false, SDLoc(N)).first;
}
SDValue DAGTypeLegalizer::SoftenFloatRes_FMAXNUM(SDNode *N) {
EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
SDValue Ops[2] = { GetSoftenedFloat(N->getOperand(0)),
GetSoftenedFloat(N->getOperand(1)) };
return TLI.makeLibCall(DAG, GetFPLibCall(N->getValueType(0),
RTLIB::FMAX_F32,
RTLIB::FMAX_F64,
RTLIB::FMAX_F80,
RTLIB::FMAX_F128,
RTLIB::FMAX_PPCF128),
NVT, Ops, 2, false, SDLoc(N)).first;
}
SDValue DAGTypeLegalizer::SoftenFloatRes_FADD(SDNode *N) {
EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
SDValue Ops[2] = { GetSoftenedFloat(N->getOperand(0)),
@ -856,6 +884,8 @@ void DAGTypeLegalizer::ExpandFloatResult(SDNode *N, unsigned ResNo) {
case ISD::ConstantFP: ExpandFloatRes_ConstantFP(N, Lo, Hi); break;
case ISD::FABS: ExpandFloatRes_FABS(N, Lo, Hi); break;
case ISD::FMINNUM: ExpandFloatRes_FMINNUM(N, Lo, Hi); break;
case ISD::FMAXNUM: ExpandFloatRes_FMAXNUM(N, Lo, Hi); break;
case ISD::FADD: ExpandFloatRes_FADD(N, Lo, Hi); break;
case ISD::FCEIL: ExpandFloatRes_FCEIL(N, Lo, Hi); break;
case ISD::FCOPYSIGN: ExpandFloatRes_FCOPYSIGN(N, Lo, Hi); break;
@ -919,6 +949,26 @@ void DAGTypeLegalizer::ExpandFloatRes_FABS(SDNode *N, SDValue &Lo,
ISD::SETEQ);
}
void DAGTypeLegalizer::ExpandFloatRes_FMINNUM(SDNode *N, SDValue &Lo,
SDValue &Hi) {
SDValue Call = LibCallify(GetFPLibCall(N->getValueType(0),
RTLIB::FMIN_F32, RTLIB::FMIN_F64,
RTLIB::FMIN_F80, RTLIB::FMIN_F128,
RTLIB::FMIN_PPCF128),
N, false);
GetPairElements(Call, Lo, Hi);
}
void DAGTypeLegalizer::ExpandFloatRes_FMAXNUM(SDNode *N, SDValue &Lo,
SDValue &Hi) {
SDValue Call = LibCallify(GetFPLibCall(N->getValueType(0),
RTLIB::FMAX_F32, RTLIB::FMAX_F64,
RTLIB::FMAX_F80, RTLIB::FMAX_F128,
RTLIB::FMAX_PPCF128),
N, false);
GetPairElements(Call, Lo, Hi);
}
void DAGTypeLegalizer::ExpandFloatRes_FADD(SDNode *N, SDValue &Lo,
SDValue &Hi) {
SDValue Call = LibCallify(GetFPLibCall(N->getValueType(0),

View File

@ -387,6 +387,8 @@ private:
SDValue SoftenFloatRes_ConstantFP(ConstantFPSDNode *N);
SDValue SoftenFloatRes_EXTRACT_VECTOR_ELT(SDNode *N);
SDValue SoftenFloatRes_FABS(SDNode *N);
SDValue SoftenFloatRes_FMINNUM(SDNode *N);
SDValue SoftenFloatRes_FMAXNUM(SDNode *N);
SDValue SoftenFloatRes_FADD(SDNode *N);
SDValue SoftenFloatRes_FCEIL(SDNode *N);
SDValue SoftenFloatRes_FCOPYSIGN(SDNode *N);
@ -450,6 +452,8 @@ private:
void ExpandFloatResult(SDNode *N, unsigned ResNo);
void ExpandFloatRes_ConstantFP(SDNode *N, SDValue &Lo, SDValue &Hi);
void ExpandFloatRes_FABS (SDNode *N, SDValue &Lo, SDValue &Hi);
void ExpandFloatRes_FMINNUM (SDNode *N, SDValue &Lo, SDValue &Hi);
void ExpandFloatRes_FMAXNUM (SDNode *N, SDValue &Lo, SDValue &Hi);
void ExpandFloatRes_FADD (SDNode *N, SDValue &Lo, SDValue &Hi);
void ExpandFloatRes_FCEIL (SDNode *N, SDValue &Lo, SDValue &Hi);
void ExpandFloatRes_FCOPYSIGN (SDNode *N, SDValue &Lo, SDValue &Hi);

View File

@ -290,6 +290,8 @@ SDValue VectorLegalizer::LegalizeOp(SDValue Op) {
case ISD::FP_TO_UINT:
case ISD::FNEG:
case ISD::FABS:
case ISD::FMINNUM:
case ISD::FMAXNUM:
case ISD::FCOPYSIGN:
case ISD::FSQRT:
case ISD::FSIN:

View File

@ -106,6 +106,9 @@ void DAGTypeLegalizer::ScalarizeVectorResult(SDNode *N, unsigned ResNo) {
case ISD::FCOPYSIGN:
case ISD::FDIV:
case ISD::FMUL:
case ISD::FMINNUM:
case ISD::FMAXNUM:
case ISD::FPOW:
case ISD::FREM:
case ISD::FSUB:
@ -627,6 +630,8 @@ void DAGTypeLegalizer::SplitVectorResult(SDNode *N, unsigned ResNo) {
case ISD::FCOPYSIGN:
case ISD::FSUB:
case ISD::FMUL:
case ISD::FMINNUM:
case ISD::FMAXNUM:
case ISD::SDIV:
case ISD::UDIV:
case ISD::FDIV:
@ -1583,6 +1588,8 @@ void DAGTypeLegalizer::WidenVectorResult(SDNode *N, unsigned ResNo) {
case ISD::OR:
case ISD::SUB:
case ISD::XOR:
case ISD::FMINNUM:
case ISD::FMAXNUM:
Res = WidenVecRes_Binary(N);
break;

View File

@ -5087,6 +5087,18 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) {
getValue(I.getArgOperand(0))));
return nullptr;
}
case Intrinsic::minnum:
setValue(&I, DAG.getNode(ISD::FMINNUM, sdl,
getValue(I.getArgOperand(0)).getValueType(),
getValue(I.getArgOperand(0)),
getValue(I.getArgOperand(1))));
return nullptr;
case Intrinsic::maxnum:
setValue(&I, DAG.getNode(ISD::FMAXNUM, sdl,
getValue(I.getArgOperand(0)).getValueType(),
getValue(I.getArgOperand(0)),
getValue(I.getArgOperand(1))));
return nullptr;
case Intrinsic::copysign:
setValue(&I, DAG.getNode(ISD::FCOPYSIGN, sdl,
getValue(I.getArgOperand(0)).getValueType(),
@ -5887,6 +5899,26 @@ bool SelectionDAGBuilder::visitUnaryFloatCall(const CallInst &I,
return true;
}
/// visitBinaryFloatCall - If a call instruction is a unary floating-point
/// operation (as expected), translate it to an SDNode with the specified opcode
/// and return true.
bool SelectionDAGBuilder::visitBinaryFloatCall(const CallInst &I,
unsigned Opcode) {
// Sanity check that it really is a unary floating-point call.
if (I.getNumArgOperands() != 2 ||
!I.getArgOperand(0)->getType()->isFloatingPointTy() ||
I.getType() != I.getArgOperand(0)->getType() ||
I.getType() != I.getArgOperand(1)->getType() ||
!I.onlyReadsMemory())
return false;
SDValue Tmp0 = getValue(I.getArgOperand(0));
SDValue Tmp1 = getValue(I.getArgOperand(1));
EVT VT = Tmp0.getValueType();
setValue(&I, DAG.getNode(Opcode, getCurSDLoc(), VT, Tmp0, Tmp1));
return true;
}
void SelectionDAGBuilder::visitCall(const CallInst &I) {
// Handle inline assembly differently.
if (isa<InlineAsm>(I.getCalledValue())) {
@ -5943,6 +5975,18 @@ void SelectionDAGBuilder::visitCall(const CallInst &I) {
if (visitUnaryFloatCall(I, ISD::FABS))
return;
break;
case LibFunc::fmin:
case LibFunc::fminf:
case LibFunc::fminl:
if (visitBinaryFloatCall(I, ISD::FMINNUM))
return;
break;
case LibFunc::fmax:
case LibFunc::fmaxf:
case LibFunc::fmaxl:
if (visitBinaryFloatCall(I, ISD::FMAXNUM))
return;
break;
case LibFunc::sin:
case LibFunc::sinf:
case LibFunc::sinl:

View File

@ -768,6 +768,7 @@ private:
bool visitStrLenCall(const CallInst &I);
bool visitStrNLenCall(const CallInst &I);
bool visitUnaryFloatCall(const CallInst &I, unsigned Opcode);
bool visitBinaryFloatCall(const CallInst &I, unsigned Opcode);
void visitAtomicLoad(const LoadInst &I);
void visitAtomicStore(const StoreInst &I);

View File

@ -141,6 +141,8 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const {
// Unary operators
case ISD::FABS: return "fabs";
case ISD::FMINNUM: return "fminnum";
case ISD::FMAXNUM: return "fmaxnum";
case ISD::FNEG: return "fneg";
case ISD::FSQRT: return "fsqrt";
case ISD::FSIN: return "fsin";

View File

@ -206,6 +206,16 @@ static void InitLibcallNames(const char **Names, const Triple &TT) {
Names[RTLIB::FLOOR_F80] = "floorl";
Names[RTLIB::FLOOR_F128] = "floorl";
Names[RTLIB::FLOOR_PPCF128] = "floorl";
Names[RTLIB::FMIN_F32] = "fminf";
Names[RTLIB::FMIN_F64] = "fmin";
Names[RTLIB::FMIN_F80] = "fminl";
Names[RTLIB::FMIN_F128] = "fminl";
Names[RTLIB::FMIN_PPCF128] = "fminl";
Names[RTLIB::FMAX_F32] = "fmaxf";
Names[RTLIB::FMAX_F64] = "fmax";
Names[RTLIB::FMAX_F80] = "fmaxl";
Names[RTLIB::FMAX_F128] = "fmaxl";
Names[RTLIB::FMAX_PPCF128] = "fmaxl";
Names[RTLIB::ROUND_F32] = "roundf";
Names[RTLIB::ROUND_F64] = "round";
Names[RTLIB::ROUND_F80] = "roundl";
@ -757,6 +767,8 @@ void TargetLoweringBase::initActions() {
// These operations default to expand.
setOperationAction(ISD::FGETSIGN, (MVT::SimpleValueType)VT, Expand);
setOperationAction(ISD::CONCAT_VECTORS, (MVT::SimpleValueType)VT, Expand);
setOperationAction(ISD::FMINNUM, (MVT::SimpleValueType)VT, Expand);
setOperationAction(ISD::FMAXNUM, (MVT::SimpleValueType)VT, Expand);
// These library functions default to expand.
setOperationAction(ISD::FROUND, (MVT::SimpleValueType)VT, Expand);
@ -793,6 +805,8 @@ void TargetLoweringBase::initActions() {
setOperationAction(ISD::FEXP , MVT::f16, Expand);
setOperationAction(ISD::FEXP2, MVT::f16, Expand);
setOperationAction(ISD::FFLOOR, MVT::f16, Expand);
setOperationAction(ISD::FMINNUM, MVT::f16, Expand);
setOperationAction(ISD::FMAXNUM, MVT::f16, Expand);
setOperationAction(ISD::FNEARBYINT, MVT::f16, Expand);
setOperationAction(ISD::FCEIL, MVT::f16, Expand);
setOperationAction(ISD::FRINT, MVT::f16, Expand);
@ -804,6 +818,8 @@ void TargetLoweringBase::initActions() {
setOperationAction(ISD::FEXP , MVT::f32, Expand);
setOperationAction(ISD::FEXP2, MVT::f32, Expand);
setOperationAction(ISD::FFLOOR, MVT::f32, Expand);
setOperationAction(ISD::FMINNUM, MVT::f32, Expand);
setOperationAction(ISD::FMAXNUM, MVT::f32, Expand);
setOperationAction(ISD::FNEARBYINT, MVT::f32, Expand);
setOperationAction(ISD::FCEIL, MVT::f32, Expand);
setOperationAction(ISD::FRINT, MVT::f32, Expand);
@ -815,6 +831,8 @@ void TargetLoweringBase::initActions() {
setOperationAction(ISD::FEXP , MVT::f64, Expand);
setOperationAction(ISD::FEXP2, MVT::f64, Expand);
setOperationAction(ISD::FFLOOR, MVT::f64, Expand);
setOperationAction(ISD::FMINNUM, MVT::f64, Expand);
setOperationAction(ISD::FMAXNUM, MVT::f64, Expand);
setOperationAction(ISD::FNEARBYINT, MVT::f64, Expand);
setOperationAction(ISD::FCEIL, MVT::f64, Expand);
setOperationAction(ISD::FRINT, MVT::f64, Expand);
@ -826,6 +844,8 @@ void TargetLoweringBase::initActions() {
setOperationAction(ISD::FEXP , MVT::f128, Expand);
setOperationAction(ISD::FEXP2, MVT::f128, Expand);
setOperationAction(ISD::FFLOOR, MVT::f128, Expand);
setOperationAction(ISD::FMINNUM, MVT::f128, Expand);
setOperationAction(ISD::FMAXNUM, MVT::f128, Expand);
setOperationAction(ISD::FNEARBYINT, MVT::f128, Expand);
setOperationAction(ISD::FCEIL, MVT::f128, Expand);
setOperationAction(ISD::FRINT, MVT::f128, Expand);

View File

@ -347,6 +347,8 @@ AMDGPUTargetLowering::AMDGPUTargetLowering(TargetMachine &TM) :
for (MVT VT : FloatVectorTypes) {
setOperationAction(ISD::FABS, VT, Expand);
setOperationAction(ISD::FMINNUM, VT, Expand);
setOperationAction(ISD::FMAXNUM, VT, Expand);
setOperationAction(ISD::FADD, VT, Expand);
setOperationAction(ISD::FCEIL, VT, Expand);
setOperationAction(ISD::FCOS, VT, Expand);

View File

@ -90,6 +90,11 @@ SITargetLowering::SITargetLowering(TargetMachine &TM) :
setOperationAction(ISD::FSIN, MVT::f32, Custom);
setOperationAction(ISD::FCOS, MVT::f32, Custom);
setOperationAction(ISD::FMINNUM, MVT::f32, Legal);
setOperationAction(ISD::FMAXNUM, MVT::f32, Legal);
setOperationAction(ISD::FMINNUM, MVT::f64, Legal);
setOperationAction(ISD::FMAXNUM, MVT::f64, Legal);
// We need to custom lower vector stores from local memory
setOperationAction(ISD::LOAD, MVT::v4i32, Custom);
setOperationAction(ISD::LOAD, MVT::v8i32, Custom);

View File

@ -1407,8 +1407,8 @@ defm V_MAX_LEGACY_F32 : VOP2Inst <vop2<0xe>, "V_MAX_LEGACY_F32",
VOP_F32_F32_F32, AMDGPUfmax
>;
defm V_MIN_F32 : VOP2Inst <vop2<0xf>, "V_MIN_F32", VOP_F32_F32_F32>;
defm V_MAX_F32 : VOP2Inst <vop2<0x10>, "V_MAX_F32", VOP_F32_F32_F32>;
defm V_MIN_F32 : VOP2Inst <vop2<0xf>, "V_MIN_F32", VOP_F32_F32_F32, fminnum>;
defm V_MAX_F32 : VOP2Inst <vop2<0x10>, "V_MAX_F32", VOP_F32_F32_F32, fmaxnum>;
defm V_MIN_I32 : VOP2Inst <vop2<0x11>, "V_MIN_I32", VOP_I32_I32_I32, AMDGPUsmin>;
defm V_MAX_I32 : VOP2Inst <vop2<0x12>, "V_MAX_I32", VOP_I32_I32_I32, AMDGPUsmax>;
defm V_MIN_U32 : VOP2Inst <vop2<0x13>, "V_MIN_U32", VOP_I32_I32_I32, AMDGPUumin>;
@ -1593,11 +1593,12 @@ defm V_ADD_F64 : VOP3Inst <vop3<0x164>, "V_ADD_F64",
defm V_MUL_F64 : VOP3Inst <vop3<0x165>, "V_MUL_F64",
VOP_F64_F64_F64, fmul
>;
defm V_MIN_F64 : VOP3Inst <vop3<0x166>, "V_MIN_F64",
VOP_F64_F64_F64
VOP_F64_F64_F64, fminnum
>;
defm V_MAX_F64 : VOP3Inst <vop3<0x167>, "V_MAX_F64",
VOP_F64_F64_F64
VOP_F64_F64_F64, fmaxnum
>;
} // isCommutable = 1

View File

@ -811,6 +811,8 @@ void X86TargetLowering::resetOperationActions() {
setOperationAction(ISD::FLOG10, MVT::f80, Expand);
setOperationAction(ISD::FEXP, MVT::f80, Expand);
setOperationAction(ISD::FEXP2, MVT::f80, Expand);
setOperationAction(ISD::FMINNUM, MVT::f80, Expand);
setOperationAction(ISD::FMAXNUM, MVT::f80, Expand);
// First set operation action for all vector types to either promote
// (for widening) or expand (for scalarization). Then we will selectively

View File

@ -0,0 +1,86 @@
; RUN: llc -march=ppc32 -mtriple=powerpc-unknown-linux-gnu < %s | FileCheck %s
declare float @fmaxf(float, float)
declare double @fmax(double, double)
declare ppc_fp128 @fmaxl(ppc_fp128, ppc_fp128)
declare float @llvm.maxnum.f32(float, float)
declare double @llvm.maxnum.f64(double, double)
declare ppc_fp128 @llvm.maxnum.ppcf128(ppc_fp128, ppc_fp128)
declare <2 x float> @llvm.maxnum.v2f32(<2 x float>, <2 x float>)
declare <4 x float> @llvm.maxnum.v4f32(<4 x float>, <4 x float>)
declare <8 x float> @llvm.maxnum.v8f32(<8 x float>, <8 x float>)
; CHECK-LABEL: @test_fmaxf
; CHECK: bl fmaxf
define float @test_fmaxf(float %x, float %y) {
%z = call float @fmaxf(float %x, float %y) readnone
ret float %z
}
; CHECK-LABEL: @test_fmax
; CHECK: bl fmax
define double @test_fmax(double %x, double %y) {
%z = call double @fmax(double %x, double %y) readnone
ret double %z
}
; CHECK-LABEL: @test_fmaxl
; CHECK: bl fmaxl
define ppc_fp128 @test_fmaxl(ppc_fp128 %x, ppc_fp128 %y) {
%z = call ppc_fp128 @fmaxl(ppc_fp128 %x, ppc_fp128 %y) readnone
ret ppc_fp128 %z
}
; CHECK-LABEL: @test_intrinsic_fmaxf
; CHECK: bl fmaxf
define float @test_intrinsic_fmaxf(float %x, float %y) {
%z = call float @llvm.maxnum.f32(float %x, float %y) readnone
ret float %z
}
; CHECK-LABEL: @test_intrinsic_fmax
; CHECK: bl fmax
define double @test_intrinsic_fmax(double %x, double %y) {
%z = call double @llvm.maxnum.f64(double %x, double %y) readnone
ret double %z
}
; CHECK-LABEL: @test_intrinsic_fmaxl
; CHECK: bl fmaxl
define ppc_fp128 @test_intrinsic_fmaxl(ppc_fp128 %x, ppc_fp128 %y) {
%z = call ppc_fp128 @llvm.maxnum.ppcf128(ppc_fp128 %x, ppc_fp128 %y) readnone
ret ppc_fp128 %z
}
; CHECK-LABEL: @test_intrinsic_fmaxf_v2f32
; CHECK: bl fmaxf
; CHECK: bl fmaxf
define <2 x float> @test_intrinsic_fmaxf_v2f32(<2 x float> %x, <2 x float> %y) {
%z = call <2 x float> @llvm.maxnum.v2f32(<2 x float> %x, <2 x float> %y) readnone
ret <2 x float> %z
}
; CHECK-LABEL: @test_intrinsic_fmaxf_v4f32
; CHECK: bl fmaxf
; CHECK: bl fmaxf
; CHECK: bl fmaxf
; CHECK: bl fmaxf
define <4 x float> @test_intrinsic_fmaxf_v4f32(<4 x float> %x, <4 x float> %y) {
%z = call <4 x float> @llvm.maxnum.v4f32(<4 x float> %x, <4 x float> %y) readnone
ret <4 x float> %z
}
; CHECK-LABEL: @test_intrinsic_fmaxf_v8f32
; CHECK: bl fmaxf
; CHECK: bl fmaxf
; CHECK: bl fmaxf
; CHECK: bl fmaxf
; CHECK: bl fmaxf
; CHECK: bl fmaxf
; CHECK: bl fmaxf
; CHECK: bl fmaxf
define <8 x float> @test_intrinsic_fmaxf_v8f32(<8 x float> %x, <8 x float> %y) {
%z = call <8 x float> @llvm.maxnum.v8f32(<8 x float> %x, <8 x float> %y) readnone
ret <8 x float> %z
}

View File

@ -0,0 +1,86 @@
; RUN: llc -march=ppc32 -mtriple=powerpc-unknown-linux-gnu < %s | FileCheck %s
declare float @fminf(float, float)
declare double @fmin(double, double)
declare ppc_fp128 @fminl(ppc_fp128, ppc_fp128)
declare float @llvm.minnum.f32(float, float)
declare double @llvm.minnum.f64(double, double)
declare ppc_fp128 @llvm.minnum.ppcf128(ppc_fp128, ppc_fp128)
declare <2 x float> @llvm.minnum.v2f32(<2 x float>, <2 x float>)
declare <4 x float> @llvm.minnum.v4f32(<4 x float>, <4 x float>)
declare <8 x float> @llvm.minnum.v8f32(<8 x float>, <8 x float>)
; CHECK-LABEL: @test_fminf
; CHECK: bl fminf
define float @test_fminf(float %x, float %y) {
%z = call float @fminf(float %x, float %y) readnone
ret float %z
}
; CHECK-LABEL: @test_fmin
; CHECK: bl fmin
define double @test_fmin(double %x, double %y) {
%z = call double @fmin(double %x, double %y) readnone
ret double %z
}
; CHECK-LABEL: @test_fminl
; CHECK: bl fminl
define ppc_fp128 @test_fminl(ppc_fp128 %x, ppc_fp128 %y) {
%z = call ppc_fp128 @fminl(ppc_fp128 %x, ppc_fp128 %y) readnone
ret ppc_fp128 %z
}
; CHECK-LABEL: @test_intrinsic_fmin_f32
; CHECK: bl fminf
define float @test_intrinsic_fmin_f32(float %x, float %y) {
%z = call float @llvm.minnum.f32(float %x, float %y) readnone
ret float %z
}
; CHECK-LABEL: @test_intrinsic_fmin_f64
; CHECK: bl fmin
define double @test_intrinsic_fmin_f64(double %x, double %y) {
%z = call double @llvm.minnum.f64(double %x, double %y) readnone
ret double %z
}
; CHECK-LABEL: @test_intrinsic_fmin_f128
; CHECK: bl fminl
define ppc_fp128 @test_intrinsic_fmin_f128(ppc_fp128 %x, ppc_fp128 %y) {
%z = call ppc_fp128 @llvm.minnum.ppcf128(ppc_fp128 %x, ppc_fp128 %y) readnone
ret ppc_fp128 %z
}
; CHECK-LABEL: @test_intrinsic_fminf_v2f32
; CHECK: bl fminf
; CHECK: bl fminf
define <2 x float> @test_intrinsic_fminf_v2f32(<2 x float> %x, <2 x float> %y) {
%z = call <2 x float> @llvm.minnum.v2f32(<2 x float> %x, <2 x float> %y) readnone
ret <2 x float> %z
}
; CHECK-LABEL: @test_intrinsic_fmin_v4f32
; CHECK: bl fminf
; CHECK: bl fminf
; CHECK: bl fminf
; CHECK: bl fminf
define <4 x float> @test_intrinsic_fmin_v4f32(<4 x float> %x, <4 x float> %y) {
%z = call <4 x float> @llvm.minnum.v4f32(<4 x float> %x, <4 x float> %y) readnone
ret <4 x float> %z
}
; CHECK-LABEL: @test_intrinsic_fmin_v8f32
; CHECK: bl fminf
; CHECK: bl fminf
; CHECK: bl fminf
; CHECK: bl fminf
; CHECK: bl fminf
; CHECK: bl fminf
; CHECK: bl fminf
; CHECK: bl fminf
define <8 x float> @test_intrinsic_fmin_v8f32(<8 x float> %x, <8 x float> %y) {
%z = call <8 x float> @llvm.minnum.v8f32(<8 x float> %x, <8 x float> %y) readnone
ret <8 x float> %z
}

View File

@ -0,0 +1,75 @@
; RUN: llc -march=r600 -mcpu=SI < %s | FileCheck -check-prefix=SI -check-prefix=FUNC %s
declare double @llvm.maxnum.f64(double, double) #0
declare <2 x double> @llvm.maxnum.v2f64(<2 x double>, <2 x double>) #0
declare <4 x double> @llvm.maxnum.v4f64(<4 x double>, <4 x double>) #0
declare <8 x double> @llvm.maxnum.v8f64(<8 x double>, <8 x double>) #0
declare <16 x double> @llvm.maxnum.v16f64(<16 x double>, <16 x double>) #0
; FUNC-LABEL: @test_fmax_f64
; SI: V_MAX_F64
define void @test_fmax_f64(double addrspace(1)* %out, double %a, double %b) nounwind {
%val = call double @llvm.maxnum.f64(double %a, double %b) #0
store double %val, double addrspace(1)* %out, align 8
ret void
}
; FUNC-LABEL: @test_fmax_v2f64
; SI: V_MAX_F64
; SI: V_MAX_F64
define void @test_fmax_v2f64(<2 x double> addrspace(1)* %out, <2 x double> %a, <2 x double> %b) nounwind {
%val = call <2 x double> @llvm.maxnum.v2f64(<2 x double> %a, <2 x double> %b) #0
store <2 x double> %val, <2 x double> addrspace(1)* %out, align 16
ret void
}
; FUNC-LABEL: @test_fmax_v4f64
; SI: V_MAX_F64
; SI: V_MAX_F64
; SI: V_MAX_F64
; SI: V_MAX_F64
define void @test_fmax_v4f64(<4 x double> addrspace(1)* %out, <4 x double> %a, <4 x double> %b) nounwind {
%val = call <4 x double> @llvm.maxnum.v4f64(<4 x double> %a, <4 x double> %b) #0
store <4 x double> %val, <4 x double> addrspace(1)* %out, align 32
ret void
}
; FUNC-LABEL: @test_fmax_v8f64
; SI: V_MAX_F64
; SI: V_MAX_F64
; SI: V_MAX_F64
; SI: V_MAX_F64
; SI: V_MAX_F64
; SI: V_MAX_F64
; SI: V_MAX_F64
; SI: V_MAX_F64
define void @test_fmax_v8f64(<8 x double> addrspace(1)* %out, <8 x double> %a, <8 x double> %b) nounwind {
%val = call <8 x double> @llvm.maxnum.v8f64(<8 x double> %a, <8 x double> %b) #0
store <8 x double> %val, <8 x double> addrspace(1)* %out, align 64
ret void
}
; FUNC-LABEL: @test_fmax_v16f64
; SI: V_MAX_F64
; SI: V_MAX_F64
; SI: V_MAX_F64
; SI: V_MAX_F64
; SI: V_MAX_F64
; SI: V_MAX_F64
; SI: V_MAX_F64
; SI: V_MAX_F64
; SI: V_MAX_F64
; SI: V_MAX_F64
; SI: V_MAX_F64
; SI: V_MAX_F64
; SI: V_MAX_F64
; SI: V_MAX_F64
; SI: V_MAX_F64
; SI: V_MAX_F64
define void @test_fmax_v16f64(<16 x double> addrspace(1)* %out, <16 x double> %a, <16 x double> %b) nounwind {
%val = call <16 x double> @llvm.maxnum.v16f64(<16 x double> %a, <16 x double> %b) #0
store <16 x double> %val, <16 x double> addrspace(1)* %out, align 128
ret void
}
attributes #0 = { nounwind readnone }

View File

@ -0,0 +1,191 @@
; RUN: llc -march=r600 -mcpu=SI < %s | FileCheck -check-prefix=SI -check-prefix=FUNC %s
declare float @llvm.maxnum.f32(float, float) #0
declare <2 x float> @llvm.maxnum.v2f32(<2 x float>, <2 x float>) #0
declare <4 x float> @llvm.maxnum.v4f32(<4 x float>, <4 x float>) #0
declare <8 x float> @llvm.maxnum.v8f32(<8 x float>, <8 x float>) #0
declare <16 x float> @llvm.maxnum.v16f32(<16 x float>, <16 x float>) #0
declare double @llvm.maxnum.f64(double, double)
; FUNC-LABEL: @test_fmax_f32
; SI: V_MAX_F32_e32
define void @test_fmax_f32(float addrspace(1)* %out, float %a, float %b) nounwind {
%val = call float @llvm.maxnum.f32(float %a, float %b) #0
store float %val, float addrspace(1)* %out, align 4
ret void
}
; FUNC-LABEL: @test_fmax_v2f32
; SI: V_MAX_F32_e32
; SI: V_MAX_F32_e32
define void @test_fmax_v2f32(<2 x float> addrspace(1)* %out, <2 x float> %a, <2 x float> %b) nounwind {
%val = call <2 x float> @llvm.maxnum.v2f32(<2 x float> %a, <2 x float> %b) #0
store <2 x float> %val, <2 x float> addrspace(1)* %out, align 8
ret void
}
; FUNC-LABEL: @test_fmax_v4f32
; SI: V_MAX_F32_e32
; SI: V_MAX_F32_e32
; SI: V_MAX_F32_e32
; SI: V_MAX_F32_e32
define void @test_fmax_v4f32(<4 x float> addrspace(1)* %out, <4 x float> %a, <4 x float> %b) nounwind {
%val = call <4 x float> @llvm.maxnum.v4f32(<4 x float> %a, <4 x float> %b) #0
store <4 x float> %val, <4 x float> addrspace(1)* %out, align 16
ret void
}
; FUNC-LABEL: @test_fmax_v8f32
; SI: V_MAX_F32_e32
; SI: V_MAX_F32_e32
; SI: V_MAX_F32_e32
; SI: V_MAX_F32_e32
; SI: V_MAX_F32_e32
; SI: V_MAX_F32_e32
; SI: V_MAX_F32_e32
; SI: V_MAX_F32_e32
define void @test_fmax_v8f32(<8 x float> addrspace(1)* %out, <8 x float> %a, <8 x float> %b) nounwind {
%val = call <8 x float> @llvm.maxnum.v8f32(<8 x float> %a, <8 x float> %b) #0
store <8 x float> %val, <8 x float> addrspace(1)* %out, align 32
ret void
}
; FUNC-LABEL: @test_fmax_v16f32
; SI: V_MAX_F32_e32
; SI: V_MAX_F32_e32
; SI: V_MAX_F32_e32
; SI: V_MAX_F32_e32
; SI: V_MAX_F32_e32
; SI: V_MAX_F32_e32
; SI: V_MAX_F32_e32
; SI: V_MAX_F32_e32
; SI: V_MAX_F32_e32
; SI: V_MAX_F32_e32
; SI: V_MAX_F32_e32
; SI: V_MAX_F32_e32
; SI: V_MAX_F32_e32
; SI: V_MAX_F32_e32
; SI: V_MAX_F32_e32
; SI: V_MAX_F32_e32
define void @test_fmax_v16f32(<16 x float> addrspace(1)* %out, <16 x float> %a, <16 x float> %b) nounwind {
%val = call <16 x float> @llvm.maxnum.v16f32(<16 x float> %a, <16 x float> %b) #0
store <16 x float> %val, <16 x float> addrspace(1)* %out, align 64
ret void
}
; FUNC-LABEL: @constant_fold_fmax_f32
; SI-NOT: V_MAX_F32_e32
; SI: V_MOV_B32_e32 [[REG:v[0-9]+]], 2.0
; SI: BUFFER_STORE_DWORD [[REG]]
define void @constant_fold_fmax_f32(float addrspace(1)* %out) nounwind {
%val = call float @llvm.maxnum.f32(float 1.0, float 2.0) #0
store float %val, float addrspace(1)* %out, align 4
ret void
}
; FUNC-LABEL: @constant_fold_fmax_f32_nan_nan
; SI-NOT: V_MAX_F32_e32
; SI: V_MOV_B32_e32 [[REG:v[0-9]+]], 0x7fc00000
; SI: BUFFER_STORE_DWORD [[REG]]
define void @constant_fold_fmax_f32_nan_nan(float addrspace(1)* %out) nounwind {
%val = call float @llvm.maxnum.f32(float 0x7FF8000000000000, float 0x7FF8000000000000) #0
store float %val, float addrspace(1)* %out, align 4
ret void
}
; FUNC-LABEL: @constant_fold_fmax_f32_val_nan
; SI-NOT: V_MAX_F32_e32
; SI: V_MOV_B32_e32 [[REG:v[0-9]+]], 1.0
; SI: BUFFER_STORE_DWORD [[REG]]
define void @constant_fold_fmax_f32_val_nan(float addrspace(1)* %out) nounwind {
%val = call float @llvm.maxnum.f32(float 1.0, float 0x7FF8000000000000) #0
store float %val, float addrspace(1)* %out, align 4
ret void
}
; FUNC-LABEL: @constant_fold_fmax_f32_nan_val
; SI-NOT: V_MAX_F32_e32
; SI: V_MOV_B32_e32 [[REG:v[0-9]+]], 1.0
; SI: BUFFER_STORE_DWORD [[REG]]
define void @constant_fold_fmax_f32_nan_val(float addrspace(1)* %out) nounwind {
%val = call float @llvm.maxnum.f32(float 0x7FF8000000000000, float 1.0) #0
store float %val, float addrspace(1)* %out, align 4
ret void
}
; FUNC-LABEL: @constant_fold_fmax_f32_p0_p0
; SI-NOT: V_MAX_F32_e32
; SI: V_MOV_B32_e32 [[REG:v[0-9]+]], 0
; SI: BUFFER_STORE_DWORD [[REG]]
define void @constant_fold_fmax_f32_p0_p0(float addrspace(1)* %out) nounwind {
%val = call float @llvm.maxnum.f32(float 0.0, float 0.0) #0
store float %val, float addrspace(1)* %out, align 4
ret void
}
; FUNC-LABEL: @constant_fold_fmax_f32_p0_n0
; SI-NOT: V_MAX_F32_e32
; SI: V_MOV_B32_e32 [[REG:v[0-9]+]], 0
; SI: BUFFER_STORE_DWORD [[REG]]
define void @constant_fold_fmax_f32_p0_n0(float addrspace(1)* %out) nounwind {
%val = call float @llvm.maxnum.f32(float 0.0, float -0.0) #0
store float %val, float addrspace(1)* %out, align 4
ret void
}
; FUNC-LABEL: @constant_fold_fmax_f32_n0_p0
; SI-NOT: V_MAX_F32_e32
; SI: V_MOV_B32_e32 [[REG:v[0-9]+]], 0x80000000
; SI: BUFFER_STORE_DWORD [[REG]]
define void @constant_fold_fmax_f32_n0_p0(float addrspace(1)* %out) nounwind {
%val = call float @llvm.maxnum.f32(float -0.0, float 0.0) #0
store float %val, float addrspace(1)* %out, align 4
ret void
}
; FUNC-LABEL: @constant_fold_fmax_f32_n0_n0
; SI-NOT: V_MAX_F32_e32
; SI: V_MOV_B32_e32 [[REG:v[0-9]+]], 0x80000000
; SI: BUFFER_STORE_DWORD [[REG]]
define void @constant_fold_fmax_f32_n0_n0(float addrspace(1)* %out) nounwind {
%val = call float @llvm.maxnum.f32(float -0.0, float -0.0) #0
store float %val, float addrspace(1)* %out, align 4
ret void
}
; FUNC-LABEL: @fmax_var_immediate_f32
; SI: V_MAX_F32_e64 {{v[0-9]+}}, 2.0, {{s[0-9]+}}
define void @fmax_var_immediate_f32(float addrspace(1)* %out, float %a) nounwind {
%val = call float @llvm.maxnum.f32(float %a, float 2.0) #0
store float %val, float addrspace(1)* %out, align 4
ret void
}
; FUNC-LABEL: @fmax_immediate_var_f32
; SI: V_MAX_F32_e64 {{v[0-9]+}}, 2.0, {{s[0-9]+}}
define void @fmax_immediate_var_f32(float addrspace(1)* %out, float %a) nounwind {
%val = call float @llvm.maxnum.f32(float 2.0, float %a) #0
store float %val, float addrspace(1)* %out, align 4
ret void
}
; FUNC-LABEL: @fmax_var_literal_f32
; SI: V_MOV_B32_e32 [[REG:v[0-9]+]], 0x42c60000
; SI: V_MAX_F32_e32 {{v[0-9]+}}, {{s[0-9]+}}, [[REG]]
define void @fmax_var_literal_f32(float addrspace(1)* %out, float %a) nounwind {
%val = call float @llvm.maxnum.f32(float %a, float 99.0) #0
store float %val, float addrspace(1)* %out, align 4
ret void
}
; FUNC-LABEL: @fmax_literal_var_f32
; SI: V_MOV_B32_e32 [[REG:v[0-9]+]], 0x42c60000
; SI: V_MAX_F32_e32 {{v[0-9]+}}, {{s[0-9]+}}, [[REG]]
define void @fmax_literal_var_f32(float addrspace(1)* %out, float %a) nounwind {
%val = call float @llvm.maxnum.f32(float 99.0, float %a) #0
store float %val, float addrspace(1)* %out, align 4
ret void
}
attributes #0 = { nounwind readnone }

View File

@ -0,0 +1,75 @@
; RUN: llc -march=r600 -mcpu=SI < %s | FileCheck -check-prefix=SI -check-prefix=FUNC %s
declare double @llvm.minnum.f64(double, double) #0
declare <2 x double> @llvm.minnum.v2f64(<2 x double>, <2 x double>) #0
declare <4 x double> @llvm.minnum.v4f64(<4 x double>, <4 x double>) #0
declare <8 x double> @llvm.minnum.v8f64(<8 x double>, <8 x double>) #0
declare <16 x double> @llvm.minnum.v16f64(<16 x double>, <16 x double>) #0
; FUNC-LABEL: @test_fmin_f64
; SI: V_MIN_F64
define void @test_fmin_f64(double addrspace(1)* %out, double %a, double %b) nounwind {
%val = call double @llvm.minnum.f64(double %a, double %b) #0
store double %val, double addrspace(1)* %out, align 8
ret void
}
; FUNC-LABEL: @test_fmin_v2f64
; SI: V_MIN_F64
; SI: V_MIN_F64
define void @test_fmin_v2f64(<2 x double> addrspace(1)* %out, <2 x double> %a, <2 x double> %b) nounwind {
%val = call <2 x double> @llvm.minnum.v2f64(<2 x double> %a, <2 x double> %b) #0
store <2 x double> %val, <2 x double> addrspace(1)* %out, align 16
ret void
}
; FUNC-LABEL: @test_fmin_v4f64
; SI: V_MIN_F64
; SI: V_MIN_F64
; SI: V_MIN_F64
; SI: V_MIN_F64
define void @test_fmin_v4f64(<4 x double> addrspace(1)* %out, <4 x double> %a, <4 x double> %b) nounwind {
%val = call <4 x double> @llvm.minnum.v4f64(<4 x double> %a, <4 x double> %b) #0
store <4 x double> %val, <4 x double> addrspace(1)* %out, align 32
ret void
}
; FUNC-LABEL: @test_fmin_v8f64
; SI: V_MIN_F64
; SI: V_MIN_F64
; SI: V_MIN_F64
; SI: V_MIN_F64
; SI: V_MIN_F64
; SI: V_MIN_F64
; SI: V_MIN_F64
; SI: V_MIN_F64
define void @test_fmin_v8f64(<8 x double> addrspace(1)* %out, <8 x double> %a, <8 x double> %b) nounwind {
%val = call <8 x double> @llvm.minnum.v8f64(<8 x double> %a, <8 x double> %b) #0
store <8 x double> %val, <8 x double> addrspace(1)* %out, align 64
ret void
}
; FUNC-LABEL: @test_fmin_v16f64
; SI: V_MIN_F64
; SI: V_MIN_F64
; SI: V_MIN_F64
; SI: V_MIN_F64
; SI: V_MIN_F64
; SI: V_MIN_F64
; SI: V_MIN_F64
; SI: V_MIN_F64
; SI: V_MIN_F64
; SI: V_MIN_F64
; SI: V_MIN_F64
; SI: V_MIN_F64
; SI: V_MIN_F64
; SI: V_MIN_F64
; SI: V_MIN_F64
; SI: V_MIN_F64
define void @test_fmin_v16f64(<16 x double> addrspace(1)* %out, <16 x double> %a, <16 x double> %b) nounwind {
%val = call <16 x double> @llvm.minnum.v16f64(<16 x double> %a, <16 x double> %b) #0
store <16 x double> %val, <16 x double> addrspace(1)* %out, align 128
ret void
}
attributes #0 = { nounwind readnone }

View File

@ -0,0 +1,189 @@
; RUN: llc -march=r600 -mcpu=SI < %s | FileCheck -check-prefix=SI -check-prefix=FUNC %s
declare float @llvm.minnum.f32(float, float) #0
declare <2 x float> @llvm.minnum.v2f32(<2 x float>, <2 x float>) #0
declare <4 x float> @llvm.minnum.v4f32(<4 x float>, <4 x float>) #0
declare <8 x float> @llvm.minnum.v8f32(<8 x float>, <8 x float>) #0
declare <16 x float> @llvm.minnum.v16f32(<16 x float>, <16 x float>) #0
; FUNC-LABEL: @test_fmin_f32
; SI: V_MIN_F32_e32
define void @test_fmin_f32(float addrspace(1)* %out, float %a, float %b) nounwind {
%val = call float @llvm.minnum.f32(float %a, float %b) #0
store float %val, float addrspace(1)* %out, align 4
ret void
}
; FUNC-LABEL: @test_fmin_v2f32
; SI: V_MIN_F32_e32
; SI: V_MIN_F32_e32
define void @test_fmin_v2f32(<2 x float> addrspace(1)* %out, <2 x float> %a, <2 x float> %b) nounwind {
%val = call <2 x float> @llvm.minnum.v2f32(<2 x float> %a, <2 x float> %b) #0
store <2 x float> %val, <2 x float> addrspace(1)* %out, align 8
ret void
}
; FUNC-LABEL: @test_fmin_v4f32
; SI: V_MIN_F32_e32
; SI: V_MIN_F32_e32
; SI: V_MIN_F32_e32
; SI: V_MIN_F32_e32
define void @test_fmin_v4f32(<4 x float> addrspace(1)* %out, <4 x float> %a, <4 x float> %b) nounwind {
%val = call <4 x float> @llvm.minnum.v4f32(<4 x float> %a, <4 x float> %b) #0
store <4 x float> %val, <4 x float> addrspace(1)* %out, align 16
ret void
}
; FUNC-LABEL: @test_fmin_v8f32
; SI: V_MIN_F32_e32
; SI: V_MIN_F32_e32
; SI: V_MIN_F32_e32
; SI: V_MIN_F32_e32
; SI: V_MIN_F32_e32
; SI: V_MIN_F32_e32
; SI: V_MIN_F32_e32
; SI: V_MIN_F32_e32
define void @test_fmin_v8f32(<8 x float> addrspace(1)* %out, <8 x float> %a, <8 x float> %b) nounwind {
%val = call <8 x float> @llvm.minnum.v8f32(<8 x float> %a, <8 x float> %b) #0
store <8 x float> %val, <8 x float> addrspace(1)* %out, align 32
ret void
}
; FUNC-LABEL: @test_fmin_v16f32
; SI: V_MIN_F32_e32
; SI: V_MIN_F32_e32
; SI: V_MIN_F32_e32
; SI: V_MIN_F32_e32
; SI: V_MIN_F32_e32
; SI: V_MIN_F32_e32
; SI: V_MIN_F32_e32
; SI: V_MIN_F32_e32
; SI: V_MIN_F32_e32
; SI: V_MIN_F32_e32
; SI: V_MIN_F32_e32
; SI: V_MIN_F32_e32
; SI: V_MIN_F32_e32
; SI: V_MIN_F32_e32
; SI: V_MIN_F32_e32
; SI: V_MIN_F32_e32
define void @test_fmin_v16f32(<16 x float> addrspace(1)* %out, <16 x float> %a, <16 x float> %b) nounwind {
%val = call <16 x float> @llvm.minnum.v16f32(<16 x float> %a, <16 x float> %b) #0
store <16 x float> %val, <16 x float> addrspace(1)* %out, align 64
ret void
}
; FUNC-LABEL: @constant_fold_fmin_f32
; SI-NOT: V_MIN_F32_e32
; SI: V_MOV_B32_e32 [[REG:v[0-9]+]], 1.0
; SI: BUFFER_STORE_DWORD [[REG]]
define void @constant_fold_fmin_f32(float addrspace(1)* %out) nounwind {
%val = call float @llvm.minnum.f32(float 1.0, float 2.0) #0
store float %val, float addrspace(1)* %out, align 4
ret void
}
; FUNC-LABEL: @constant_fold_fmin_f32_nan_nan
; SI-NOT: V_MIN_F32_e32
; SI: V_MOV_B32_e32 [[REG:v[0-9]+]], 0x7fc00000
; SI: BUFFER_STORE_DWORD [[REG]]
define void @constant_fold_fmin_f32_nan_nan(float addrspace(1)* %out) nounwind {
%val = call float @llvm.minnum.f32(float 0x7FF8000000000000, float 0x7FF8000000000000) #0
store float %val, float addrspace(1)* %out, align 4
ret void
}
; FUNC-LABEL: @constant_fold_fmin_f32_val_nan
; SI-NOT: V_MIN_F32_e32
; SI: V_MOV_B32_e32 [[REG:v[0-9]+]], 1.0
; SI: BUFFER_STORE_DWORD [[REG]]
define void @constant_fold_fmin_f32_val_nan(float addrspace(1)* %out) nounwind {
%val = call float @llvm.minnum.f32(float 1.0, float 0x7FF8000000000000) #0
store float %val, float addrspace(1)* %out, align 4
ret void
}
; FUNC-LABEL: @constant_fold_fmin_f32_nan_val
; SI-NOT: V_MIN_F32_e32
; SI: V_MOV_B32_e32 [[REG:v[0-9]+]], 1.0
; SI: BUFFER_STORE_DWORD [[REG]]
define void @constant_fold_fmin_f32_nan_val(float addrspace(1)* %out) nounwind {
%val = call float @llvm.minnum.f32(float 0x7FF8000000000000, float 1.0) #0
store float %val, float addrspace(1)* %out, align 4
ret void
}
; FUNC-LABEL: @constant_fold_fmin_f32_p0_p0
; SI-NOT: V_MIN_F32_e32
; SI: V_MOV_B32_e32 [[REG:v[0-9]+]], 0
; SI: BUFFER_STORE_DWORD [[REG]]
define void @constant_fold_fmin_f32_p0_p0(float addrspace(1)* %out) nounwind {
%val = call float @llvm.minnum.f32(float 0.0, float 0.0) #0
store float %val, float addrspace(1)* %out, align 4
ret void
}
; FUNC-LABEL: @constant_fold_fmin_f32_p0_n0
; SI-NOT: V_MIN_F32_e32
; SI: V_MOV_B32_e32 [[REG:v[0-9]+]], 0
; SI: BUFFER_STORE_DWORD [[REG]]
define void @constant_fold_fmin_f32_p0_n0(float addrspace(1)* %out) nounwind {
%val = call float @llvm.minnum.f32(float 0.0, float -0.0) #0
store float %val, float addrspace(1)* %out, align 4
ret void
}
; FUNC-LABEL: @constant_fold_fmin_f32_n0_p0
; SI-NOT: V_MIN_F32_e32
; SI: V_MOV_B32_e32 [[REG:v[0-9]+]], 0x80000000
; SI: BUFFER_STORE_DWORD [[REG]]
define void @constant_fold_fmin_f32_n0_p0(float addrspace(1)* %out) nounwind {
%val = call float @llvm.minnum.f32(float -0.0, float 0.0) #0
store float %val, float addrspace(1)* %out, align 4
ret void
}
; FUNC-LABEL: @constant_fold_fmin_f32_n0_n0
; SI-NOT: V_MIN_F32_e32
; SI: V_MOV_B32_e32 [[REG:v[0-9]+]], 0x80000000
; SI: BUFFER_STORE_DWORD [[REG]]
define void @constant_fold_fmin_f32_n0_n0(float addrspace(1)* %out) nounwind {
%val = call float @llvm.minnum.f32(float -0.0, float -0.0) #0
store float %val, float addrspace(1)* %out, align 4
ret void
}
; FUNC-LABEL: @fmin_var_immediate_f32
; SI: V_MIN_F32_e64 {{v[0-9]+}}, 2.0, {{s[0-9]+}}
define void @fmin_var_immediate_f32(float addrspace(1)* %out, float %a) nounwind {
%val = call float @llvm.minnum.f32(float %a, float 2.0) #0
store float %val, float addrspace(1)* %out, align 4
ret void
}
; FUNC-LABEL: @fmin_immediate_var_f32
; SI: V_MIN_F32_e64 {{v[0-9]+}}, 2.0, {{s[0-9]+}}
define void @fmin_immediate_var_f32(float addrspace(1)* %out, float %a) nounwind {
%val = call float @llvm.minnum.f32(float 2.0, float %a) #0
store float %val, float addrspace(1)* %out, align 4
ret void
}
; FUNC-LABEL: @fmin_var_literal_f32
; SI: V_MOV_B32_e32 [[REG:v[0-9]+]], 0x42c60000
; SI: V_MIN_F32_e32 {{v[0-9]+}}, {{s[0-9]+}}, [[REG]]
define void @fmin_var_literal_f32(float addrspace(1)* %out, float %a) nounwind {
%val = call float @llvm.minnum.f32(float %a, float 99.0) #0
store float %val, float addrspace(1)* %out, align 4
ret void
}
; FUNC-LABEL: @fmin_literal_var_f32
; SI: V_MOV_B32_e32 [[REG:v[0-9]+]], 0x42c60000
; SI: V_MIN_F32_e32 {{v[0-9]+}}, {{s[0-9]+}}, [[REG]]
define void @fmin_literal_var_f32(float addrspace(1)* %out, float %a) nounwind {
%val = call float @llvm.minnum.f32(float 99.0, float %a) #0
store float %val, float addrspace(1)* %out, align 4
ret void
}
attributes #0 = { nounwind readnone }

View File

@ -0,0 +1,50 @@
; RUN: llc -march=x86 -mtriple=i386-linux-gnu < %s | FileCheck %s
declare float @fmaxf(float, float)
declare double @fmax(double, double)
declare x86_fp80 @fmaxl(x86_fp80, x86_fp80)
declare float @llvm.maxnum.f32(float, float)
declare double @llvm.maxnum.f64(double, double)
declare x86_fp80 @llvm.maxnum.f80(x86_fp80, x86_fp80)
; CHECK-LABEL: @test_fmaxf
; CHECK: calll fmaxf
define float @test_fmaxf(float %x, float %y) {
%z = call float @fmaxf(float %x, float %y) readnone
ret float %z
}
; CHECK-LABEL: @test_fmax
; CHECK: calll fmax
define double @test_fmax(double %x, double %y) {
%z = call double @fmax(double %x, double %y) readnone
ret double %z
}
; CHECK-LABEL: @test_fmaxl
; CHECK: calll fmaxl
define x86_fp80 @test_fmaxl(x86_fp80 %x, x86_fp80 %y) {
%z = call x86_fp80 @fmaxl(x86_fp80 %x, x86_fp80 %y) readnone
ret x86_fp80 %z
}
; CHECK-LABEL: @test_intrinsic_fmaxf
; CHECK: calll fmaxf
define float @test_intrinsic_fmaxf(float %x, float %y) {
%z = call float @llvm.maxnum.f32(float %x, float %y) readnone
ret float %z
}
; CHECK-LABEL: @test_intrinsic_fmax
; CHECK: calll fmax
define double @test_intrinsic_fmax(double %x, double %y) {
%z = call double @llvm.maxnum.f64(double %x, double %y) readnone
ret double %z
}
; CHECK-LABEL: @test_intrinsic_fmaxl
; CHECK: calll fmaxl
define x86_fp80 @test_intrinsic_fmaxl(x86_fp80 %x, x86_fp80 %y) {
%z = call x86_fp80 @llvm.maxnum.f80(x86_fp80 %x, x86_fp80 %y) readnone
ret x86_fp80 %z
}

View File

@ -0,0 +1,95 @@
; RUN: llc -march=x86 -mtriple=i386-linux-gnu -mattr=+sse,+sse2 < %s | FileCheck %s
declare float @fminf(float, float)
declare double @fmin(double, double)
declare x86_fp80 @fminl(x86_fp80, x86_fp80)
declare float @llvm.minnum.f32(float, float)
declare double @llvm.minnum.f64(double, double)
declare x86_fp80 @llvm.minnum.f80(x86_fp80, x86_fp80)
declare <2 x float> @llvm.minnum.v2f32(<2 x float>, <2 x float>)
declare <4 x float> @llvm.minnum.v4f32(<4 x float>, <4 x float>)
declare <2 x double> @llvm.minnum.v2f64(<2 x double>, <2 x double>)
declare <8 x double> @llvm.minnum.v8f64(<8 x double>, <8 x double>)
; CHECK-LABEL: @test_fminf
; CHECK: jmp fminf
define float @test_fminf(float %x, float %y) {
%z = call float @fminf(float %x, float %y) readnone
ret float %z
}
; CHECK-LABEL: @test_fmin
; CHECK: jmp fmin
define double @test_fmin(double %x, double %y) {
%z = call double @fmin(double %x, double %y) readnone
ret double %z
}
; CHECK-LABEL: @test_fminl
; CHECK: calll fminl
define x86_fp80 @test_fminl(x86_fp80 %x, x86_fp80 %y) {
%z = call x86_fp80 @fminl(x86_fp80 %x, x86_fp80 %y) readnone
ret x86_fp80 %z
}
; CHECK-LABEL: @test_intrinsic_fminf
; CHECK: jmp fminf
define float @test_intrinsic_fminf(float %x, float %y) {
%z = call float @llvm.minnum.f32(float %x, float %y) readnone
ret float %z
}
; CHECK-LABEL: @test_intrinsic_fmin
; CHECK: jmp fmin
define double @test_intrinsic_fmin(double %x, double %y) {
%z = call double @llvm.minnum.f64(double %x, double %y) readnone
ret double %z
}
; CHECK-LABEL: @test_intrinsic_fminl
; CHECK: calll fminl
define x86_fp80 @test_intrinsic_fminl(x86_fp80 %x, x86_fp80 %y) {
%z = call x86_fp80 @llvm.minnum.f80(x86_fp80 %x, x86_fp80 %y) readnone
ret x86_fp80 %z
}
; CHECK-LABEL: @test_intrinsic_fmin_v2f32
; CHECK: calll fminf
; CHECK: calll fminf
define <2 x float> @test_intrinsic_fmin_v2f32(<2 x float> %x, <2 x float> %y) {
%z = call <2 x float> @llvm.minnum.v2f32(<2 x float> %x, <2 x float> %y) readnone
ret <2 x float> %z
}
; CHECK-LABEL: @test_intrinsic_fmin_v4f32
; CHECK: calll fminf
; CHECK: calll fminf
; CHECK: calll fminf
; CHECK: calll fminf
define <4 x float> @test_intrinsic_fmin_v4f32(<4 x float> %x, <4 x float> %y) {
%z = call <4 x float> @llvm.minnum.v4f32(<4 x float> %x, <4 x float> %y) readnone
ret <4 x float> %z
}
; CHECK-LABEL: @test_intrinsic_fmin_v2f64
; CHECK: calll fmin
; CHECK: calll fmin
define <2 x double> @test_intrinsic_fmin_v2f64(<2 x double> %x, <2 x double> %y) {
%z = call <2 x double> @llvm.minnum.v2f64(<2 x double> %x, <2 x double> %y) readnone
ret <2 x double> %z
}
; CHECK-LABEL: @test_intrinsic_fmin_v8f64
; CHECK: calll fmin
; CHECK: calll fmin
; CHECK: calll fmin
; CHECK: calll fmin
; CHECK: calll fmin
; CHECK: calll fmin
; CHECK: calll fmin
; CHECK: calll fmin
define <8 x double> @test_intrinsic_fmin_v8f64(<8 x double> %x, <8 x double> %y) {
%z = call <8 x double> @llvm.minnum.v8f64(<8 x double> %x, <8 x double> %y) readnone
ret <8 x double> %z
}