[llvm] [SLP]Analyze widened reduction leaves in the narrow type (PR #216062)

Ryan Buchner via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 20 12:59:39 PDT 2026


================
@@ -31342,6 +31416,39 @@ class HorizontalReduction {
                                          SameValuesCounter, RootTrackedToOrig);
         }
 
+        // Widen and shift per lane. Map back from extractelements to the
+        // original reduced values for the shift amounts. The absorbed narrow
+        // and-masks and the bits truncated by the absorbed narrow shls are
+        // masked off after the shift.
+        if (!NarrowedLeafShifts.empty()) {
+          Type *WideTy = ReductionRoot->getType();
+          unsigned VF = getNumElements(VectorizedRoot->getType());
+          VectorizedRoot =
+              Builder.CreateZExt(VectorizedRoot, getWidenedType(WideTy, VF));
+          SmallVector<Constant *> ShiftConsts(VF, ConstantInt::get(WideTy, 0));
+          SmallVector<Constant *> MaskConsts(VF,
+                                             Constant::getAllOnesValue(WideTy));
+          bool AnyShift = false;
+          bool AnyMask = false;
+          for (auto [Idx, Val] : enumerate(VL)) {
+            const NarrowedLeafInfo &L =
+                NarrowedLeafShifts.at(TrackedToOrig[Pos + Idx]);
+            unsigned Lane = V.findRootLaneForValue(Val);
+            ShiftConsts[Lane] = ConstantInt::get(WideTy, L.Shift);
+            AnyShift |= L.Shift != 0;
+            if (!L.Mask.isAllOnes()) {
+              MaskConsts[Lane] = ConstantInt::get(WideTy, L.Mask);
+              AnyMask = true;
+            }
+          }
+          if (AnyShift)
+            VectorizedRoot = Builder.CreateShl(
+                VectorizedRoot, ConstantVector::get(ShiftConsts));
+          if (AnyMask)
+            VectorizedRoot = Builder.CreateAnd(VectorizedRoot,
+                                               ConstantVector::get(MaskConsts));
----------------
bababuck wrote:

I think we should emit the `and` before the `shl` and the `zext`. In cases such as the motivating example, it will cause the `and` mask to become constant across all lanes. In other cases where that doesn't occur, moving it prior to the `zext` will allow the mask to be in a smaller `8 bit` type which will allow for cheaper materialization on different backends. For RISCV, if the vector width is small enough, we can synthesize <8 x i8> as an i64 in the scalar side and then move it to the vector side using an int->vec move instruction before bitcasting it to <8 x i8>. 

https://github.com/llvm/llvm-project/pull/216062


More information about the llvm-commits mailing list