xref: /llvm-project/llvm/test/Transforms/InstCombine/urem-via-cmp-select.ll (revision 15d5c59280c9943b23a372ca5fdd8a88ce930514)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=instcombine -S | FileCheck %s
3
4; https://alive2.llvm.org/ce/z/5eCiWi
5define i8 @urem_assume(i8 %x, i8 %n) {
6; CHECK-LABEL: @urem_assume(
7; CHECK-NEXT:    [[X_FR:%.*]] = freeze i8 [[X:%.*]]
8; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i8 [[X_FR]], [[N:%.*]]
9; CHECK-NEXT:    tail call void @llvm.assume(i1 [[CMP]])
10; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[X_FR]], 1
11; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i8 [[ADD]], [[N]]
12; CHECK-NEXT:    [[OUT:%.*]] = select i1 [[TMP1]], i8 0, i8 [[ADD]]
13; CHECK-NEXT:    ret i8 [[OUT]]
14;
15  %cmp = icmp ult i8 %x, %n
16  tail call void @llvm.assume(i1 %cmp)
17  %add = add nuw i8 %x, 1
18  %out = urem i8 %add, %n
19  ret i8 %out
20}
21
22; https://alive2.llvm.org/ce/z/MGgtYN
23define i8 @urem_assume_without_nuw(i8 %x, i8 %n) {
24; CHECK-LABEL: @urem_assume_without_nuw(
25; CHECK-NEXT:    [[X_FR:%.*]] = freeze i8 [[X:%.*]]
26; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i8 [[X_FR]], [[N:%.*]]
27; CHECK-NEXT:    tail call void @llvm.assume(i1 [[CMP]])
28; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[X_FR]], 1
29; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i8 [[ADD]], [[N]]
30; CHECK-NEXT:    [[OUT:%.*]] = select i1 [[TMP1]], i8 0, i8 [[ADD]]
31; CHECK-NEXT:    ret i8 [[OUT]]
32;
33  %cmp = icmp ult i8 %x, %n
34  tail call void @llvm.assume(i1 %cmp)
35  %add = add i8 %x, 1
36  %out = urem i8 %add, %n
37  ret i8 %out
38}
39
40; Negative test: The assume is false
41define i8 @urem_assume_eq(i8 %x, i8 %n) {
42; CHECK-LABEL: @urem_assume_eq(
43; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[X:%.*]], [[N:%.*]]
44; CHECK-NEXT:    tail call void @llvm.assume(i1 [[CMP]])
45; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[X]], 1
46; CHECK-NEXT:    [[OUT:%.*]] = urem i8 [[ADD]], [[N]]
47; CHECK-NEXT:    ret i8 [[OUT]]
48;
49  %cmp = icmp eq i8 %x, %n
50  tail call void @llvm.assume(i1 %cmp)
51  %add = add i8 %x, 1
52  %out = urem i8 %add, %n
53  ret i8 %out
54}
55
56; Negative test: The assume is false
57define i8 @urem_assume_ne(i8 %x, i8 %n) {
58; CHECK-LABEL: @urem_assume_ne(
59; CHECK-NEXT:  start:
60; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i8 [[X:%.*]], [[N:%.*]]
61; CHECK-NEXT:    tail call void @llvm.assume(i1 [[CMP]])
62; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[X]], 1
63; CHECK-NEXT:    [[OUT:%.*]] = urem i8 [[ADD]], [[N]]
64; CHECK-NEXT:    ret i8 [[OUT]]
65;
66start:
67  %cmp = icmp ne i8 %x, %n
68  tail call void @llvm.assume(i1 %cmp)
69  %add = add i8 %x, 1
70  %out = urem i8 %add, %n
71  ret i8 %out
72}
73
74; Negative test: The add constant is not 1
75define i8 @urem_assume_with_unexpected_const(i8 %x, i8 %n) {
76; CHECK-LABEL: @urem_assume_with_unexpected_const(
77; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i8 [[X:%.*]], [[N:%.*]]
78; CHECK-NEXT:    tail call void @llvm.assume(i1 [[CMP]])
79; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[X]], 2
80; CHECK-NEXT:    [[OUT:%.*]] = urem i8 [[ADD]], [[N]]
81; CHECK-NEXT:    ret i8 [[OUT]]
82;
83  %cmp = icmp ult i8 %x, %n
84  tail call void @llvm.assume(i1 %cmp)
85  %add = add i8 %x, 2            ; Transform only when the constant is 1
86  %out = urem i8 %add, %n
87  ret i8 %out
88}
89
90; https://alive2.llvm.org/ce/z/gNhZ2x
91define i8 @urem_without_assume(i8 %arg, i8 %arg2) {
92; CHECK-LABEL: @urem_without_assume(
93; CHECK-NEXT:    [[X:%.*]] = urem i8 [[ARG:%.*]], [[ARG2:%.*]]
94; CHECK-NEXT:    [[X_FR:%.*]] = freeze i8 [[X]]
95; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[X_FR]], 1
96; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i8 [[ADD]], [[ARG2]]
97; CHECK-NEXT:    [[OUT:%.*]] = select i1 [[TMP1]], i8 0, i8 [[ADD]]
98; CHECK-NEXT:    ret i8 [[OUT]]
99;
100  %x = urem i8 %arg, %arg2
101  %add = add i8 %x, 1
102  %out = urem i8 %add, %arg2
103  ret i8 %out
104}
105
106; https://alive2.llvm.org/ce/z/eHkgRa
107define i8 @urem_with_dominating_condition(i8 %x, i8 %n) {
108; CHECK-LABEL: @urem_with_dominating_condition(
109; CHECK-NEXT:  start:
110; CHECK-NEXT:    [[X_FR:%.*]] = freeze i8 [[X:%.*]]
111; CHECK-NEXT:    [[COND:%.*]] = icmp ult i8 [[X_FR]], [[N:%.*]]
112; CHECK-NEXT:    br i1 [[COND]], label [[DOTBB0:%.*]], label [[DOTBB1:%.*]]
113; CHECK:       .bb0:
114; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[X_FR]], 1
115; CHECK-NEXT:    [[TMP0:%.*]] = icmp eq i8 [[ADD]], [[N]]
116; CHECK-NEXT:    [[OUT:%.*]] = select i1 [[TMP0]], i8 0, i8 [[ADD]]
117; CHECK-NEXT:    ret i8 [[OUT]]
118; CHECK:       .bb1:
119; CHECK-NEXT:    ret i8 0
120;
121start:
122  %cond = icmp ult i8 %x, %n
123  br i1 %cond, label %.bb0, label %.bb1 ; Should also works for a dominating condition
124.bb0:
125  %add = add i8 %x, 1
126  %out = urem i8 %add, %n
127  ret i8 %out
128.bb1:
129  ret i8 0
130}
131
132; Revert the dominating condition and target branch at the same time.
133define i8 @urem_with_dominating_condition_false(i8 %x, i8 %n) {
134; CHECK-LABEL: @urem_with_dominating_condition_false(
135; CHECK-NEXT:  start:
136; CHECK-NEXT:    [[X_FR:%.*]] = freeze i8 [[X:%.*]]
137; CHECK-NEXT:    [[COND_NOT:%.*]] = icmp ult i8 [[X_FR]], [[N:%.*]]
138; CHECK-NEXT:    br i1 [[COND_NOT]], label [[DOTBB0:%.*]], label [[DOTBB1:%.*]]
139; CHECK:       .bb0:
140; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[X_FR]], 1
141; CHECK-NEXT:    [[TMP0:%.*]] = icmp eq i8 [[ADD]], [[N]]
142; CHECK-NEXT:    [[OUT:%.*]] = select i1 [[TMP0]], i8 0, i8 [[ADD]]
143; CHECK-NEXT:    ret i8 [[OUT]]
144; CHECK:       .bb1:
145; CHECK-NEXT:    ret i8 0
146;
147start:
148  %cond = icmp uge i8 %x, %n
149  br i1 %cond, label %.bb1, label %.bb0 ; Swap the branch targets
150.bb0:
151  %add = add i8 %x, 1
152  %out = urem i8 %add, %n
153  ret i8 %out
154.bb1:
155  ret i8 0
156}
157
158; Negative test
159define noundef i8 @urem_with_opposite_condition(i8 %x, i8 %n) {
160; CHECK-LABEL: @urem_with_opposite_condition(
161; CHECK-NEXT:    [[COND:%.*]] = icmp ult i8 [[X:%.*]], [[N:%.*]]
162; CHECK-NEXT:    br i1 [[COND]], label [[DOTBB1:%.*]], label [[DOTBB0:%.*]]
163; CHECK:       .bb0:
164; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[X]], 1
165; CHECK-NEXT:    [[OUT:%.*]] = urem i8 [[ADD]], [[N]]
166; CHECK-NEXT:    ret i8 [[OUT]]
167; CHECK:       .bb1:
168; CHECK-NEXT:    ret i8 0
169;
170  %cond = icmp ult i8 %x, %n
171  br i1 %cond, label %.bb1, label %.bb0 ; Revert the condition
172.bb0:
173  %add = add i8 %x, 1
174  %out = urem i8 %add, %n
175  ret i8 %out
176.bb1:
177  ret i8 0
178}
179
180declare void @llvm.assume(i1 noundef)
181