Skip to content

Commit 4bf70dd

Browse files
committed
Set signext or zeroext for integer arguments on LoongArch64
1 parent 18ee046 commit 4bf70dd

14 files changed

+268
-92
lines changed

compiler/rustc_target/src/callconv/loongarch.rs

+27
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::abi::call::{ArgAbi, ArgExtension, CastTarget, FnAbi, PassMode, Reg, RegKind, Uniform};
22
use crate::abi::{self, Abi, FieldsShape, HasDataLayout, Size, TyAbiInterface, TyAndLayout};
33
use crate::spec::HasTargetSpec;
4+
use crate::spec::abi::Abi as SpecAbi;
45

56
#[derive(Copy, Clone)]
67
enum RegPassKind {
@@ -359,3 +360,29 @@ where
359360
);
360361
}
361362
}
363+
364+
pub(crate) fn compute_rust_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>, abi: SpecAbi)
365+
where
366+
Ty: TyAbiInterface<'a, C> + Copy,
367+
C: HasDataLayout + HasTargetSpec,
368+
{
369+
if abi == SpecAbi::RustIntrinsic {
370+
return;
371+
}
372+
373+
let grlen = cx.data_layout().pointer_size.bits();
374+
375+
for arg in fn_abi.args.iter_mut() {
376+
if arg.is_ignore() {
377+
continue;
378+
}
379+
380+
// LLVM integers types do not differentiate between signed or unsigned integers.
381+
// Some LoongArch instructions do not have a `.w` suffix version, they use all the
382+
// GRLEN bits. By explicitly setting the `signext` or `zeroext` attribute
383+
// according to signedness to avoid unnecessary integer extending instructions.
384+
//
385+
// This is similar to the RISC-V case, see https://github.com/rust-lang/rust/issues/114508 for details.
386+
extend_integer_width(arg, grlen);
387+
}
388+
}

