Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 90a40a6

Browse files
committedOct 22, 2024
Auto merge of #131955 - SpriteOvO:riscv-int-arg-attr, r=<try>
Set `signext` or `zeroext` for integer arguments on RISC-V and LoongArch64 Fixes #114508. This PR contains 3 commits: - the first one introduces a new function `adjust_for_rust_abi` in `rustc_target`, and moves the x86 specific adjustment code into it; - the second one adds RISC-V specific adjustment code into it, which sets `signext` or `zeroext` attribute for integer arguments. - **UPDATE**: added the 3rd commit for apply the same adjustment for LoongArch64. r? `@workingjubilee` CC `@coastalwhite` `@Urgau` `@topperc` `@michaelmaitland` try-job: dist-loongarch64-linux try-job: dist-riscv64-linux try-job: test-various try-job: i686-gnu-nopt try-job: i686-gnu
2 parents 4392847 + 2dfd4d0 commit 90a40a6

20 files changed

+434
-173
lines changed
 

‎compiler/rustc_target/src/callconv/loongarch.rs

+28
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,30 @@ 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
386+
// https://github.com/rust-lang/rust/issues/114508 for details.
387+
extend_integer_width(arg, grlen);
388+
}
389+
}

‎compiler/rustc_target/src/callconv/mod.rs

+116-1
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1-
use std::fmt;
21
use std::str::FromStr;
2+
use std::{fmt, iter};
33

4+
use rustc_abi::AddressSpace;
5+
use rustc_abi::Primitive::Pointer;
46
pub use rustc_abi::{Reg, RegKind};
57
use rustc_macros::HashStable_Generic;
68
use rustc_span::Symbol;
79

810
use crate::abi::{self, Abi, Align, HasDataLayout, Size, TyAbiInterface, TyAndLayout};
11+
use crate::spec::abi::Abi as SpecAbi;
912
use crate::spec::{self, HasTargetSpec, HasWasmCAbiOpt, WasmCAbi};
1013

1114
mod aarch64;
@@ -716,6 +719,118 @@ impl<'a, Ty> FnAbi<'a, Ty> {
716719

717720
Ok(())
718721
}
722+
723+
pub fn adjust_for_rust_abi<C>(&mut self, cx: &C, abi: SpecAbi)
724+
where
725+
Ty: TyAbiInterface<'a, C> + Copy,
726+
C: HasDataLayout + HasTargetSpec,
727+
{
728+
let spec = cx.target_spec();
729+
match &spec.arch[..] {
730+
"x86" => x86::compute_rust_abi_info(cx, self, abi),
731+
"riscv32" | "riscv64" => riscv::compute_rust_abi_info(cx, self, abi),
732+
"loongarch64" => loongarch::compute_rust_abi_info(cx, self, abi),
733+
_ => {}
734+
};
735+
736+
for (arg_idx, arg) in self
737+
.args
738+
.iter_mut()
739+
.enumerate()
740+
.map(|(idx, arg)| (Some(idx), arg))
741+
.chain(iter::once((None, &mut self.ret)))
742+
{
743+
if arg.is_ignore() {
744+
continue;
745+
}
746+
747+
if arg_idx.is_none() && arg.layout.size > Pointer(AddressSpace::DATA).size(cx) * 2 {
748+
// Return values larger than 2 registers using a return area
749+
// pointer. LLVM and Cranelift disagree about how to return
750+
// values that don't fit in the registers designated for return
751+
// values. LLVM will force the entire return value to be passed
752+
// by return area pointer, while Cranelift will look at each IR level
753+
// return value independently and decide to pass it in a
754+
// register or not, which would result in the return value
755+
// being passed partially in registers and partially through a
756+
// return area pointer.
757+
//
758+
// While Cranelift may need to be fixed as the LLVM behavior is
759+
// generally more correct with respect to the surface language,
760+
// forcing this behavior in rustc itself makes it easier for
761+
// other backends to conform to the Rust ABI and for the C ABI
762+
// rustc already handles this behavior anyway.
763+
//
764+
// In addition LLVM's decision to pass the return value in
765+
// registers or using a return area pointer depends on how
766+
// exactly the return type is lowered to an LLVM IR type. For
767+
// example `Option<u128>` can be lowered as `{ i128, i128 }`
768+
// in which case the x86_64 backend would use a return area
769+
// pointer, or it could be passed as `{ i32, i128 }` in which
770+
// case the x86_64 backend would pass it in registers by taking
771+
// advantage of an LLVM ABI extension that allows using 3
772+
// registers for the x86_64 sysv call conv rather than the
773+
// officially specified 2 registers.
774+
//
775+
// FIXME: Technically we should look at the amount of available
776+
// return registers rather than guessing that there are 2
777+
// registers for return values. In practice only a couple of
778+
// architectures have less than 2 return registers. None of
779+
// which supported by Cranelift.
780+
//
781+
// NOTE: This adjustment is only necessary for the Rust ABI as
782+
// for other ABI's the calling convention implementations in
783+
// rustc_target already ensure any return value which doesn't
784+
// fit in the available amount of return registers is passed in
785+
// the right way for the current target.
786+
arg.make_indirect();
787+
continue;
788+
}
789+
790+
match arg.layout.abi {
791+
Abi::Aggregate { .. } => {}
792+
793+
// This is a fun case! The gist of what this is doing is
794+
// that we want callers and callees to always agree on the
795+
// ABI of how they pass SIMD arguments. If we were to *not*
796+
// make these arguments indirect then they'd be immediates
797+
// in LLVM, which means that they'd used whatever the
798+
// appropriate ABI is for the callee and the caller. That
799+
// means, for example, if the caller doesn't have AVX
800+
// enabled but the callee does, then passing an AVX argument
801+
// across this boundary would cause corrupt data to show up.
802+
//
803+
// This problem is fixed by unconditionally passing SIMD
804+
// arguments through memory between callers and callees
805+
// which should get them all to agree on ABI regardless of
806+
// target feature sets. Some more information about this
807+
// issue can be found in #44367.
808+
//
809+
// Note that the intrinsic ABI is exempt here as
810+
// that's how we connect up to LLVM and it's unstable
811+
// anyway, we control all calls to it in libstd.
812+
Abi::Vector { .. } if abi != SpecAbi::RustIntrinsic && spec.simd_types_indirect => {
813+
arg.make_indirect();
814+
continue;
815+
}
816+
817+
_ => continue,
818+
}
819+
// Compute `Aggregate` ABI.
820+
821+
let is_indirect_not_on_stack =
822+
matches!(arg.mode, PassMode::Indirect { on_stack: false, .. });
823+
assert!(is_indirect_not_on_stack);
824+
825+
let size = arg.layout.size;
826+
if !arg.layout.is_unsized() && size <= Pointer(AddressSpace::DATA).size(cx) {
827+
// We want to pass small aggregates as immediates, but using
828+
// an LLVM aggregate type for this leads to bad optimizations,
829+
// so we pick an appropriately sized integer type instead.
830+
arg.cast_to(Reg { kind: RegKind::Integer, size });
831+
}
832+
}
833+
}
719834
}
720835

