Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Allow Rvalue::Repeat to return true in rvalue_creates_operand too
The conversation in 143502 made be realize how easy this is to handle, since the only possibilty is ZSTs -- everything else ends up with the destination being `LocalKind::Memory` and thus doesn't call `codegen_rvalue_operand` at all.

This gets us perilously close to a world where `rvalue_creates_operand` only ever returns true.  I'll try out such a world next :)
  • Loading branch information
scottmcm committed Jul 20, 2025
commit 0586c63e070981af7df53e2f778d3e50293d8103
16 changes: 12 additions & 4 deletions compiler/rustc_codegen_ssa/src/mir/rvalue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -630,7 +630,17 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
OperandRef { val: OperandValue::Immediate(static_), layout }
}
mir::Rvalue::Use(ref operand) => self.codegen_operand(bx, operand),
mir::Rvalue::Repeat(..) => bug!("{rvalue:?} in codegen_rvalue_operand"),
mir::Rvalue::Repeat(ref elem, len_const) => {
// All arrays have `BackendRepr::Memory`, so only the ZST cases
// end up here. Anything else forces the destination local to be
// `Memory`, and thus ends up handled in `codegen_rvalue` instead.
let operand = self.codegen_operand(bx, elem);
let array_ty = Ty::new_array_with_const_len(bx.tcx(), operand.layout.ty, len_const);
let array_ty = self.monomorphize(array_ty);
let array_layout = bx.layout_of(array_ty);
assert!(array_layout.is_zst());
OperandRef { val: OperandValue::ZeroSized, layout: array_layout }
}
mir::Rvalue::Aggregate(ref kind, ref fields) => {
let (variant_index, active_field_index) = match **kind {
mir::AggregateKind::Adt(_, variant_index, _, _, active_field_index) => {
Expand Down Expand Up @@ -1000,12 +1010,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
mir::Rvalue::NullaryOp(..) |
mir::Rvalue::ThreadLocalRef(_) |
mir::Rvalue::Use(..) |
mir::Rvalue::Repeat(..) | // (*)
mir::Rvalue::Aggregate(..) | // (*)
mir::Rvalue::WrapUnsafeBinder(..) => // (*)
true,
// Arrays are always aggregates, so it's not worth checking anything here.
// (If it's really `[(); N]` or `[T; 0]` and we use the place path, fine.)
mir::Rvalue::Repeat(..) => false,
}

// (*) this is only true if the type is suitable
Expand Down
39 changes: 39 additions & 0 deletions tests/codegen/repeat-operand.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
//@ compile-flags: -Copt-level=1 -Cno-prepopulate-passes

// This test is here to hit the `Rvalue::Repeat` case in `codegen_rvalue_operand`.
// It only applies when the resulting array is a ZST, so the test is written in
// such a way as to keep MIR optimizations from seeing that fact and removing
// the local and statement altogether. (At the time of writing, no other codegen
// test hit that code path, nor did a stage 2 build of the compiler.)

#![crate_type = "lib"]

#[repr(transparent)]
pub struct Wrapper<T, const N: usize>([T; N]);

// CHECK-LABEL: define {{.+}}do_repeat{{.+}}()
// CHECK-NEXT: start:
// CHECK-NOT: alloca
// CHECK-NEXT: ret void
// CHECK-LABEL: define {{.+}}do_repeat{{.+}}(i32 noundef %x)
// CHECK-NEXT: start:
// CHECK-NOT: alloca
// CHECK-NEXT: ret void
#[inline(never)]
pub fn do_repeat<T: Copy, const N: usize>(x: T) -> Wrapper<T, N> {
Wrapper([x; N])
}

// CHECK-LABEL: @trigger_repeat_zero_len
#[no_mangle]
pub fn trigger_repeat_zero_len() -> Wrapper<u32, 0> {
// CHECK: call void {{.+}}do_repeat{{.+}}(i32 noundef 4)
do_repeat(4)
}

// CHECK-LABEL: @trigger_repeat_zst
#[no_mangle]
pub fn trigger_repeat_zst() -> Wrapper<(), 8> {
// CHECK: call void {{.+}}do_repeat{{.+}}()
do_repeat(())
}