• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -instcombine -instcombine-infinite-loop-threshold=2 -S | FileCheck %s
3
4; These xor-of-icmps could be replaced with and-of-icmps, but %cond0 has extra
5; uses, so we don't consider it, even though some cases are freely invertible.
6
7; %cond0 is extra-used in select, which is freely invertible.
8define i1 @v0_select_of_consts(i32 %X, i32* %selected) {
9; CHECK-LABEL: @v0_select_of_consts(
10; CHECK-NEXT:    [[COND0_INV:%.*]] = icmp sgt i32 [[X:%.*]], 32767
11; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND0_INV]], i32 32767, i32 -32768
12; CHECK-NEXT:    store i32 [[SELECT]], i32* [[SELECTED:%.*]], align 4
13; CHECK-NEXT:    [[X_OFF:%.*]] = add i32 [[X]], 32767
14; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 [[X_OFF]], 65535
15; CHECK-NEXT:    ret i1 [[TMP1]]
16;
17  %cond0 = icmp sgt i32 %X, 32767
18  %cond1 = icmp sgt i32 %X, -32768
19  %select = select i1 %cond0, i32 32767, i32 -32768
20  store i32 %select, i32* %selected
21  %res = xor i1 %cond0, %cond1
22  ret i1 %res
23}
24define i1 @v1_select_of_var_and_const(i32 %X, i32 %Y, i32* %selected) {
25; CHECK-LABEL: @v1_select_of_var_and_const(
26; CHECK-NEXT:    [[COND0:%.*]] = icmp slt i32 [[X:%.*]], 32768
27; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND0]], i32 -32768, i32 [[Y:%.*]]
28; CHECK-NEXT:    store i32 [[SELECT]], i32* [[SELECTED:%.*]], align 4
29; CHECK-NEXT:    [[X_OFF:%.*]] = add i32 [[X]], 32767
30; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 [[X_OFF]], 65535
31; CHECK-NEXT:    ret i1 [[TMP1]]
32;
33  %cond0 = icmp sgt i32 %X, 32767
34  %cond1 = icmp sgt i32 %X, -32768
35  %select = select i1 %cond0, i32 %Y, i32 -32768
36  store i32 %select, i32* %selected
37  %res = xor i1 %cond0, %cond1
38  ret i1 %res
39}
40define i1 @v2_select_of_const_and_var(i32 %X, i32 %Y, i32* %selected) {
41; CHECK-LABEL: @v2_select_of_const_and_var(
42; CHECK-NEXT:    [[COND0_INV:%.*]] = icmp sgt i32 [[X:%.*]], 32767
43; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND0_INV]], i32 32767, i32 [[Y:%.*]]
44; CHECK-NEXT:    store i32 [[SELECT]], i32* [[SELECTED:%.*]], align 4
45; CHECK-NEXT:    [[X_OFF:%.*]] = add i32 [[X]], 32767
46; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 [[X_OFF]], 65535
47; CHECK-NEXT:    ret i1 [[TMP1]]
48;
49  %cond0 = icmp sgt i32 %X, 32767
50  %cond1 = icmp sgt i32 %X, -32768
51  %select = select i1 %cond0, i32 32767, i32 %Y
52  store i32 %select, i32* %selected
53  %res = xor i1 %cond0, %cond1
54  ret i1 %res
55}
56
57; Branch is also freely invertible
58define i1 @v3_branch(i32 %X, i32* %dst0, i32* %dst1) {
59; CHECK-LABEL: @v3_branch(
60; CHECK-NEXT:  begin:
61; CHECK-NEXT:    [[COND0:%.*]] = icmp slt i32 [[X:%.*]], 32768
62; CHECK-NEXT:    br i1 [[COND0]], label [[BB1:%.*]], label [[BB0:%.*]]
63; CHECK:       bb0:
64; CHECK-NEXT:    store i32 0, i32* [[DST0:%.*]], align 4
65; CHECK-NEXT:    br label [[END:%.*]]
66; CHECK:       bb1:
67; CHECK-NEXT:    store i32 0, i32* [[DST1:%.*]], align 4
68; CHECK-NEXT:    br label [[END]]
69; CHECK:       end:
70; CHECK-NEXT:    [[X_OFF:%.*]] = add i32 [[X]], 32767
71; CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i32 [[X_OFF]], 65535
72; CHECK-NEXT:    ret i1 [[TMP0]]
73;
74begin:
75  %cond0 = icmp sgt i32 %X, 32767
76  %cond1 = icmp sgt i32 %X, -32768
77  br i1 %cond0, label %bb0, label %bb1
78bb0:
79  store i32 0, i32* %dst0
80  br label %end
81bb1:
82  store i32 0, i32* %dst1
83  br label %end
84end:
85  %res = xor i1 %cond0, %cond1
86  ret i1 %res
87}
88
89; Can invert 'not'.
90define i1 @v4_not_store(i32 %X, i1* %not_cond) {
91; CHECK-LABEL: @v4_not_store(
92; CHECK-NEXT:    [[COND0:%.*]] = icmp slt i32 [[X:%.*]], 32768
93; CHECK-NEXT:    store i1 [[COND0]], i1* [[NOT_COND:%.*]], align 1
94; CHECK-NEXT:    [[X_OFF:%.*]] = add i32 [[X]], 32767
95; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 [[X_OFF]], 65535
96; CHECK-NEXT:    ret i1 [[TMP1]]
97;
98  %cond0 = icmp sgt i32 %X, 32767
99  %not_cond0 = xor i1 %cond0, -1
100  store i1 %not_cond0, i1* %not_cond
101  %cond1 = icmp sgt i32 %X, -32768
102  %select = select i1 %cond0, i32 32767, i32 -32768
103  %res = xor i1 %cond0, %cond1
104  ret i1 %res
105}
106
107; All extra uses are invertible.
108define i1 @v5_select_and_not(i32 %X, i32 %Y, i32* %selected, i1* %not_cond) {
109; CHECK-LABEL: @v5_select_and_not(
110; CHECK-NEXT:    [[COND0:%.*]] = icmp slt i32 [[X:%.*]], 32768
111; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND0]], i32 [[Y:%.*]], i32 32767
112; CHECK-NEXT:    store i1 [[COND0]], i1* [[NOT_COND:%.*]], align 1
113; CHECK-NEXT:    store i32 [[SELECT]], i32* [[SELECTED:%.*]], align 4
114; CHECK-NEXT:    [[X_OFF:%.*]] = add i32 [[X]], 32767
115; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 [[X_OFF]], 65535
116; CHECK-NEXT:    ret i1 [[TMP1]]
117;
118  %cond0 = icmp sgt i32 %X, 32767
119  %cond1 = icmp sgt i32 %X, -32768
120  %select = select i1 %cond0, i32 32767, i32 %Y
121  %not_cond0 = xor i1 %cond0, -1
122  store i1 %not_cond0, i1* %not_cond
123  store i32 %select, i32* %selected
124  %res = xor i1 %cond0, %cond1
125  ret i1 %res
126}
127
128; Not all extra uses are invertible.
129define i1 @n6_select_and_not(i32 %X, i32 %Y, i32* %selected, i1* %not_cond) {
130; CHECK-LABEL: @n6_select_and_not(
131; CHECK-NEXT:    [[COND0:%.*]] = icmp sgt i32 [[X:%.*]], 32767
132; CHECK-NEXT:    [[COND1:%.*]] = icmp sgt i32 [[X]], -32768
133; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND0]], i32 32767, i32 [[Y:%.*]]
134; CHECK-NEXT:    store i1 [[COND0]], i1* [[NOT_COND:%.*]], align 1
135; CHECK-NEXT:    store i32 [[SELECT]], i32* [[SELECTED:%.*]], align 4
136; CHECK-NEXT:    [[RES:%.*]] = xor i1 [[COND0]], [[COND1]]
137; CHECK-NEXT:    ret i1 [[RES]]
138;
139  %cond0 = icmp sgt i32 %X, 32767
140  %cond1 = icmp sgt i32 %X, -32768
141  %select = select i1 %cond0, i32 32767, i32 %Y
142  store i1 %cond0, i1* %not_cond
143  store i32 %select, i32* %selected
144  %res = xor i1 %cond0, %cond1
145  ret i1 %res
146}
147
148; Not freely invertible, would require extra 'not' instruction.
149define i1 @n7_store(i32 %X, i1* %cond) {
150; CHECK-LABEL: @n7_store(
151; CHECK-NEXT:    [[COND0:%.*]] = icmp sgt i32 [[X:%.*]], 32767
152; CHECK-NEXT:    store i1 [[COND0]], i1* [[COND:%.*]], align 1
153; CHECK-NEXT:    [[COND1:%.*]] = icmp sgt i32 [[X]], -32768
154; CHECK-NEXT:    [[RES:%.*]] = xor i1 [[COND0]], [[COND1]]
155; CHECK-NEXT:    ret i1 [[RES]]
156;
157  %cond0 = icmp sgt i32 %X, 32767
158  store i1 %cond0, i1* %cond
159  %cond1 = icmp sgt i32 %X, -32768
160  %select = select i1 %cond0, i32 32767, i32 -32768
161  %res = xor i1 %cond0, %cond1
162  ret i1 %res
163}
164