721836
impl FromStr for Conv {

‎compiler/rustc_target/src/callconv/riscv.rs

+27
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use crate::abi::call::{ArgAbi, ArgExtension, CastTarget, FnAbi, PassMode, Reg, RegKind, Uniform};
88
use crate::abi::{self, Abi, FieldsShape, HasDataLayout, Size, TyAbiInterface, TyAndLayout};
99
use crate::spec::HasTargetSpec;
10+
use crate::spec::abi::Abi as SpecAbi;
1011

1112
#[derive(Copy, Clone)]
1213
enum RegPassKind {
@@ -365,3 +366,29 @@ where
365366
);
366367
}
367368
}
369+
370+
pub(crate) fn compute_rust_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>, abi: SpecAbi)
371+
where
372+
Ty: TyAbiInterface<'a, C> + Copy,
373+
C: HasDataLayout + HasTargetSpec,
374+
{
375+
if abi == SpecAbi::RustIntrinsic {
376+
return;
377+
}
378+
379+
let xlen = cx.data_layout().pointer_size.bits();
380+
381+
for arg in fn_abi.args.iter_mut() {
382+
if arg.is_ignore() {
383+
continue;
384+
}
385+
386+
// LLVM integers types do not differentiate between signed or unsigned integers.
387+
// Some RISC-V instructions do not have a `.w` suffix version, they use all the
388+
// XLEN bits. By explicitly setting the `signext` or `zeroext` attribute
389+
// according to signedness to avoid unnecessary integer extending instructions.
390+
//
391+
// See https://github.com/rust-lang/rust/issues/114508 for details.
392+
extend_integer_width(arg, xlen);
393+
}
394+
}

‎compiler/rustc_target/src/callconv/x86.rs

+39
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
1+
use rustc_abi::Float::*;
2+
use rustc_abi::Primitive::Float;
3+
14
use crate::abi::call::{ArgAttribute, FnAbi, PassMode, Reg, RegKind};
25
use crate::abi::{Abi, Align, HasDataLayout, TyAbiInterface, TyAndLayout};
36
use crate::spec::HasTargetSpec;
7+
use crate::spec::abi::Abi as SpecAbi;
48

59
#[derive(PartialEq)]
610
pub(crate) enum Flavor {
@@ -183,3 +187,38 @@ where
183187
}
184188
}
185189
}
190+
191+
pub(crate) fn compute_rust_abi_info<'a, Ty, C>(_cx: &C, fn_abi: &mut FnAbi<'a, Ty>, abi: SpecAbi)
192+
where
193+
Ty: TyAbiInterface<'a, C> + Copy,
194+
C: HasDataLayout + HasTargetSpec,
195+
{
196+
// Avoid returning floats in x87 registers on x86 as loading and storing from x87
197+
// registers will quiet signalling NaNs.
198+
if !fn_abi.ret.is_ignore()
199+
// Intrinsics themselves are not actual "real" functions, so theres no need to change their ABIs.
200+
&& abi != SpecAbi::RustIntrinsic
201+
{
202+
match fn_abi.ret.layout.abi {
203+
// Handle similar to the way arguments with an `Abi::Aggregate` abi are handled
204+
// in `adjust_for_rust_abi`, by returning arguments up to the size of a pointer (32 bits on x86)
205+
// cast to an appropriately sized integer.
206+
Abi::Scalar(s) if s.primitive() == Float(F32) => {
207+
// Same size as a pointer, return in a register.
208+
fn_abi.ret.cast_to(Reg::i32());
209+
}
210+
Abi::Scalar(s) if s.primitive() == Float(F64) => {
211+
// Larger than a pointer, return indirectly.
212+
fn_abi.ret.make_indirect();
213+
}
214+
Abi::ScalarPair(s1, s2)
215+
if matches!(s1.primitive(), Float(F32 | F64))
216+
|| matches!(s2.primitive(), Float(F32 | F64)) =>
217+
{
218+
// Larger than a pointer, return indirectly.
219+
fn_abi.ret.make_indirect();
220+
}
221+
_ => {}
222+
};
223+
}
224+
}

‎compiler/rustc_ty_utils/src/abi.rs

+8-137
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
use std::iter;
22

