aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Reames <preames@rivosinc.com>2022-07-13 17:12:48 -0700
committerPhilip Reames <listmail@philipreames.com>2022-07-13 17:15:07 -0700
commitddd4ed99445dba17ccffc22a9d74a5448745a466 (patch)
tree24fa2aaabf2b2b87e086a2b78a5acb40f1d4a885
parent6f7347b888a475a20451863b5142c455d2b0450b (diff)
downloadllvm-ddd4ed99445dba17ccffc22a9d74a5448745a466.zip
llvm-ddd4ed99445dba17ccffc22a9d74a5448745a466.tar.gz
llvm-ddd4ed99445dba17ccffc22a9d74a5448745a466.tar.bz2
[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.
-rw-r--r--llvm/test/Transforms/LoopStrengthReduce/RISCV/icmp-zero.ll188
-rw-r--r--llvm/test/Transforms/LoopStrengthReduce/RISCV/lit.local.cfg2
2 files changed, 190 insertions, 0 deletions
diff --git a/llvm/test/Transforms/LoopStrengthReduce/RISCV/icmp-zero.ll b/llvm/test/Transforms/LoopStrengthReduce/RISCV/icmp-zero.ll
new file mode 100644
index 0000000..10994ac
--- /dev/null
+++ b/llvm/test/Transforms/LoopStrengthReduce/RISCV/icmp-zero.ll
@@ -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()
diff --git a/llvm/test/Transforms/LoopStrengthReduce/RISCV/lit.local.cfg b/llvm/test/Transforms/LoopStrengthReduce/RISCV/lit.local.cfg
new file mode 100644
index 0000000..c638201
--- /dev/null
+++ b/llvm/test/Transforms/LoopStrengthReduce/RISCV/lit.local.cfg
@@ -0,0 +1,2 @@
+if not 'RISCV' in config.root.targets:
+ config.unsupported = True