[llvm] [InstCombine] Fold redundant select guards for ctpop (PR #195443)
Yunbo Ni via llvm-commits
llvm-commits at lists.llvm.org
Sat May 2 05:46:43 PDT 2026
================
@@ -4317,6 +4317,26 @@ Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) {
if (Instruction *I = canonicalizeScalarSelectOfVecs(SI, *this))
return I;
+ // Fold: select (icmp ult X, 2), X, ctpop(X) --> ctpop(X)
+ // Fold: select (icmp eq X, -1), BitWidth, ctpop(X) --> ctpop(X)
+ // ctpop(0)==0, ctpop(1)==1, ctpop(-1)==BitWidth, so guards are redundant.
+ {
+ Value *X;
+ CmpPredicate CtpopPred;
+ Value *CtpopCmpLHS, *CtpopCmpRHS;
+ unsigned CtpopBitWidth = SelType->getScalarSizeInBits();
+ if (match(FalseVal, m_Intrinsic<Intrinsic::ctpop>(m_Value(X))) &&
+ match(CondVal, m_ICmp(CtpopPred, m_Value(CtpopCmpLHS), m_Value(CtpopCmpRHS)))) {
+ if (CtpopCmpLHS == X && CtpopPred == ICmpInst::ICMP_ULT &&
+ match(CtpopCmpRHS, m_SpecificInt(2)) && TrueVal == X)
+ return replaceInstUsesWith(SI, FalseVal);
----------------
cardigan1008 wrote:
> Please call `dropPoisonGeneratingAnnotations` on ctpop and re-queue the instruction. See also `foldIsPowerOf2OrZero`.
Here is a related miscompilation case:
```llvm
declare i32 @llvm.ctpop.i32(i32)
declare void @use_noundef(i32 noundef)
define i32 @mut_allones_range_i32(i32 %x) {
%cmp = icmp eq i32 %x, -1
%pop = call range(i32 0, 32) i32 @llvm.ctpop.i32(i32 %x)
%res = select i1 %cmp, i32 32, i32 %pop
call void @use_noundef(i32 %res)
ret i32 %res
}
```
Alive2 proof: https://alive2.llvm.org/ce/z/tpHsL8
> Found with [Archer](https://github.com/cuhk-s3/Archer). Please let me know if anything is wrong.
https://github.com/llvm/llvm-project/pull/195443
More information about the llvm-commits
mailing list