1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes=instcombine -S | FileCheck %s
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]]
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)
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
34 %pow2_or_zero = and i8 %neg, %x
35 %cmp = icmp slt i8 %pow2_or_zero, 0
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)
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>
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]]
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)
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
90 %pow2_or_zero = and i8 %neg, %x
91 %cmp = icmp sgt i8 %pow2_or_zero, -1
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)
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>
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]]
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