3-
use rustc_abi::Float::*;
4-
use rustc_abi::Primitive::{Float, Pointer};
5-
use rustc_abi::{Abi, AddressSpace, PointerKind, Scalar, Size};
3+
use rustc_abi::Primitive::Pointer;
4+
use rustc_abi::{Abi, PointerKind, Scalar, Size};
65
use rustc_hir as hir;
76
use rustc_hir::lang_items::LangItem;
87
use rustc_middle::bug;
@@ -14,8 +13,7 @@ use rustc_middle::ty::{self, InstanceKind, Ty, TyCtxt};
1413
use rustc_session::config::OptLevel;
1514
use rustc_span::def_id::DefId;
1615
use rustc_target::abi::call::{
17-
ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, Conv, FnAbi, PassMode, Reg, RegKind,
18-
RiscvInterruptKind,
16+
ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, Conv, FnAbi, PassMode, RiscvInterruptKind,
1917
};
2018
use rustc_target::spec::abi::Abi as SpecAbi;
2119
use tracing::debug;
@@ -679,6 +677,8 @@ fn fn_abi_adjust_for_abi<'tcx>(
679677
let tcx = cx.tcx();
680678

681679
if abi == SpecAbi::Rust || abi == SpecAbi::RustCall || abi == SpecAbi::RustIntrinsic {
680+
fn_abi.adjust_for_rust_abi(cx, abi);
681+
682682
// Look up the deduced parameter attributes for this function, if we have its def ID and
683683
// we're optimizing in non-incremental mode. We'll tag its parameters with those attributes
684684
// as appropriate.
@@ -689,141 +689,17 @@ fn fn_abi_adjust_for_abi<'tcx>(
689689
&[]
690690
};
691691

692-
let fixup = |arg: &mut ArgAbi<'tcx, Ty<'tcx>>, arg_idx: Option<usize>| {
692+
for (arg_idx, arg) in fn_abi.args.iter_mut().enumerate() {
693693
if arg.is_ignore() {
694-
return;
695-
}
696-
697-
// Avoid returning floats in x87 registers on x86 as loading and storing from x87
698-
// registers will quiet signalling NaNs.
699-
if tcx.sess.target.arch == "x86"
700-
&& arg_idx.is_none()
701-
// Intrinsics themselves are not actual "real" functions, so theres no need to
702-
// change their ABIs.
703-
&& abi != SpecAbi::RustIntrinsic
704-
{
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;
713-
}
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-
{
723-
// Larger than a pointer, return indirectly.
724-
arg.make_indirect();
725-
return;
726-
}
727-
_ => {}
728-
};
729-
}
730-
731-
if arg_idx.is_none() && arg.layout.size > Pointer(AddressSpace::DATA).size(cx) * 2 {
732-
// Return values larger than 2 registers using a return area
733-
// pointer. LLVM and Cranelift disagree about how to return
734-
// values that don't fit in the registers designated for return
735-
// values. LLVM will force the entire return value to be passed
736-
// by return area pointer, while Cranelift will look at each IR level
737-
// return value independently and decide to pass it in a
738-
// register or not, which would result in the return value
739-
// being passed partially in registers and partially through a
740-
// return area pointer.
741-
//
742-
// While Cranelift may need to be fixed as the LLVM behavior is
743-
// generally more correct with respect to the surface language,
744-
// forcing this behavior in rustc itself makes it easier for
745-
// other backends to conform to the Rust ABI and for the C ABI
746-
// rustc already handles this behavior anyway.
747-
//
748-
// In addition LLVM's decision to pass the return value in
749-
// registers or using a return area pointer depends on how
750-
// exactly the return type is lowered to an LLVM IR type. For
751-
// example `Option<u128>` can be lowered as `{ i128, i128 }`
752-
// in which case the x86_64 backend would use a return area
753-
// pointer, or it could be passed as `{ i32, i128 }` in which
754-
// case the x86_64 backend would pass it in registers by taking
755-
// advantage of an LLVM ABI extension that allows using 3
756-
// registers for the x86_64 sysv call conv rather than the
757-
// officially specified 2 registers.
758-
//
759-
// FIXME: Technically we should look at the amount of available
760-
// return registers rather than guessing that there are 2
761-
// registers for return values. In practice only a couple of
762-
// architectures have less than 2 return registers. None of
763-
// which supported by Cranelift.
764-
//
765-
// NOTE: This adjustment is only necessary for the Rust ABI as
766-
// for other ABI's the calling convention implementations in
767-
// rustc_target already ensure any return value which doesn't
768-
// fit in the available amount of return registers is passed in
769-
// the right way for the current target.
770-
arg.make_indirect();
771-
return;
772-
}
773-
774-
match arg.layout.abi {
775-
Abi::Aggregate { .. } => {}
776-
777-
// This is a fun case! The gist of what this is doing is
778-
// that we want callers and callees to always agree on the
779-
// ABI of how they pass SIMD arguments. If we were to *not*
780-
// make these arguments indirect then they'd be immediates
781-
// in LLVM, which means that they'd used whatever the
782-
// appropriate ABI is for the callee and the caller. That
783-
// means, for example, if the caller doesn't have AVX
784-
// enabled but the callee does, then passing an AVX argument
785-
// across this boundary would cause corrupt data to show up.
786-
//
787-
// This problem is fixed by unconditionally passing SIMD
788-
// arguments through memory between callers and callees
789-
// which should get them all to agree on ABI regardless of
790-
// target feature sets. Some more information about this
791-
// issue can be found in #44367.
792-
//
793-
// Note that the intrinsic ABI is exempt here as
794-
// that's how we connect up to LLVM and it's unstable
795-
// anyway, we control all calls to it in libstd.
796-
Abi::Vector { .. }
797-
if abi != SpecAbi::RustIntrinsic && tcx.sess.target.simd_types_indirect =>
798-
{
799-
arg.make_indirect();
800-
return;
801-
}
802-
803-
_ => return,
804-
}
805-
// Compute `Aggregate` ABI.
806-
807-
let is_indirect_not_on_stack =
808-
matches!(arg.mode, PassMode::Indirect { on_stack: false, .. });
809-
assert!(is_indirect_not_on_stack, "{:?}", arg);
810-
811-
let size = arg.layout.size;
812-
if !arg.layout.is_unsized() && size <= Pointer(AddressSpace::DATA).size(cx) {
813-
// We want to pass small aggregates as immediates, but using
814-
// an LLVM aggregate type for this leads to bad optimizations,
815-
// so we pick an appropriately sized integer type instead.
816-
arg.cast_to(Reg { kind: RegKind::Integer, size });
694+
continue;
817695
}
818696

