[DAG] vector cond ? x / C1: x / C2 should avoid twice division
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
Separated from https://github.com/llvm/llvm-project/issues/214466#issuecomment-5354966246
https://godbolt.org/z/4bn5djfc8
https://alive2.llvm.org/ce/z/RyssHH
```llvm
define <4 x i64> @src(<4 x i64> %x, <4 x i1> %c) {
%a = udiv <4 x i64> %x, splat (i64 137)
%b = udiv <4 x i64> %x, splat (i64 71)
%r = select <4 x i1> %c, <4 x i64> %a, <4 x i64> %b
ret <4 x i64> %r
}
define <4 x i64> @tgt(<4 x i64> %x, <4 x i1> %c) {
%vecinit = shufflevector <4 x i64> %x, <4 x i64> poison, <8 x i32>
%div = udiv <8 x i64> %vecinit,
%a = shufflevector <8 x i64> %div, <8 x i64> poison, <4 x i32>
%b = shufflevector <8 x i64> %div, <8 x i64> poison, <4 x i32>
%r = select <4 x i1> %c, <4 x i64> %a, <4 x i64> %b
ret <4 x i64> %r
}
```
```llvm
----------------------------------------
define <4 x i64> @src(<4 x i64> %x, <4 x i1> %c) {
#0:
%a = udiv <4 x i64> %x, { 137, 137, 137, 137 }
%b = udiv <4 x i64> %x, { 71, 71, 71, 71 }
%r = select <4 x i1> %c, <4 x i64> %a, <4 x i64> %b
ret <4 x i64> %r
}
=>
define <4 x i64> @tgt(<4 x i64> %x, <4 x i1> %c) {
#0:
%vecinit = shufflevector <4 x i64> %x, <4 x i64> poison, 0, 1, 2, 3, 0, 1, 2, 3
%div = udiv <8 x i64> %vecinit, { 137, 137, 137, 137, 71, 71, 71, 71 }
%a = shufflevector <8 x i64> %div, <8 x i64> poison, 0, 1, 2, 3
%b = shufflevector <8 x i64> %div, <8 x i64> poison, 4, 5, 6, 7
%r = select <4 x i1> %c, <4 x i64> %a, <4 x i64> %b
ret <4 x i64> %r
}
Transformation seems to be correct!
```
```asm
Iterations: 100
Instructions: 4100
Total Cycles: 1711
Total uOps: 4100
Dispatch Width: 6
uOps Per Cycle: 2.40
IPC: 2.40
Block RThroughput: 7.5
Instruction Info:
[1]: #uOps
[2]: Latency
[3]: RThroughput
[4]: MayLoad
[5]: MayStore
[6]: HasSideEffects (U)
[1] [2] [3] [4] [5] [6] Instructions:
1 1 0.50 vpslld xmm1, xmm1, 31
1 8 0.50 * vpbroadcastq ymm5, qword ptr [rip + .LCPI0_1]
1 1 0.50 vpsrlq ymm2, ymm0, 32
1 0 0.17 vpxor xmm4, xmm4, xmm4
1 8 0.50 * vpbroadcastq ymm7, qword ptr [rip + .LCPI0_3]
1 1 1.00 vpmovd2m k1, xmm1
1 8 0.50 * vpbroadcastq ymm1, qword ptr [rip + .LCPI0_0]
1 3 0.50 vpmuludq ymm6, ymm0, ymm5
1 3 0.50 vpmuludq ymm5, ymm2, ymm5
1 3 0.50 vpmuludq ymm3, ymm2, ymm1
1 3 0.50 vpmuludq ymm1, ymm0, ymm1
1 1 0.50 vpsrlq ymm1, ymm1, 32
1 1 0.25 vpaddq ymm1, ymm3, ymm1
1 1 0.50 vpsrlq ymm3, ymm1, 32
1 1 0.25 vpblendd ymm1, ymm1, ymm4, 170
1 1 0.25 vpaddq ymm1, ymm6, ymm1
1 1 0.25 vpaddq ymm3, ymm5, ymm3
1 3 0.50 vpmuludq ymm6, ymm0, ymm7
1 1 0.50 vpsrlq ymm1, ymm1, 32
1 1 0.25 vpaddq ymm1, ymm3, ymm1
1 1 0.25 vpsubq ymm3, ymm0, ymm1
1 1 0.50 vpsrlq ymm3, ymm3, 1
1 1 0.25 vpaddq ymm1, ymm3, ymm1
1 8 0.50 * vpbroadcastq ymm3, qword ptr [rip + .LCPI0_2]
1 3 0.50 vpmuludq ymm5, ymm2, ymm3
1 3 0.50 vpmuludq ymm3, ymm0, ymm3
1 3 0.50 vpmuludq ymm2, ymm2, ymm7
1 1 0.50 vpsrlq ymm3, ymm3, 32
1 1 0.25 vpaddq ymm3, ymm5, ymm3
1 1 0.50 vpsrlq ymm5, ymm3, 32
1 1 0.25 vpblendd ymm3, ymm3, ymm4, 170
1 1 0.25 vpaddq ymm3, ymm6, ymm3
1 1 0.25 vpaddq ymm2, ymm2, ymm5
1 1 0.50 vpsrlq ymm3, ymm3, 32
1 1 0.25 vpaddq ymm2, ymm2, ymm3
1 1 0.25 vpsubq ymm0, ymm0, ymm2
1 1 0.50 vpsrlq ymm0, ymm0, 1
1 1 0.25 vpaddq ymm0, ymm0, ymm2
1 1 0.50 vpsrlq ymm0, ymm0, 6
1 1 0.50 vpsrlq ymm0 {k1}, ymm1, 7
1 5 0.50 U ret
```
```asm
Iterations: 100
Instructions: 2500
Total Cycles: 2710
Total uOps: 2600
Dispatch Width: 6
uOps Per Cycle: 0.96
IPC: 0.92
Block RThroughput: 4.3
Instruction Info:
[1]: #uOps
[2]: Latency
[3]: RThroughput
[4]: MayLoad
[5]: MayStore
[6]: HasSideEffects (U)
[1] [2] [3] [4] [5] [6] Instructions:
1 8 0.50 * vmovdqa64 zmm2, zmmword ptr [rip + .LCPI0_0]
1 1 0.50 vpslld xmm1, xmm1, 31
1 1 1.00 vinserti64x4 zmm0, zmm0, ymm0, 1
1 8 0.50 * vmovdqa64 zmm4, zmmword ptr [rip + .LCPI0_2]
1 1 1.00 vpmovd2m k1, xmm1
1 1 0.50 vpsrlq zmm1, zmm0, 32
1 3 1.00 vpmuludq zmm3, zmm1, zmm2
1 3 1.00 vpmuludq zmm2, zmm0, zmm2
1 3 1.00 vpmuludq zmm5, zmm0, zmm4
1 3 1.00 vpmuludq zmm1, zmm1, zmm4
1 1 0.50 vpsrlq zmm2, zmm2, 32
1 1 0.50 vpaddq zmm2, zmm3, zmm2
1 1 0.50 vpsrlq zmm3, zmm2, 32
1 8 0.50 * vpandq zmm2, zmm2, qword ptr [rip + .LCPI0_1]{1to8}
1 1 0.50 vpaddq zmm1, zmm1, zmm3
1 1 0.50 vpaddq zmm2, zmm5, zmm2
1 1 0.50 vpsrlq zmm2, zmm2, 32
1 1 0.50 vpaddq zmm1, zmm1, zmm2
1 1 0.50 vpsubq zmm0, zmm0, zmm1
1 1 0.50 vpsrlq zmm0, zmm0, 1
1 1 0.50 vpaddq zmm0, zmm0, zmm1
2 8 1.00 * vpsrlvq zmm1, zmm0, zmmword ptr [rip + .LCPI0_3]
1 1 1.00 vextracti64x4 ymm0, zmm1, 1
1 0 0.17 vmovdqa64 ymm0 {k1}, ymm1
1 5 0.50 U ret
```
It should be packaged as a widened constant division, and extract the result based on condition (If the widened division is still legal)
Contributor guide
Research direction
Start with the LLVM IR examples and compare the linked Godbolt and Alive2 results to understand the proposed widened constant division and conditional extraction. Trace the DAG combine or vector-division optimization entry point, then add focused regression coverage showing that the two divisions are packaged when widening is legal and that the generated result remains correct.
Written by the indexing model from the issue text.
Assessment
- Domain
- compilers, performance
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100