[llvm] r345541 - [InstSimplify] add tests for abs/nabs+icmp folding; NFC

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Mon Oct 29 14:05:41 PDT 2018


Author: spatel
Date: Mon Oct 29 14:05:41 2018
New Revision: 345541

URL: http://llvm.org/viewvc/llvm-project?rev=345541&view=rev
Log:
[InstSimplify] add tests for abs/nabs+icmp folding; NFC

Added:
    llvm/trunk/test/Transforms/InstSimplify/icmp-abs-nabs.ll

Added: llvm/trunk/test/Transforms/InstSimplify/icmp-abs-nabs.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/icmp-abs-nabs.ll?rev=345541&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/icmp-abs-nabs.ll (added)
+++ llvm/trunk/test/Transforms/InstSimplify/icmp-abs-nabs.ll Mon Oct 29 14:05:41 2018
@@ -0,0 +1,401 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -instsimplify -S | FileCheck %s
+
+; This is canonical form for this IR.
+
+define i1 @abs_nsw_is_positive(i32 %x) {
+; CHECK-LABEL: @abs_nsw_is_positive(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 0
+; CHECK-NEXT:    [[NEGX:%.*]] = sub nsw i32 0, [[X]]
+; CHECK-NEXT:    [[ABS:%.*]] = select i1 [[CMP]], i32 [[NEGX]], i32 [[X]]
+; CHECK-NEXT:    [[R:%.*]] = icmp sgt i32 [[ABS]], -1
+; CHECK-NEXT:    ret i1 [[R]]
+;
+  %cmp = icmp slt i32 %x, 0
+  %negx = sub nsw i32 0, %x
+  %abs = select i1 %cmp, i32 %negx, i32 %x
+  %r = icmp sgt i32 %abs, -1
+  ret i1 %r
+}
+
+; Test non-canonical predicate and non-canonical form of abs().
+
+define i1 @abs_nsw_is_positive_sge(i32 %x) {
+; CHECK-LABEL: @abs_nsw_is_positive_sge(
+; CHECK-NEXT:    ret i1 true
+;
+  %cmp = icmp slt i32 %x, 1
+  %negx = sub nsw i32 0, %x
+  %abs = select i1 %cmp, i32 %negx, i32 %x
+  %r = icmp sge i32 %abs, 0
+  ret i1 %r
+}
+
+; This is a range-based analysis. Any negative constant works.
+
+define i1 @abs_nsw_is_positive_reduced_range(i32 %x) {
+; CHECK-LABEL: @abs_nsw_is_positive_reduced_range(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 0
+; CHECK-NEXT:    [[NEGX:%.*]] = sub nsw i32 0, [[X]]
+; CHECK-NEXT:    [[ABS:%.*]] = select i1 [[CMP]], i32 [[NEGX]], i32 [[X]]
+; CHECK-NEXT:    [[R:%.*]] = icmp sgt i32 [[ABS]], -42
+; CHECK-NEXT:    ret i1 [[R]]
+;
+  %cmp = icmp slt i32 %x, 0
+  %negx = sub nsw i32 0, %x
+  %abs = select i1 %cmp, i32 %negx, i32 %x
+  %r = icmp sgt i32 %abs, -42
+  ret i1 %r
+}
+
+; Negative test - we need 'nsw' in the abs().
+
+define i1 @abs_is_positive_reduced_range(i32 %x) {
+; CHECK-LABEL: @abs_is_positive_reduced_range(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 0
+; CHECK-NEXT:    [[NEGX:%.*]] = sub i32 0, [[X]]
+; CHECK-NEXT:    [[ABS:%.*]] = select i1 [[CMP]], i32 [[NEGX]], i32 [[X]]
+; CHECK-NEXT:    [[R:%.*]] = icmp sgt i32 [[ABS]], 42
+; CHECK-NEXT:    ret i1 [[R]]
+;
+  %cmp = icmp slt i32 %x, 0
+  %negx = sub i32 0, %x
+  %abs = select i1 %cmp, i32 %negx, i32 %x
+  %r = icmp sgt i32 %abs, 42
+  ret i1 %r
+}
+
+; Negative test - range intersection is not subset.
+
+define i1 @abs_nsw_is_positive_wrong_range(i32 %x) {
+; CHECK-LABEL: @abs_nsw_is_positive_wrong_range(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 0
+; CHECK-NEXT:    [[NEGX:%.*]] = sub nsw i32 0, [[X]]
+; CHECK-NEXT:    [[ABS:%.*]] = select i1 [[CMP]], i32 [[NEGX]], i32 [[X]]
+; CHECK-NEXT:    [[R:%.*]] = icmp sgt i32 [[ABS]], 0
+; CHECK-NEXT:    ret i1 [[R]]
+;
+  %cmp = icmp slt i32 %x, 0
+  %negx = sub nsw i32 0, %x
+  %abs = select i1 %cmp, i32 %negx, i32 %x
+  %r = icmp sgt i32 %abs, 0
+  ret i1 %r
+}
+
+; This is canonical form for this IR.
+
+define i1 @abs_nsw_is_not_negative(i32 %x) {
+; CHECK-LABEL: @abs_nsw_is_not_negative(
+; CHECK-NEXT:    ret i1 false
+;
+  %cmp = icmp slt i32 %x, 0
+  %negx = sub nsw i32 0, %x
+  %abs = select i1 %cmp, i32 %negx, i32 %x
+  %r = icmp slt i32 %abs, 0
+  ret i1 %r
+}
+
+; Test non-canonical predicate and non-canonical form of abs().
+
+define i1 @abs_nsw_is_not_negative_sle(i32 %x) {
+; CHECK-LABEL: @abs_nsw_is_not_negative_sle(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 1
+; CHECK-NEXT:    [[NEGX:%.*]] = sub nsw i32 0, [[X]]
+; CHECK-NEXT:    [[ABS:%.*]] = select i1 [[CMP]], i32 [[NEGX]], i32 [[X]]
+; CHECK-NEXT:    [[R:%.*]] = icmp sle i32 [[ABS]], -1
+; CHECK-NEXT:    ret i1 [[R]]
+;
+  %cmp = icmp slt i32 %x, 1
+  %negx = sub nsw i32 0, %x
+  %abs = select i1 %cmp, i32 %negx, i32 %x
+  %r = icmp sle i32 %abs, -1
+  ret i1 %r
+}
+
+; This is a range-based analysis. Any negative constant works.
+
+define i1 @abs_nsw_is_not_negative_reduced_range(i32 %x) {
+; CHECK-LABEL: @abs_nsw_is_not_negative_reduced_range(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 0
+; CHECK-NEXT:    [[NEGX:%.*]] = sub nsw i32 0, [[X]]
+; CHECK-NEXT:    [[ABS:%.*]] = select i1 [[CMP]], i32 [[NEGX]], i32 [[X]]
+; CHECK-NEXT:    [[R:%.*]] = icmp slt i32 [[ABS]], -24
+; CHECK-NEXT:    ret i1 [[R]]
+;
+  %cmp = icmp slt i32 %x, 0
+  %negx = sub nsw i32 0, %x
+  %abs = select i1 %cmp, i32 %negx, i32 %x
+  %r = icmp slt i32 %abs, -24
+  ret i1 %r
+}
+
+; Negative test - we need 'nsw' in the abs().
+
+define i1 @abs_is_not_negative_reduced_range(i32 %x) {
+; CHECK-LABEL: @abs_is_not_negative_reduced_range(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 0
+; CHECK-NEXT:    [[NEGX:%.*]] = sub i32 0, [[X]]
+; CHECK-NEXT:    [[ABS:%.*]] = select i1 [[CMP]], i32 [[NEGX]], i32 [[X]]
+; CHECK-NEXT:    [[R:%.*]] = icmp slt i32 [[ABS]], 42
+; CHECK-NEXT:    ret i1 [[R]]
+;
+  %cmp = icmp slt i32 %x, 0
+  %negx = sub i32 0, %x
+  %abs = select i1 %cmp, i32 %negx, i32 %x
+  %r = icmp slt i32 %abs, 42
+  ret i1 %r
+}
+
+; Negative test - range intersection is not empty.
+
+define i1 @abs_nsw_is_not_negative_wrong_range(i32 %x) {
+; CHECK-LABEL: @abs_nsw_is_not_negative_wrong_range(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 0
+; CHECK-NEXT:    [[NEGX:%.*]] = sub nsw i32 0, [[X]]
+; CHECK-NEXT:    [[ABS:%.*]] = select i1 [[CMP]], i32 [[NEGX]], i32 [[X]]
+; CHECK-NEXT:    [[R:%.*]] = icmp sle i32 [[ABS]], 0
+; CHECK-NEXT:    ret i1 [[R]]
+;
+  %cmp = icmp slt i32 %x, 0
+  %negx = sub nsw i32 0, %x
+  %abs = select i1 %cmp, i32 %negx, i32 %x
+  %r = icmp sle i32 %abs, 0
+  ret i1 %r
+}
+
+; This is canonical form for this IR. For nabs(), we don't require 'nsw'
+
+define i1 @nabs_is_negative_or_0(i32 %x) {
+; CHECK-LABEL: @nabs_is_negative_or_0(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 0
+; CHECK-NEXT:    [[NEGX:%.*]] = sub i32 0, [[X]]
+; CHECK-NEXT:    [[NABS:%.*]] = select i1 [[CMP]], i32 [[X]], i32 [[NEGX]]
+; CHECK-NEXT:    [[R:%.*]] = icmp slt i32 [[NABS]], 1
+; CHECK-NEXT:    ret i1 [[R]]
+;
+  %cmp = icmp slt i32 %x, 0
+  %negx = sub i32 0, %x
+  %nabs = select i1 %cmp, i32 %x, i32 %negx
+  %r = icmp slt i32 %nabs, 1
+  ret i1 %r
+}
+
+; Test non-canonical predicate and non-canonical form of nabs().
+
+define i1 @nabs_is_negative_or_0_sle(i32 %x) {
+; CHECK-LABEL: @nabs_is_negative_or_0_sle(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 1
+; CHECK-NEXT:    [[NEGX:%.*]] = sub i32 0, [[X]]
+; CHECK-NEXT:    [[NABS:%.*]] = select i1 [[CMP]], i32 [[X]], i32 [[NEGX]]
+; CHECK-NEXT:    [[R:%.*]] = icmp sle i32 [[NABS]], 0
+; CHECK-NEXT:    ret i1 [[R]]
+;
+  %cmp = icmp slt i32 %x, 1
+  %negx = sub i32 0, %x
+  %nabs = select i1 %cmp, i32 %x, i32 %negx
+  %r = icmp sle i32 %nabs, 0
+  ret i1 %r
+}
+
+; This is a range-based analysis. Any positive constant works.
+
+define i1 @nabs_is_negative_or_0_reduced_range(i32 %x) {
+; CHECK-LABEL: @nabs_is_negative_or_0_reduced_range(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 1
+; CHECK-NEXT:    [[NEGX:%.*]] = sub i32 0, [[X]]
+; CHECK-NEXT:    [[NABS:%.*]] = select i1 [[CMP]], i32 [[X]], i32 [[NEGX]]
+; CHECK-NEXT:    [[R:%.*]] = icmp slt i32 [[NABS]], 421
+; CHECK-NEXT:    ret i1 [[R]]
+;
+  %cmp = icmp slt i32 %x, 1
+  %negx = sub i32 0, %x
+  %nabs = select i1 %cmp, i32 %x, i32 %negx
+  %r = icmp slt i32 %nabs, 421
+  ret i1 %r
+}
+
+; Negative test - range intersection is not subset.
+
+define i1 @nabs_is_negative_or_0_wrong_range(i32 %x) {
+; CHECK-LABEL: @nabs_is_negative_or_0_wrong_range(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 1
+; CHECK-NEXT:    [[NEGX:%.*]] = sub i32 0, [[X]]
+; CHECK-NEXT:    [[NABS:%.*]] = select i1 [[CMP]], i32 [[X]], i32 [[NEGX]]
+; CHECK-NEXT:    [[R:%.*]] = icmp slt i32 [[NABS]], 0
+; CHECK-NEXT:    ret i1 [[R]]
+;
+  %cmp = icmp slt i32 %x, 1
+  %negx = sub i32 0, %x
+  %nabs = select i1 %cmp, i32 %x, i32 %negx
+  %r = icmp slt i32 %nabs, 0
+  ret i1 %r
+}
+
+; This is canonical form for this IR. For nabs(), we don't require 'nsw'
+
+define i1 @nabs_is_not_over_0(i32 %x) {
+; CHECK-LABEL: @nabs_is_not_over_0(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 0
+; CHECK-NEXT:    [[NEGX:%.*]] = sub i32 0, [[X]]
+; CHECK-NEXT:    [[NABS:%.*]] = select i1 [[CMP]], i32 [[X]], i32 [[NEGX]]
+; CHECK-NEXT:    [[R:%.*]] = icmp sgt i32 [[NABS]], 0
+; CHECK-NEXT:    ret i1 [[R]]
+;
+  %cmp = icmp slt i32 %x, 0
+  %negx = sub i32 0, %x
+  %nabs = select i1 %cmp, i32 %x, i32 %negx
+  %r = icmp sgt i32 %nabs, 0
+  ret i1 %r
+}
+
+; Test non-canonical predicate and non-canonical form of nabs().
+
+define i1 @nabs_is_not_over_0_sle(i32 %x) {
+; CHECK-LABEL: @nabs_is_not_over_0_sle(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 1
+; CHECK-NEXT:    [[NEGX:%.*]] = sub i32 0, [[X]]
+; CHECK-NEXT:    [[NABS:%.*]] = select i1 [[CMP]], i32 [[X]], i32 [[NEGX]]
+; CHECK-NEXT:    [[R:%.*]] = icmp sge i32 [[NABS]], 1
+; CHECK-NEXT:    ret i1 [[R]]
+;
+  %cmp = icmp slt i32 %x, 1
+  %negx = sub i32 0, %x
+  %nabs = select i1 %cmp, i32 %x, i32 %negx
+  %r = icmp sge i32 %nabs, 1
+  ret i1 %r
+}
+
+; This is a range-based analysis. Any positive constant works.
+
+define i1 @nabs_is_not_over_0_reduced_range(i32 %x) {
+; CHECK-LABEL: @nabs_is_not_over_0_reduced_range(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 1
+; CHECK-NEXT:    [[NEGX:%.*]] = sub i32 0, [[X]]
+; CHECK-NEXT:    [[NABS:%.*]] = select i1 [[CMP]], i32 [[X]], i32 [[NEGX]]
+; CHECK-NEXT:    [[R:%.*]] = icmp sgt i32 [[NABS]], 4223
+; CHECK-NEXT:    ret i1 [[R]]
+;
+  %cmp = icmp slt i32 %x, 1
+  %negx = sub i32 0, %x
+  %nabs = select i1 %cmp, i32 %x, i32 %negx
+  %r = icmp sgt i32 %nabs, 4223
+  ret i1 %r
+}
+
+; Negative test - range intersection is not subset.
+
+define i1 @nabs_is_not_over_0_wrong_range(i32 %x) {
+; CHECK-LABEL: @nabs_is_not_over_0_wrong_range(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 1
+; CHECK-NEXT:    [[NEGX:%.*]] = sub i32 0, [[X]]
+; CHECK-NEXT:    [[NABS:%.*]] = select i1 [[CMP]], i32 [[X]], i32 [[NEGX]]
+; CHECK-NEXT:    [[R:%.*]] = icmp sgt i32 [[NABS]], -1
+; CHECK-NEXT:    ret i1 [[R]]
+;
+  %cmp = icmp slt i32 %x, 1
+  %negx = sub i32 0, %x
+  %nabs = select i1 %cmp, i32 %x, i32 %negx
+  %r = icmp sgt i32 %nabs, -1
+  ret i1 %r
+}
+
+; More miscellaneous tests for predicates/types.
+
+; Equality predicates are ok.
+
+define i1 @abs_nsw_is_positive_eq(i32 %x) {
+; CHECK-LABEL: @abs_nsw_is_positive_eq(
+; CHECK-NEXT:    ret i1 false
+;
+  %cmp = icmp slt i32 %x, 1
+  %negx = sub nsw i32 0, %x
+  %abs = select i1 %cmp, i32 %negx, i32 %x
+  %r = icmp eq i32 %abs, -8
+  ret i1 %r
+}
+
+; An unsigned compare may work.
+
+define i1 @abs_nsw_is_positive_ult(i8 %x) {
+; CHECK-LABEL: @abs_nsw_is_positive_ult(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i8 [[X:%.*]], 0
+; CHECK-NEXT:    [[NEGX:%.*]] = sub nsw i8 0, [[X]]
+; CHECK-NEXT:    [[ABS:%.*]] = select i1 [[CMP]], i8 [[NEGX]], i8 [[X]]
+; CHECK-NEXT:    [[R:%.*]] = icmp ult i8 [[ABS]], -117
+; CHECK-NEXT:    ret i1 [[R]]
+;
+  %cmp = icmp slt i8 %x, 0
+  %negx = sub nsw i8 0, %x
+  %abs = select i1 %cmp, i8 %negx, i8 %x
+  %r = icmp ult i8 %abs, 139
+  ret i1 %r
+}
+
+; An unsigned compare may work.
+
+define i1 @abs_nsw_is_not_negative_ugt(i8 %x) {
+; CHECK-LABEL: @abs_nsw_is_not_negative_ugt(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i8 [[X:%.*]], 0
+; CHECK-NEXT:    [[NEGX:%.*]] = sub nsw i8 0, [[X]]
+; CHECK-NEXT:    [[ABS:%.*]] = select i1 [[CMP]], i8 [[NEGX]], i8 [[X]]
+; CHECK-NEXT:    [[R:%.*]] = icmp ugt i8 [[ABS]], 127
+; CHECK-NEXT:    ret i1 [[R]]
+;
+  %cmp = icmp slt i8 %x, 0
+  %negx = sub nsw i8 0, %x
+  %abs = select i1 %cmp, i8 %negx, i8 %x
+  %r = icmp ugt i8 %abs, 127
+  ret i1 %r
+}
+
+; Vector types are ok.
+
+define <2 x i1> @abs_nsw_is_not_negative_vec_splat(<2 x i32> %x) {
+; CHECK-LABEL: @abs_nsw_is_not_negative_vec_splat(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt <2 x i32> [[X:%.*]], zeroinitializer
+; CHECK-NEXT:    [[NEGX:%.*]] = sub nsw <2 x i32> zeroinitializer, [[X]]
+; CHECK-NEXT:    [[ABS:%.*]] = select <2 x i1> [[CMP]], <2 x i32> [[NEGX]], <2 x i32> [[X]]
+; CHECK-NEXT:    [[R:%.*]] = icmp slt <2 x i32> [[ABS]], <i32 -8, i32 -8>
+; CHECK-NEXT:    ret <2 x i1> [[R]]
+;
+  %cmp = icmp slt <2 x i32> %x, zeroinitializer
+  %negx = sub nsw <2 x i32> zeroinitializer, %x
+  %abs = select <2 x i1> %cmp, <2 x i32> %negx, <2 x i32> %x
+  %r = icmp slt <2 x i32> %abs, <i32 -8, i32 -8>
+  ret <2 x i1> %r
+}
+
+; Equality predicates are ok.
+
+define i1 @nabs_is_negative_or_0_ne(i8 %x) {
+; CHECK-LABEL: @nabs_is_negative_or_0_ne(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i8 [[X:%.*]], 0
+; CHECK-NEXT:    [[NEGX:%.*]] = sub i8 0, [[X]]
+; CHECK-NEXT:    [[NABS:%.*]] = select i1 [[CMP]], i8 [[X]], i8 [[NEGX]]
+; CHECK-NEXT:    [[R:%.*]] = icmp ne i8 [[NABS]], 12
+; CHECK-NEXT:    ret i1 [[R]]
+;
+  %cmp = icmp slt i8 %x, 0
+  %negx = sub i8 0, %x
+  %nabs = select i1 %cmp, i8 %x, i8 %negx
+  %r = icmp ne i8 %nabs, 12
+  ret i1 %r
+}
+
+; Vector types are ok.
+
+define <3 x i1> @nabs_is_not_over_0_sle_vec_splat(<3 x i33> %x) {
+; CHECK-LABEL: @nabs_is_not_over_0_sle_vec_splat(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt <3 x i33> [[X:%.*]], <i33 1, i33 1, i33 1>
+; CHECK-NEXT:    [[NEGX:%.*]] = sub <3 x i33> zeroinitializer, [[X]]
+; CHECK-NEXT:    [[NABS:%.*]] = select <3 x i1> [[CMP]], <3 x i33> [[X]], <3 x i33> [[NEGX]]
+; CHECK-NEXT:    [[R:%.*]] = icmp sge <3 x i33> [[NABS]], <i33 1, i33 1, i33 1>
+; CHECK-NEXT:    ret <3 x i1> [[R]]
+;
+  %cmp = icmp slt <3 x i33> %x, <i33 1, i33 1, i33 1>
+  %negx = sub <3 x i33> zeroinitializer, %x
+  %nabs = select <3 x i1> %cmp, <3 x i33> %x, <3 x i33> %negx
+  %r = icmp sge <3 x i33> %nabs, <i33 1, i33 1, i33 1>
+  ret <3 x i1> %r
+}
+




More information about the llvm-commits mailing list