Add a version of calculateRegisterUsage that works estimates register usage for a VPlan. This mostly just ports the existing code, with some updates to figure out what recipes will generate vectors vs scalars. There are number of changes in the computed register usages, but they should be more accurate w.r.t. to the generated vector code. There are the following changes: * Scalar usage increases in most cases by 1, as we always create a scalar canonical IV, which is alive across the loop and is not considered by the legacy implementation * Output is ordered by insertion, now scalar registers are added first due the canonical IV phi. * Using the VPlan, we now also more precisely know if an induction will be vectorized or scalarized. Depends on https://github.com/llvm/llvm-project/pull/126415 PR: https://github.com/llvm/llvm-project/pull/126437
58 lines
2.1 KiB
LLVM
58 lines
2.1 KiB
LLVM
; RUN: opt -passes=loop-vectorize -debug-only=loop-vectorize -disable-output -prefer-predicate-over-epilogue=scalar-epilogue 2>&1 < %s | FileCheck %s
|
|
; REQUIRES: asserts
|
|
|
|
target triple = "aarch64"
|
|
|
|
; Test that shows how many registers the loop vectorizer thinks an illegal <VF x i1> will consume.
|
|
|
|
; CHECK-LABEL: LV: Checking a loop in 'or_reduction_neon' from <stdin>
|
|
; CHECK: LV(REG): VF = 32
|
|
; CHECK-NEXT: LV(REG): Found max usage: 2 item
|
|
; CHECK-NEXT: LV(REG): RegisterClass: Generic::ScalarRC, 2 registers
|
|
; CHECK-NEXT: LV(REG): RegisterClass: Generic::VectorRC, 72 registers
|
|
|
|
define i1 @or_reduction_neon(i32 %arg, ptr %ptr) {
|
|
entry:
|
|
br label %loop
|
|
exit:
|
|
ret i1 %reduction_next
|
|
loop:
|
|
%induction = phi i32 [ 0, %entry ], [ %induction_next, %loop ]
|
|
%reduction = phi i1 [ 0, %entry ], [ %reduction_next, %loop ]
|
|
%gep = getelementptr inbounds i32, ptr %ptr, i32 %induction
|
|
%loaded = load i32, ptr %gep
|
|
%i1 = icmp eq i32 %loaded, %induction
|
|
%reduction_next = or i1 %i1, %reduction
|
|
%induction_next = add nuw i32 %induction, 1
|
|
%cond = icmp eq i32 %induction_next, %arg
|
|
br i1 %cond, label %exit, label %loop, !llvm.loop !32
|
|
}
|
|
|
|
; CHECK-LABEL: LV: Checking a loop in 'or_reduction_sve'
|
|
; CHECK: LV(REG): VF = 64
|
|
; CHECK-NEXT: LV(REG): Found max usage: 2 item
|
|
; CHECK-NEXT: LV(REG): RegisterClass: Generic::ScalarRC, 2 registers
|
|
; CHECK-NEXT: LV(REG): RegisterClass: Generic::VectorRC, 136 registers
|
|
|
|
define i1 @or_reduction_sve(i32 %arg, ptr %ptr) vscale_range(2,2) "target-features"="+sve" {
|
|
entry:
|
|
br label %loop
|
|
exit:
|
|
ret i1 %reduction_next
|
|
loop:
|
|
%induction = phi i32 [ 0, %entry ], [ %induction_next, %loop ]
|
|
%reduction = phi i1 [ true, %entry ], [ %reduction_next, %loop ]
|
|
%gep = getelementptr inbounds i32, ptr %ptr, i32 %induction
|
|
%loaded = load i32, ptr %gep
|
|
%i1 = icmp eq i32 %loaded, %induction
|
|
%reduction_next = or i1 %i1, %reduction
|
|
%induction_next = add nuw i32 %induction, 1
|
|
%cond = icmp eq i32 %induction_next, %arg
|
|
br i1 %cond, label %exit, label %loop, !llvm.loop !64
|
|
}
|
|
|
|
!32 = distinct !{!32, !33}
|
|
!33 = !{!"llvm.loop.vectorize.width", i32 32}
|
|
!64 = distinct !{!64, !65}
|
|
!65 = !{!"llvm.loop.vectorize.width", i32 64}
|