xref: /llvm-project/llvm/test/Transforms/InstCombine/fold-signbit-test-power2.ll (revision 38fffa630ee80163dc65e759392ad29798905679)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=instcombine -S | FileCheck %s
3
4declare void @use(i8)
5declare void @use_i1(i1)
6declare void @use_i1_vec(<2 x i1>)
7
8; (X & -X) < 0 --> X == MinSignC
9; (X & X) > -1 --> X != MinSignC
10
11define 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]]
17;
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
24}
25
26define 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]]
31;
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
37}
38
39define <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]]
45;
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
52}
53
54define <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]]
59;
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
65}
66
67define 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]]
73;
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
80}
81
82define 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]]
87;
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
93}
94
95define <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]]
101;
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
108}
109
110define <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]]
115;
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
121}
122
123define 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]]
131;
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
138}
139