Skip to content

[LoopUnroll][RISCV] Crash when unrolling loop containing vector instructions #83294

Closed
@frasercrmck

Description

@frasercrmck

When optimizing for RISC-V without the vector extension enabled, the RISCVTargetTransformInfo returns an invalid cost and the loop unroller asserts.

This is happening on both tip (64422cf) and on LLVM 18.1.0 RC4 (461274b).

; RUN: opt -mattr=+f,+d -S --passes=loop-unroll-full -S -disable-output
target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128"
target triple = "riscv64-unknown-unknown-elf"

define void @foo() {
entry:
  br label %for.body

for.body:                                         ; preds = %for.body, %entry
  %indvars.iv1 = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %entry ]
  %0 = load float, ptr null, align 4
  %splat.splat.i.i.i = shufflevector <2 x float> zeroinitializer, <2 x float> zeroinitializer, <2 x i32> zeroinitializer
  %cmp1.i.i.i = fcmp ogt <2 x float> zeroinitializer, zeroinitializer
  %splat.splat3.i.i.i = shufflevector <2 x i32> zeroinitializer, <2 x i32> zeroinitializer, <2 x i32> zeroinitializer
  %xor3.i.i.i.i.i = select <2 x i1> zeroinitializer, <2 x i32> zeroinitializer, <2 x i32> zeroinitializer
  %1 = load float, ptr null, align 4
  %splat.splat8.i.i.i = shufflevector <2 x float> zeroinitializer, <2 x float> zeroinitializer, <2 x i32> zeroinitializer
  %sub.i.i.i = fsub <2 x float> zeroinitializer, zeroinitializer
  %mul.i.i.i = shl i64 0, 0
  %2 = load float, ptr null, align 4
  %splat.splat.i.i.i.i = shufflevector <2 x float> zeroinitializer, <2 x float> zeroinitializer, <2 x i32> zeroinitializer
  %xor3.i.i.i.v.i.i = select <2 x i1> zeroinitializer, <2 x float> zeroinitializer, <2 x float> zeroinitializer
  %indvars.iv.next = add i64 %indvars.iv1, 1
  %exitcond = icmp ne i64 %indvars.iv1, 8
  br i1 %exitcond, label %for.body, label %exit

exit:                                             ; preds = %for.body
  ret void
}

Should show:

opt: /llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp:680: std::optional<EstimatedUnrollCost> analyzeLoopUnrollCost(const llvm::Loop *, unsigned int, llvm::DominatorTree &, llvm::ScalarEvolution &, const SmallPtrSetImpl<const llvm::Value *> &, const llvm::TargetTransformInfo &, unsigned int, unsigned int): Assertion `UnrolledCost.isValid() && RolledDynamicCost.isValid() && "All instructions must have a valid cost, whether the " "loop is rolled or unrolled."' failed.

This is a regression against LLVM 17, which reports (with the same input but with --debug):

Loop Unroll: F[foo] Loop %for.body
  Loop Size = Invalid
  Not unrolling loop which contains instructions with invalid cost.

I've been away from LLVM for a while so don't know if this is a failure in the RISCV cost model or an overly restrictive loop unroller.

It looks like with LLVM 17, the CodeSize costs were deemed to be Invalid by the UnrollCostEstimator, so the unroller exited early. Now since LLVM 18 they are no longer Invalid so the unroller tries to calculate profitability in analyzeLoopUnrollCost which can't handle Invalid costs and asserts.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Status

    Done

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions