From ddd4ed99445dba17ccffc22a9d74a5448745a466 Mon Sep 17 00:00:00 2001 From: Philip Reames Date: Wed, 13 Jul 2022 17:12:48 -0700 Subject: [PATCH] [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. --- .../LoopStrengthReduce/RISCV/icmp-zero.ll | 188 +++++++++++++++++++++ .../LoopStrengthReduce/RISCV/lit.local.cfg | 2 + 2 files changed, 190 insertions(+) create mode 100644 llvm/test/Transforms/LoopStrengthReduce/RISCV/icmp-zero.ll create mode 100644 llvm/test/Transforms/LoopStrengthReduce/RISCV/lit.local.cfg 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 -- 2.7.4