[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