[LSR] Add test coverage for ICmpZero cases involving urem RHS

For the moment, we're pretty conservative here.  My motivating case is the vscale one (as that is idiomatic for scalable vectorized loops on RISCV).  There are two obvious approaches to fixing this, and I tried to add reasonable coverage for both even though I'll likely only fix one.
This commit is contained in:
Philip Reames 2022-07-13 17:12:48 -07:00 committed by Philip Reames
parent 6f7347b888
commit ddd4ed9944
2 changed files with 190 additions and 0 deletions

View File

@ -0,0 +1,188 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -loop-reduce -S | FileCheck %s
target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n64-S128"
target triple = "riscv64"
define void @icmp_zero(i64 %N, ptr %p) {
; CHECK-LABEL: @icmp_zero(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]
; CHECK: vector.body:
; CHECK-NEXT: [[LSR_IV:%.*]] = phi i64 [ [[LSR_IV_NEXT:%.*]], [[VECTOR_BODY]] ], [ [[N:%.*]], [[ENTRY:%.*]] ]
; CHECK-NEXT: store i64 0, ptr [[P:%.*]], align 8
; CHECK-NEXT: [[LSR_IV_NEXT]] = add i64 [[LSR_IV]], -2
; CHECK-NEXT: [[DONE:%.*]] = icmp eq i64 [[LSR_IV_NEXT]], 0
; CHECK-NEXT: br i1 [[DONE]], label [[EXIT:%.*]], label [[VECTOR_BODY]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
entry:
br label %vector.body
vector.body:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %vector.body ]
store i64 0, ptr %p
%iv.next = add i64 %iv, 2
%done = icmp eq i64 %iv.next, %N
br i1 %done, label %exit, label %vector.body
exit:
ret void
}
define void @icmp_zero_urem_nonzero_con(i64 %N, ptr %p) {
; CHECK-LABEL: @icmp_zero_urem_nonzero_con(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[UREM:%.*]] = urem i64 [[N:%.*]], 16
; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]
; CHECK: vector.body:
; CHECK-NEXT: [[LSR_IV:%.*]] = phi i64 [ [[LSR_IV_NEXT:%.*]], [[VECTOR_BODY]] ], [ [[UREM]], [[ENTRY:%.*]] ]
; CHECK-NEXT: store i64 0, ptr [[P:%.*]], align 8
; CHECK-NEXT: [[LSR_IV_NEXT]] = add i64 [[LSR_IV]], -2
; CHECK-NEXT: [[DONE:%.*]] = icmp eq i64 [[LSR_IV_NEXT]], 0
; CHECK-NEXT: br i1 [[DONE]], label [[EXIT:%.*]], label [[VECTOR_BODY]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
entry:
%urem = urem i64 %N, 16
br label %vector.body
vector.body:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %vector.body ]
store i64 0, ptr %p
%iv.next = add i64 %iv, 2
%done = icmp eq i64 %iv.next, %urem
br i1 %done, label %exit, label %vector.body
exit:
ret void
}
; FIXME: We could handle this case even though we don't know %M. The
; faulting instruction is already outside the loop!
define void @icmp_zero_urem_invariant(i64 %N, i64 %M, ptr %p) {
; CHECK-LABEL: @icmp_zero_urem_invariant(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[UREM:%.*]] = urem i64 [[N:%.*]], [[M:%.*]]
; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]
; CHECK: vector.body:
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[VECTOR_BODY]] ]
; CHECK-NEXT: store i64 0, ptr [[P:%.*]], align 8
; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 2
; CHECK-NEXT: [[DONE:%.*]] = icmp eq i64 [[IV_NEXT]], [[UREM]]
; CHECK-NEXT: br i1 [[DONE]], label [[EXIT:%.*]], label [[VECTOR_BODY]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
entry:
%urem = urem i64 %N, %M
br label %vector.body
vector.body:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %vector.body ]
store i64 0, ptr %p
%iv.next = add i64 %iv, 2
%done = icmp eq i64 %iv.next, %urem
br i1 %done, label %exit, label %vector.body
exit:
ret void
}
; Negative test - We can not hoist because we don't know value of %M.
define void @icmp_zero_urem_nohoist(i64 %N, i64 %M, ptr %p) {
; CHECK-LABEL: @icmp_zero_urem_nohoist(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]
; CHECK: vector.body:
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[VECTOR_BODY]] ]
; CHECK-NEXT: store i64 0, ptr [[P:%.*]], align 8
; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 2
; CHECK-NEXT: [[UREM:%.*]] = urem i64 [[N:%.*]], [[M:%.*]]
; CHECK-NEXT: [[DONE:%.*]] = icmp eq i64 [[IV_NEXT]], [[UREM]]
; CHECK-NEXT: br i1 [[DONE]], label [[EXIT:%.*]], label [[VECTOR_BODY]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
entry:
br label %vector.body
vector.body:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %vector.body ]
store i64 0, ptr %p
%iv.next = add i64 %iv, 2
%urem = urem i64 %N, %M
%done = icmp eq i64 %iv.next, %urem
br i1 %done, label %exit, label %vector.body
exit:
ret void
}
define void @icmp_zero_urem_nonzero(i64 %N, i64 %M, ptr %p) {
; CHECK-LABEL: @icmp_zero_urem_nonzero(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[NONZERO:%.*]] = add nuw i64 [[M:%.*]], 1
; CHECK-NEXT: [[UREM:%.*]] = urem i64 [[N:%.*]], [[NONZERO]]
; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]
; CHECK: vector.body:
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[VECTOR_BODY]] ]
; CHECK-NEXT: store i64 0, ptr [[P:%.*]], align 8
; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 2
; CHECK-NEXT: [[DONE:%.*]] = icmp eq i64 [[IV_NEXT]], [[UREM]]
; CHECK-NEXT: br i1 [[DONE]], label [[EXIT:%.*]], label [[VECTOR_BODY]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
entry:
%nonzero = add nuw i64 %M, 1
%urem = urem i64 %N, %nonzero
br label %vector.body
vector.body:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %vector.body ]
store i64 0, ptr %p
%iv.next = add i64 %iv, 2
%done = icmp eq i64 %iv.next, %urem
br i1 %done, label %exit, label %vector.body
exit:
ret void
}
; FIXME: We can hoist this because vscale is never equal to zero
define void @icmp_zero_urem_vscale(i64 %N, ptr %p) {
; CHECK-LABEL: @icmp_zero_urem_vscale(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[VSCALE:%.*]] = call i64 @llvm.vscale.i64()
; CHECK-NEXT: [[UREM:%.*]] = urem i64 [[N:%.*]], [[VSCALE]]
; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]
; CHECK: vector.body:
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[VECTOR_BODY]] ]
; CHECK-NEXT: store i64 0, ptr [[P:%.*]], align 8
; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 2
; CHECK-NEXT: [[DONE:%.*]] = icmp eq i64 [[IV_NEXT]], [[UREM]]
; CHECK-NEXT: br i1 [[DONE]], label [[EXIT:%.*]], label [[VECTOR_BODY]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
entry:
%vscale = call i64 @llvm.vscale.i64()
%urem = urem i64 %N, %vscale
br label %vector.body
vector.body:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %vector.body ]
store i64 0, ptr %p
%iv.next = add i64 %iv, 2
%done = icmp eq i64 %iv.next, %urem
br i1 %done, label %exit, label %vector.body
exit:
ret void
}
declare i64 @llvm.vscale.i64()

View File

@ -0,0 +1,2 @@
if not 'RISCV' in config.root.targets:
config.unsupported = True