[llvm] [AggressiveInstCombine] POPCNT generation for bit-count pattern (PR #177109)
Craig Topper via llvm-commits
llvm-commits at lists.llvm.org
Mon Mar 16 08:44:02 PDT 2026
================
@@ -372,6 +372,140 @@ static bool tryToRecognizePopCount(Instruction &I) {
return false;
}
+// Try to recognize below function as popcount intrinsic.
+// https://doc.lagout.org/security/Hackers%20Delight.pdf
+// Also used in TargetLowering::expandCTPOP().
+//
+// int popcount32(unsigned int i) {
+// uWord = (uWord & 0x55555555) + ((uWord>>1) & 0x55555555);
+// uWord = (uWord & 0x33333333) + ((uWord>>2) & 0x33333333);
+// uWord = (uWord & 0x0F0F0F0F) + ((uWord>>4) & 0x0F0F0F0F);
+// uWord = (uWord & 0x00FF00FF) + ((uWord>>8) & 0x00FF00FF);
+// return (uWord & 0x0000FFFF) + (uWord>>16);
+// }
+// int popcount64(unsigned long i) {
+// uWord = (uWord & 0x5555555555555555) + ((uWord>>1) & 0x5555555555555555);
+// uWord = (uWord & 0x3333333333333333) + ((uWord>>2) & 0x3333333333333333);
+// uWord = (uWord & 0x0F0F0F0F0F0F0F0F) + ((uWord>>4) & 0x0F0F0F0F0F0F0F0F);
+// uWord = (uWord & 0x00FF00FF00FF00FF) + ((uWord>>8) & 0x00FF00FF00FF00FF);
+// return (uWord & 0x0000FFFF0000FFFF) + ((uWord>>16) & 0x0000FFFF0000FFFF);
+// return (uWord & 0x00000000FFFFFFFF) + (uWord>>32) & 0x00000000FFFFFFFF;
+// }
+static bool tryToRecognizePopCount1(Instruction &I) {
+ if (I.getOpcode() != Instruction::Add)
+ return false;
+
+ Type *Ty = I.getType();
+ if (!Ty->isIntOrIntVectorTy())
+ return false;
+
+ unsigned Len = Ty->getScalarSizeInBits();
+ if (!(Len <= 64 && Len > 8 && Len % 8 == 0))
+ return false;
+
+ APInt Mask55 = APInt::getSplat(Len, APInt(8, 0x55));
+ APInt Mask33 = APInt::getSplat(Len, APInt(8, 0x33));
+ APInt Mask0F = APInt::getSplat(Len, APInt(8, 0x0F));
+ APInt Mask00FF;
+ if (Len == 16) {
+ Mask00FF = APInt(16, 0x00FF);
+ } else {
+ Mask00FF = APInt::getSplat(Len, APInt(16, 0x00FF));
+ }
+ APInt Mask0000FFFF;
+ if (Len <= 32) {
+ Mask0000FFFF = APInt(32, 0x0000FFFF);
+ } else {
+ Mask0000FFFF = APInt::getSplat(Len, APInt(32, 0x0000FFFF));
+ }
+
+ APInt Mask64 = APInt(64, 0x00000000FFFFFFFF);
+ // Matching "(uWord & 0x00000000FFFFFFFF) + (uWord>>32)".
+ // OR
+ // Matching "(uWord & 0x00000000FFFFFFFF) + ((uWord>>32) &
+ // 0x00000000FFFFFFFF)".
+ Value *ShiftOp;
+ Value *Start = &I;
+ bool Is64 = false;
+ if (match(Start,
+ m_c_Add(m_And(m_LShr(m_Value(ShiftOp), m_SpecificInt(32)),
+ m_SpecificInt(Mask64)),
+ m_And(m_Deferred(ShiftOp), m_SpecificInt(Mask64)))) ||
+ match(Start,
+ m_c_Add(m_LShr(m_Value(ShiftOp), m_SpecificInt(32)),
+ m_And(m_Deferred(ShiftOp), m_SpecificInt(Mask64))))) {
+ Start = ShiftOp;
+ Is64 = true;
+ }
+ Value *LShrOp0;
+ // Matching "(uWord & 0x0000FFFF) + (uWord>>16)".
+ // Matching "(uWord & 0x0000FFFF) + ((uWord>>16) & 0x0000FFFF)".
+ bool Test16 = match(
+ Start, m_c_Add(m_And(m_LShr(m_Value(LShrOp0), m_SpecificInt(16)),
+ m_SpecificInt(Mask0000FFFF)),
+ m_And(m_Deferred(LShrOp0), m_SpecificInt(Mask0000FFFF))));
+
+ bool Is32 = false;
+ if ((Is64 && Test16) ||
+ (!Is64 && Len == 32 &&
+ (Test16 ||
+ match(Start, m_c_Add(m_LShr(m_Value(LShrOp0), m_SpecificInt(16)),
+ m_And(m_Deferred(LShrOp0),
+ m_SpecificInt(Mask0000FFFF))))))) {
+ Start = LShrOp0;
+ Is32 = true;
+ }
+ Value *ShiftOp0;
+ // Matching "uWord = (uWord & 0x00FF00FF) + ((uWord>>8) & 0x00FF00FF);".
+ // OR
+ // Matching "uWord = (uWord & 0x00FF00FF) + (uWord>>8) ;".
+ bool Test8 = match(
+ Start, m_c_Add(m_And(m_LShr(m_Value(ShiftOp0), m_SpecificInt(8)),
+ m_SpecificInt(Mask00FF)),
+ m_And(m_Deferred(ShiftOp0), m_SpecificInt(Mask00FF))));
+ if (!((Is32 && Test8) ||
+ (!Is32 && Len == 16 &&
+ (Test8 ||
+ match(Start, m_c_Add(m_LShr(m_Value(ShiftOp0), m_SpecificInt(8)),
+ m_And(m_Deferred(ShiftOp0),
+ m_SpecificInt(Mask00FF)))))))) {
+ return false;
+ }
+
+ Value *ShiftOp1;
+ // Matching "uWord = (uWord & 0x0F0F0F0F) + ((uWord>>4) & 0x0F0F0F0F)".
+ if (!match(ShiftOp0,
+ m_c_Add(m_And(m_LShr(m_Value(ShiftOp1), m_SpecificInt(4)),
+ m_SpecificInt(Mask0F)),
+ m_And(m_Deferred(ShiftOp1), m_SpecificInt(Mask0F))))) {
+ return false;
+ }
+
+ Value *ShiftOp2;
+ // Matching "uWord = (uWord & 0x33333333) + ((uWord>>2) & 0x33333333)".
+ if (match(ShiftOp1,
----------------
topperc wrote:
Invert this condition and early exit.
https://github.com/llvm/llvm-project/pull/177109
More information about the llvm-commits
mailing list