[llvm] [SLP] Allow UDiv X, C <--> LShr X, log2(C) tranformations in BinOpSameOpcodeHelper (PR #181731)

Ryan Buchner via llvm-commits llvm-commits at lists.llvm.org
Mon Feb 16 12:16:09 PST 2026


================
@@ -51,14 +51,21 @@ entry:
 define void @test_add_udiv(ptr %arr1, ptr %arr2, i32 %a0, i32 %a1, i32 %a2, i32 %a3) {
 ; CHECK-LABEL: @test_add_udiv(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[TMP0:%.*]] = load <4 x i32>, ptr [[ARR1:%.*]], align 4
-; CHECK-NEXT:    [[TMP5:%.*]] = insertelement <4 x i32> <i32 0, i32 0, i32 poison, i32 0>, i32 [[A2:%.*]], i32 2
-; CHECK-NEXT:    [[TMP6:%.*]] = add <4 x i32> [[TMP5]], <i32 1, i32 1, i32 42, i32 1>
-; CHECK-NEXT:    [[TMP1:%.*]] = insertelement <4 x i32> <i32 poison, i32 poison, i32 0, i32 poison>, i32 [[A0:%.*]], i32 0
+; CHECK-NEXT:    [[GEP1_2:%.*]] = getelementptr i32, ptr [[ARR1:%.*]], i32 2
+; CHECK-NEXT:    [[GEP1_3:%.*]] = getelementptr i32, ptr [[ARR1]], i32 3
+; CHECK-NEXT:    [[V2:%.*]] = load i32, ptr [[GEP1_2]], align 4
+; CHECK-NEXT:    [[V3:%.*]] = load i32, ptr [[GEP1_3]], align 4
+; CHECK-NEXT:    [[Y2:%.*]] = add nsw i32 [[A2:%.*]], 42
+; CHECK-NEXT:    [[TMP0:%.*]] = load <2 x i32>, ptr [[ARR1]], align 4
----------------
bababuck wrote:

Not sure. From what I gathered digging into this earlier, the SLP considers this a performance increase because the vector division is considered to be so expensive. Prior to the chance, this gets vectorized with `SLP: Decided to vectorize cost = -2` , and after the change it is vectorized with `SLP: Decided to vectorize cost = -2`.

That aside, the actual cause of this change is caused by the behavior in `VLOperands.reorder()`. When costing the order of operations, this change allows `UDiv` to be combined with `Add X, 0`, which is considered beneficial and leads to the flipping of the operands of `Add (UDiv %v2, %y2), 0` to `Add 0, (UDiv %v2, %y2)` which eventually leads to the behavior change we see. I can write up an issue for the improvements to `VLOperands.reorder()` that would make it behave better in this situation.

To demonstrate this, if we take the same test and flip the operands:
```
  %res0 = add nsw i32 %v0, %y0 -> %y0, %v0
  %res1 = add nsw i32 %v1, %y1 -> %y1, %v1
  %res2 = udiv i32 %v2, %y2
  %res3 = add nsw i32 %v3, %y3 -> %y3, %v3
```
the resulting output is the same as the changed output from this MR:
```
define void @test_add_udiv_reorder(ptr %arr1, ptr %arr2, i32 %a0, i32 %a1, i32 %a2, i32 %a3) #0 {
entry:
  %gep1.2 = getelementptr i32, ptr %arr1, i32 2
  %gep1.3 = getelementptr i32, ptr %arr1, i32 3
  %v2 = load i32, ptr %gep1.2, align 4
  %v3 = load i32, ptr %gep1.3, align 4
  %y2 = add nsw i32 %a2, 42
  %0 = load <2 x i32>, ptr %arr1, align 4
  %res2 = udiv i32 %v2, %y2
  %1 = insertelement <4 x i32> poison, i32 %a0, i32 0
  %2 = insertelement <4 x i32> %1, i32 %a1, i32 1
  %3 = insertelement <4 x i32> %2, i32 %a3, i32 3
  %4 = insertelement <4 x i32> %3, i32 %res2, i32 2
  %5 = add nsw <4 x i32> %4, <i32 1146, i32 146, i32 0, i32 0>
  %6 = insertelement <4 x i32> <i32 poison, i32 poison, i32 0, i32 poison>, i32 %v3, i32 3
  %7 = shufflevector <2 x i32> %0, <2 x i32> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison>
  %8 = shufflevector <4 x i32> %6, <4 x i32> %7, <4 x i32> <i32 4, i32 5, i32 2, i32 3>
  %9 = add nsw <4 x i32> %5, %8
  store <4 x i32> %9, ptr %arr2, align 4
  ret void
}
```

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


More information about the llvm-commits mailing list