diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 08da90d535da1..aae0e661a1fd5 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -767,30 +767,11 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { count: u64, dest: PlaceRef<'tcx, &'ll Value>, ) { - let zero = self.const_usize(0); - let count = self.const_usize(count); - - let header_bb = self.append_sibling_block("repeat_loop_header"); - let body_bb = self.append_sibling_block("repeat_loop_body"); - let next_bb = self.append_sibling_block("repeat_loop_next"); - - self.br(header_bb); - - let mut header_bx = Self::build(self.cx, header_bb); - let i = header_bx.phi(self.val_ty(zero), &[zero], &[self.llbb()]); - - let keep_going = header_bx.icmp(IntPredicate::IntULT, i, count); - header_bx.cond_br(keep_going, body_bb, next_bb); - - let mut body_bx = Self::build(self.cx, body_bb); - let dest_elem = dest.project_index(&mut body_bx, i); - cg_elem.val.store(&mut body_bx, dest_elem); - - let next = body_bx.unchecked_uadd(i, self.const_usize(1)); - body_bx.br(header_bb); - header_bx.add_incoming_to_phi(i, next, body_bb); - - *self = Self::build(self.cx, next_bb); + if self.cx.sess().opts.optimize == OptLevel::No { + self.write_operand_repeatedly_unoptimized(cg_elem, count, dest); + } else { + self.write_operand_repeatedly_optimized(cg_elem, count, dest); + } } fn range_metadata(&mut self, load: &'ll Value, range: WrappingRange) { @@ -1527,6 +1508,78 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { pub(crate) fn set_unpredictable(&mut self, inst: &'ll Value) { self.set_metadata_node(inst, llvm::MD_unpredictable, &[]); } + + fn write_operand_repeatedly_optimized( + &mut self, + cg_elem: OperandRef<'tcx, &'ll Value>, + count: u64, + dest: PlaceRef<'tcx, &'ll Value>, + ) { + let zero = self.const_usize(0); + let count = self.const_usize(count); + + let header_bb = self.append_sibling_block("repeat_loop_header"); + let body_bb = self.append_sibling_block("repeat_loop_body"); + let next_bb = self.append_sibling_block("repeat_loop_next"); + + self.br(header_bb); + + let mut header_bx = Self::build(self.cx, header_bb); + let i = header_bx.phi(self.val_ty(zero), &[zero], &[self.llbb()]); + + let keep_going = header_bx.icmp(IntPredicate::IntULT, i, count); + header_bx.cond_br(keep_going, body_bb, next_bb); + + let mut body_bx = Self::build(self.cx, body_bb); + let dest_elem = dest.project_index(&mut body_bx, i); + cg_elem.val.store(&mut body_bx, dest_elem); + + let next = body_bx.unchecked_uadd(i, self.const_usize(1)); + body_bx.br(header_bb); + header_bx.add_incoming_to_phi(i, next, body_bb); + + *self = Self::build(self.cx, next_bb); + } + + fn write_operand_repeatedly_unoptimized( + &mut self, + cg_elem: OperandRef<'tcx, &'ll Value>, + count: u64, + dest: PlaceRef<'tcx, &'ll Value>, + ) { + let zero = self.const_usize(0); + let count = self.const_usize(count); + let start = dest.project_index(self, zero).val.llval; + let end = dest.project_index(self, count).val.llval; + + let header_bb = self.append_sibling_block("repeat_loop_header"); + let body_bb = self.append_sibling_block("repeat_loop_body"); + let next_bb = self.append_sibling_block("repeat_loop_next"); + + self.br(header_bb); + + let mut header_bx = Self::build(self.cx, header_bb); + let current = header_bx.phi(self.val_ty(start), &[start], &[self.llbb()]); + + let keep_going = header_bx.icmp(IntPredicate::IntNE, current, end); + header_bx.cond_br(keep_going, body_bb, next_bb); + + let mut body_bx = Self::build(self.cx, body_bb); + let align = dest.val.align.restrict_for_offset(dest.layout.field(self.cx(), 0).size); + cg_elem + .val + .store(&mut body_bx, PlaceRef::new_sized_aligned(current, cg_elem.layout, align)); + + let next = body_bx.inbounds_gep( + self.backend_type(cg_elem.layout), + current, + &[self.const_usize(1)], + ); + body_bx.br(header_bb); + header_bx.add_incoming_to_phi(current, next, body_bb); + + *self = Self::build(self.cx, next_bb); + } } impl<'a, 'll, CX: Borrow>> GenericBuilder<'a, 'll, CX> { pub(crate) fn minnum(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { diff --git a/tests/debuginfo/basic-stepping.rs b/tests/debuginfo/basic-stepping.rs index f6399814a43a8..5cb8a44955635 100644 --- a/tests/debuginfo/basic-stepping.rs +++ b/tests/debuginfo/basic-stepping.rs @@ -20,8 +20,8 @@ // FIXME(#33013): gdb-command: next // FIXME(#33013): gdb-check: let g = b'9'; // FIXME(#33013): gdb-command: next -// FIXME(#33013): gdb-check: let h = ["whatever"; 8]; -// FIXME(#33013): gdb-command: next +// gdb-check: let h = ["whatever"; 8]; +// gdb-command: next // gdb-check: let i = [1,2,3,4]; // gdb-command: next // gdb-check: let j = (23, "hi");