[AArch64][NFC] NFC for const vector as Instruction operand (#116790)
[llvm-project.git] / llvm / test / Transforms / InstCombine / fold-signbit-test-power2.ll
blobbe02eb6dd334633372ab292ea5cf12624adbdeb2
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes=instcombine -S | FileCheck %s
4 declare void @use(i8)
5 declare void @use_i1(i1)
6 declare void @use_i1_vec(<2 x i1>)
8 ; (X & -X) < 0 --> X == MinSignC
9 ; (X & X) > -1 --> X != MinSignC
11 define i1 @pow2_or_zero_is_negative(i8 %x) {
12 ; CHECK-LABEL: @pow2_or_zero_is_negative(
13 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[X:%.*]], -128
14 ; CHECK-NEXT:    [[CMP_2:%.*]] = icmp eq i8 [[X]], -128
15 ; CHECK-NEXT:    call void @use_i1(i1 [[CMP_2]])
16 ; CHECK-NEXT:    ret i1 [[CMP]]
18   %neg = sub i8 0, %x
19   %pow2_or_zero = and i8 %x, %neg
20   %cmp = icmp slt i8 %pow2_or_zero, 0
21   %cmp.2 = icmp ugt i8 %pow2_or_zero, 127
22   call void @use_i1(i1 %cmp.2)
23   ret i1 %cmp
26 define i1 @pow2_or_zero_is_negative_commute(i8 %A) {
27 ; CHECK-LABEL: @pow2_or_zero_is_negative_commute(
28 ; CHECK-NEXT:    [[X:%.*]] = mul i8 [[A:%.*]], 42
29 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[X]], -128
30 ; CHECK-NEXT:    ret i1 [[CMP]]
32   %x = mul i8 42, %A ; thwart complexity-based canonicalization
33   %neg = sub i8 0, %x
34   %pow2_or_zero = and i8 %neg, %x
35   %cmp = icmp slt i8 %pow2_or_zero, 0
36   ret i1 %cmp
39 define <2 x i1> @pow2_or_zero_is_negative_vec(<2 x i8> %x) {
40 ; CHECK-LABEL: @pow2_or_zero_is_negative_vec(
41 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq <2 x i8> [[X:%.*]], splat (i8 -128)
42 ; CHECK-NEXT:    [[CMP_2:%.*]] = icmp eq <2 x i8> [[X]], splat (i8 -128)
43 ; CHECK-NEXT:    call void @use_i1_vec(<2 x i1> [[CMP_2]])
44 ; CHECK-NEXT:    ret <2 x i1> [[CMP]]
46   %neg = sub <2 x i8> <i8 0, i8 0>, %x
47   %pow2_or_zero = and <2 x i8> %x, %neg
48   %cmp = icmp slt <2 x i8> %pow2_or_zero, <i8 0, i8 0>
49   %cmp.2 = icmp ugt <2 x i8> %pow2_or_zero, <i8 127, i8 127>
50   call void @use_i1_vec(<2 x i1> %cmp.2)
51   ret <2 x i1> %cmp
54 define <2 x i1> @pow2_or_zero_is_negative_vec_commute(<2 x i8> %A) {
55 ; CHECK-LABEL: @pow2_or_zero_is_negative_vec_commute(
56 ; CHECK-NEXT:    [[X:%.*]] = mul <2 x i8> [[A:%.*]], splat (i8 42)
57 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq <2 x i8> [[X]], splat (i8 -128)
58 ; CHECK-NEXT:    ret <2 x i1> [[CMP]]
60   %x = mul <2 x i8> <i8 42, i8 42>, %A ; thwart complexity-based canonicalization
61   %neg = sub <2 x i8> <i8 0, i8 0>, %x
62   %pow2_or_zero = and <2 x i8> %neg, %x
63   %cmp = icmp slt <2 x i8> %pow2_or_zero, <i8 0, i8 0>
64   ret <2 x i1> %cmp
67 define i1 @pow2_or_zero_is_not_negative(i8 %x) {
68 ; CHECK-LABEL: @pow2_or_zero_is_not_negative(
69 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i8 [[X:%.*]], -128
70 ; CHECK-NEXT:    [[CMP_2:%.*]] = icmp ne i8 [[X]], -128
71 ; CHECK-NEXT:    call void @use_i1(i1 [[CMP_2]])
72 ; CHECK-NEXT:    ret i1 [[CMP]]
74   %neg = sub i8 0, %x
75   %pow2_or_zero = and i8 %x, %neg
76   %cmp = icmp sgt i8 %pow2_or_zero, -1
77   %cmp.2 = icmp ult i8 %pow2_or_zero, -128
78   call void @use_i1(i1 %cmp.2)
79   ret i1 %cmp
82 define i1 @pow2_or_zero_is_not_negative_commute(i8 %A) {
83 ; CHECK-LABEL: @pow2_or_zero_is_not_negative_commute(
84 ; CHECK-NEXT:    [[X:%.*]] = mul i8 [[A:%.*]], 42
85 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i8 [[X]], -128
86 ; CHECK-NEXT:    ret i1 [[CMP]]
88   %x = mul i8 42, %A ; thwart complexity-based canonicalization
89   %neg = sub i8 0, %x
90   %pow2_or_zero = and i8 %neg, %x
91   %cmp = icmp sgt i8 %pow2_or_zero, -1
92   ret i1 %cmp
95 define <2 x i1> @pow2_or_zero_is_not_negative_vec(<2 x i8> %x) {
96 ; CHECK-LABEL: @pow2_or_zero_is_not_negative_vec(
97 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ne <2 x i8> [[X:%.*]], splat (i8 -128)
98 ; CHECK-NEXT:    [[CMP_2:%.*]] = icmp ne <2 x i8> [[X]], splat (i8 -128)
99 ; CHECK-NEXT:    call void @use_i1_vec(<2 x i1> [[CMP_2]])
100 ; CHECK-NEXT:    ret <2 x i1> [[CMP]]
102   %neg = sub <2 x i8> <i8 0, i8 0>, %x
103   %pow2_or_zero = and <2 x i8> %x, %neg
104   %cmp = icmp sgt <2 x i8> %pow2_or_zero, <i8 -1, i8 -1>
105   %cmp.2 = icmp ult <2 x i8> %pow2_or_zero, <i8 -128, i8 -128>
106   call void @use_i1_vec(<2 x i1> %cmp.2)
107   ret <2 x i1> %cmp
110 define <2 x i1> @pow2_or_zero_is_not_negative_vec_commute(<2 x i8> %A) {
111 ; CHECK-LABEL: @pow2_or_zero_is_not_negative_vec_commute(
112 ; CHECK-NEXT:    [[X:%.*]] = mul <2 x i8> [[A:%.*]], splat (i8 42)
113 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ne <2 x i8> [[X]], splat (i8 -128)
114 ; CHECK-NEXT:    ret <2 x i1> [[CMP]]
116   %x = mul <2 x i8> <i8 42, i8 42>, %A ; thwart complexity-based canonicalization
117   %neg = sub <2 x i8> <i8 0, i8 0>, %x
118   %pow2_or_zero = and <2 x i8> %neg, %x
119   %cmp = icmp sgt <2 x i8> %pow2_or_zero, <i8 -1, i8 -1>
120   ret <2 x i1> %cmp
123 define i1 @pow2_or_zero_is_negative_extra_use(i8 %x) {
124 ; CHECK-LABEL: @pow2_or_zero_is_negative_extra_use(
125 ; CHECK-NEXT:    [[NEG:%.*]] = sub i8 0, [[X:%.*]]
126 ; CHECK-NEXT:    call void @use(i8 [[NEG]])
127 ; CHECK-NEXT:    [[POW2_OR_ZERO:%.*]] = and i8 [[X]], [[NEG]]
128 ; CHECK-NEXT:    call void @use(i8 [[POW2_OR_ZERO]])
129 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[X]], -128
130 ; CHECK-NEXT:    ret i1 [[CMP]]
132   %neg = sub i8 0, %x
133   call void @use(i8 %neg)
134   %pow2_or_zero = and i8 %x, %neg
135   call void @use(i8 %pow2_or_zero)
136   %cmp = icmp slt i8 %pow2_or_zero, 0
137   ret i1 %cmp