Skip to content

Commit 4776f5f

Browse files
committed
CodeGen: Add ISD::AssertNoFPClass
It is used to mark a value that we are sure that it is not some fcType. The examples include: * An arguments of a function is marked with nofpclass * Output value of an intrinsic can be sure to not be some type So that the following operation can make some assumptions. fix typo assernofpclass Add isKnownNeverNaN test Mention operands Fix typo Fix AssertNoFPClass assert Fix code styles 1. Use Op.getConstantOperandVal to get Constant value 2. (NoFPClass & fcNan) == fcNan 3. Use N2->getAsZExtValue() to get Constant value 4. Use getTargetConstant with ptr width to fix 32bit target 5. Don't propagate the flags 6. Add MIPSr6 testcase for 32bit target tests Add Vector test case Add DemandedElts Use 32bit target Fix MERGE_VALUE cases Add aggregate tests with fmin Fix comment Add snan and qnan test cases Test both array and struct Fix WidenVectorResult Fix PromoteHalf support Use seperate function for assertnofpclass Fix wrong dead code from SoftPromoteHalfRes_UnaryOp Fix internal error
1 parent d915355 commit 4776f5f

File tree

13 files changed

+565
-6
lines changed

13 files changed

+565
-6
lines changed

llvm/include/llvm/CodeGen/ISDOpcodes.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,15 @@ enum NodeType {
6767
/// poisoned the assertion will not be true for that value.
6868
AssertAlign,
6969

70+
/// AssertNoFPClass - These nodes record if a register contains a float
71+
/// value that is known to be not some type.
72+
/// This node takes two operands. The first is the node that is known
73+
/// never to be some float types; the second is a constant value with
74+
/// the value of FPClassTest (casted to uint32_t).
75+
/// NOTE: In case of the source value (or any vector element value) is
76+
/// poisoned the assertion will not be true for that value.
77+
AssertNoFPClass,
78+
7079
/// Various leaf nodes.
7180
BasicBlock,
7281
VALUETYPE,

llvm/include/llvm/Target/TargetSelectionDAG.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -875,6 +875,7 @@ def SDT_assert : SDTypeProfile<1, 1,
875875
[SDTCisInt<0>, SDTCisInt<1>, SDTCisSameAs<1, 0>]>;
876876
def assertsext : SDNode<"ISD::AssertSext", SDT_assert>;
877877
def assertzext : SDNode<"ISD::AssertZext", SDT_assert>;
878+
def assertnofpclass : SDNode<"ISD::AssertNoFPClass", SDTFPUnaryOp>;
878879
def assertalign : SDNode<"ISD::AssertAlign", SDT_assert>;
879880

880881
def convergencectrl_anchor : SDNode<"ISD::CONVERGENCECTRL_ANCHOR",

llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ void DAGTypeLegalizer::SoftenFloatResult(SDNode *N, unsigned ResNo) {
168168
case ISD::POISON:
169169
case ISD::UNDEF: R = SoftenFloatRes_UNDEF(N); break;
170170
case ISD::VAARG: R = SoftenFloatRes_VAARG(N); break;
171+
case ISD::AssertNoFPClass: R = GetSoftenedFloat(N->getOperand(0)); break;
171172
case ISD::VECREDUCE_FADD:
172173
case ISD::VECREDUCE_FMUL:
173174
case ISD::VECREDUCE_FMIN:
@@ -2582,6 +2583,7 @@ bool DAGTypeLegalizer::PromoteFloatOperand(SDNode *N, unsigned OpNo) {
25822583
case ISD::LLROUND:
25832584
case ISD::LRINT:
25842585
case ISD::LLRINT: R = PromoteFloatOp_UnaryOp(N, OpNo); break;
2586+
case ISD::AssertNoFPClass: R = PromoteFloatOp_UnaryOpExt1(N, OpNo); break;
25852587
case ISD::FP_TO_SINT_SAT:
25862588
case ISD::FP_TO_UINT_SAT:
25872589
R = PromoteFloatOp_FP_TO_XINT_SAT(N, OpNo); break;
@@ -2640,6 +2642,13 @@ SDValue DAGTypeLegalizer::PromoteFloatOp_UnaryOp(SDNode *N, unsigned OpNo) {
26402642
return DAG.getNode(N->getOpcode(), SDLoc(N), N->getValueType(0), Op);
26412643
}
26422644

2645+
// Convert the promoted float value to the desired integer type
2646+
SDValue DAGTypeLegalizer::PromoteFloatOp_UnaryOpExt1(SDNode *N, unsigned OpNo) {
2647+
SDValue Op = GetPromotedFloat(N->getOperand(0));
2648+
return DAG.getNode(N->getOpcode(), SDLoc(N), N->getValueType(0), Op,
2649+
N->getOperand(1));
2650+
}
2651+
26432652
SDValue DAGTypeLegalizer::PromoteFloatOp_FP_TO_XINT_SAT(SDNode *N,
26442653
unsigned OpNo) {
26452654
SDValue Op = GetPromotedFloat(N->getOperand(0));
@@ -2804,6 +2813,9 @@ void DAGTypeLegalizer::PromoteFloatResult(SDNode *N, unsigned ResNo) {
28042813
case ISD::FTAN:
28052814
case ISD::FTANH:
28062815
case ISD::FCANONICALIZE: R = PromoteFloatRes_UnaryOp(N); break;
2816+
case ISD::AssertNoFPClass:
2817+
R = PromoteFloatRes_UnaryOpExt1(N);
2818+
break;
28072819

28082820
// Binary FP Operations
28092821
case ISD::FADD:
@@ -2996,10 +3008,18 @@ SDValue DAGTypeLegalizer::PromoteFloatRes_UnaryOp(SDNode *N) {
29963008
EVT VT = N->getValueType(0);
29973009
EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
29983010
SDValue Op = GetPromotedFloat(N->getOperand(0));
2999-
30003011
return DAG.getNode(N->getOpcode(), SDLoc(N), NVT, Op);
30013012
}
30023013

3014+
// Unary operation with a more non-float operand where the result and the
3015+
// operand have PromoteFloat type action. Construct a new SDNode with the
3016+
// promoted float value of the old operand.
3017+
SDValue DAGTypeLegalizer::PromoteFloatRes_UnaryOpExt1(SDNode *N) {
3018+
EVT VT = N->getValueType(0);
3019+
EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
3020+
SDValue Op = GetPromotedFloat(N->getOperand(0));
3021+
return DAG.getNode(N->getOpcode(), SDLoc(N), NVT, Op, N->getOperand(1));
3022+
}
30033023
// Binary operations where the result and both operands have PromoteFloat type
30043024
// action. Construct a new SDNode with the promoted float values of the old
30053025
// operands.
@@ -3281,6 +3301,9 @@ void DAGTypeLegalizer::SoftPromoteHalfResult(SDNode *N, unsigned ResNo) {
32813301
case ISD::FTAN:
32823302
case ISD::FTANH:
32833303
case ISD::FCANONICALIZE: R = SoftPromoteHalfRes_UnaryOp(N); break;
3304+
case ISD::AssertNoFPClass:
3305+
R = SoftPromoteHalfRes_UnaryOpExt1(N);
3306+
break;
32843307

32853308
// Binary FP Operations
32863309
case ISD::FADD:
@@ -3607,6 +3630,21 @@ SDValue DAGTypeLegalizer::SoftPromoteHalfRes_UnaryOp(SDNode *N) {
36073630
return DAG.getNode(GetPromotionOpcode(NVT, OVT), dl, MVT::i16, Res);
36083631
}
36093632

3633+
SDValue DAGTypeLegalizer::SoftPromoteHalfRes_UnaryOpExt1(SDNode *N) {
3634+
EVT OVT = N->getValueType(0);
3635+
EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), OVT);
3636+
SDValue Op = GetSoftPromotedHalf(N->getOperand(0));
3637+
SDLoc dl(N);
3638+
3639+
// Promote to the larger FP type.
3640+
Op = DAG.getNode(GetPromotionOpcode(OVT, NVT), dl, NVT, Op);
3641+
3642+
SDValue Res = DAG.getNode(N->getOpcode(), dl, NVT, Op, N->getOperand(1));
3643+
3644+
// Convert back to FP16 as an integer.
3645+
return DAG.getNode(GetPromotionOpcode(NVT, OVT), dl, MVT::i16, Res);
3646+
}
3647+
36103648
SDValue DAGTypeLegalizer::SoftPromoteHalfRes_BinOp(SDNode *N) {
36113649
EVT OVT = N->getValueType(0);
36123650
EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), OVT);

llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,9 @@ class LLVM_LIBRARY_VISIBILITY DAGTypeLegalizer {
8080
/// Pretend all of this node's results are legal.
8181
bool IgnoreNodeResults(SDNode *N) const {
8282
return N->getOpcode() == ISD::TargetConstant ||
83-
N->getOpcode() == ISD::Register;
83+
N->getOpcode() == ISD::Register ||
84+
(N->getOpcode() == ISD::AssertNoFPClass &&
85+
IgnoreNodeResults(N->getOperand(0).getNode()));
8486
}
8587

8688
// Bijection from SDValue to unique id. As each created node gets a
@@ -772,6 +774,7 @@ class LLVM_LIBRARY_VISIBILITY DAGTypeLegalizer {
772774
SDValue PromoteFloatRes_SELECT(SDNode *N);
773775
SDValue PromoteFloatRes_SELECT_CC(SDNode *N);
774776
SDValue PromoteFloatRes_UnaryOp(SDNode *N);
777+
SDValue PromoteFloatRes_UnaryOpExt1(SDNode *N);
775778
SDValue PromoteFloatRes_UNDEF(SDNode *N);
776779
SDValue BitcastToInt_ATOMIC_SWAP(SDNode *N);
777780
SDValue PromoteFloatRes_XINT_TO_FP(SDNode *N);
@@ -785,6 +788,7 @@ class LLVM_LIBRARY_VISIBILITY DAGTypeLegalizer {
785788
SDValue PromoteFloatOp_FP_EXTEND(SDNode *N, unsigned OpNo);
786789
SDValue PromoteFloatOp_STRICT_FP_EXTEND(SDNode *N, unsigned OpNo);
787790
SDValue PromoteFloatOp_UnaryOp(SDNode *N, unsigned OpNo);
791+
SDValue PromoteFloatOp_UnaryOpExt1(SDNode *N, unsigned OpNo);
788792
SDValue PromoteFloatOp_FP_TO_XINT_SAT(SDNode *N, unsigned OpNo);
789793
SDValue PromoteFloatOp_STORE(SDNode *N, unsigned OpNo);
790794
SDValue PromoteFloatOp_ATOMIC_STORE(SDNode *N, unsigned OpNo);
@@ -796,6 +800,8 @@ class LLVM_LIBRARY_VISIBILITY DAGTypeLegalizer {
796800
//===--------------------------------------------------------------------===//
797801

798802
SDValue GetSoftPromotedHalf(SDValue Op) {
803+
while (Op.getNode()->getOpcode() == ISD::AssertNoFPClass)
804+
Op = Op.getNode()->getOperand(0);
799805
TableId &PromotedId = SoftPromotedHalfs[getTableId(Op)];
800806
SDValue PromotedOp = getSDValue(PromotedId);
801807
assert(PromotedOp.getNode() && "Operand wasn't promoted?");
@@ -820,6 +826,7 @@ class LLVM_LIBRARY_VISIBILITY DAGTypeLegalizer {
820826
SDValue SoftPromoteHalfRes_SELECT(SDNode *N);
821827
SDValue SoftPromoteHalfRes_SELECT_CC(SDNode *N);
822828
SDValue SoftPromoteHalfRes_UnaryOp(SDNode *N);
829+
SDValue SoftPromoteHalfRes_UnaryOpExt1(SDNode *N);
823830
SDValue SoftPromoteHalfRes_XINT_TO_FP(SDNode *N);
824831
SDValue SoftPromoteHalfRes_UNDEF(SDNode *N);
825832
SDValue SoftPromoteHalfRes_VECREDUCE(SDNode *N);

llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ void DAGTypeLegalizer::ScalarizeVectorResult(SDNode *N, unsigned ResNo) {
6161
case ISD::AssertZext:
6262
case ISD::AssertSext:
6363
case ISD::FPOWI:
64+
case ISD::AssertNoFPClass:
6465
R = ScalarizeVecRes_UnaryOpWithExtraInput(N);
6566
break;
6667
case ISD::INSERT_VECTOR_ELT: R = ScalarizeVecRes_INSERT_VECTOR_ELT(N); break;
@@ -1276,6 +1277,7 @@ void DAGTypeLegalizer::SplitVectorResult(SDNode *N, unsigned ResNo) {
12761277
case ISD::UINT_TO_FP:
12771278
case ISD::VP_UINT_TO_FP:
12781279
case ISD::FCANONICALIZE:
1280+
case ISD::AssertNoFPClass:
12791281
SplitVecRes_UnaryOp(N, Lo, Hi);
12801282
break;
12811283
case ISD::ADDRSPACECAST:
@@ -2614,7 +2616,7 @@ void DAGTypeLegalizer::SplitVecRes_UnaryOp(SDNode *N, SDValue &Lo,
26142616
const SDNodeFlags Flags = N->getFlags();
26152617
unsigned Opcode = N->getOpcode();
26162618
if (N->getNumOperands() <= 2) {
2617-
if (Opcode == ISD::FP_ROUND) {
2619+
if (Opcode == ISD::FP_ROUND || Opcode == ISD::AssertNoFPClass) {
26182620
Lo = DAG.getNode(Opcode, dl, LoVT, Lo, N->getOperand(1), Flags);
26192621
Hi = DAG.getNode(Opcode, dl, HiVT, Hi, N->getOperand(1), Flags);
26202622
} else {
@@ -4879,6 +4881,7 @@ void DAGTypeLegalizer::WidenVectorResult(SDNode *N, unsigned ResNo) {
48794881
case ISD::FREEZE:
48804882
case ISD::ARITH_FENCE:
48814883
case ISD::FCANONICALIZE:
4884+
case ISD::AssertNoFPClass:
48824885
Res = WidenVecRes_Unary(N);
48834886
break;
48844887
case ISD::FMA: case ISD::VP_FMA:
@@ -5623,6 +5626,9 @@ SDValue DAGTypeLegalizer::WidenVecRes_Unary(SDNode *N) {
56235626
SDValue InOp = GetWidenedVector(N->getOperand(0));
56245627
if (N->getNumOperands() == 1)
56255628
return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, InOp, N->getFlags());
5629+
if (N->getOpcode() == ISD::AssertNoFPClass)
5630+
return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, InOp,
5631+
N->getOperand(1), N->getFlags());
56265632

56275633
assert(N->getNumOperands() == 3 && "Unexpected number of operands!");
56285634
assert(N->isVPOpcode() && "Expected VP opcode");

llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5832,6 +5832,15 @@ bool SelectionDAG::isKnownNeverNaN(SDValue Op, const APInt &DemandedElts,
58325832
return false;
58335833
return true;
58345834
}
5835+
case ISD::AssertNoFPClass: {
5836+
FPClassTest NoFPClass =
5837+
static_cast<FPClassTest>(Op.getConstantOperandVal(1));
5838+
if ((NoFPClass & fcNan) == fcNan)
5839+
return true;
5840+
if (SNaN && (NoFPClass & fcSNan) == fcSNan)
5841+
return true;
5842+
return isKnownNeverNaN(Op.getOperand(0), DemandedElts, SNaN, Depth + 1);
5843+
}
58355844
default:
58365845
if (Opcode >= ISD::BUILTIN_OP_END || Opcode == ISD::INTRINSIC_WO_CHAIN ||
58375846
Opcode == ISD::INTRINSIC_W_CHAIN || Opcode == ISD::INTRINSIC_VOID) {
@@ -7491,6 +7500,16 @@ SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT,
74917500
N2.getOpcode() == ISD::TargetConstant && "Invalid FP_ROUND!");
74927501
if (N1.getValueType() == VT) return N1; // noop conversion.
74937502
break;
7503+
case ISD::AssertNoFPClass: {
7504+
assert(N1.getValueType().isFloatingPoint() &&
7505+
"AssertNoFPClass is used for a non-floating type");
7506+
assert(isa<ConstantSDNode>(N2) && "NoFPClass is not Constant");
7507+
FPClassTest NoFPClass = static_cast<FPClassTest>(N2->getAsZExtVal());
7508+
assert(llvm::to_underlying(NoFPClass) <=
7509+
BitmaskEnumDetail::Mask<FPClassTest>() &&
7510+
"FPClassTest value too large");
7511+
break;
7512+
}
74947513
case ISD::AssertSext:
74957514
case ISD::AssertZext: {
74967515
EVT EVT = cast<VTSDNode>(N2)->getVT();

llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11803,9 +11803,18 @@ void SelectionDAGISel::LowerArguments(const Function &F) {
1180311803
else if (Arg.hasAttribute(Attribute::ZExt))
1180411804
AssertOp = ISD::AssertZext;
1180511805

11806-
ArgValues.push_back(getCopyFromParts(DAG, dl, &InVals[i], NumParts,
11807-
PartVT, VT, nullptr, NewRoot,
11808-
F.getCallingConv(), AssertOp));
11806+
SDValue OutVal =
11807+
getCopyFromParts(DAG, dl, &InVals[i], NumParts, PartVT, VT, nullptr,
11808+
NewRoot, F.getCallingConv(), AssertOp);
11809+
11810+
FPClassTest NoFPClass = Arg.getNoFPClass();
11811+
if (NoFPClass != fcNone) {
11812+
SDValue SDNoFPClass = DAG.getTargetConstant(
11813+
static_cast<uint64_t>(NoFPClass), dl, MVT::i32);
11814+
OutVal = DAG.getNode(ISD::AssertNoFPClass, dl, OutVal.getValueType(),
11815+
OutVal, SDNoFPClass);
11816+
}
11817+
ArgValues.push_back(OutVal);
1180911818
}
1181011819

1181111820
i += NumParts;

llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const {
124124
case ISD::TokenFactor: return "TokenFactor";
125125
case ISD::AssertSext: return "AssertSext";
126126
case ISD::AssertZext: return "AssertZext";
127+
case ISD::AssertNoFPClass: return "AssertNoFPClass";
127128
case ISD::AssertAlign: return "AssertAlign";
128129

129130
case ISD::BasicBlock: return "BasicBlock";

llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3264,6 +3264,7 @@ void SelectionDAGISel::SelectCodeCommon(SDNode *NodeToMatch,
32643264
return;
32653265
case ISD::AssertSext:
32663266
case ISD::AssertZext:
3267+
case ISD::AssertNoFPClass:
32673268
case ISD::AssertAlign:
32683269
ReplaceUses(SDValue(NodeToMatch, 0), NodeToMatch->getOperand(0));
32693270
CurDAG->RemoveDeadNode(NodeToMatch);

0 commit comments

Comments
 (0)