[llvm] [X86] Shrink i32 unsigned compares to i8/i16 when high bits are zero (PR #197801)
Weiwen He via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 8 06:07:35 PDT 2026
================
@@ -24316,6 +24285,34 @@ static SDValue EmitCmp(SDValue Op0, SDValue Op1, X86::CondCode X86CC,
Op1 = DAG.getNode(ISD::TRUNCATE, dl, CmpVT, Op1);
}
+ // Try to shrink i32 unsigned compares to i8 or i16 when both operands'
+ // high bits are known zero and neither operand is a constant. Eligible
+ // i64 compares are shrunk to i32 above.
+ if (CmpVT == MVT::i32 && !isX86CCSigned(X86CC) &&
+ Op0.hasOneUse() && // Hacky way to not break CSE opportunities with sub.
+ !isa<ConstantSDNode>(Op0) && !isa<ConstantSDNode>(Op1)) {
+ auto BothOpsFit = [&](unsigned Bits) {
+ APInt Hi = APInt::getHighBitsSet(32, 32 - Bits);
+ return DAG.MaskedValueIsZero(Op0, Hi) && DAG.MaskedValueIsZero(Op1, Hi);
+ };
+ // Narrowing to i16 is only when this enables an (and x, 0xFFFF) in an
+ // operand to be removed downstream
+ auto IsI16Eliminable = [](SDValue Op) {
+ if (Op.getOpcode() == ISD::AND)
+ if (auto *C = dyn_cast<ConstantSDNode>(Op.getOperand(1)))
+ return C->getAPIntValue().countr_one() >= 16;
----------------
he-weiwen wrote:
The idea was that if the constant mask has more than 16 trailing 1s, and we can prove the full expression fit in 16 bit, then it should be equivalent to `and(x, 0xFFFF)` after truncation.
But it seems that case is canonicalized to `and(x, 0xFFFF)` already by the time we reach here, so `countr_one() == 16` would work the same.
https://github.com/llvm/llvm-project/pull/197801
More information about the llvm-commits
mailing list