[llvm] [X86] Avoid shl->mul lowbit-isolate fold on znver5/znver6 when unprofitable (PR #217776)
PJ Dailey via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 20 17:03:38 PDT 2026
================
@@ -50792,6 +50792,44 @@ static SDValue combineMul(SDNode *N, SelectionDAG &DAG,
if (SDValue V = combineMulToPMADD52(N, DL, DAG, Subtarget))
return V;
+ // #214517 folds shl X, cttz(Y) into mul(and(neg(Y), Y), X), which is
+ // usually profitable but is worse on some subtargets: on znver5 the mul
+ // form lowers to blsi+imul while the shl form lowers to tzcnt+shlx,
+ // which has better latency/throughput despite matching instruction count
+ // (https://github.com/llvm/llvm-project/issues/216550). Reverse the fold
+ // when the target prefers it. Only valid when Y is provably nonzero:
+ // cttz(Y) returns the bit width when Y == 0, and shl by an out-of-range
+ // amount is poison, while the mul form is well-defined (0) at Y == 0 -
+ // so the rewrite would be a miscompile for Y == 0 without that guard.
+ if (Subtarget.preferShlOverBlsiMul()) {
+ auto MatchLowBitIsolate = [](SDValue And) -> SDValue {
+ if (And.getOpcode() != ISD::AND || !And.hasOneUse())
+ return SDValue();
+ SDValue Op0 = And.getOperand(0);
+ SDValue Op1 = And.getOperand(1);
+ auto IsNegOf = [](SDValue Sub, SDValue Y) {
+ return Sub.getOpcode() == ISD::SUB &&
+ isNullConstant(Sub.getOperand(0)) && Sub.getOperand(1) == Y;
+ };
+ if (IsNegOf(Op0, Op1))
+ return Op1;
+ if (IsNegOf(Op1, Op0))
+ return Op0;
+ return SDValue();
+ };
+
+ for (unsigned I = 0; I != 2; ++I) {
+ SDValue Y = MatchLowBitIsolate(N->getOperand(I));
+ if (!Y)
+ continue;
+ SDValue X = N->getOperand(1 - I);
+ if (!DAG.isKnownNeverZero(Y))
+ continue;
+ SDValue Cttz = DAG.getNode(ISD::CTTZ, DL, VT, Y);
----------------
PjDailey11 wrote:
Yes, that's more accurate as well
https://github.com/llvm/llvm-project/pull/217776
More information about the llvm-commits
mailing list