Re-land [openmp] Fix warnings when building on Windows with latest MSVC or Clang...
[llvm-project.git] / llvm / test / Transforms / InstCombine / trunc-demand.ll
blob4f6e79285eaa89bf05729113a911a0cce5a23cf8
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes=instcombine -S | FileCheck %s
4 declare void @use6(i6)
5 declare void @use8(i8)
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]]
14   %s = lshr i8 %x, 2
15   %t = trunc i8 %s to i6
16   %r = and i6 %t, 14
17   ret i6 %r
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]]
28   %s = lshr i8 %x, 2
29   %t = trunc i8 %s to i6
30   %r = and i6 %t, 15
31   ret i6 %r
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]]
43   %s = lshr i8 %x, 2
44   %t = trunc i8 %s to i6
45   %r = and i6 %t, 31
46   ret i6 %r
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]]
59   %s = lshr i8 %x, 2
60   call void @use8(i8 %s)
61   %t = trunc i8 %s to i6
62   %r = and i6 %t, 15
63   ret i6 %r
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]]
76   %s = lshr i8 %x, 2
77   %t = trunc i8 %s to i6
78   call void @use6(i6 %t)
79   %r = and i6 %t, 15
80   ret i6 %r
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>
95   ret <2 x i7> %r
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>
109   ret <2 x i7> %r
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>
124   ret <2 x i7> %r
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]]
136   %s = lshr i8 %x, 1
137   %t = trunc i8 %s to i6
138   %r = or i6 %t, 32 ; 0b100000
139   ret i6 %r
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]]
149   %s = lshr i8 %x, 4
150   %t = trunc i8 %s to i6
151   %r = or i6 %t, 60 ; 0b111100
152   ret i6 %r
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]]
164   %s = lshr i8 %x, 4
165   %t = trunc i8 %s to i6
166   %r = or i6 %t, 56 ; 0b111000
167   ret i6 %r