compiler/rustc_target/src/callconv/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -729,6 +729,7 @@ impl<'a, Ty> FnAbi<'a, Ty> {
729729
match &spec.arch[..] {
730730
"x86" => x86::compute_rust_abi_info(cx, self, abi),
731731
"riscv32" | "riscv64" => riscv::compute_rust_abi_info(cx, self, abi),
732+
"loongarch64" => loongarch::compute_rust_abi_info(cx, self, abi),
732733
_ => {}
733734
};
734735

tests/assembly/rust-abi-arg-attr.rs

+20-5
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
//@ assembly-output: emit-asm
2-
//@ revisions: riscv64 riscv64-zbb
3-
//@ only-riscv64
4-
//@ compile-flags: --target riscv64gc-unknown-linux-gnu
2+
//@ revisions: riscv64 riscv64-zbb loongarch64
53
//@ compile-flags: -C opt-level=3
6-
//@ [riscv64] compile-flags:
4+
//@ [riscv64] only-riscv64
5+
//@ [riscv64] compile-flags: --target riscv64gc-unknown-linux-gnu
6+
//@ [riscv64] needs-llvm-components: riscv
7+
//@ [riscv64-zbb] only-riscv64
8+
//@ [riscv64-zbb] compile-flags: --target riscv64gc-unknown-linux-gnu
79
//@ [riscv64-zbb] compile-flags: -C target-feature=+zbb
8-
//@ needs-llvm-components: riscv
10+
//@ [riscv64-zbb] needs-llvm-components: riscv
11+
//@ [loongarch64] only-loongarch64
12+
//@ [loongarch64] compile-flags: --target loongarch64-unknown-linux-gnu
13+
//@ [loongarch64] needs-llvm-components: loongarch
914

1015
#![crate_type = "lib"]
1116

@@ -20,6 +25,11 @@ pub fn issue_114508_u32(a: u32, b: u32) -> u32 {
2025

2126
// riscv64-zbb-NEXT: maxu a0, a0, a1
2227

28+
// loongarch64-NEXT: sltu $a2, $a1, $a0
29+
// loongarch64-NEXT: masknez $a1, $a1, $a2
30+
// loongarch64-NEXT: maskeqz $a0, $a0, $a2
31+
// loongarch64-NEXT: or $a0, $a0, $a1
32+
2333
// CHECK-NEXT: ret
2434
u32::max(a, b)
2535
}
@@ -35,6 +45,11 @@ pub fn issue_114508_i32(a: i32, b: i32) -> i32 {
3545

3646
// riscv64-zbb-NEXT: max a0, a0, a1
3747

48+
// loongarch64-NEXT: slt $a2, $a1, $a0
49+
// loongarch64-NEXT: masknez $a1, $a1, $a2
50+
// loongarch64-NEXT: maskeqz $a0, $a0, $a2
51+
// loongarch64-NEXT: or $a0, $a0, $a1
52+
3853
// CHECK-NEXT: ret
3954
i32::max(a, b)
4055
}

tests/codegen/checked_ilog.rs

+8-3
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,23 @@
11
//@ compile-flags: -O
2-
//@ revisions: others riscv64
2+
//@ revisions: others riscv64 loongarch64
33

44
//@[others] ignore-riscv64
5+
//@[others] ignore-loongarch64
56
//@[riscv64] only-riscv64
67
//@[riscv64] compile-flags: --target riscv64gc-unknown-linux-gnu
78
//@[riscv64] needs-llvm-components: riscv
9+
//@[loongarch64] only-loongarch64
10+
//@[loongarch64] compile-flags: --target loongarch64-unknown-linux-gnu
11+
//@[loongarch64] needs-llvm-components: loongarch
812

913
#![crate_type = "lib"]
1014

1115
// Ensure that when val < base, we do not divide or multiply.
1216

1317
// CHECK-LABEL: @checked_ilog
14-
// others-SAME: (i16 noundef %val, i16 noundef %base)
15-
// riscv64-SAME: (i16 noundef zeroext %val, i16 noundef zeroext %base)
18+
// others-SAME: (i16 noundef %val, i16 noundef %base)
19+
// riscv64-SAME: (i16 noundef zeroext %val, i16 noundef zeroext %base)
20+
// loongarch64-SAME: (i16 noundef zeroext %val, i16 noundef zeroext %base)
1621
#[no_mangle]
1722
pub fn checked_ilog(val: u16, base: u16) -> Option<u32> {
1823
// CHECK-NOT: udiv

tests/codegen/checked_math.rs

+23-13
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
//@ compile-flags: -O -Z merge-functions=disabled
2-
//@ revisions: others riscv64
2+
//@ revisions: others riscv64 loongarch64
33

44
//@[others] ignore-riscv64
5+
//@[others] ignore-loongarch64
56
//@[riscv64] only-riscv64
67
//@[riscv64] compile-flags: --target riscv64gc-unknown-linux-gnu
78
//@[riscv64] needs-llvm-components: riscv
9+
//@[loongarch64] only-loongarch64
10+
//@[loongarch64] compile-flags: --target loongarch64-unknown-linux-gnu
11+
//@[loongarch64] needs-llvm-components: loongarch
812

913
#![crate_type = "lib"]
1014
#![feature(unchecked_shifts)]
@@ -14,8 +18,9 @@
1418
// Thanks to poison semantics, this doesn't even need branches.
1519

1620
// CHECK-LABEL: @checked_sub_unsigned
17-
// others-SAME: (i16 noundef %a, i16 noundef %b)
18-
// riscv64-SAME: (i16 noundef zeroext %a, i16 noundef zeroext %b)
21+
// others-SAME: (i16 noundef %a, i16 noundef %b)
22+
// riscv64-SAME: (i16 noundef zeroext %a, i16 noundef zeroext %b)
23+
// loongarch64-SAME: (i16 noundef zeroext %a, i16 noundef zeroext %b)
1924
#[no_mangle]
2025
pub fn checked_sub_unsigned(a: u16, b: u16) -> Option<u16> {
2126
// CHECK-DAG: %[[IS_SOME:.+]] = icmp uge i16 %a, %b
@@ -33,8 +38,9 @@ pub fn checked_sub_unsigned(a: u16, b: u16) -> Option<u16> {
3338
// looking for no-wrap flags, we just need there to not be any masking.
3439

3540
// CHECK-LABEL: @checked_shl_unsigned
36-
// others-SAME: (i32 noundef %a, i32 noundef %b)
37-
// riscv64-SAME: (i32 noundef signext %a, i32 noundef signext %b)
41+
// others-SAME: (i32 noundef %a, i32 noundef %b)
42+
// riscv64-SAME: (i32 noundef signext %a, i32 noundef signext %b)
43+
// loongarch64-SAME: (i32 noundef signext %a, i32 noundef signext %b)
3844
#[no_mangle]
3945
pub fn checked_shl_unsigned(a: u32, b: u32) -> Option<u32> {
4046
// CHECK-DAG: %[[IS_SOME:.+]] = icmp ult i32 %b, 32
@@ -49,8 +55,9 @@ pub fn checked_shl_unsigned(a: u32, b: u32) -> Option<u32> {
4955
}
5056

5157
// CHECK-LABEL: @checked_shr_unsigned
52-
// others-SAME: (i32 noundef %a, i32 noundef %b)
53-
// riscv64-SAME: (i32 noundef signext %a, i32 noundef signext %b)
58+
// others-SAME: (i32 noundef %a, i32 noundef %b)
59+
// riscv64-SAME: (i32 noundef signext %a, i32 noundef signext %b)
60+
// loongarch64-SAME: (i32 noundef signext %a, i32 noundef signext %b)
5461
#[no_mangle]
5562
pub fn checked_shr_unsigned(a: u32, b: u32) -> Option<u32> {
5663
// CHECK-DAG: %[[IS_SOME:.+]] = icmp ult i32 %b, 32
@@ -65,8 +72,9 @@ pub fn checked_shr_unsigned(a: u32, b: u32) -> Option<u32> {
6572
}
6673

6774
// CHECK-LABEL: @checked_shl_signed
68-
// others-SAME: (i32 noundef %a, i32 noundef %b)
69-
// riscv64-SAME: (i32 noundef signext %a, i32 noundef signext %b)
75+
// others-SAME: (i32 noundef %a, i32 noundef %b)
76+
// riscv64-SAME: (i32 noundef signext %a, i32 noundef signext %b)
77+
// loongarch64-SAME: (i32 noundef signext %a, i32 noundef signext %b)
7078
#[no_mangle]
7179
pub fn checked_shl_signed(a: i32, b: u32) -> Option<i32> {
7280
// CHECK-DAG: %[[IS_SOME:.+]] = icmp ult i32 %b, 32
@@ -81,8 +89,9 @@ pub fn checked_shl_signed(a: i32, b: u32) -> Option<i32> {
8189
}
8290

8391
// CHECK-LABEL: @checked_shr_signed
84-
// others-SAME: (i32 noundef %a, i32 noundef %b)
85-
// riscv64-SAME: (i32 noundef signext %a, i32 noundef signext %b)
92+
// others-SAME: (i32 noundef %a, i32 noundef %b)
93+
// riscv64-SAME: (i32 noundef signext %a, i32 noundef signext %b)
94+
// loongarch64-SAME: (i32 noundef signext %a, i32 noundef signext %b)
8695
#[no_mangle]
8796
pub fn checked_shr_signed(a: i32, b: u32) -> Option<i32> {
8897
// CHECK-DAG: %[[IS_SOME:.+]] = icmp ult i32 %b, 32
@@ -97,8 +106,9 @@ pub fn checked_shr_signed(a: i32, b: u32) -> Option<i32> {
97106
}
98107

99108
// CHECK-LABEL: @checked_add_one_unwrap_unsigned
100-
// others-SAME: (i32 noundef %x)
101-
// riscv64-SAME: (i32 noundef signext %x)
109+
// others-SAME: (i32 noundef %x)
110+
// riscv64-SAME: (i32 noundef signext %x)
111+
// loongarch64-SAME: (i32 noundef signext %x)
102112
#[no_mangle]
103113
pub fn checked_add_one_unwrap_unsigned(x: u32) -> u32 {
104114
// CHECK: %[[IS_MAX:.+]] = icmp eq i32 %x, -1

tests/codegen/comparison-operators-newtype.rs

+17-9
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,16 @@
33
// in the operators for such a type all optimize away.
44

55
//@ compile-flags: -C opt-level=1
6-
//@ revisions: others riscv64
6+
//@ revisions: others riscv64 loongarch64
77

88
//@[others] ignore-riscv64
9+
//@[others] ignore-loongarch64
910
//@[riscv64] only-riscv64
1011
//@[riscv64] compile-flags: --target riscv64gc-unknown-linux-gnu
1112
//@[riscv64] needs-llvm-components: riscv
13+
//@[loongarch64] only-loongarch64
14+
//@[loongarch64] compile-flags: --target loongarch64-unknown-linux-gnu
15+
//@[loongarch64] needs-llvm-components: loongarch
1216

1317
#![crate_type = "lib"]
1418

@@ -18,8 +22,9 @@ use std::cmp::Ordering;
1822
pub struct Foo(u16);
1923

2024
// CHECK-LABEL: @check_lt
21-
// others-SAME: (i16 noundef %[[A:.+]], i16 noundef %[[B:.+]])
22-
// riscv64-SAME: (i16 noundef zeroext %[[A:.+]], i16 noundef zeroext %[[B:.+]])
25+
// others-SAME: (i16 noundef %[[A:.+]], i16 noundef %[[B:.+]])
26+
// riscv64-SAME: (i16 noundef zeroext %[[A:.+]], i16 noundef zeroext %[[B:.+]])
27+
// loongarch64-SAME: (i16 noundef zeroext %[[A:.+]], i16 noundef zeroext %[[B:.+]])
2328
#[no_mangle]
2429
pub fn check_lt(a: Foo, b: Foo) -> bool {
2530
// CHECK: %[[R:.+]] = icmp ult i16 %[[A]], %[[B]]
@@ -28,8 +33,9 @@ pub fn check_lt(a: Foo, b: Foo) -> bool {
2833
}
2934

3035
// CHECK-LABEL: @check_le
31-
// others-SAME: (i16 noundef %[[A:.+]], i16 noundef %[[B:.+]])
32-
// riscv64-SAME: (i16 noundef zeroext %[[A:.+]], i16 noundef zeroext %[[B:.+]])
36+
// others-SAME: (i16 noundef %[[A:.+]], i16 noundef %[[B:.+]])
37+
// riscv64-SAME: (i16 noundef zeroext %[[A:.+]], i16 noundef zeroext %[[B:.+]])
38+
// loongarch64-SAME: (i16 noundef zeroext %[[A:.+]], i16 noundef zeroext %[[B:.+]])
3339
#[no_mangle]
3440
pub fn check_le(a: Foo, b: Foo) -> bool {
3541
// CHECK: %[[R:.+]] = icmp ule i16 %[[A]], %[[B]]
@@ -38,8 +44,9 @@ pub fn check_le(a: Foo, b: Foo) -> bool {
3844
}
3945

4046
// CHECK-LABEL: @check_gt
41-
// others-SAME: (i16 noundef %[[A:.+]], i16 noundef %[[B:.+]])
42-
// riscv64-SAME: (i16 noundef zeroext %[[A:.+]], i16 noundef zeroext %[[B:.+]])
47+
// others-SAME: (i16 noundef %[[A:.+]], i16 noundef %[[B:.+]])
48+
// riscv64-SAME: (i16 noundef zeroext %[[A:.+]], i16 noundef zeroext %[[B:.+]])
49+
// loongarch64-SAME: (i16 noundef zeroext %[[A:.+]], i16 noundef zeroext %[[B:.+]])
4350
#[no_mangle]
4451
pub fn check_gt(a: Foo, b: Foo) -> bool {
4552
// CHECK: %[[R:.+]] = icmp ugt i16 %[[A]], %[[B]]
@@ -48,8 +55,9 @@ pub fn check_gt(a: Foo, b: Foo) -> bool {
4855
}
4956

5057
// CHECK-LABEL: @check_ge
51-
// others-SAME: (i16 noundef %[[A:.+]], i16 noundef %[[B:.+]])
52-
// riscv64-SAME: (i16 noundef zeroext %[[A:.+]], i16 noundef zeroext %[[B:.+]])
58+
// others-SAME: (i16 noundef %[[A:.+]], i16 noundef %[[B:.+]])
59+
// riscv64-SAME: (i16 noundef zeroext %[[A:.+]], i16 noundef zeroext %[[B:.+]])
60+
// loongarch64-SAME: (i16 noundef zeroext %[[A:.+]], i16 noundef zeroext %[[B:.+]])
5361
#[no_mangle]
5462
pub fn check_ge(a: Foo, b: Foo) -> bool {
5563
// CHECK: %[[R:.+]] = icmp uge i16 %[[A]], %[[B]]

tests/codegen/fewer-names.rs

+20-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
//@ compile-flags: -Coverflow-checks=no -O
2-
//@ revisions: YES NO riscv64-YES riscv64-NO
2+
//@ revisions: YES NO riscv64-YES riscv64-NO loongarch64-YES loongarch64-NO
33
//@ [YES] ignore-riscv64
4+
//@ [YES] ignore-loongarch64
45
//@ [YES] compile-flags: -Zfewer-names=yes
56
//@ [NO] ignore-riscv64
7+
//@ [NO] ignore-loongarch64
68
//@ [NO] compile-flags: -Zfewer-names=no
79
//@ [riscv64-YES] only-riscv64
810
//@ [riscv64-YES] compile-flags: --target riscv64gc-unknown-linux-gnu
@@ -12,6 +14,14 @@
1214
//@ [riscv64-NO] compile-flags: --target riscv64gc-unknown-linux-gnu
1315
//@ [riscv64-NO] compile-flags: -Zfewer-names=no
1416
//@ [riscv64-NO] needs-llvm-components: riscv
17+
//@ [loongarch64-YES] only-loongarch64
18+
//@ [loongarch64-YES] compile-flags: --target loongarch64-unknown-linux-gnu
19+
//@ [loongarch64-YES] compile-flags: -Zfewer-names=yes
20+
//@ [loongarch64-YES] needs-llvm-components: loongarch
21+
//@ [loongarch64-NO] only-loongarch64
22+
//@ [loongarch64-NO] compile-flags: --target loongarch64-unknown-linux-gnu
23+
//@ [loongarch64-NO] compile-flags: -Zfewer-names=no
24+
//@ [loongarch64-NO] needs-llvm-components: loongarch
1525
#![crate_type = "lib"]
1626

1727
#[no_mangle]
@@ -33,6 +43,15 @@ pub fn sum(x: u32, y: u32) -> u32 {
3343
// riscv64-NO-NEXT: start:
3444
// riscv64-NO-NEXT: %z = add i32 %y, %x
3545
// riscv64-NO-NEXT: ret i32 %z
46+
47+
// loongarch64-YES-LABEL: define{{.*}}i32 @sum(i32 noundef signext %0, i32 noundef signext %1)
48+
// loongarch64-YES-NEXT: %3 = add i32 %1, %0
49+
// loongarch64-YES-NEXT: ret i32 %3
50+
51+
// loongarch64-NO-LABEL: define{{.*}}i32 @sum(i32 noundef signext %x, i32 noundef signext %y)
52+
// loongarch64-NO-NEXT: start:
53+
// loongarch64-NO-NEXT: %z = add i32 %y, %x
54+
// loongarch64-NO-NEXT: ret i32 %z
3655
let z = x + y;
3756
z
3857
}

tests/codegen/function-arguments.rs

+17-9
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
//@ compile-flags: -O -C no-prepopulate-passes
2-
//@ revisions: others riscv64
2+
//@ revisions: others riscv64 loongarch64
33

44
//@[others] ignore-riscv64
5+
//@[others] ignore-loongarch64
56
//@[riscv64] only-riscv64
67
//@[riscv64] compile-flags: --target riscv64gc-unknown-linux-gnu
78
//@[riscv64] needs-llvm-components: riscv
9+
//@[loongarch64] only-loongarch64
10+
//@[loongarch64] compile-flags: --target loongarch64-unknown-linux-gnu
11+
//@[loongarch64] needs-llvm-components: loongarch
812

913
#![crate_type = "lib"]
1014
#![feature(dyn_star)]
@@ -39,8 +43,9 @@ pub fn boolean(x: bool) -> bool {
3943
x
4044
}
4145

42-
// others: i8 @maybeuninit_boolean(i8 %x)
43-
// riscv64: i8 @maybeuninit_boolean(i8 zeroext %x)
46+
// others: i8 @maybeuninit_boolean(i8 %x)
47+
// riscv64: i8 @maybeuninit_boolean(i8 zeroext %x)
48+
// loongarch64: i8 @maybeuninit_boolean(i8 zeroext %x)
4449
#[no_mangle]
4550
pub fn maybeuninit_boolean(x: MaybeUninit<bool>) -> MaybeUninit<bool> {
4651
x
@@ -52,23 +57,26 @@ pub fn enum_bool(x: MyBool) -> MyBool {
5257
x
5358
}
5459

55-
// others: i8 @maybeuninit_enum_bool(i8 %x)
56-
// riscv64: i8 @maybeuninit_enum_bool(i8 zeroext %x)
60+
// others: i8 @maybeuninit_enum_bool(i8 %x)
61+
// riscv64: i8 @maybeuninit_enum_bool(i8 zeroext %x)
62+
// loongarch64: i8 @maybeuninit_enum_bool(i8 zeroext %x)
5763
#[no_mangle]
5864
pub fn maybeuninit_enum_bool(x: MaybeUninit<MyBool>) -> MaybeUninit<MyBool> {
5965
x
6066
}
6167

6268
// ignore-tidy-linelength
63-
// others: noundef{{( range\(i32 0, 1114112\))?}} i32 @char(i32 noundef{{( range\(i32 0, 1114112\))?}} %x)
64-
// riscv64: noundef{{( range\(i32 0, 1114112\))?}} i32 @char(i32 noundef signext{{( range\(i32 0, 1114112\))?}} %x)
69+
// others: noundef{{( range\(i32 0, 1114112\))?}} i32 @char(i32 noundef{{( range\(i32 0, 1114112\))?}} %x)
70+
// riscv64: noundef{{( range\(i32 0, 1114112\))?}} i32 @char(i32 noundef signext{{( range\(i32 0, 1114112\))?}} %x)
71+
// loongarch64: noundef{{( range\(i32 0, 1114112\))?}} i32 @char(i32 noundef signext{{( range\(i32 0, 1114112\))?}} %x)
6572
#[no_mangle]
6673
pub fn char(x: char) -> char {
6774
x
6875
}
6976

70-
// others: i32 @maybeuninit_char(i32 %x)
71-
// riscv64: i32 @maybeuninit_char(i32 signext %x)
77+
// others: i32 @maybeuninit_char(i32 %x)
78+
// riscv64: i32 @maybeuninit_char(i32 signext %x)
79+
// loongarch64: i32 @maybeuninit_char(i32 signext %x)
7280
#[no_mangle]
7381
pub fn maybeuninit_char(x: MaybeUninit<char>) -> MaybeUninit<char> {
7482
x

0 commit comments

Comments
 (0)