mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-12-16 16:16:45 +00:00
Add minnum / maxnum codegen
llvm-svn: 220342
This commit is contained in:
parent
74dd906076
commit
2257f6b589
@ -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,
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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),
|
||||
|
@ -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);
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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";
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
86
test/CodeGen/PowerPC/fmaxnum.ll
Normal file
86
test/CodeGen/PowerPC/fmaxnum.ll
Normal 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
|
||||
}
|
86
test/CodeGen/PowerPC/fminnum.ll
Normal file
86
test/CodeGen/PowerPC/fminnum.ll
Normal 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
|
||||
}
|
75
test/CodeGen/R600/fmaxnum.f64.ll
Normal file
75
test/CodeGen/R600/fmaxnum.f64.ll
Normal 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 }
|
191
test/CodeGen/R600/fmaxnum.ll
Normal file
191
test/CodeGen/R600/fmaxnum.ll
Normal 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 }
|
75
test/CodeGen/R600/fminnum.f64.ll
Normal file
75
test/CodeGen/R600/fminnum.f64.ll
Normal 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 }
|
189
test/CodeGen/R600/fminnum.ll
Normal file
189
test/CodeGen/R600/fminnum.ll
Normal 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 }
|
50
test/CodeGen/X86/fmaxnum.ll
Normal file
50
test/CodeGen/X86/fmaxnum.ll
Normal 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
|
||||
}
|
95
test/CodeGen/X86/fminnum.ll
Normal file
95
test/CodeGen/X86/fminnum.ll
Normal 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
|
||||
}
|
Loading…
Reference in New Issue
Block a user