LoopVectorizer generates type <32 x i64> on AVX, looks unexpected and leads to bad codegen
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
Godbolt repro: https://godbolt.org/z/9YW7ocfr9
Run `opt -passes=loop-vectorize` on this code:
```llvm
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128-pu1:64:64-pu2:32:32-p3:64:64-p4:32:32"
target triple = "x86_64-unknown-linux"
define void @test() #0 {
bb:
br label %bb1
bb1: ; preds = %bb2, %bb
%phi = phi i64 [ %add, %bb2 ], [ 0, %bb ]
%add = add i64 %phi, 1
%and = and i64 %phi, 1
%uitofp = uitofp i64 %and to float
%fcmp = fcmp ule float %uitofp, 1.000000e+00
br i1 %fcmp, label %bb2, label %bb4
bb2: ; preds = %bb1
%icmp = icmp ugt i64 %phi, 97566
br i1 %icmp, label %bb3, label %bb1
bb3: ; preds = %bb2
ret void
bb4: ; preds = %bb1
ret void
}
attributes #0 = { "target-features"="+avx" }
```
It ends up producing this:
```llvm
define void @test() #0 {
bb:
br label %vector.ph
vector.ph:
br label %vector.body
vector.body:
%index = phi i64 [ 0, %vector.ph ], [ %index.next, %vector.body.interim ]
%vec.ind = phi <32 x i64> [ , %vector.ph ], [ %vec.ind.next, %vector.body.interim ]
%0 = and <32 x i64> %vec.ind, splat (i64 1)
%1 = uitofp <32 x i64> %0 to <32 x float>
%2 = fcmp ogt <32 x float> %1, splat (float 1.000000e+00)
%3 = freeze <32 x i1> %2
%4 = call i1 @llvm.vector.reduce.or.v32i1(<32 x i1> %3)
%index.next = add nuw i64 %index, 32
%5 = icmp eq i64 %index.next, 97568
%vec.ind.next = add <32 x i64> %vec.ind, splat (i64 32)
br i1 %4, label %vector.early.exit, label %vector.body.interim
vector.body.interim:
br i1 %5, label %middle.block, label %vector.body
middle.block:
br label %bb3
vector.early.exit:
br label %bb4
bb3:
ret void
bb4:
ret void
}
declare i1 @llvm.vector.reduce.or.v32i1(<32 x i1>) #1
attributes #0 = { "target-features"="+avx" }
attributes #1 = { nocallback nocreateundeforpoison nofree nosync nounwind speculatable willreturn memory(none) }
```
Type `<32 x i64>` doesn't have a hardware support. llc can generate legal code, but we see that it is doing weird things in the original example. In spite of loads/stores, it would never generate anything wider than available register. So I think this behavior is unexpected. If it is, please explain why.
Contributor guide
Research direction
Start by running the provided LLVM IR through opt -passes=loop-vectorize and then llc, and compare the generated <32 x i64> vector and machine code with the Godbolt reproduction. Trace the LoopVectorizer decision that selects the vector width and determine whether the observed width and code generation are expected. Done means the behavior is explained and, if confirmed incorrect, covered by an appropriate LLVM regression test.
Written by the indexing model from the issue text.
Assessment
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100