1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -S -instcombine < %s | FileCheck %s
3
4; TODO: The entire thing should be folded to and i16 %0, 255.
5
6define i16 @foo(i16 %x)  {
7; CHECK-LABEL: @foo(
8; CHECK-NEXT:    [[T1:%.*]] = and i16 [[X:%.*]], 255
9; CHECK-NEXT:    ret i16 [[T1]]
10;
11  %t1 = and i16 %x, 255
12  %t2 = zext i16 %t1 to i32
13  %t3 = icmp ult i32 %t2, 255
14  %t4 = select i1 %t3, i32 %t2, i32 255
15  %t5 = trunc i32 %t4 to i16
16  %t6 = and i16 %t5, 255
17  ret i16 %t6
18}
19
20; This contains a min/max pair to clamp a value to 12 bits.
21; By analyzing the clamp pattern, we can tell the add doesn't have signed overflow.
22define i16 @min_max_clamp(i16 %x) {
23; CHECK-LABEL: @min_max_clamp(
24; CHECK-NEXT:    [[A:%.*]] = icmp sgt i16 [[X:%.*]], -2048
25; CHECK-NEXT:    [[B:%.*]] = select i1 [[A]], i16 [[X]], i16 -2048
26; CHECK-NEXT:    [[C:%.*]] = icmp slt i16 [[B]], 2047
27; CHECK-NEXT:    [[D:%.*]] = select i1 [[C]], i16 [[B]], i16 2047
28; CHECK-NEXT:    [[E:%.*]] = add nsw i16 [[D]], 1
29; CHECK-NEXT:    ret i16 [[E]]
30;
31  %a = icmp sgt i16 %x, -2048
32  %b = select i1 %a, i16 %x, i16 -2048
33  %c = icmp slt i16 %b, 2047
34  %d = select i1 %c, i16 %b, i16 2047
35  %e = add i16 %d, 1
36  ret i16 %e
37}
38
39; Same as above with min/max reversed.
40define i16 @min_max_clamp_2(i16 %x) {
41; CHECK-LABEL: @min_max_clamp_2(
42; CHECK-NEXT:    [[A:%.*]] = icmp slt i16 [[X:%.*]], 2047
43; CHECK-NEXT:    [[B:%.*]] = select i1 [[A]], i16 [[X]], i16 2047
44; CHECK-NEXT:    [[C:%.*]] = icmp sgt i16 [[B]], -2048
45; CHECK-NEXT:    [[D:%.*]] = select i1 [[C]], i16 [[B]], i16 -2048
46; CHECK-NEXT:    [[E:%.*]] = add nsw i16 [[D]], 1
47; CHECK-NEXT:    ret i16 [[E]]
48;
49  %a = icmp slt i16 %x, 2047
50  %b = select i1 %a, i16 %x, i16 2047
51  %c = icmp sgt i16 %b, -2048
52  %d = select i1 %c, i16 %b, i16 -2048
53  %e = add i16 %d, 1
54  ret i16 %e
55}
56
57; This contains a min/max pair to clamp a value to 12 bits.
58; By analyzing the clamp pattern, we can tell that the second add doesn't
59; overflow the original type and can be moved before the extend.
60define i32 @min_max_clamp_3(i16 %x) {
61; CHECK-LABEL: @min_max_clamp_3(
62; CHECK-NEXT:    [[A:%.*]] = icmp sgt i16 [[X:%.*]], -2048
63; CHECK-NEXT:    [[B:%.*]] = select i1 [[A]], i16 [[X]], i16 -2048
64; CHECK-NEXT:    [[C:%.*]] = icmp slt i16 [[B]], 2047
65; CHECK-NEXT:    [[D:%.*]] = select i1 [[C]], i16 [[B]], i16 2047
66; CHECK-NEXT:    [[G:%.*]] = sext i16 [[D]] to i32
67; CHECK-NEXT:    ret i32 [[G]]
68;
69  %a = icmp sgt i16 %x, -2048
70  %b = select i1 %a, i16 %x, i16 -2048
71  %c = icmp slt i16 %b, 2047
72  %d = select i1 %c, i16 %b, i16 2047
73  %e = add i16 %d, 1
74  %f = sext i16 %e to i32
75  %g = add i32 %f, -1
76  ret i32 %g
77}
78
79; Same as above with min/max order reversed
80define i32 @min_max_clamp_4(i16 %x) {
81; CHECK-LABEL: @min_max_clamp_4(
82; CHECK-NEXT:    [[A:%.*]] = icmp slt i16 [[X:%.*]], 2047
83; CHECK-NEXT:    [[B:%.*]] = select i1 [[A]], i16 [[X]], i16 2047
84; CHECK-NEXT:    [[C:%.*]] = icmp sgt i16 [[B]], -2048
85; CHECK-NEXT:    [[D:%.*]] = select i1 [[C]], i16 [[B]], i16 -2048
86; CHECK-NEXT:    [[G:%.*]] = sext i16 [[D]] to i32
87; CHECK-NEXT:    ret i32 [[G]]
88;
89  %a = icmp slt i16 %x, 2047
90  %b = select i1 %a, i16 %x, i16 2047
91  %c = icmp sgt i16 %b, -2048
92  %d = select i1 %c, i16 %b, i16 -2048
93  %e = add i16 %d, 1
94  %f = sext i16 %e to i32
95  %g = add i32 %f, -1
96  ret i32 %g
97}
98