Skip to content

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

Description

@xortator

Godbolt repro: https://godbolt.org/z/9YW7ocfr9

Run opt -passes=loop-vectorize on this code:

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:

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> [ <i64 0, i64 1, i64 2, i64 3, i64 4, i64 5, i64 6, i64 7, i64 8, i64 9, i64 10, i64 11, i64 12, i64 13, i64 14, i64 15, i64 16, i64 17, i64 18, i64 19, i64 20, i64 21, i64 22, i64 23, i64 24, i64 25, i64 26, i64 27, i64 28, i64 29, i64 30, i64 31>, %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.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions