From 0ebbea6fd5b58924e5f9c3eab92c0bdcce25de98 Mon Sep 17 00:00:00 2001 From: Asuna Date: Sun, 20 Oct 2024 02:36:36 +0200 Subject: [PATCH] Set `signext` or `zeroext` for integer arguments on RISC-V --- compiler/rustc_target/src/callconv/mod.rs | 1 + compiler/rustc_target/src/callconv/riscv.rs | 27 +++++++++++ tests/assembly/riscv64gc-zbb.rs | 23 +++++++++ tests/codegen/checked_ilog.rs | 9 +++- tests/codegen/checked_math.rs | 24 +++++++--- tests/codegen/comparison-operators-newtype.rs | 18 +++++-- tests/codegen/fewer-names.rs | 25 ++++++++-- tests/codegen/function-arguments.rs | 20 ++++++-- tests/codegen/intrinsics/three_way_compare.rs | 40 +++++++++++++++- tests/codegen/mir-aggregate-no-alloca.rs | 48 ++++++++++++++----- tests/codegen/range-attribute.rs | 17 +++++-- tests/codegen/transmute-scalar.rs | 9 +++- tests/codegen/union-abi.rs | 15 +++++- tests/codegen/var-names.rs | 9 +++- 14 files changed, 247 insertions(+), 38 deletions(-) create mode 100644 tests/assembly/riscv64gc-zbb.rs diff --git a/compiler/rustc_target/src/callconv/mod.rs b/compiler/rustc_target/src/callconv/mod.rs index c8432869de8f5..6e101d72c5a8b 100644 --- a/compiler/rustc_target/src/callconv/mod.rs +++ b/compiler/rustc_target/src/callconv/mod.rs @@ -728,6 +728,7 @@ impl<'a, Ty> FnAbi<'a, Ty> { let spec = cx.target_spec(); match &spec.arch[..] { "x86" => x86::compute_rust_abi_info(cx, self, abi), + "riscv32" | "riscv64" => riscv::compute_rust_abi_info(cx, self, abi), _ => {} }; diff --git a/compiler/rustc_target/src/callconv/riscv.rs b/compiler/rustc_target/src/callconv/riscv.rs index be6bc701b497e..f96169e6a618f 100644 --- a/compiler/rustc_target/src/callconv/riscv.rs +++ b/compiler/rustc_target/src/callconv/riscv.rs @@ -7,6 +7,7 @@ use crate::abi::call::{ArgAbi, ArgExtension, CastTarget, FnAbi, PassMode, Reg, RegKind, Uniform}; use crate::abi::{self, Abi, FieldsShape, HasDataLayout, Size, TyAbiInterface, TyAndLayout}; use crate::spec::HasTargetSpec; +use crate::spec::abi::Abi as SpecAbi; #[derive(Copy, Clone)] enum RegPassKind { @@ -365,3 +366,29 @@ where ); } } + +pub(crate) fn compute_rust_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>, abi: SpecAbi) +where + Ty: TyAbiInterface<'a, C> + Copy, + C: HasDataLayout + HasTargetSpec, +{ + if abi == SpecAbi::RustIntrinsic { + return; + } + + let xlen = cx.data_layout().pointer_size.bits(); + + for arg in fn_abi.args.iter_mut() { + if arg.is_ignore() { + continue; + } + + // LLVM integers types do not differentiate between signed or unsigned integers. + // Some RISC-V instructions do not have a `.w` suffix version, they use all the + // XLEN bits. By explicitly setting the `signext` or `zeroext` attribute + // according to signedness to avoid unnecessary integer extending instructions. + // + // See https://github.com/rust-lang/rust/issues/114508 for details. + extend_integer_width(arg, xlen); + } +} diff --git a/tests/assembly/riscv64gc-zbb.rs b/tests/assembly/riscv64gc-zbb.rs new file mode 100644 index 0000000000000..257ff2f97a473 --- /dev/null +++ b/tests/assembly/riscv64gc-zbb.rs @@ -0,0 +1,23 @@ +//@ assembly-output: emit-asm +//@ compile-flags: --target riscv64gc-unknown-linux-gnu +//@ compile-flags: -C target-feature=+zbb +//@ compile-flags: -C opt-level=3 +//@ needs-llvm-components: riscv + +#![crate_type = "lib"] + +#[no_mangle] +// CHECK-LABEL: issue_114508_u32: +pub fn issue_114508_u32(a: u32, b: u32) -> u32 { + // CHECK: maxu a0, a0, a1 + // CHECK-NEXT: ret + u32::max(a, b) +} + +#[no_mangle] +// CHECK-LABEL: issue_114508_i32: +pub fn issue_114508_i32(a: i32, b: i32) -> i32 { + // CHECK: max a0, a0, a1 + // CHECK-NEXT: ret + i32::max(a, b) +} diff --git a/tests/codegen/checked_ilog.rs b/tests/codegen/checked_ilog.rs index 8f3c07119feeb..3c890935006e6 100644 --- a/tests/codegen/checked_ilog.rs +++ b/tests/codegen/checked_ilog.rs @@ -1,11 +1,18 @@ //@ compile-flags: -O +//@ revisions: others riscv64 + +//@[others] ignore-riscv64 +//@[riscv64] only-riscv64 +//@[riscv64] compile-flags: --target riscv64gc-unknown-linux-gnu +//@[riscv64] needs-llvm-components: riscv #![crate_type = "lib"] // Ensure that when val < base, we do not divide or multiply. // CHECK-LABEL: @checked_ilog -// CHECK-SAME: (i16 noundef %val, i16 noundef %base) +// others-SAME: (i16 noundef %val, i16 noundef %base) +// riscv64-SAME: (i16 noundef zeroext %val, i16 noundef zeroext %base) #[no_mangle] pub fn checked_ilog(val: u16, base: u16) -> Option { // CHECK-NOT: udiv diff --git a/tests/codegen/checked_math.rs b/tests/codegen/checked_math.rs index 75df5866d6ea0..0086a23d5a3b2 100644 --- a/tests/codegen/checked_math.rs +++ b/tests/codegen/checked_math.rs @@ -1,4 +1,10 @@ //@ compile-flags: -O -Z merge-functions=disabled +//@ revisions: others riscv64 + +//@[others] ignore-riscv64 +//@[riscv64] only-riscv64 +//@[riscv64] compile-flags: --target riscv64gc-unknown-linux-gnu +//@[riscv64] needs-llvm-components: riscv #![crate_type = "lib"] #![feature(unchecked_shifts)] @@ -8,7 +14,8 @@ // Thanks to poison semantics, this doesn't even need branches. // CHECK-LABEL: @checked_sub_unsigned -// CHECK-SAME: (i16 noundef %a, i16 noundef %b) +// others-SAME: (i16 noundef %a, i16 noundef %b) +// riscv64-SAME: (i16 noundef zeroext %a, i16 noundef zeroext %b) #[no_mangle] pub fn checked_sub_unsigned(a: u16, b: u16) -> Option { // CHECK-DAG: %[[IS_SOME:.+]] = icmp uge i16 %a, %b @@ -26,7 +33,8 @@ pub fn checked_sub_unsigned(a: u16, b: u16) -> Option { // looking for no-wrap flags, we just need there to not be any masking. // CHECK-LABEL: @checked_shl_unsigned -// CHECK-SAME: (i32 noundef %a, i32 noundef %b) +// others-SAME: (i32 noundef %a, i32 noundef %b) +// riscv64-SAME: (i32 noundef signext %a, i32 noundef signext %b) #[no_mangle] pub fn checked_shl_unsigned(a: u32, b: u32) -> Option { // CHECK-DAG: %[[IS_SOME:.+]] = icmp ult i32 %b, 32 @@ -41,7 +49,8 @@ pub fn checked_shl_unsigned(a: u32, b: u32) -> Option { } // CHECK-LABEL: @checked_shr_unsigned -// CHECK-SAME: (i32 noundef %a, i32 noundef %b) +// others-SAME: (i32 noundef %a, i32 noundef %b) +// riscv64-SAME: (i32 noundef signext %a, i32 noundef signext %b) #[no_mangle] pub fn checked_shr_unsigned(a: u32, b: u32) -> Option { // CHECK-DAG: %[[IS_SOME:.+]] = icmp ult i32 %b, 32 @@ -56,7 +65,8 @@ pub fn checked_shr_unsigned(a: u32, b: u32) -> Option { } // CHECK-LABEL: @checked_shl_signed -// CHECK-SAME: (i32 noundef %a, i32 noundef %b) +// others-SAME: (i32 noundef %a, i32 noundef %b) +// riscv64-SAME: (i32 noundef signext %a, i32 noundef signext %b) #[no_mangle] pub fn checked_shl_signed(a: i32, b: u32) -> Option { // CHECK-DAG: %[[IS_SOME:.+]] = icmp ult i32 %b, 32 @@ -71,7 +81,8 @@ pub fn checked_shl_signed(a: i32, b: u32) -> Option { } // CHECK-LABEL: @checked_shr_signed -// CHECK-SAME: (i32 noundef %a, i32 noundef %b) +// others-SAME: (i32 noundef %a, i32 noundef %b) +// riscv64-SAME: (i32 noundef signext %a, i32 noundef signext %b) #[no_mangle] pub fn checked_shr_signed(a: i32, b: u32) -> Option { // CHECK-DAG: %[[IS_SOME:.+]] = icmp ult i32 %b, 32 @@ -86,7 +97,8 @@ pub fn checked_shr_signed(a: i32, b: u32) -> Option { } // CHECK-LABEL: @checked_add_one_unwrap_unsigned -// CHECK-SAME: (i32 noundef %x) +// others-SAME: (i32 noundef %x) +// riscv64-SAME: (i32 noundef signext %x) #[no_mangle] pub fn checked_add_one_unwrap_unsigned(x: u32) -> u32 { // CHECK: %[[IS_MAX:.+]] = icmp eq i32 %x, -1 diff --git a/tests/codegen/comparison-operators-newtype.rs b/tests/codegen/comparison-operators-newtype.rs index d336c4e6ed3da..c5778286e0c12 100644 --- a/tests/codegen/comparison-operators-newtype.rs +++ b/tests/codegen/comparison-operators-newtype.rs @@ -3,6 +3,12 @@ // in the operators for such a type all optimize away. //@ compile-flags: -C opt-level=1 +//@ revisions: others riscv64 + +//@[others] ignore-riscv64 +//@[riscv64] only-riscv64 +//@[riscv64] compile-flags: --target riscv64gc-unknown-linux-gnu +//@[riscv64] needs-llvm-components: riscv #![crate_type = "lib"] @@ -12,7 +18,8 @@ use std::cmp::Ordering; pub struct Foo(u16); // CHECK-LABEL: @check_lt -// CHECK-SAME: (i16 noundef %[[A:.+]], i16 noundef %[[B:.+]]) +// others-SAME: (i16 noundef %[[A:.+]], i16 noundef %[[B:.+]]) +// riscv64-SAME: (i16 noundef zeroext %[[A:.+]], i16 noundef zeroext %[[B:.+]]) #[no_mangle] pub fn check_lt(a: Foo, b: Foo) -> bool { // CHECK: %[[R:.+]] = icmp ult i16 %[[A]], %[[B]] @@ -21,7 +28,8 @@ pub fn check_lt(a: Foo, b: Foo) -> bool { } // CHECK-LABEL: @check_le -// CHECK-SAME: (i16 noundef %[[A:.+]], i16 noundef %[[B:.+]]) +// others-SAME: (i16 noundef %[[A:.+]], i16 noundef %[[B:.+]]) +// riscv64-SAME: (i16 noundef zeroext %[[A:.+]], i16 noundef zeroext %[[B:.+]]) #[no_mangle] pub fn check_le(a: Foo, b: Foo) -> bool { // CHECK: %[[R:.+]] = icmp ule i16 %[[A]], %[[B]] @@ -30,7 +38,8 @@ pub fn check_le(a: Foo, b: Foo) -> bool { } // CHECK-LABEL: @check_gt -// CHECK-SAME: (i16 noundef %[[A:.+]], i16 noundef %[[B:.+]]) +// others-SAME: (i16 noundef %[[A:.+]], i16 noundef %[[B:.+]]) +// riscv64-SAME: (i16 noundef zeroext %[[A:.+]], i16 noundef zeroext %[[B:.+]]) #[no_mangle] pub fn check_gt(a: Foo, b: Foo) -> bool { // CHECK: %[[R:.+]] = icmp ugt i16 %[[A]], %[[B]] @@ -39,7 +48,8 @@ pub fn check_gt(a: Foo, b: Foo) -> bool { } // CHECK-LABEL: @check_ge -// CHECK-SAME: (i16 noundef %[[A:.+]], i16 noundef %[[B:.+]]) +// others-SAME: (i16 noundef %[[A:.+]], i16 noundef %[[B:.+]]) +// riscv64-SAME: (i16 noundef zeroext %[[A:.+]], i16 noundef zeroext %[[B:.+]]) #[no_mangle] pub fn check_ge(a: Foo, b: Foo) -> bool { // CHECK: %[[R:.+]] = icmp uge i16 %[[A]], %[[B]] diff --git a/tests/codegen/fewer-names.rs b/tests/codegen/fewer-names.rs index b14dd30482c59..3930b5744afa0 100644 --- a/tests/codegen/fewer-names.rs +++ b/tests/codegen/fewer-names.rs @@ -1,7 +1,17 @@ //@ compile-flags: -Coverflow-checks=no -O -//@ revisions: YES NO -//@ [YES]compile-flags: -Zfewer-names=yes -//@ [NO] compile-flags: -Zfewer-names=no +//@ revisions: YES NO riscv64-YES riscv64-NO +//@ [YES] ignore-riscv64 +//@ [YES] compile-flags: -Zfewer-names=yes +//@ [NO] ignore-riscv64 +//@ [NO] compile-flags: -Zfewer-names=no +//@ [riscv64-YES] only-riscv64 +//@ [riscv64-YES] compile-flags: --target riscv64gc-unknown-linux-gnu +//@ [riscv64-YES] compile-flags: -Zfewer-names=yes +//@ [riscv64-YES] needs-llvm-components: riscv +//@ [riscv64-NO] only-riscv64 +//@ [riscv64-NO] compile-flags: --target riscv64gc-unknown-linux-gnu +//@ [riscv64-NO] compile-flags: -Zfewer-names=no +//@ [riscv64-NO] needs-llvm-components: riscv #![crate_type = "lib"] #[no_mangle] @@ -14,6 +24,15 @@ pub fn sum(x: u32, y: u32) -> u32 { // NO-NEXT: start: // NO-NEXT: %z = add i32 %y, %x // NO-NEXT: ret i32 %z + + // riscv64-YES-LABEL: define{{.*}}i32 @sum(i32 noundef signext %0, i32 noundef signext %1) + // riscv64-YES-NEXT: %3 = add i32 %1, %0 + // riscv64-YES-NEXT: ret i32 %3 + + // riscv64-NO-LABEL: define{{.*}}i32 @sum(i32 noundef signext %x, i32 noundef signext %y) + // riscv64-NO-NEXT: start: + // riscv64-NO-NEXT: %z = add i32 %y, %x + // riscv64-NO-NEXT: ret i32 %z let z = x + y; z } diff --git a/tests/codegen/function-arguments.rs b/tests/codegen/function-arguments.rs index bf9f405192b69..9ae7e407457f0 100644 --- a/tests/codegen/function-arguments.rs +++ b/tests/codegen/function-arguments.rs @@ -1,4 +1,11 @@ //@ compile-flags: -O -C no-prepopulate-passes +//@ revisions: others riscv64 + +//@[others] ignore-riscv64 +//@[riscv64] only-riscv64 +//@[riscv64] compile-flags: --target riscv64gc-unknown-linux-gnu +//@[riscv64] needs-llvm-components: riscv + #![crate_type = "lib"] #![feature(dyn_star)] #![feature(allocator_api)] @@ -32,7 +39,8 @@ pub fn boolean(x: bool) -> bool { x } -// CHECK: i8 @maybeuninit_boolean(i8 %x) +// others: i8 @maybeuninit_boolean(i8 %x) +// riscv64: i8 @maybeuninit_boolean(i8 zeroext %x) #[no_mangle] pub fn maybeuninit_boolean(x: MaybeUninit) -> MaybeUninit { x @@ -44,19 +52,23 @@ pub fn enum_bool(x: MyBool) -> MyBool { x } -// CHECK: i8 @maybeuninit_enum_bool(i8 %x) +// others: i8 @maybeuninit_enum_bool(i8 %x) +// riscv64: i8 @maybeuninit_enum_bool(i8 zeroext %x) #[no_mangle] pub fn maybeuninit_enum_bool(x: MaybeUninit) -> MaybeUninit { x } -// CHECK: noundef{{( range\(i32 0, 1114112\))?}} i32 @char(i32 noundef{{( range\(i32 0, 1114112\))?}} %x) +// ignore-tidy-linelength +// others: noundef{{( range\(i32 0, 1114112\))?}} i32 @char(i32 noundef{{( range\(i32 0, 1114112\))?}} %x) +// riscv64: noundef{{( range\(i32 0, 1114112\))?}} i32 @char(i32 noundef signext{{( range\(i32 0, 1114112\))?}} %x) #[no_mangle] pub fn char(x: char) -> char { x } -// CHECK: i32 @maybeuninit_char(i32 %x) +// others: i32 @maybeuninit_char(i32 %x) +// riscv64: i32 @maybeuninit_char(i32 signext %x) #[no_mangle] pub fn maybeuninit_char(x: MaybeUninit) -> MaybeUninit { x diff --git a/tests/codegen/intrinsics/three_way_compare.rs b/tests/codegen/intrinsics/three_way_compare.rs index f3b631abc227e..6a4a7b640d500 100644 --- a/tests/codegen/intrinsics/three_way_compare.rs +++ b/tests/codegen/intrinsics/three_way_compare.rs @@ -1,6 +1,16 @@ -//@ revisions: DEBUG OPTIM +//@ revisions: DEBUG OPTIM riscv64-DEBUG riscv64-OPTIM +//@ [DEBUG] ignore-riscv64 //@ [DEBUG] compile-flags: -C opt-level=0 +//@ [OPTIM] ignore-riscv64 //@ [OPTIM] compile-flags: -C opt-level=3 +//@ [riscv64-DEBUG] only-riscv64 +//@ [riscv64-DEBUG] compile-flags: --target riscv64gc-unknown-linux-gnu +//@ [riscv64-DEBUG] compile-flags: -C opt-level=0 +//@ [riscv64-DEBUG] needs-llvm-components: riscv +//@ [riscv64-OPTIM] only-riscv64 +//@ [riscv64-OPTIM] compile-flags: --target riscv64gc-unknown-linux-gnu +//@ [riscv64-OPTIM] compile-flags: -C opt-level=3 +//@ [riscv64-OPTIM] needs-llvm-components: riscv //@ compile-flags: -C no-prepopulate-passes #![crate_type = "lib"] @@ -12,6 +22,8 @@ use std::intrinsics::three_way_compare; // CHECK-LABEL: @signed_cmp // DEBUG-SAME: (i16 %a, i16 %b) // OPTIM-SAME: (i16 noundef %a, i16 noundef %b) +// riscv64-DEBUG-SAME: (i16 signext %a, i16 signext %b) +// riscv64-OPTIM-SAME: (i16 noundef signext %a, i16 noundef signext %b) pub fn signed_cmp(a: i16, b: i16) -> std::cmp::Ordering { // DEBUG: %[[GT:.+]] = icmp sgt i16 %a, %b // DEBUG: %[[ZGT:.+]] = zext i1 %[[GT]] to i8 @@ -24,6 +36,18 @@ pub fn signed_cmp(a: i16, b: i16) -> std::cmp::Ordering { // OPTIM: %[[CGE:.+]] = select i1 %[[NE]], i8 1, i8 0 // OPTIM: %[[CGEL:.+]] = select i1 %[[LT]], i8 -1, i8 %[[CGE]] // OPTIM: ret i8 %[[CGEL]] + + // riscv64-DEBUG: %[[GT:.+]] = icmp sgt i16 %a, %b + // riscv64-DEBUG: %[[ZGT:.+]] = zext i1 %[[GT]] to i8 + // riscv64-DEBUG: %[[LT:.+]] = icmp slt i16 %a, %b + // riscv64-DEBUG: %[[ZLT:.+]] = zext i1 %[[LT]] to i8 + // riscv64-DEBUG: %[[R:.+]] = sub nsw i8 %[[ZGT]], %[[ZLT]] + + // riscv64-OPTIM: %[[LT:.+]] = icmp slt i16 %a, %b + // riscv64-OPTIM: %[[NE:.+]] = icmp ne i16 %a, %b + // riscv64-OPTIM: %[[CGE:.+]] = select i1 %[[NE]], i8 1, i8 0 + // riscv64-OPTIM: %[[CGEL:.+]] = select i1 %[[LT]], i8 -1, i8 %[[CGE]] + // riscv64-OPTIM: ret i8 %[[CGEL]] three_way_compare(a, b) } @@ -31,6 +55,8 @@ pub fn signed_cmp(a: i16, b: i16) -> std::cmp::Ordering { // CHECK-LABEL: @unsigned_cmp // DEBUG-SAME: (i16 %a, i16 %b) // OPTIM-SAME: (i16 noundef %a, i16 noundef %b) +// riscv64-DEBUG-SAME: (i16 zeroext %a, i16 zeroext %b) +// riscv64-OPTIM-SAME: (i16 noundef zeroext %a, i16 noundef zeroext %b) pub fn unsigned_cmp(a: u16, b: u16) -> std::cmp::Ordering { // DEBUG: %[[GT:.+]] = icmp ugt i16 %a, %b // DEBUG: %[[ZGT:.+]] = zext i1 %[[GT]] to i8 @@ -43,5 +69,17 @@ pub fn unsigned_cmp(a: u16, b: u16) -> std::cmp::Ordering { // OPTIM: %[[CGE:.+]] = select i1 %[[NE]], i8 1, i8 0 // OPTIM: %[[CGEL:.+]] = select i1 %[[LT]], i8 -1, i8 %[[CGE]] // OPTIM: ret i8 %[[CGEL]] + + // riscv64-DEBUG: %[[GT:.+]] = icmp ugt i16 %a, %b + // riscv64-DEBUG: %[[ZGT:.+]] = zext i1 %[[GT]] to i8 + // riscv64-DEBUG: %[[LT:.+]] = icmp ult i16 %a, %b + // riscv64-DEBUG: %[[ZLT:.+]] = zext i1 %[[LT]] to i8 + // riscv64-DEBUG: %[[R:.+]] = sub nsw i8 %[[ZGT]], %[[ZLT]] + + // riscv64-OPTIM: %[[LT:.+]] = icmp ult i16 %a, %b + // riscv64-OPTIM: %[[NE:.+]] = icmp ne i16 %a, %b + // riscv64-OPTIM: %[[CGE:.+]] = select i1 %[[NE]], i8 1, i8 0 + // riscv64-OPTIM: %[[CGEL:.+]] = select i1 %[[LT]], i8 -1, i8 %[[CGE]] + // riscv64-OPTIM: ret i8 %[[CGEL]] three_way_compare(a, b) } diff --git a/tests/codegen/mir-aggregate-no-alloca.rs b/tests/codegen/mir-aggregate-no-alloca.rs index 04ffb0755382b..8826e5c9e3220 100644 --- a/tests/codegen/mir-aggregate-no-alloca.rs +++ b/tests/codegen/mir-aggregate-no-alloca.rs @@ -1,7 +1,12 @@ // 32-bit systems will return 128bit values using a return area pointer. -//@ revisions: bit32 bit64 +//@ revisions: bit32 bit64 riscv64 //@[bit32] only-32bit +//@[bit32] ignore-riscv64 //@[bit64] only-64bit +//@[bit64] ignore-riscv64 +//@[riscv64] only-riscv64 +//@[riscv64] compile-flags: --target riscv64gc-unknown-linux-gnu +//@[riscv64] needs-llvm-components: riscv //@ compile-flags: -O -C no-prepopulate-passes -Z randomize-layout=no #![crate_type = "lib"] @@ -9,7 +14,9 @@ #[repr(transparent)] pub struct Transparent32(u32); -// CHECK: i32 @make_transparent(i32 noundef %x) +// bit32: i32 @make_transparent(i32 noundef %x) +// bit64: i32 @make_transparent(i32 noundef %x) +// riscv64: i32 @make_transparent(i32 noundef signext %x) #[no_mangle] pub fn make_transparent(x: u32) -> Transparent32 { // CHECK-NOT: alloca @@ -18,7 +25,9 @@ pub fn make_transparent(x: u32) -> Transparent32 { a } -// CHECK: i32 @make_closure(i32 noundef %x) +// bit32: i32 @make_closure(i32 noundef %x) +// bit64: i32 @make_closure(i32 noundef %x) +// riscv64: i32 @make_closure(i32 noundef signext %x) #[no_mangle] pub fn make_closure(x: i32) -> impl Fn(i32) -> i32 { // CHECK-NOT: alloca @@ -40,7 +49,9 @@ pub fn make_transparent_pair(x: (u16, u16)) -> TransparentPair { a } -// CHECK-LABEL: { i32, i32 } @make_2_tuple(i32 noundef %x) +// bit32-LABEL: { i32, i32 } @make_2_tuple(i32 noundef %x) +// bit64-LABEL: { i32, i32 } @make_2_tuple(i32 noundef %x) +// riscv64-LABEL: { i32, i32 } @make_2_tuple(i32 noundef signext %x) #[no_mangle] pub fn make_2_tuple(x: u32) -> (u32, u32) { // CHECK-NOT: alloca @@ -59,7 +70,10 @@ pub fn make_cell_of_bool(b: bool) -> std::cell::Cell { std::cell::Cell::new(b) } -// CHECK-LABEL: { i8, i16 } @make_cell_of_bool_and_short(i1 noundef zeroext %b, i16 noundef %s) +// ignore-tidy-linelength +// bit32-LABEL: { i8, i16 } @make_cell_of_bool_and_short(i1 noundef zeroext %b, i16 noundef %s) +// bit64-LABEL: { i8, i16 } @make_cell_of_bool_and_short(i1 noundef zeroext %b, i16 noundef %s) +// riscv64-LABEL: { i8, i16 } @make_cell_of_bool_and_short(i1 noundef zeroext %b, i16 noundef zeroext %s) #[no_mangle] pub fn make_cell_of_bool_and_short(b: bool, s: u16) -> std::cell::Cell<(bool, u16)> { // CHECK-NOT: alloca @@ -92,7 +106,9 @@ pub fn make_struct_0() -> Struct0 { pub struct Struct1(i32); -// CHECK-LABEL: i32 @make_struct_1(i32 noundef %a) +// bit32-LABEL: i32 @make_struct_1(i32 noundef %a) +// bit64-LABEL: i32 @make_struct_1(i32 noundef %a) +// riscv64-LABEL: i32 @make_struct_1(i32 noundef signext %a) #[no_mangle] pub fn make_struct_1(a: i32) -> Struct1 { // CHECK: ret i32 %a @@ -102,9 +118,10 @@ pub fn make_struct_1(a: i32) -> Struct1 { pub struct Struct2Asc(i16, i64); -// bit32-LABEL: void @make_struct_2_asc({{.*}} sret({{[^,]*}}) {{.*}} %s, -// bit64-LABEL: { i64, i16 } @make_struct_2_asc( -// CHECK-SAME: i16 noundef %a, i64 noundef %b) +// ignore-tidy-linelength +// bit32-LABEL: void @make_struct_2_asc({{.*}} sret({{[^,]*}}) {{.*}} %s, i16 noundef %a, i64 noundef %b) +// bit64-LABEL: { i64, i16 } @make_struct_2_asc(i16 noundef %a, i64 noundef %b) +// riscv64-LABEL: { i64, i16 } @make_struct_2_asc(i16 noundef signext %a, i64 noundef %b) #[no_mangle] pub fn make_struct_2_asc(a: i16, b: i64) -> Struct2Asc { // CHECK-NOT: alloca @@ -114,15 +131,19 @@ pub fn make_struct_2_asc(a: i16, b: i64) -> Struct2Asc { // bit64: %[[TEMP0:.+]] = insertvalue { i64, i16 } poison, i64 %b, 0 // bit64: %[[TEMP1:.+]] = insertvalue { i64, i16 } %[[TEMP0]], i16 %a, 1 // bit64: ret { i64, i16 } %[[TEMP1]] + // riscv64: %[[TEMP0:.+]] = insertvalue { i64, i16 } poison, i64 %b, 0 + // riscv64: %[[TEMP1:.+]] = insertvalue { i64, i16 } %[[TEMP0]], i16 %a, 1 + // riscv64: ret { i64, i16 } %[[TEMP1]] let s = Struct2Asc(a, b); s } pub struct Struct2Desc(i64, i16); -// bit32-LABEL: void @make_struct_2_desc({{.*}} sret({{[^,]*}}) {{.*}} %s, -// bit64-LABEL: { i64, i16 } @make_struct_2_desc( -// CHECK-SAME: i64 noundef %a, i16 noundef %b) +// ignore-tidy-linelength +// bit32-LABEL: void @make_struct_2_desc({{.*}} sret({{[^,]*}}) {{.*}} %s, i64 noundef %a, i16 noundef %b) +// bit64-LABEL: { i64, i16 } @make_struct_2_desc(i64 noundef %a, i16 noundef %b) +// riscv64-LABEL: { i64, i16 } @make_struct_2_desc(i64 noundef %a, i16 noundef signext %b) #[no_mangle] pub fn make_struct_2_desc(a: i64, b: i16) -> Struct2Desc { // CHECK-NOT: alloca @@ -132,6 +153,9 @@ pub fn make_struct_2_desc(a: i64, b: i16) -> Struct2Desc { // bit64: %[[TEMP0:.+]] = insertvalue { i64, i16 } poison, i64 %a, 0 // bit64: %[[TEMP1:.+]] = insertvalue { i64, i16 } %[[TEMP0]], i16 %b, 1 // bit64: ret { i64, i16 } %[[TEMP1]] + // riscv64: %[[TEMP0:.+]] = insertvalue { i64, i16 } poison, i64 %a, 0 + // riscv64: %[[TEMP1:.+]] = insertvalue { i64, i16 } %[[TEMP0]], i16 %b, 1 + // riscv64: ret { i64, i16 } %[[TEMP1]] let s = Struct2Desc(a, b); s } diff --git a/tests/codegen/range-attribute.rs b/tests/codegen/range-attribute.rs index 8972fc76ca28b..4348c8438acc7 100644 --- a/tests/codegen/range-attribute.rs +++ b/tests/codegen/range-attribute.rs @@ -2,9 +2,14 @@ // with scalar value. // 32-bit systems will return 128bit values using a return area pointer. -//@ revisions: bit32 bit64 +//@ revisions: bit32 bit64 riscv64 //@[bit32] only-32bit +//@[bit32] ignore-riscv64 //@[bit64] only-64bit +//@[bit64] ignore-riscv64 +//@[riscv64] only-riscv64 +//@[riscv64] compile-flags: --target riscv64gc-unknown-linux-gnu +//@[riscv64] needs-llvm-components: riscv //@ compile-flags: -O -C no-prepopulate-passes //@ min-llvm-version: 19 @@ -19,12 +24,15 @@ pub fn helper(_: usize) {} // bit32: void @nonzero_int({{.*}} sret([16 x i8]) {{.*}}, i128 noundef range(i128 1, 0) %x) // bit64: noundef range(i128 1, 0) i128 @nonzero_int(i128 noundef range(i128 1, 0) %x) +// riscv64: noundef range(i128 1, 0) i128 @nonzero_int(i128 noundef range(i128 1, 0) %x) #[no_mangle] pub fn nonzero_int(x: NonZero) -> NonZero { x } -// CHECK: noundef range(i8 0, 3) i8 @optional_bool(i8 noundef range(i8 0, 3) %x) +// bit32: noundef range(i8 0, 3) i8 @optional_bool(i8 noundef range(i8 0, 3) %x) +// bit64: noundef range(i8 0, 3) i8 @optional_bool(i8 noundef range(i8 0, 3) %x) +// riscv64: noundef range(i8 0, 3) i8 @optional_bool(i8 noundef zeroext range(i8 0, 3) %x) #[no_mangle] pub fn optional_bool(x: Option) -> Option { x @@ -36,7 +44,9 @@ pub enum Enum0 { C, } -// CHECK: noundef range(i8 0, 4) i8 @enum0_value(i8 noundef range(i8 0, 4) %x) +// bit32: noundef range(i8 0, 4) i8 @enum0_value(i8 noundef range(i8 0, 4) %x) +// bit64: noundef range(i8 0, 4) i8 @enum0_value(i8 noundef range(i8 0, 4) %x) +// riscv64: noundef range(i8 0, 4) i8 @enum0_value(i8 noundef zeroext range(i8 0, 4) %x) #[no_mangle] pub fn enum0_value(x: Enum0) -> Enum0 { x @@ -50,6 +60,7 @@ pub enum Enum1 { // bit32: void @enum1_value({{.*}} sret({{[^,]*}}) {{[^,]*}}, [[ENUM1_TYP:i[0-9]+]] // bit64: { [[ENUM1_TYP:i[0-9]+]], i64 } @enum1_value([[ENUM1_TYP]] +// riscv64: { [[ENUM1_TYP:i[0-9]+]], i64 } @enum1_value([[ENUM1_TYP]] // CHECK-SAME: noundef range([[ENUM1_TYP]] 0, 3) %x.0, i64 noundef %x.1) #[no_mangle] pub fn enum1_value(x: Enum1) -> Enum1 { diff --git a/tests/codegen/transmute-scalar.rs b/tests/codegen/transmute-scalar.rs index caaa70962d5b4..0ffd8fefd815c 100644 --- a/tests/codegen/transmute-scalar.rs +++ b/tests/codegen/transmute-scalar.rs @@ -1,4 +1,10 @@ //@ compile-flags: -C opt-level=0 -C no-prepopulate-passes +//@ revisions: others riscv64 + +//@[others] ignore-riscv64 +//@[riscv64] only-riscv64 +//@[riscv64] compile-flags: --target riscv64gc-unknown-linux-gnu +//@[riscv64] needs-llvm-components: riscv #![crate_type = "lib"] @@ -25,7 +31,8 @@ pub fn bool_to_byte(b: bool) -> u8 { unsafe { std::mem::transmute(b) } } -// CHECK-LABEL: define{{.*}}zeroext i1 @byte_to_bool(i8 %byte) +// others-LABEL: define{{.*}}zeroext i1 @byte_to_bool(i8 %byte) +// riscv64-LABEL: define{{.*}}zeroext i1 @byte_to_bool(i8 zeroext %byte) // CHECK: %_0 = trunc i8 %byte to i1 // CHECK-NEXT: ret i1 %_0 #[no_mangle] diff --git a/tests/codegen/union-abi.rs b/tests/codegen/union-abi.rs index b3c67a59730d9..256061e840557 100644 --- a/tests/codegen/union-abi.rs +++ b/tests/codegen/union-abi.rs @@ -2,11 +2,16 @@ //@ compile-flags: -O -C no-prepopulate-passes // 32-bit x86 returns `f32` differently to avoid the x87 stack. // 32-bit systems will return 128bit values using a return area pointer. -//@ revisions: x86 bit32 bit64 +//@ revisions: x86 riscv64 bit32 bit64 //@[x86] only-x86 +//@[riscv64] only-riscv64 +//@[riscv64] compile-flags: --target riscv64gc-unknown-linux-gnu +//@[riscv64] needs-llvm-components: riscv //@[bit32] ignore-x86 +//@[bit32] ignore-riscv64 //@[bit32] only-32bit //@[bit64] ignore-x86 +//@[bit64] ignore-riscv64 //@[bit64] only-64bit // This test that using union forward the abi of the inner type, as @@ -76,6 +81,7 @@ pub union UnionF32 { } // x86: define {{(dso_local )?}}i32 @test_UnionF32(float %_1) +// riscv64: define {{(dso_local )?}}float @test_UnionF32(float %_1) // bit32: define {{(dso_local )?}}float @test_UnionF32(float %_1) // bit64: define {{(dso_local )?}}float @test_UnionF32(float %_1) #[no_mangle] @@ -89,6 +95,7 @@ pub union UnionF32F32 { } // x86: define {{(dso_local )?}}i32 @test_UnionF32F32(float %_1) +// riscv64: define {{(dso_local )?}}float @test_UnionF32F32(float %_1) // bit32: define {{(dso_local )?}}float @test_UnionF32F32(float %_1) // bit64: define {{(dso_local )?}}float @test_UnionF32F32(float %_1) #[no_mangle] @@ -111,6 +118,7 @@ pub union UnionU128 { a: u128, } // x86: define {{(dso_local )?}}void @test_UnionU128({{.*}}sret([16 x i8]){{.*}}, i128 %_1) +// riscv64: define {{(dso_local )?}}i128 @test_UnionU128(i128 %_1) // bit32: define {{(dso_local )?}}void @test_UnionU128({{.*}}sret([16 x i8]){{.*}}, i128 %_1) // bit64: define {{(dso_local )?}}i128 @test_UnionU128(i128 %_1) #[no_mangle] @@ -131,7 +139,10 @@ pub fn test_CUnionU128(_: CUnionU128) { pub union UnionBool { b: bool, } -// CHECK: define {{(dso_local )?}}noundef zeroext i1 @test_UnionBool(i8 %b) +// x86: define {{(dso_local )?}}noundef zeroext i1 @test_UnionBool(i8 %b) +// riscv64: define {{(dso_local )?}}noundef zeroext i1 @test_UnionBool(i8 zeroext %b) +// bit32: define {{(dso_local )?}}noundef zeroext i1 @test_UnionBool(i8 %b) +// bit64: define {{(dso_local )?}}noundef zeroext i1 @test_UnionBool(i8 %b) #[no_mangle] pub fn test_UnionBool(b: UnionBool) -> bool { unsafe { b.b } diff --git a/tests/codegen/var-names.rs b/tests/codegen/var-names.rs index fd163a55551b6..fee06dd9ed3a4 100644 --- a/tests/codegen/var-names.rs +++ b/tests/codegen/var-names.rs @@ -1,8 +1,15 @@ //@ compile-flags: -O -C no-prepopulate-passes +//@ revisions: others riscv64 + +//@[others] ignore-riscv64 +//@[riscv64] only-riscv64 +//@[riscv64] compile-flags: --target riscv64gc-unknown-linux-gnu +//@[riscv64] needs-llvm-components: riscv #![crate_type = "lib"] -// CHECK-LABEL: define{{.*}}i32 @test(i32 noundef %a, i32 noundef %b) +// others-LABEL: define{{.*}}i32 @test(i32 noundef %a, i32 noundef %b) +// riscv64-LABEL: define{{.*}}i32 @test(i32 noundef signext %a, i32 noundef signext %b) #[no_mangle] pub fn test(a: u32, b: u32) -> u32 { let c = a + b;