forked from OSchip/llvm-project
[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:
parent
6f7347b888
commit
ddd4ed9944
|
@ -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()
|
|
@ -0,0 +1,2 @@
|
|||
if not 'RISCV' in config.root.targets:
|
||||
config.unsupported = True
|
Loading…
Reference in New Issue