1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes=instcombine -S | FileCheck %s
7 define i6 @trunc_lshr(i8 %x) {
8 ; CHECK-LABEL: @trunc_lshr(
9 ; CHECK-NEXT: [[TMP1:%.*]] = trunc i8 [[X:%.*]] to i6
10 ; CHECK-NEXT: [[TMP2:%.*]] = lshr i6 [[TMP1]], 2
11 ; CHECK-NEXT: [[R:%.*]] = and i6 [[TMP2]], 14
12 ; CHECK-NEXT: ret i6 [[R]]
15 %t = trunc i8 %s to i6
20 ; The 'and' is eliminated.
22 define i6 @trunc_lshr_exact_mask(i8 %x) {
23 ; CHECK-LABEL: @trunc_lshr_exact_mask(
24 ; CHECK-NEXT: [[TMP1:%.*]] = trunc i8 [[X:%.*]] to i6
25 ; CHECK-NEXT: [[TMP2:%.*]] = lshr i6 [[TMP1]], 2
26 ; CHECK-NEXT: ret i6 [[TMP2]]
29 %t = trunc i8 %s to i6
34 ; negative test - a high bit of x is in the result
36 define i6 @trunc_lshr_big_mask(i8 %x) {
37 ; CHECK-LABEL: @trunc_lshr_big_mask(
38 ; CHECK-NEXT: [[S:%.*]] = lshr i8 [[X:%.*]], 2
39 ; CHECK-NEXT: [[T:%.*]] = trunc i8 [[S]] to i6
40 ; CHECK-NEXT: [[R:%.*]] = and i6 [[T]], 31
41 ; CHECK-NEXT: ret i6 [[R]]
44 %t = trunc i8 %s to i6
49 ; negative test - too many uses
51 define i6 @trunc_lshr_use1(i8 %x) {
52 ; CHECK-LABEL: @trunc_lshr_use1(
53 ; CHECK-NEXT: [[S:%.*]] = lshr i8 [[X:%.*]], 2
54 ; CHECK-NEXT: call void @use8(i8 [[S]])
55 ; CHECK-NEXT: [[T:%.*]] = trunc i8 [[S]] to i6
56 ; CHECK-NEXT: [[R:%.*]] = and i6 [[T]], 15
57 ; CHECK-NEXT: ret i6 [[R]]
60 call void @use8(i8 %s)
61 %t = trunc i8 %s to i6
66 ; negative test - too many uses
68 define i6 @trunc_lshr_use2(i8 %x) {
69 ; CHECK-LABEL: @trunc_lshr_use2(
70 ; CHECK-NEXT: [[S:%.*]] = lshr i8 [[X:%.*]], 2
71 ; CHECK-NEXT: [[T:%.*]] = trunc i8 [[S]] to i6
72 ; CHECK-NEXT: call void @use6(i6 [[T]])
73 ; CHECK-NEXT: [[R:%.*]] = and i6 [[T]], 15
74 ; CHECK-NEXT: ret i6 [[R]]
77 %t = trunc i8 %s to i6
78 call void @use6(i6 %t)
83 ; Splat vectors are ok.
85 define <2 x i7> @trunc_lshr_vec_splat(<2 x i16> %x) {
86 ; CHECK-LABEL: @trunc_lshr_vec_splat(
87 ; CHECK-NEXT: [[TMP1:%.*]] = trunc <2 x i16> [[X:%.*]] to <2 x i7>
88 ; CHECK-NEXT: [[TMP2:%.*]] = lshr <2 x i7> [[TMP1]], <i7 5, i7 5>
89 ; CHECK-NEXT: [[R:%.*]] = and <2 x i7> [[TMP2]], <i7 1, i7 1>
90 ; CHECK-NEXT: ret <2 x i7> [[R]]
92 %s = lshr <2 x i16> %x, <i16 5, i16 5>
93 %t = trunc <2 x i16> %s to <2 x i7>
94 %r = and <2 x i7> %t, <i7 1, i7 1>
98 ; The 'and' is eliminated.
100 define <2 x i7> @trunc_lshr_vec_splat_exact_mask(<2 x i16> %x) {
101 ; CHECK-LABEL: @trunc_lshr_vec_splat_exact_mask(
102 ; CHECK-NEXT: [[TMP1:%.*]] = trunc <2 x i16> [[X:%.*]] to <2 x i7>
103 ; CHECK-NEXT: [[TMP2:%.*]] = lshr <2 x i7> [[TMP1]], <i7 6, i7 6>
104 ; CHECK-NEXT: ret <2 x i7> [[TMP2]]
106 %s = lshr <2 x i16> %x, <i16 6, i16 6>
107 %t = trunc <2 x i16> %s to <2 x i7>
108 %r = and <2 x i7> %t, <i7 1, i7 1>
112 ; negative test - the shift is too big for the narrow type
114 define <2 x i7> @trunc_lshr_big_shift(<2 x i16> %x) {
115 ; CHECK-LABEL: @trunc_lshr_big_shift(
116 ; CHECK-NEXT: [[S:%.*]] = lshr <2 x i16> [[X:%.*]], <i16 7, i16 7>
117 ; CHECK-NEXT: [[T:%.*]] = trunc <2 x i16> [[S]] to <2 x i7>
118 ; CHECK-NEXT: [[R:%.*]] = and <2 x i7> [[T]], <i7 1, i7 1>
119 ; CHECK-NEXT: ret <2 x i7> [[R]]
121 %s = lshr <2 x i16> %x, <i16 7, i16 7>
122 %t = trunc <2 x i16> %s to <2 x i7>
123 %r = and <2 x i7> %t, <i7 1, i7 1>
127 ; High bits could also be set rather than cleared.
129 define i6 @or_trunc_lshr(i8 %x) {
130 ; CHECK-LABEL: @or_trunc_lshr(
131 ; CHECK-NEXT: [[TMP1:%.*]] = trunc i8 [[X:%.*]] to i6
132 ; CHECK-NEXT: [[TMP2:%.*]] = lshr i6 [[TMP1]], 1
133 ; CHECK-NEXT: [[R:%.*]] = or disjoint i6 [[TMP2]], -32
134 ; CHECK-NEXT: ret i6 [[R]]
137 %t = trunc i8 %s to i6
138 %r = or i6 %t, 32 ; 0b100000
142 define i6 @or_trunc_lshr_more(i8 %x) {
143 ; CHECK-LABEL: @or_trunc_lshr_more(
144 ; CHECK-NEXT: [[TMP1:%.*]] = trunc i8 [[X:%.*]] to i6
145 ; CHECK-NEXT: [[TMP2:%.*]] = lshr i6 [[TMP1]], 4
146 ; CHECK-NEXT: [[R:%.*]] = or disjoint i6 [[TMP2]], -4
147 ; CHECK-NEXT: ret i6 [[R]]
150 %t = trunc i8 %s to i6
151 %r = or i6 %t, 60 ; 0b111100
155 ; negative test - need all high bits to be undemanded
157 define i6 @or_trunc_lshr_small_mask(i8 %x) {
158 ; CHECK-LABEL: @or_trunc_lshr_small_mask(
159 ; CHECK-NEXT: [[S:%.*]] = lshr i8 [[X:%.*]], 4
160 ; CHECK-NEXT: [[T:%.*]] = trunc i8 [[S]] to i6
161 ; CHECK-NEXT: [[R:%.*]] = or i6 [[T]], -8
162 ; CHECK-NEXT: ret i6 [[R]]
165 %t = trunc i8 %s to i6
166 %r = or i6 %t, 56 ; 0b111000