819697
// If we deduced that this parameter was read-only, add that to the attribute list now.
820698
//
821699
// The `readonly` parameter only applies to pointers, so we can only do this if the
822700
// argument was passed indirectly. (If the argument is passed directly, it's an SSA
823701
// value, so it's implicitly immutable.)
824-
if let (Some(arg_idx), &mut PassMode::Indirect { ref mut attrs, .. }) =
825-
(arg_idx, &mut arg.mode)
826-
{
702+
if let &mut PassMode::Indirect { ref mut attrs, .. } = &mut arg.mode {
827703
// The `deduced_param_attrs` list could be empty if this is a type of function
828704
// we can't deduce any parameters for, so make sure the argument index is in
829705
// bounds.
@@ -834,11 +710,6 @@ fn fn_abi_adjust_for_abi<'tcx>(
834710
}
835711
}
836712
}
837-
};
838-
839-
fixup(&mut fn_abi.ret, None);
840-
for (arg_idx, arg) in fn_abi.args.iter_mut().enumerate() {
841-
fixup(arg, Some(arg_idx));
842713
}
843714
} else {
844715
fn_abi

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

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
//@ assembly-output: emit-asm
2+
//@ revisions: riscv64 riscv64-zbb loongarch64
3+
//@ compile-flags: -C opt-level=3
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
9+
//@ [riscv64-zbb] compile-flags: -C target-feature=+zbb
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
14+
15+
#![crate_type = "lib"]
16+
17+
#[no_mangle]
18+
// CHECK-LABEL: issue_114508_u32:
19+
pub fn issue_114508_u32(a: u32, b: u32) -> u32 {
20+
// CHECK-NEXT: .cfi_startproc
21+
22+
// riscv64-NEXT: bltu a1, a0, .[[RET:.+]]
23+
// riscv64-NEXT: mv a0, a1
24+
// riscv64-NEXT: .[[RET]]:
25+
26+
// riscv64-zbb-NEXT: maxu a0, a0, a1
27+
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+
33+
// CHECK-NEXT: ret
34+
u32::max(a, b)
35+
}
36+
37+
#[no_mangle]
38+
// CHECK-LABEL: issue_114508_i32:
39+
pub fn issue_114508_i32(a: i32, b: i32) -> i32 {
40+
// CHECK-NEXT: .cfi_startproc
41+
42+
// riscv64-NEXT: blt a1, a0, .[[RET:.+]]
43+
// riscv64-NEXT: mv a0, a1
44+
// riscv64-NEXT: .[[RET]]:
45+
46+
// riscv64-zbb-NEXT: max a0, a0, a1
47+
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+
53+
// CHECK-NEXT: ret
54+
i32::max(a, b)
55+
}

‎tests/codegen/checked_ilog.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
// Ensure that when val < base, we do not divide or multiply.
66

77
// CHECK-LABEL: @checked_ilog
8-
// CHECK-SAME: (i16 noundef %val, i16 noundef %base)
8+
// CHECK-SAME: (i16{{.*}} %val, i16{{.*}} %base)
99
#[no_mangle]
1010
pub fn checked_ilog(val: u16, base: u16) -> Option<u32> {
1111
// CHECK-NOT: udiv

‎tests/codegen/checked_math.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// Thanks to poison semantics, this doesn't even need branches.
99

1010
// CHECK-LABEL: @checked_sub_unsigned
11-
// CHECK-SAME: (i16 noundef %a, i16 noundef %b)
11+
// CHECK-SAME: (i16{{.*}} %a, i16{{.*}} %b)
1212
#[no_mangle]
1313
pub fn checked_sub_unsigned(a: u16, b: u16) -> Option<u16> {
1414
// CHECK-DAG: %[[IS_SOME:.+]] = icmp uge i16 %a, %b
@@ -26,7 +26,7 @@ pub fn checked_sub_unsigned(a: u16, b: u16) -> Option<u16> {
2626
// looking for no-wrap flags, we just need there to not be any masking.
2727

2828
// CHECK-LABEL: @checked_shl_unsigned
29-
// CHECK-SAME: (i32 noundef %a, i32 noundef %b)
29+
// CHECK-SAME: (i32{{.*}} %a, i32{{.*}} %b)
3030
#[no_mangle]
3131
pub fn checked_shl_unsigned(a: u32, b: u32) -> Option<u32> {
3232
// CHECK-DAG: %[[IS_SOME:.+]] = icmp ult i32 %b, 32
@@ -41,7 +41,7 @@ pub fn checked_shl_unsigned(a: u32, b: u32) -> Option<u32> {
4141
}
4242

4343
// CHECK-LABEL: @checked_shr_unsigned
44-
// CHECK-SAME: (i32 noundef %a, i32 noundef %b)
44+
// CHECK-SAME: (i32{{.*}} %a, i32{{.*}} %b)
4545
#[no_mangle]
4646
pub fn checked_shr_unsigned(a: u32, b: u32) -> Option<u32> {
4747
// CHECK-DAG: %[[IS_SOME:.+]] = icmp ult i32 %b, 32
@@ -56,7 +56,7 @@ pub fn checked_shr_unsigned(a: u32, b: u32) -> Option<u32> {
5656
}
5757

5858
// CHECK-LABEL: @checked_shl_signed
59-
// CHECK-SAME: (i32 noundef %a, i32 noundef %b)
59+
// CHECK-SAME: (i32{{.*}} %a, i32{{.*}} %b)
6060
#[no_mangle]
6161
pub fn checked_shl_signed(a: i32, b: u32) -> Option<i32> {
6262
// CHECK-DAG: %[[IS_SOME:.+]] = icmp ult i32 %b, 32
@@ -71,7 +71,7 @@ pub fn checked_shl_signed(a: i32, b: u32) -> Option<i32> {
7171
}
7272

7373
// CHECK-LABEL: @checked_shr_signed
74-
// CHECK-SAME: (i32 noundef %a, i32 noundef %b)
74+
// CHECK-SAME: (i32{{.*}} %a, i32{{.*}} %b)
7575
#[no_mangle]
7676
pub fn checked_shr_signed(a: i32, b: u32) -> Option<i32> {
7777
// CHECK-DAG: %[[IS_SOME:.+]] = icmp ult i32 %b, 32
@@ -86,7 +86,7 @@ pub fn checked_shr_signed(a: i32, b: u32) -> Option<i32> {
8686
}
8787

8888
// CHECK-LABEL: @checked_add_one_unwrap_unsigned
89-
// CHECK-SAME: (i32 noundef %x)
89+
// CHECK-SAME: (i32{{.*}} %x)
9090
#[no_mangle]
9191
pub fn checked_add_one_unwrap_unsigned(x: u32) -> u32 {
9292
// CHECK: %[[IS_MAX:.+]] = icmp eq i32 %x, -1

‎tests/codegen/comparison-operators-newtype.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use std::cmp::Ordering;
1212
pub struct Foo(u16);
1313

1414
// CHECK-LABEL: @check_lt
15-
// CHECK-SAME: (i16 noundef %[[A:.+]], i16 noundef %[[B:.+]])
15+
// CHECK-SAME: (i16{{.*}} %[[A:.+]], i16{{.*}} %[[B:.+]])
1616
#[no_mangle]
1717
pub fn check_lt(a: Foo, b: Foo) -> bool {
1818
// CHECK: %[[R:.+]] = icmp ult i16 %[[A]], %[[B]]
@@ -21,7 +21,7 @@ pub fn check_lt(a: Foo, b: Foo) -> bool {
2121
}
2222

2323
// CHECK-LABEL: @check_le
24-
// CHECK-SAME: (i16 noundef %[[A:.+]], i16 noundef %[[B:.+]])
24+
// CHECK-SAME: (i16{{.*}} %[[A:.+]], i16{{.*}} %[[B:.+]])
2525
#[no_mangle]
2626
pub fn check_le(a: Foo, b: Foo) -> bool {
2727
// CHECK: %[[R:.+]] = icmp ule i16 %[[A]], %[[B]]
@@ -30,7 +30,7 @@ pub fn check_le(a: Foo, b: Foo) -> bool {
3030
}
3131

3232
// CHECK-LABEL: @check_gt
33-
// CHECK-SAME: (i16 noundef %[[A:.+]], i16 noundef %[[B:.+]])
33+
// CHECK-SAME: (i16{{.*}} %[[A:.+]], i16{{.*}} %[[B:.+]])
3434
#[no_mangle]
3535
pub fn check_gt(a: Foo, b: Foo) -> bool {
3636
// CHECK: %[[R:.+]] = icmp ugt i16 %[[A]], %[[B]]
@@ -39,7 +39,7 @@ pub fn check_gt(a: Foo, b: Foo) -> bool {
3939
}
4040

4141
// CHECK-LABEL: @check_ge
42-
// CHECK-SAME: (i16 noundef %[[A:.+]], i16 noundef %[[B:.+]])
42+
// CHECK-SAME: (i16{{.*}} %[[A:.+]], i16{{.*}} %[[B:.+]])
4343
#[no_mangle]
4444
pub fn check_ge(a: Foo, b: Foo) -> bool {
4545
// CHECK: %[[R:.+]] = icmp uge i16 %[[A]], %[[B]]

‎tests/codegen/fewer-names.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@
66

77
#[no_mangle]
88
pub fn sum(x: u32, y: u32) -> u32 {
9-
// YES-LABEL: define{{.*}}i32 @sum(i32 noundef %0, i32 noundef %1)
9+
// YES-LABEL: define{{.*}}i32 @sum(i32{{.*}} %0, i32{{.*}} %1)
1010
// YES-NEXT: %3 = add i32 %1, %0
1111
// YES-NEXT: ret i32 %3
1212

13-
// NO-LABEL: define{{.*}}i32 @sum(i32 noundef %x, i32 noundef %y)
13+
// NO-LABEL: define{{.*}}i32 @sum(i32{{.*}} %x, i32{{.*}} %y)
1414
// NO-NEXT: start:
1515
// NO-NEXT: %z = add i32 %y, %x
1616
// NO-NEXT: ret i32 %z

‎tests/codegen/function-arguments.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ pub fn boolean(x: bool) -> bool {
3232
x
3333
}
3434

35-
// CHECK: i8 @maybeuninit_boolean(i8 %x)
35+
// CHECK: i8 @maybeuninit_boolean(i8{{.*}} %x)
3636
#[no_mangle]
3737
pub fn maybeuninit_boolean(x: MaybeUninit<bool>) -> MaybeUninit<bool> {
3838
x
@@ -44,19 +44,19 @@ pub fn enum_bool(x: MyBool) -> MyBool {
4444
x
4545
}
4646

47-
// CHECK: i8 @maybeuninit_enum_bool(i8 %x)
47+
// CHECK: i8 @maybeuninit_enum_bool(i8{{.*}} %x)
4848
#[no_mangle]
4949
pub fn maybeuninit_enum_bool(x: MaybeUninit<MyBool>) -> MaybeUninit<MyBool> {
5050
x
5151
}
5252

53-
// CHECK: noundef{{( range\(i32 0, 1114112\))?}} i32 @char(i32 noundef{{( range\(i32 0, 1114112\))?}} %x)
53+
// CHECK: noundef{{( range\(i32 0, 1114112\))?}} i32 @char(i32{{.*}}{{( range\(i32 0, 1114112\))?}} %x)
5454
#[no_mangle]
5555
pub fn char(x: char) -> char {
5656
x
5757
}
5858

59-
// CHECK: i32 @maybeuninit_char(i32 %x)
59+
// CHECK: i32 @maybeuninit_char(i32{{.*}} %x)
6060
#[no_mangle]
6161
pub fn maybeuninit_char(x: MaybeUninit<char>) -> MaybeUninit<char> {
6262
x

‎tests/codegen/intrinsics/three_way_compare.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@ use std::intrinsics::three_way_compare;
1010

1111
#[no_mangle]
1212
// CHECK-LABEL: @signed_cmp
13-
// DEBUG-SAME: (i16 %a, i16 %b)
14-
// OPTIM-SAME: (i16 noundef %a, i16 noundef %b)
13+
// CHECK-SAME: (i16{{.*}} %a, i16{{.*}} %b)
1514
pub fn signed_cmp(a: i16, b: i16) -> std::cmp::Ordering {
1615
// DEBUG: %[[GT:.+]] = icmp sgt i16 %a, %b
1716
// DEBUG: %[[ZGT:.+]] = zext i1 %[[GT]] to i8
@@ -29,8 +28,7 @@ pub fn signed_cmp(a: i16, b: i16) -> std::cmp::Ordering {
2928

3029
#[no_mangle]
3130
// CHECK-LABEL: @unsigned_cmp
32-
// DEBUG-SAME: (i16 %a, i16 %b)
33-
// OPTIM-SAME: (i16 noundef %a, i16 noundef %b)
31+
// CHECK-SAME: (i16{{.*}} %a, i16{{.*}} %b)
3432
pub fn unsigned_cmp(a: u16, b: u16) -> std::cmp::Ordering {
3533
// DEBUG: %[[GT:.+]] = icmp ugt i16 %a, %b
3634
// DEBUG: %[[ZGT:.+]] = zext i1 %[[GT]] to i8

‎tests/codegen/mir-aggregate-no-alloca.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
#[repr(transparent)]
1010
pub struct Transparent32(u32);
1111

12-
// CHECK: i32 @make_transparent(i32 noundef %x)
12+
// CHECK: i32 @make_transparent(i32{{.*}} %x)
1313
#[no_mangle]
1414
pub fn make_transparent(x: u32) -> Transparent32 {
1515
// CHECK-NOT: alloca
@@ -18,7 +18,7 @@ pub fn make_transparent(x: u32) -> Transparent32 {
1818
a
1919
}
2020

21-
// CHECK: i32 @make_closure(i32 noundef %x)
21+
// CHECK: i32 @make_closure(i32{{.*}} %x)
2222
#[no_mangle]
2323
pub fn make_closure(x: i32) -> impl Fn(i32) -> i32 {
2424
// CHECK-NOT: alloca
@@ -40,7 +40,7 @@ pub fn make_transparent_pair(x: (u16, u16)) -> TransparentPair {
4040
a
4141
}
4242

43-
// CHECK-LABEL: { i32, i32 } @make_2_tuple(i32 noundef %x)
43+
// CHECK-LABEL: { i32, i32 } @make_2_tuple(i32{{.*}} %x)
4444
#[no_mangle]
4545
pub fn make_2_tuple(x: u32) -> (u32, u32) {
4646
// CHECK-NOT: alloca
@@ -59,7 +59,7 @@ pub fn make_cell_of_bool(b: bool) -> std::cell::Cell<bool> {
5959
std::cell::Cell::new(b)
6060
}
6161

62-
// CHECK-LABEL: { i8, i16 } @make_cell_of_bool_and_short(i1 noundef zeroext %b, i16 noundef %s)
62+
// CHECK-LABEL: { i8, i16 } @make_cell_of_bool_and_short(i1 noundef zeroext %b, i16{{.*}} %s)
6363
#[no_mangle]
6464
pub fn make_cell_of_bool_and_short(b: bool, s: u16) -> std::cell::Cell<(bool, u16)> {
6565
// CHECK-NOT: alloca
@@ -92,7 +92,7 @@ pub fn make_struct_0() -> Struct0 {
9292

9393
pub struct Struct1(i32);
9494

95-
// CHECK-LABEL: i32 @make_struct_1(i32 noundef %a)
95+
// CHECK-LABEL: i32 @make_struct_1(i32{{.*}} %a)
9696
#[no_mangle]
9797
pub fn make_struct_1(a: i32) -> Struct1 {
9898
// CHECK: ret i32 %a
@@ -104,7 +104,7 @@ pub struct Struct2Asc(i16, i64);
104104

105105
// bit32-LABEL: void @make_struct_2_asc({{.*}} sret({{[^,]*}}) {{.*}} %s,
106106
// bit64-LABEL: { i64, i16 } @make_struct_2_asc(
107-
// CHECK-SAME: i16 noundef %a, i64 noundef %b)
107+
// CHECK-SAME: i16{{.*}} %a, i64 noundef %b)
108108
#[no_mangle]
109109
pub fn make_struct_2_asc(a: i16, b: i64) -> Struct2Asc {
110110
// CHECK-NOT: alloca
@@ -122,7 +122,7 @@ pub struct Struct2Desc(i64, i16);
122122

123123
// bit32-LABEL: void @make_struct_2_desc({{.*}} sret({{[^,]*}}) {{.*}} %s,
124124
// bit64-LABEL: { i64, i16 } @make_struct_2_desc(
125-
// CHECK-SAME: i64 noundef %a, i16 noundef %b)
125+
// CHECK-SAME: i64 noundef %a, i16{{.*}} %b)
126126
#[no_mangle]
127127
pub fn make_struct_2_desc(a: i64, b: i16) -> Struct2Desc {
128128
// CHECK-NOT: alloca

‎tests/codegen/range-attribute.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ pub fn nonzero_int(x: NonZero<u128>) -> NonZero<u128> {
2424
x
2525
}
2626

27-
// CHECK: noundef range(i8 0, 3) i8 @optional_bool(i8 noundef range(i8 0, 3) %x)
27+
// CHECK: noundef range(i8 0, 3) i8 @optional_bool(i8{{.*}} range(i8 0, 3) %x)
2828
#[no_mangle]
2929
pub fn optional_bool(x: Option<bool>) -> Option<bool> {
3030
x
@@ -36,7 +36,7 @@ pub enum Enum0 {
3636
C,
3737
}
3838

39-
// CHECK: noundef range(i8 0, 4) i8 @enum0_value(i8 noundef range(i8 0, 4) %x)
39+
// CHECK: noundef range(i8 0, 4) i8 @enum0_value(i8{{.*}} range(i8 0, 4) %x)
4040
#[no_mangle]
4141
pub fn enum0_value(x: Enum0) -> Enum0 {
4242
x
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
//@ compile-flags: -O -C no-prepopulate-passes
2+
//@ revisions: others riscv64 loongarch64
3+
4+
//@[others] ignore-riscv64
5+
//@[others] ignore-loongarch64
6+
7+
//@[riscv64] only-riscv64
8+
//@[riscv64] compile-flags: --target riscv64gc-unknown-linux-gnu
9+
//@[riscv64] needs-llvm-components: riscv
10+
11+
//@[loongarch64] only-loongarch64
12+
//@[loongarch64] compile-flags: --target loongarch64-unknown-linux-gnu
13+
//@[loongarch64] needs-llvm-components: loongarch
14+
15+
#![crate_type = "lib"]
16+
17+
#[no_mangle]
18+
// others: define noundef i8 @arg_attr_u8(i8 noundef %x)
19+
// riscv64: define noundef i8 @arg_attr_u8(i8 noundef zeroext %x)
20+
// loongarch64: define noundef i8 @arg_attr_u8(i8 noundef zeroext %x)
21+
pub fn arg_attr_u8(x: u8) -> u8 {
22+
x
23+
}
24+
25+
#[no_mangle]
26+
// others: define noundef i16 @arg_attr_u16(i16 noundef %x)
27+
// riscv64: define noundef i16 @arg_attr_u16(i16 noundef zeroext %x)
28+
// loongarch64: define noundef i16 @arg_attr_u16(i16 noundef zeroext %x)
29+
pub fn arg_attr_u16(x: u16) -> u16 {
30+
x
31+
}
32+
33+
#[no_mangle]
34+
// others: define noundef i32 @arg_attr_u32(i32 noundef %x)
35+
// riscv64: define noundef i32 @arg_attr_u32(i32 noundef signext %x)
36+
// loongarch64: define noundef i32 @arg_attr_u32(i32 noundef signext %x)
37+
pub fn arg_attr_u32(x: u32) -> u32 {
38+
x
39+
}
40+
41+
#[no_mangle]
42+
// others: define noundef i64 @arg_attr_u64(i64 noundef %x)
43+
// riscv64: define noundef i64 @arg_attr_u64(i64 noundef %x)
44+
// loongarch64: define noundef i64 @arg_attr_u64(i64 noundef %x)
45+
pub fn arg_attr_u64(x: u64) -> u64 {
46+
x
47+
}
48+
49+
#[no_mangle]
50+
// others: define noundef i128 @arg_attr_u128(i128 noundef %x)
51+
// riscv64: define noundef i128 @arg_attr_u128(i128 noundef %x)
52+
// loongarch64: define noundef i128 @arg_attr_u128(i128 noundef %x)
53+
pub fn arg_attr_u128(x: u128) -> u128 {
54+
x
55+
}
56+
57+
#[no_mangle]
58+
// others: define noundef i8 @arg_attr_i8(i8 noundef %x)
59+
// riscv64: define noundef i8 @arg_attr_i8(i8 noundef signext %x)
60+
// loongarch64: define noundef i8 @arg_attr_i8(i8 noundef signext %x)
61+
pub fn arg_attr_i8(x: i8) -> i8 {
62+
x
63+
}
64+
65+
#[no_mangle]
66+
// others: define noundef i16 @arg_attr_i16(i16 noundef %x)
67+
// riscv64: define noundef i16 @arg_attr_i16(i16 noundef signext %x)
68+
// loongarch64: define noundef i16 @arg_attr_i16(i16 noundef signext %x)
69+
pub fn arg_attr_i16(x: i16) -> i16 {
70+
x
71+
}
72+
73+
#[no_mangle]
74+
// others: define noundef i32 @arg_attr_i32(i32 noundef %x)
75+
// riscv64: define noundef i32 @arg_attr_i32(i32 noundef signext %x)
76+
// loongarch64: define noundef i32 @arg_attr_i32(i32 noundef signext %x)
77+
pub fn arg_attr_i32(x: i32) -> i32 {
78+
x
79+
}
80+
81+
#[no_mangle]
82+
// others: define noundef i64 @arg_attr_i64(i64 noundef %x)
83+
// riscv64: define noundef i64 @arg_attr_i64(i64 noundef %x)
84+
// loongarch64: define noundef i64 @arg_attr_i64(i64 noundef %x)
85+
pub fn arg_attr_i64(x: i64) -> i64 {
86+
x
87+
}
88+
89+
#[no_mangle]
90+
// others: define noundef i128 @arg_attr_i128(i128 noundef %x)
91+
// riscv64: define noundef i128 @arg_attr_i128(i128 noundef %x)
92+
// loongarch64: define noundef i128 @arg_attr_i128(i128 noundef %x)
93+
pub fn arg_attr_i128(x: i128) -> i128 {
94+
x
95+
}
96+
97+
#[no_mangle]
98+
// others: define noundef zeroext i1 @arg_attr_bool(i1 noundef zeroext %x)
99+
// riscv64: define noundef zeroext i1 @arg_attr_bool(i1 noundef zeroext %x)
100+
// loongarch64: define noundef zeroext i1 @arg_attr_bool(i1 noundef zeroext %x)
101+
pub fn arg_attr_bool(x: bool) -> bool {
102+
x
103+
}
104+
105+
#[no_mangle]
106+
// ignore-tidy-linelength
107+
// others: define noundef{{( range\(i32 0, 1114112\))?}} i32 @arg_attr_char(i32 noundef{{( range\(i32 0, 1114112\))?}} %x)
108+
// riscv64: define noundef{{( range\(i32 0, 1114112\))?}} i32 @arg_attr_char(i32 noundef signext{{( range\(i32 0, 1114112\))?}} %x)
109+
// loongarch64: define noundef{{( range\(i32 0, 1114112\))?}} i32 @arg_attr_char(i32 noundef signext{{( range\(i32 0, 1114112\))?}} %x)
110+
pub fn arg_attr_char(x: char) -> char {
111+
x
112+
}
113+
114+
#[no_mangle]
115+
// others: define noundef float @arg_attr_f32(float noundef %x)
116+
// riscv64: define noundef float @arg_attr_f32(float noundef %x)
117+
// loongarch64: define noundef float @arg_attr_f32(float noundef %x)
118+
pub fn arg_attr_f32(x: f32) -> f32 {
119+
x
120+
}
121+
122+
#[no_mangle]
123+
// others: define noundef double @arg_attr_f64(double noundef %x)
124+
// riscv64: define noundef double @arg_attr_f64(double noundef %x)
125+
// loongarch64: define noundef double @arg_attr_f64(double noundef %x)
126+
pub fn arg_attr_f64(x: f64) -> f64 {
127+
x
128+
}

‎tests/codegen/sanitizer/cfi/emit-type-checks-attr-no-sanitize.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ pub fn foo(f: fn(i32) -> i32, arg: i32) -> i32 {
1212
// CHECK: Function Attrs: {{.*}}
1313
// CHECK-LABEL: define{{.*}}foo{{.*}}!type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
1414
// CHECK: start:
15-
// CHECK-NEXT: {{%.+}} = call i32 %f(i32 %arg)
15+
// CHECK-NEXT: {{%.+}} = call i32 %f(i32{{.*}} %arg)
1616
// CHECK-NEXT: ret i32 {{%.+}}
1717
f(arg)
1818
}

‎tests/codegen/sanitizer/cfi/emit-type-checks.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ pub fn foo(f: fn(i32) -> i32, arg: i32) -> i32 {
1111
// CHECK: [[TT:%.+]] = call i1 @llvm.type.test(ptr {{%f|%0}}, metadata !"{{[[:print:]]+}}")
1212
// CHECK-NEXT: br i1 [[TT]], label %type_test.pass, label %type_test.fail
1313
// CHECK: type_test.pass:
14-
// CHECK-NEXT: {{%.+}} = call i32 %f(i32 %arg)
14+
// CHECK-NEXT: {{%.+}} = call i32 %f(i32{{.*}} %arg)
1515
// CHECK: type_test.fail:
1616
// CHECK-NEXT: call void @llvm.trap()
1717
// CHECK-NEXT: unreachable

‎tests/codegen/transmute-scalar.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ pub fn bool_to_byte(b: bool) -> u8 {
2525
unsafe { std::mem::transmute(b) }
2626
}
2727

28-
// CHECK-LABEL: define{{.*}}zeroext i1 @byte_to_bool(i8 %byte)
28+
// CHECK-LABEL: define{{.*}}zeroext i1 @byte_to_bool(i8{{.*}} %byte)
2929
// CHECK: %_0 = trunc i8 %byte to i1
3030
// CHECK-NEXT: ret i1 %_0
3131
#[no_mangle]

‎tests/codegen/union-abi.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ pub fn test_CUnionU128(_: CUnionU128) {
131131
pub union UnionBool {
132132
b: bool,
133133
}
134-
// CHECK: define {{(dso_local )?}}noundef zeroext i1 @test_UnionBool(i8 %b)
134+
// CHECK: define {{(dso_local )?}}noundef zeroext i1 @test_UnionBool(i8{{.*}} %b)
135135
#[no_mangle]
136136
pub fn test_UnionBool(b: UnionBool) -> bool {
137137
unsafe { b.b }

‎tests/codegen/var-names.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
#![crate_type = "lib"]
44

5-
// CHECK-LABEL: define{{.*}}i32 @test(i32 noundef %a, i32 noundef %b)
5+
// CHECK-LABEL: define{{.*}}i32 @test(i32{{.*}} %a, i32{{.*}} %b)
66
#[no_mangle]
77
pub fn test(a: u32, b: u32) -> u32 {
88
let c = a + b;

0 commit comments

Comments
 (0)
Please sign in to comment.