/// Returns true if \p V is a constant min signed integer value.
bool isMinSignedConstant(SDValue V);
+/// Returns true if \p V is a neutral element of Opc with Flags.
+/// When OperandNo is 0, it checks that V is a left identity. Otherwise, it
+/// checks that V is a right identity.
+bool isNeutralConstant(unsigned Opc, SDNodeFlags Flags, SDValue V,
+ unsigned OperandNo);
+
/// Return the non-bitcasted source operand of \p V if it exists.
/// If \p V is not a bitcasted value, it is returned as-is.
SDValue peekThroughBitcasts(SDValue V);
return Const != nullptr && Const->isMinSignedValue();
}
+bool llvm::isNeutralConstant(unsigned Opcode, SDNodeFlags Flags, SDValue V,
+ unsigned OperandNo) {
+ if (auto *Const = dyn_cast<ConstantSDNode>(V)) {
+ switch (Opcode) {
+ case ISD::ADD:
+ case ISD::OR:
+ case ISD::XOR:
+ case ISD::UMAX:
+ return Const->isZero();
+ case ISD::MUL:
+ return Const->isOne();
+ case ISD::AND:
+ case ISD::UMIN:
+ return Const->isAllOnes();
+ case ISD::SMAX:
+ return Const->isMinSignedValue();
+ case ISD::SMIN:
+ return Const->isMaxSignedValue();
+ case ISD::SUB:
+ case ISD::SHL:
+ case ISD::SRA:
+ case ISD::SRL:
+ return OperandNo == 1 && Const->isZero();
+ case ISD::UDIV:
+ case ISD::SDIV:
+ return OperandNo == 1 && Const->isOne();
+ }
+ } else if (auto *ConstFP = dyn_cast<ConstantFPSDNode>(V)) {
+ switch (Opcode) {
+ case ISD::FADD:
+ return ConstFP->isZero() &&
+ (Flags.hasNoSignedZeros() || ConstFP->isNegative());
+ case ISD::FSUB:
+ return OperandNo == 1 && ConstFP->isZero() &&
+ (Flags.hasNoSignedZeros() || !ConstFP->isNegative());
+ case ISD::FMUL:
+ return ConstFP->isExactlyValue(1.0);
+ case ISD::FDIV:
+ return OperandNo == 1 && ConstFP->isExactlyValue(1.0);
+ case ISD::FMINNUM:
+ case ISD::FMAXNUM: {
+ // Neutral element for fminnum is NaN, Inf or FLT_MAX, depending on FMF.
+ EVT VT = V.getValueType();
+ const fltSemantics &Semantics = SelectionDAG::EVTToAPFloatSemantics(VT);
+ APFloat NeutralAF = !Flags.hasNoNaNs()
+ ? APFloat::getQNaN(Semantics)
+ : !Flags.hasNoInfs()
+ ? APFloat::getInf(Semantics)
+ : APFloat::getLargest(Semantics);
+ if (Opcode == ISD::FMAXNUM)
+ NeutralAF.changeSign();
+
+ return ConstFP->isExactlyValue(NeutralAF);
+ }
+ }
+ }
+ return false;
+}
+
SDValue llvm::peekThroughBitcasts(SDValue V) {
while (V.getOpcode() == ISD::BITCAST)
V = V.getOperand(0);
if (!isOneConstant(ScalarV.getOperand(2)))
return SDValue();
- // TODO: Deal with value other than neutral element.
- auto IsRVVNeutralElement = [Opc, &DAG](SDNode *N, SDValue V) {
- if (Opc == ISD::FADD && N->getFlags().hasNoSignedZeros() &&
- isNullFPConstant(V))
- return true;
- return DAG.getNeutralElement(Opc, SDLoc(V), V.getSimpleValueType(),
- N->getFlags()) == V;
- };
-
// Check the scalar of ScalarV is neutral element
- if (!IsRVVNeutralElement(N, ScalarV.getOperand(1)))
+ // TODO: Deal with value other than neutral element.
+ if (!isNeutralConstant(N->getOpcode(), N->getFlags(), ScalarV.getOperand(1),
+ 0))
return SDValue();
if (!ScalarV.hasOneUse())