• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
6define 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
30define 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
54define 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
67define 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.
115define 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:
144define 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
165define 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
179define 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, i32* %addr
184   %shifted = lshr i32 %fields, 23
185   %masked = and i32 %shifted, 7
186   ret i32 %masked
187}
188
189define 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, i64* %addr
193   %shifted = lshr i64 %fields, 25
194   %masked = and i64 %shifted, 1023
195   ret i64 %masked
196}
197
198define 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, i32* %addr
203   %shifted = shl i32 %fields, 23
204   %extended = ashr i32 %shifted, 29
205   ret i32 %extended
206}
207
208define 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, i64* %addr
213   %shifted = shl i64 %fields, 1
214   %extended = ashr i64 %shifted, 1
215   ret i64 %extended
216}
217