Skip to content

Commit 912e356

Browse files
committed
Auto merge of rust-lang#131871 - RalfJung:x86-32-float, r=workingjubilee
x86-32 float return for 'Rust' ABI: treat all float types consistently This helps with rust-lang#131819: for our own ABI on x86-32, we want to *never* use the float registers. The previous logic only considered F32 and F64, but skipped F16 and F128. So I made the logic just apply to all float types. try-job: i686-gnu try-job: i686-gnu-nopt
2 parents 86d69c7 + 0906819 commit 912e356

File tree

4 files changed

+50
-48
lines changed

4 files changed

+50
-48
lines changed

compiler/rustc_ty_utils/src/abi.rs

+15-22
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use std::iter;
22

3-
use rustc_abi::Float::*;
43
use rustc_abi::Primitive::{Float, Pointer};
54
use rustc_abi::{Abi, AddressSpace, PointerKind, Scalar, Size};
65
use rustc_hir as hir;
@@ -695,37 +694,31 @@ fn fn_abi_adjust_for_abi<'tcx>(
695694
}
696695

697696
// Avoid returning floats in x87 registers on x86 as loading and storing from x87
698-
// registers will quiet signalling NaNs.
697+
// registers will quiet signalling NaNs. Also avoid using SSE registers since they
698+
// are not always available (depending on target features).
699699
if tcx.sess.target.arch == "x86"
700700
&& arg_idx.is_none()
701701
// Intrinsics themselves are not actual "real" functions, so theres no need to
702702
// change their ABIs.
703703
&& abi != SpecAbi::RustIntrinsic
704704
{
705-
match arg.layout.abi {
706-
// Handle similar to the way arguments with an `Abi::Aggregate` abi are handled
707-
// below, by returning arguments up to the size of a pointer (32 bits on x86)
708-
// cast to an appropriately sized integer.
709-
Abi::Scalar(s) if s.primitive() == Float(F32) => {
710-
// Same size as a pointer, return in a register.
711-
arg.cast_to(Reg::i32());
712-
return;
705+
let has_float = match arg.layout.abi {
706+
Abi::Scalar(s) => matches!(s.primitive(), Float(_)),
707+
Abi::ScalarPair(s1, s2) => {
708+
matches!(s1.primitive(), Float(_)) || matches!(s2.primitive(), Float(_))
713709
}
714-
Abi::Scalar(s) if s.primitive() == Float(F64) => {
715-
// Larger than a pointer, return indirectly.
716-
arg.make_indirect();
717-
return;
718-
}
719-
Abi::ScalarPair(s1, s2)
720-
if matches!(s1.primitive(), Float(F32 | F64))
721-
|| matches!(s2.primitive(), Float(F32 | F64)) =>
722-
{
710+
_ => false, // anyway not passed via registers on x86
711+
};
712+
if has_float {
713+
if arg.layout.size <= Pointer(AddressSpace::DATA).size(cx) {
714+
// Same size or smaller than pointer, return in a register.
715+
arg.cast_to(Reg { kind: RegKind::Integer, size: arg.layout.size });
716+
} else {
723717
// Larger than a pointer, return indirectly.
724718
arg.make_indirect();
725-
return;
726719
}
727-
_ => {}
728-
};
720+
return;
721+
}
729722
}
730723

731724
if arg_idx.is_none() && arg.layout.size > Pointer(AddressSpace::DATA).size(cx) * 2 {

tests/assembly/x86-return-float.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -305,8 +305,10 @@ pub unsafe fn call_other_f64(x: &mut (usize, f64)) {
305305
// CHECK-LABEL: return_f16:
306306
#[no_mangle]
307307
pub fn return_f16(x: f16) -> f16 {
308-
// CHECK: pinsrw $0, {{.*}}(%ebp), %xmm0
309-
// CHECK-NOT: xmm0
308+
// CHECK: pushl %ebp
309+
// CHECK: movl %esp, %ebp
310+
// CHECK: movzwl 8(%ebp), %eax
311+
// CHECK: popl %ebp
310312
// CHECK: retl
311313
x
312314
}

tests/codegen/float/f128.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// 32-bit x86 returns `f32` and `f64` differently to avoid the x87 stack.
1+
// 32-bit x86 returns float types differently to avoid the x87 stack.
22
// 32-bit systems will return 128bit values using a return area pointer.
33
//@ revisions: x86 bit32 bit64
44
//@[x86] only-x86
@@ -152,7 +152,9 @@ pub fn f128_rem_assign(a: &mut f128, b: f128) {
152152

153153
/* float to float conversions */
154154

155-
// CHECK-LABEL: half @f128_as_f16(
155+
// x86-LABEL: i16 @f128_as_f16(
156+
// bits32-LABEL: half @f128_as_f16(
157+
// bits64-LABEL: half @f128_as_f16(
156158
#[no_mangle]
157159
pub fn f128_as_f16(a: f128) -> f16 {
158160
// CHECK: fptrunc fp128 %{{.+}} to half

tests/codegen/float/f16.rs

+27-22
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// 32-bit x86 returns `f32` and `f64` differently to avoid the x87 stack.
1+
// 32-bit x86 returns float types differently to avoid the x87 stack.
22
// 32-bit systems will return 128bit values using a return area pointer.
33
//@ revisions: x86 bit32 bit64
44
//@[x86] only-x86
@@ -58,42 +58,44 @@ pub fn f16_le(a: f16, b: f16) -> bool {
5858
a <= b
5959
}
6060

61-
// CHECK-LABEL: half @f16_neg(
61+
// This is where we check the argument and return ABI for f16.
62+
// other-LABEL: half @f16_neg(half
63+
// x86-LABEL: i16 @f16_neg(half
6264
#[no_mangle]
6365
pub fn f16_neg(a: f16) -> f16 {
6466
// CHECK: fneg half %{{.+}}
6567
-a
6668
}
6769

68-
// CHECK-LABEL: half @f16_add(
70+
// CHECK-LABEL: @f16_add
6971
#[no_mangle]
7072
pub fn f16_add(a: f16, b: f16) -> f16 {
7173
// CHECK: fadd half %{{.+}}, %{{.+}}
7274
a + b
7375
}
7476

75-
// CHECK-LABEL: half @f16_sub(
77+
// CHECK-LABEL: @f16_sub
7678
#[no_mangle]
7779
pub fn f16_sub(a: f16, b: f16) -> f16 {
7880
// CHECK: fsub half %{{.+}}, %{{.+}}
7981
a - b
8082
}
8183

82-
// CHECK-LABEL: half @f16_mul(
84+
// CHECK-LABEL: @f16_mul
8385
#[no_mangle]
8486
pub fn f16_mul(a: f16, b: f16) -> f16 {
8587
// CHECK: fmul half %{{.+}}, %{{.+}}
8688
a * b
8789
}
8890

89-
// CHECK-LABEL: half @f16_div(
91+
// CHECK-LABEL: @f16_div
9092
#[no_mangle]
9193
pub fn f16_div(a: f16, b: f16) -> f16 {
9294
// CHECK: fdiv half %{{.+}}, %{{.+}}
9395
a / b
9496
}
9597

96-
// CHECK-LABEL: half @f16_rem(
98+
// CHECK-LABEL: @f16_rem
9799
#[no_mangle]
98100
pub fn f16_rem(a: f16, b: f16) -> f16 {
99101
// CHECK: frem half %{{.+}}, %{{.+}}
@@ -142,10 +144,13 @@ pub fn f16_rem_assign(a: &mut f16, b: f16) {
142144

143145
/* float to float conversions */
144146

145-
// CHECK-LABEL: half @f16_as_self(
147+
// other-LABEL: half @f16_as_self(
148+
// x86-LABEL: i16 @f16_as_self(
146149
#[no_mangle]
147150
pub fn f16_as_self(a: f16) -> f16 {
148-
// CHECK: ret half %{{.+}}
151+
// other-CHECK: ret half %{{.+}}
152+
// x86-CHECK: bitcast half
153+
// x86-CHECK: ret i16
149154
a as f16
150155
}
151156

@@ -176,21 +181,21 @@ pub fn f16_as_f128(a: f16) -> f128 {
176181
a as f128
177182
}
178183

179-
// CHECK-LABEL: half @f32_as_f16(
184+
// CHECK-LABEL: @f32_as_f16
180185
#[no_mangle]
181186
pub fn f32_as_f16(a: f32) -> f16 {
182187
// CHECK: fptrunc float %{{.+}} to half
183188
a as f16
184189
}
185190

186-
// CHECK-LABEL: half @f64_as_f16(
191+
// CHECK-LABEL: @f64_as_f16
187192
#[no_mangle]
188193
pub fn f64_as_f16(a: f64) -> f16 {
189194
// CHECK: fptrunc double %{{.+}} to half
190195
a as f16
191196
}
192197

193-
// CHECK-LABEL: half @f128_as_f16(
198+
// CHECK-LABEL: @f128_as_f16
194199
#[no_mangle]
195200
pub fn f128_as_f16(a: f128) -> f16 {
196201
// CHECK: fptrunc fp128 %{{.+}} to half
@@ -273,70 +278,70 @@ pub fn f16_as_i128(a: f16) -> i128 {
273278

274279
/* int to float conversions */
275280

276-
// CHECK-LABEL: half @u8_as_f16(
281+
// CHECK-LABEL: @u8_as_f16
277282
#[no_mangle]
278283
pub fn u8_as_f16(a: u8) -> f16 {
279284
// CHECK: uitofp i8 %{{.+}} to half
280285
a as f16
281286
}
282287

283-
// CHECK-LABEL: half @u16_as_f16(
288+
// CHECK-LABEL: @u16_as_f16
284289
#[no_mangle]
285290
pub fn u16_as_f16(a: u16) -> f16 {
286291
// CHECK: uitofp i16 %{{.+}} to half
287292
a as f16
288293
}
289294

290-
// CHECK-LABEL: half @u32_as_f16(
295+
// CHECK-LABEL: @u32_as_f16
291296
#[no_mangle]
292297
pub fn u32_as_f16(a: u32) -> f16 {
293298
// CHECK: uitofp i32 %{{.+}} to half
294299
a as f16
295300
}
296301

297-
// CHECK-LABEL: half @u64_as_f16(
302+
// CHECK-LABEL: @u64_as_f16
298303
#[no_mangle]
299304
pub fn u64_as_f16(a: u64) -> f16 {
300305
// CHECK: uitofp i64 %{{.+}} to half
301306
a as f16
302307
}
303308

304-
// CHECK-LABEL: half @u128_as_f16(
309+
// CHECK-LABEL: @u128_as_f16
305310
#[no_mangle]
306311
pub fn u128_as_f16(a: u128) -> f16 {
307312
// CHECK: uitofp i128 %{{.+}} to half
308313
a as f16
309314
}
310315

311-
// CHECK-LABEL: half @i8_as_f16(
316+
// CHECK-LABEL: @i8_as_f16
312317
#[no_mangle]
313318
pub fn i8_as_f16(a: i8) -> f16 {
314319
// CHECK: sitofp i8 %{{.+}} to half
315320
a as f16
316321
}
317322

318-
// CHECK-LABEL: half @i16_as_f16(
323+
// CHECK-LABEL: @i16_as_f16
319324
#[no_mangle]
320325
pub fn i16_as_f16(a: i16) -> f16 {
321326
// CHECK: sitofp i16 %{{.+}} to half
322327
a as f16
323328
}
324329

325-
// CHECK-LABEL: half @i32_as_f16(
330+
// CHECK-LABEL: @i32_as_f16
326331
#[no_mangle]
327332
pub fn i32_as_f16(a: i32) -> f16 {
328333
// CHECK: sitofp i32 %{{.+}} to half
329334
a as f16
330335
}
331336

332-
// CHECK-LABEL: half @i64_as_f16(
337+
// CHECK-LABEL: @i64_as_f16
333338
#[no_mangle]
334339
pub fn i64_as_f16(a: i64) -> f16 {
335340
// CHECK: sitofp i64 %{{.+}} to half
336341
a as f16
337342
}
338343

339-
// CHECK-LABEL: half @i128_as_f16(
344+
// CHECK-LABEL: @i128_as_f16
340345
#[no_mangle]
341346
pub fn i128_as_f16(a: i128) -> f16 {
342347
// CHECK: sitofp i128 %{{.+}} to half

0 commit comments

Comments
 (0)