llvm / llvm/llvm-project

LoopVectorizer generates type <32 x i64> on AVX, looks unexpected and leads to bad codegen

Open
#208,202 0 comments 0 reactions 0 assignees View on GitHub
vectorizers
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.