• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -instcombine -S | FileCheck %s
3
4; Fold
5;   ((%x * %y) u/ %x) != %y
6; to
7;   @llvm.umul.with.overflow(%x, %y) + extractvalue
8
9define i1 @t0_basic(i8 %x, i8 %y) {
10; CHECK-LABEL: @t0_basic(
11; CHECK-NEXT:    [[UMUL:%.*]] = call { i8, i1 } @llvm.umul.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
12; CHECK-NEXT:    [[UMUL_OV:%.*]] = extractvalue { i8, i1 } [[UMUL]], 1
13; CHECK-NEXT:    ret i1 [[UMUL_OV]]
14;
15  %t0 = mul i8 %x, %y
16  %t1 = udiv i8 %t0, %x
17  %r = icmp ne i8 %t1, %y
18  ret i1 %r
19}
20
21define <2 x i1> @t1_vec(<2 x i8> %x, <2 x i8> %y) {
22; CHECK-LABEL: @t1_vec(
23; CHECK-NEXT:    [[UMUL:%.*]] = call { <2 x i8>, <2 x i1> } @llvm.umul.with.overflow.v2i8(<2 x i8> [[X:%.*]], <2 x i8> [[Y:%.*]])
24; CHECK-NEXT:    [[UMUL_OV:%.*]] = extractvalue { <2 x i8>, <2 x i1> } [[UMUL]], 1
25; CHECK-NEXT:    ret <2 x i1> [[UMUL_OV]]
26;
27  %t0 = mul <2 x i8> %x, %y
28  %t1 = udiv <2 x i8> %t0, %x
29  %r = icmp ne <2 x i8> %t1, %y
30  ret <2 x i1> %r
31}
32
33declare i8 @gen8()
34
35define i1 @t2_commutative(i8 %x) {
36; CHECK-LABEL: @t2_commutative(
37; CHECK-NEXT:    [[Y:%.*]] = call i8 @gen8()
38; CHECK-NEXT:    [[UMUL:%.*]] = call { i8, i1 } @llvm.umul.with.overflow.i8(i8 [[X:%.*]], i8 [[Y]])
39; CHECK-NEXT:    [[UMUL_OV:%.*]] = extractvalue { i8, i1 } [[UMUL]], 1
40; CHECK-NEXT:    ret i1 [[UMUL_OV]]
41;
42  %y = call i8 @gen8()
43  %t0 = mul i8 %y, %x ; swapped
44  %t1 = udiv i8 %t0, %x
45  %r = icmp ne i8 %t1, %y
46  ret i1 %r
47}
48
49define i1 @t3_commutative(i8 %x) {
50; CHECK-LABEL: @t3_commutative(
51; CHECK-NEXT:    [[Y:%.*]] = call i8 @gen8()
52; CHECK-NEXT:    [[UMUL:%.*]] = call { i8, i1 } @llvm.umul.with.overflow.i8(i8 [[X:%.*]], i8 [[Y]])
53; CHECK-NEXT:    [[UMUL_OV:%.*]] = extractvalue { i8, i1 } [[UMUL]], 1
54; CHECK-NEXT:    ret i1 [[UMUL_OV]]
55;
56  %y = call i8 @gen8()
57  %t0 = mul i8 %y, %x ; swapped
58  %t1 = udiv i8 %t0, %x
59  %r = icmp ne i8 %t1, %y
60  ret i1 %r
61}
62
63define i1 @t4_commutative(i8 %x) {
64; CHECK-LABEL: @t4_commutative(
65; CHECK-NEXT:    [[Y:%.*]] = call i8 @gen8()
66; CHECK-NEXT:    [[UMUL:%.*]] = call { i8, i1 } @llvm.umul.with.overflow.i8(i8 [[X:%.*]], i8 [[Y]])
67; CHECK-NEXT:    [[UMUL_OV:%.*]] = extractvalue { i8, i1 } [[UMUL]], 1
68; CHECK-NEXT:    ret i1 [[UMUL_OV]]
69;
70  %y = call i8 @gen8()
71  %t0 = mul i8 %y, %x ; swapped
72  %t1 = udiv i8 %t0, %x
73  %r = icmp ne i8 %y, %t1 ; swapped
74  ret i1 %r
75}
76
77; Extra-use tests
78
79declare void @use8(i8)
80
81define i1 @t5_extrause0(i8 %x, i8 %y) {
82; CHECK-LABEL: @t5_extrause0(
83; CHECK-NEXT:    [[UMUL:%.*]] = call { i8, i1 } @llvm.umul.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
84; CHECK-NEXT:    [[UMUL_VAL:%.*]] = extractvalue { i8, i1 } [[UMUL]], 0
85; CHECK-NEXT:    [[UMUL_OV:%.*]] = extractvalue { i8, i1 } [[UMUL]], 1
86; CHECK-NEXT:    call void @use8(i8 [[UMUL_VAL]])
87; CHECK-NEXT:    ret i1 [[UMUL_OV]]
88;
89  %t0 = mul i8 %x, %y
90  call void @use8(i8 %t0)
91  %t1 = udiv i8 %t0, %x
92  %r = icmp ne i8 %t1, %y
93  ret i1 %r
94}
95
96define i1 @t6_extrause1(i8 %x, i8 %y) {
97; CHECK-LABEL: @t6_extrause1(
98; CHECK-NEXT:    [[T0:%.*]] = mul i8 [[X:%.*]], [[Y:%.*]]
99; CHECK-NEXT:    [[T1:%.*]] = udiv i8 [[T0]], [[X]]
100; CHECK-NEXT:    call void @use8(i8 [[T1]])
101; CHECK-NEXT:    [[R:%.*]] = icmp ne i8 [[T1]], [[Y]]
102; CHECK-NEXT:    ret i1 [[R]]
103;
104  %t0 = mul i8 %x, %y
105  %t1 = udiv i8 %t0, %x
106  call void @use8(i8 %t1)
107  %r = icmp ne i8 %t1, %y
108  ret i1 %r
109}
110
111define i1 @t7_extrause2(i8 %x, i8 %y) {
112; CHECK-LABEL: @t7_extrause2(
113; CHECK-NEXT:    [[T0:%.*]] = mul i8 [[X:%.*]], [[Y:%.*]]
114; CHECK-NEXT:    call void @use8(i8 [[T0]])
115; CHECK-NEXT:    [[T1:%.*]] = udiv i8 [[T0]], [[X]]
116; CHECK-NEXT:    call void @use8(i8 [[T1]])
117; CHECK-NEXT:    [[R:%.*]] = icmp ne i8 [[T1]], [[Y]]
118; CHECK-NEXT:    ret i1 [[R]]
119;
120  %t0 = mul i8 %x, %y
121  call void @use8(i8 %t0)
122  %t1 = udiv i8 %t0, %x
123  call void @use8(i8 %t1)
124  %r = icmp ne i8 %t1, %y
125  ret i1 %r
126}
127
128; Negative tests
129
130define i1 @n8_different_x(i8 %x0, i8 %x1, i8 %y) {
131; CHECK-LABEL: @n8_different_x(
132; CHECK-NEXT:    [[T0:%.*]] = mul i8 [[X0:%.*]], [[Y:%.*]]
133; CHECK-NEXT:    [[T1:%.*]] = udiv i8 [[T0]], [[X1:%.*]]
134; CHECK-NEXT:    [[R:%.*]] = icmp ne i8 [[T1]], [[Y]]
135; CHECK-NEXT:    ret i1 [[R]]
136;
137  %t0 = mul i8 %x0, %y
138  %t1 = udiv i8 %t0, %x1
139  %r = icmp ne i8 %t1, %y
140  ret i1 %r
141}
142
143define i1 @n9_different_y(i8 %x, i8 %y0, i8 %y1) {
144; CHECK-LABEL: @n9_different_y(
145; CHECK-NEXT:    [[T0:%.*]] = mul i8 [[X:%.*]], [[Y0:%.*]]
146; CHECK-NEXT:    [[T1:%.*]] = udiv i8 [[T0]], [[X]]
147; CHECK-NEXT:    [[R:%.*]] = icmp ne i8 [[T1]], [[Y1:%.*]]
148; CHECK-NEXT:    ret i1 [[R]]
149;
150  %t0 = mul i8 %x, %y0
151  %t1 = udiv i8 %t0, %x
152  %r = icmp ne i8 %t1, %y1
153  ret i1 %r
154}
155
156define i1 @n10_wrong_pred(i8 %x, i8 %y) {
157; CHECK-LABEL: @n10_wrong_pred(
158; CHECK-NEXT:    [[T0:%.*]] = mul i8 [[X:%.*]], [[Y:%.*]]
159; CHECK-NEXT:    [[T1:%.*]] = udiv i8 [[T0]], [[X]]
160; CHECK-NEXT:    [[R:%.*]] = icmp ugt i8 [[T1]], [[Y]]
161; CHECK-NEXT:    ret i1 [[R]]
162;
163  %t0 = mul i8 %x, %y
164  %t1 = udiv i8 %t0, %x
165  %r = icmp ugt i8 %t1, %y
166  ret i1 %r
167}
168