[FastISel][AArch64] Optimize compare-and-branch for i1 to use 'tbz'.
[oota-llvm.git] / test / CodeGen / AArch64 / bitfield.ll
1 ; RUN: llc -verify-machineinstrs < %s -mtriple=aarch64-none-linux-gnu | FileCheck %s --check-prefix=CHECK
2
3 @var32 = global i32 0
4 @var64 = global i64 0
5
6 define void @test_extendb(i8 %var) {
7 ; CHECK-LABEL: test_extendb:
8
9   %sxt32 = sext i8 %var to i32
10   store volatile i32 %sxt32, i32* @var32
11 ; CHECK: sxtb {{w[0-9]+}}, {{w[0-9]+}}
12
13   %sxt64 = sext i8 %var to i64
14   store volatile i64 %sxt64, i64* @var64
15 ; CHECK: sxtb {{x[0-9]+}}, {{w[0-9]+}}
16
17 ; N.b. this doesn't actually produce a bitfield instruction at the
18 ; moment, but it's still a good test to have and the semantics are
19 ; correct.
20   %uxt32 = zext i8 %var to i32
21   store volatile i32 %uxt32, i32* @var32
22 ; CHECK: and {{w[0-9]+}}, {{w[0-9]+}}, #0xff
23
24   %uxt64 = zext i8 %var to i64
25   store volatile i64 %uxt64, i64* @var64
26 ; CHECK: and {{x[0-9]+}}, {{x[0-9]+}}, #0xff
27   ret void
28 }
29
30 define void @test_extendh(i16 %var) {
31 ; CHECK-LABEL: test_extendh:
32
33   %sxt32 = sext i16 %var to i32
34   store volatile i32 %sxt32, i32* @var32
35 ; CHECK: sxth {{w[0-9]+}}, {{w[0-9]+}}
36
37   %sxt64 = sext i16 %var to i64
38   store volatile i64 %sxt64, i64* @var64
39 ; CHECK: sxth {{x[0-9]+}}, {{w[0-9]+}}
40
41 ; N.b. this doesn't actually produce a bitfield instruction at the
42 ; moment, but it's still a good test to have and the semantics are
43 ; correct.
44   %uxt32 = zext i16 %var to i32
45   store volatile i32 %uxt32, i32* @var32
46 ; CHECK: and {{w[0-9]+}}, {{w[0-9]+}}, #0xffff
47
48   %uxt64 = zext i16 %var to i64
49   store volatile i64 %uxt64, i64* @var64
50 ; CHECK: and {{x[0-9]+}}, {{x[0-9]+}}, #0xffff
51   ret void
52 }
53
54 define void @test_extendw(i32 %var) {
55 ; CHECK-LABEL: test_extendw:
56
57   %sxt64 = sext i32 %var to i64
58   store volatile i64 %sxt64, i64* @var64
59 ; CHECK: sxtw {{x[0-9]+}}, {{w[0-9]+}}
60
61   %uxt64 = zext i32 %var to i64
62   store volatile i64 %uxt64, i64* @var64
63 ; CHECK: ubfx {{x[0-9]+}}, {{x[0-9]+}}, #0, #32
64   ret void
65 }
66
67 define void @test_shifts(i32 %val32, i64 %val64) {
68 ; CHECK-LABEL: test_shifts:
69
70   %shift1 = ashr i32 %val32, 31
71   store volatile i32 %shift1, i32* @var32
72 ; CHECK: asr {{w[0-9]+}}, {{w[0-9]+}}, #31
73
74   %shift2 = lshr i32 %val32, 8
75   store volatile i32 %shift2, i32* @var32
76 ; CHECK: lsr {{w[0-9]+}}, {{w[0-9]+}}, #8
77
78   %shift3 = shl i32 %val32, 1
79   store volatile i32 %shift3, i32* @var32
80 ; CHECK: lsl {{w[0-9]+}}, {{w[0-9]+}}, #1
81
82   %shift4 = ashr i64 %val64, 31
83   store volatile i64 %shift4, i64* @var64
84 ; CHECK: asr {{x[0-9]+}}, {{x[0-9]+}}, #31
85
86   %shift5 = lshr i64 %val64, 8
87   store volatile i64 %shift5, i64* @var64
88 ; CHECK: lsr {{x[0-9]+}}, {{x[0-9]+}}, #8
89
90   %shift6 = shl i64 %val64, 63
91   store volatile i64 %shift6, i64* @var64
92 ; CHECK: lsl {{x[0-9]+}}, {{x[0-9]+}}, #63
93
94   %shift7 = ashr i64 %val64, 63
95   store volatile i64 %shift7, i64* @var64
96 ; CHECK: asr {{x[0-9]+}}, {{x[0-9]+}}, #63
97
98   %shift8 = lshr i64 %val64, 63
99   store volatile i64 %shift8, i64* @var64
100 ; CHECK: lsr {{x[0-9]+}}, {{x[0-9]+}}, #63
101
102   %shift9 = lshr i32 %val32, 31
103   store volatile i32 %shift9, i32* @var32
104 ; CHECK: lsr {{w[0-9]+}}, {{w[0-9]+}}, #31
105
106   %shift10 = shl i32 %val32, 31
107   store volatile i32 %shift10, i32* @var32
108 ; CHECK: lsl {{w[0-9]+}}, {{w[0-9]+}}, #31
109
110   ret void
111 }
112
113 ; LLVM can produce in-register extensions taking place entirely with
114 ; 64-bit registers too.
115 define void @test_sext_inreg_64(i64 %in) {
116 ; CHECK-LABEL: test_sext_inreg_64:
117
118 ; i1 doesn't have an official alias, but crops up and is handled by
119 ; the bitfield ops.
120   %trunc_i1 = trunc i64 %in to i1
121   %sext_i1 = sext i1 %trunc_i1 to i64
122   store volatile i64 %sext_i1, i64* @var64
123 ; CHECK: sbfx {{x[0-9]+}}, {{x[0-9]+}}, #0, #1
124
125   %trunc_i8 = trunc i64 %in to i8
126   %sext_i8 = sext i8 %trunc_i8 to i64
127   store volatile i64 %sext_i8, i64* @var64
128 ; CHECK: sxtb {{x[0-9]+}}, {{w[0-9]+}}
129
130   %trunc_i16 = trunc i64 %in to i16
131   %sext_i16 = sext i16 %trunc_i16 to i64
132   store volatile i64 %sext_i16, i64* @var64
133 ; CHECK: sxth {{x[0-9]+}}, {{w[0-9]+}}
134
135   %trunc_i32 = trunc i64 %in to i32
136   %sext_i32 = sext i32 %trunc_i32 to i64
137   store volatile i64 %sext_i32, i64* @var64
138 ; CHECK: sxtw {{x[0-9]+}}, {{w[0-9]+}}
139   ret void
140 }
141
142 ; These instructions don't actually select to official bitfield
143 ; operations, but it's important that we select them somehow:
144 define void @test_zext_inreg_64(i64 %in) {
145 ; CHECK-LABEL: test_zext_inreg_64:
146
147   %trunc_i8 = trunc i64 %in to i8
148   %zext_i8 = zext i8 %trunc_i8 to i64
149   store volatile i64 %zext_i8, i64* @var64
150 ; CHECK: and {{x[0-9]+}}, {{x[0-9]+}}, #0xff
151
152   %trunc_i16 = trunc i64 %in to i16
153   %zext_i16 = zext i16 %trunc_i16 to i64
154   store volatile i64 %zext_i16, i64* @var64
155 ; CHECK: and {{x[0-9]+}}, {{x[0-9]+}}, #0xffff
156
157   %trunc_i32 = trunc i64 %in to i32
158   %zext_i32 = zext i32 %trunc_i32 to i64
159   store volatile i64 %zext_i32, i64* @var64
160 ; CHECK: and {{x[0-9]+}}, {{x[0-9]+}}, #0xffffffff
161
162   ret void
163 }
164
165 define i64 @test_sext_inreg_from_32(i32 %in) {
166 ; CHECK-LABEL: test_sext_inreg_from_32:
167
168   %small = trunc i32 %in to i1
169   %ext = sext i1 %small to i64
170
171   ; Different registers are of course, possible, though suboptimal. This is
172   ; making sure that a 64-bit "(sext_inreg (anyext GPR32), i1)" uses the 64-bit
173   ; sbfx rather than just 32-bits.
174 ; CHECK: sbfx x0, x0, #0, #1
175   ret i64 %ext
176 }
177
178
179 define i32 @test_ubfx32(i32* %addr) {
180 ; CHECK-LABEL: test_ubfx32:
181 ; CHECK: ubfx {{w[0-9]+}}, {{w[0-9]+}}, #23, #3
182
183    %fields = load i32* %addr
184    %shifted = lshr i32 %fields, 23
185    %masked = and i32 %shifted, 7
186    ret i32 %masked
187 }
188
189 define i64 @test_ubfx64(i64* %addr) {
190 ; CHECK-LABEL: test_ubfx64:
191 ; CHECK: ubfx {{x[0-9]+}}, {{x[0-9]+}}, #25, #10
192    %fields = load i64* %addr
193    %shifted = lshr i64 %fields, 25
194    %masked = and i64 %shifted, 1023
195    ret i64 %masked
196 }
197
198 define i32 @test_sbfx32(i32* %addr) {
199 ; CHECK-LABEL: test_sbfx32:
200 ; CHECK: sbfx {{w[0-9]+}}, {{w[0-9]+}}, #6, #3
201
202    %fields = load i32* %addr
203    %shifted = shl i32 %fields, 23
204    %extended = ashr i32 %shifted, 29
205    ret i32 %extended
206 }
207
208 define i64 @test_sbfx64(i64* %addr) {
209 ; CHECK-LABEL: test_sbfx64:
210 ; CHECK: sbfx {{x[0-9]+}}, {{x[0-9]+}}, #0, #63
211
212    %fields = load i64* %addr
213    %shifted = shl i64 %fields, 1
214    %extended = ashr i64 %shifted, 1
215    ret i64 %extended
216 }