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

Philip Reames via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 13 17:15:34 PDT 2022


Author: Philip Reames
Date: 2022-07-13T17:15:07-07:00
New Revision: ddd4ed99445dba17ccffc22a9d74a5448745a466

URL: https://github.com/llvm/llvm-project/commit/ddd4ed99445dba17ccffc22a9d74a5448745a466
DIFF: https://github.com/llvm/llvm-project/commit/ddd4ed99445dba17ccffc22a9d74a5448745a466.diff

LOG: [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.

Added: 
    llvm/test/Transforms/LoopStrengthReduce/RISCV/icmp-zero.ll
    llvm/test/Transforms/LoopStrengthReduce/RISCV/lit.local.cfg

Modified: 
    

Removed: 
    


################################################################################
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 0000000000000..10994ace4a9ae
--- /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 0000000000000..c63820126f8ca
--- /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


        


More information about the llvm-commits mailing list