[llvm] [GlobalIsel] Visit ICmp (PR #105991)
Jason Eckhardt via llvm-commits
llvm-commits at lists.llvm.org
Sun Aug 25 16:45:02 PDT 2024
Thorsten =?utf-8?q?Schütt?= <schuett at gmail.com>,
Thorsten =?utf-8?q?Schütt?= <schuett at gmail.com>
Message-ID:
In-Reply-To: <llvm.org/llvm/llvm-project/pull/105991 at github.com>
================
@@ -1984,3 +1984,323 @@ Type *llvm::getTypeForLLT(LLT Ty, LLVMContext &C) {
Ty.getElementCount());
return IntegerType::get(C, Ty.getSizeInBits());
}
+
+APInt llvm::GIConstant::getScalarValue() const {
+ assert(Kind == GIConstantKind::Scalar && "Expected scalar constant");
+
+ return Value;
+}
+
+std::optional<GIConstant>
+llvm::GIConstant::getConstant(Register Const, const MachineRegisterInfo &MRI) {
+ MachineInstr *Constant = getDefIgnoringCopies(Const, MRI);
+
+ if (GSplatVector *Splat = dyn_cast<GSplatVector>(Constant)) {
+ std::optional<ValueAndVReg> MayBeConstant =
+ getIConstantVRegValWithLookThrough(Splat->getValueReg(), MRI);
+ if (!MayBeConstant)
+ return std::nullopt;
+ return GIConstant(MayBeConstant->Value, GIConstantKind::ScalableVector);
+ }
+
+ if (GBuildVector *Build = dyn_cast<GBuildVector>(Constant)) {
+ SmallVector<APInt> Values;
+ unsigned NumSources = Build->getNumSources();
+ for (unsigned I = 0; I < NumSources; ++I) {
+ Register SrcReg = Build->getSourceReg(I);
+ std::optional<ValueAndVReg> MayBeConstant =
+ getIConstantVRegValWithLookThrough(SrcReg, MRI);
+ if (!MayBeConstant)
+ return std::nullopt;
+ Values.push_back(MayBeConstant->Value);
+ }
+ return GIConstant(Values);
+ }
+
+ std::optional<ValueAndVReg> MayBeConstant =
+ getIConstantVRegValWithLookThrough(Const, MRI);
+ if (!MayBeConstant)
+ return std::nullopt;
+
+ return GIConstant(MayBeConstant->Value, GIConstantKind::Scalar);
+}
+
+static bool isKnownNonZero(Register Reg, const MachineRegisterInfo &MRI,
+ GISelKnownBits *KB, unsigned Depth);
+
+bool llvm::isKnownNonZero(Register Reg, const MachineRegisterInfo &MRI,
+ GISelKnownBits *KB, unsigned Depth) {
+ if (!Reg.isVirtual())
+ return false;
+
+ LLT Ty = MRI.getType(Reg);
+ if (!Ty.isValid())
+ return false;
+
+ if (Ty.isPointer())
+ return false;
+
+ assert(Ty.isScalar() && "Expected a scalar value");
+ return ::isKnownNonZero(Reg, MRI, KB, Depth);
+}
+
+static bool matchOpWithOpEqZero(Register Op0, Register Op1,
+ const MachineRegisterInfo &MRI) {
+ MachineInstr *MI = MRI.getVRegDef(Op0);
+
+ bool Result = false;
+
+ if (GZextOrSextOp *ZS = dyn_cast<GZextOrSextOp>(MI)) {
+ MachineInstr *SrcMI = MRI.getVRegDef(ZS->getSrcReg());
+ if (GICmp *Cmp = dyn_cast<GICmp>(SrcMI)) {
+ std::optional<ValueAndVReg> MayBeConstant =
+ getIConstantVRegValWithLookThrough(Cmp->getRHSReg(), MRI);
+ if (MayBeConstant)
+ Result |= (MayBeConstant->Value == 0) && (Cmp->getLHSReg() == Op1) &&
+ (Cmp->getCond() == ICmpInst::ICMP_EQ);
+ }
+ }
+
+ MI = MRI.getVRegDef(Op1);
+ if (GZextOrSextOp *ZS = dyn_cast<GZextOrSextOp>(MI)) {
+ MachineInstr *SrcMI = MRI.getVRegDef(ZS->getSrcReg());
+ if (GICmp *Cmp = dyn_cast<GICmp>(SrcMI)) {
+ std::optional<ValueAndVReg> MayBeConstant =
+ getIConstantVRegValWithLookThrough(Cmp->getRHSReg(), MRI);
+ if (MayBeConstant)
+ Result |= (MayBeConstant->Value == 0) && (Cmp->getLHSReg() == Op0) &&
+ (Cmp->getCond() == ICmpInst::ICMP_EQ);
+ }
+ }
+
+ return Result;
+}
+
+static bool isNonZeroAdd(const GBinOp &Add, const MachineRegisterInfo &MRI,
+ GISelKnownBits *KB, unsigned Depth,
+ unsigned BitWidth) {
+ bool NSW = Add.getFlag(MachineInstr::MIFlag::NoSWrap);
+ bool NUW = Add.getFlag(MachineInstr::MIFlag::NoUWrap);
+ Register LHS = Add.getLHSReg();
+ Register RHS = Add.getRHSReg();
+
+ // (X + (X != 0)) is non zero
+ if (matchOpWithOpEqZero(LHS, RHS, MRI))
+ return true;
+
+ if (NUW)
+ return ::isKnownNonZero(RHS, MRI, KB, Depth) ||
+ ::isKnownNonZero(LHS, MRI, KB, Depth);
+
+ KnownBits LHSKnown = KB->getKnownBits(LHS);
+ KnownBits RHSKnown = KB->getKnownBits(RHS);
+
+ // If LHS and RHS are both non-negative (as signed values) then their sum is
+ // not zero unless both LHS and RHS are zero.
+ if (LHSKnown.isNonNegative() && RHSKnown.isNonNegative())
+ if (::isKnownNonZero(LHS, MRI, KB, Depth) ||
+ ::isKnownNonZero(RHS, MRI, KB, Depth))
+ return true;
+
+ // If LHS and RHS are both negative (as signed values) then their sum is not
+ // zero unless both LHS and RHS equal INT_MIN.
+ if (LHSKnown.isNegative() && RHSKnown.isNegative()) {
+ APInt Mask = APInt::getSignedMaxValue(BitWidth);
+ // The sign bit of LHS is set. If some other bit is set then LHS is not
+ // equal to INT_MIN.
+ if (LHSKnown.One.intersects(Mask))
+ return true;
+ // The sign bit of RHS is set. If some other bit is set then RHS is not
+ // equal to INT_MIN.
+ if (RHSKnown.One.intersects(Mask))
+ return true;
+ }
+
+ // The sum of a non-negative number and a power of two is not zero.
+ if (LHSKnown.isNonNegative() && ::isKnownToBeAPowerOfTwo(RHS, MRI, KB))
+ return true;
+ if (RHSKnown.isNonNegative() && ::isKnownToBeAPowerOfTwo(LHS, MRI, KB))
+ return true;
+
+ return KnownBits::add(LHSKnown, RHSKnown, NSW, NUW).isNonZero();
+}
+
+static bool isKnownNonZeroBinOp(const GBinOp &BinOp,
+ const MachineRegisterInfo &MRI,
+ GISelKnownBits *KB, unsigned Depth) {
+ unsigned BitWidth = MRI.getType(BinOp.getReg(0)).getScalarSizeInBits();
+ switch (BinOp.getOpcode()) {
+ case TargetOpcode::G_XOR:
+ // (X ^ (X != 0)) is non zero
+ if (matchOpWithOpEqZero(BinOp.getLHSReg(), BinOp.getRHSReg(), MRI))
+ return true;
+ break;
+ case TargetOpcode::G_OR: {
+ // (X | (X != 0)) is non zero
----------------
nvjle wrote:
CS nit: Period.
https://github.com/llvm/llvm-project/pull/105991
More information about the llvm-commits
mailing list