Skip to content

Allow Rvalue::Repeat to return true in rvalue_creates_operand too #143720

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
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
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 @@ -649,7 +649,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 @@ -1019,12 +1029,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(())
}
Loading