1
Fork 0

Build StKind::CopyOverlapping

This replaces where it was previously being constructed in intrinsics, with direct construction
of the Statement.
This commit is contained in:
kadmin 2021-01-23 03:55:41 +00:00
parent 845e4b5962
commit d4ae9ff826
5 changed files with 100 additions and 77 deletions

View file

@ -837,10 +837,21 @@ fn codegen_stmt<'tcx>(
dst, dst,
count, count,
}) => { }) => {
let dst = codegen_operand(fx, dst).load_scalar(fx); let dst = codegen_operand(fx, dst);
let pointee = dst
.layout()
.pointee_info_at(fx, rustc_target::abi::Size::ZERO)
.expect("Expected pointer");
let dst = dst.load_scalar(fx);
let src = codegen_operand(fx, src).load_scalar(fx); let src = codegen_operand(fx, src).load_scalar(fx);
let count = codegen_operand(fx, count).load_scalar(fx); let count = codegen_operand(fx, count).load_scalar(fx);
fx.bcx.call_memcpy(fx.cx.module.target_config(), dst, src, count); let elem_size: u64 = pointee.size.bytes();
let bytes = if elem_size != 1 {
fx.bcx.ins().imul_imm(count, elem_size as i64)
} else {
count
};
fx.bcx.call_memcpy(fx.cx.module.target_config(), dst, src, bytes);
} }
} }
} }

View file

@ -9,6 +9,7 @@
#![feature(or_patterns)] #![feature(or_patterns)]
#![feature(associated_type_bounds)] #![feature(associated_type_bounds)]
#![recursion_limit = "256"] #![recursion_limit = "256"]
#![feature(box_syntax)]
//! This crate contains codegen code that is used by all codegen backends (LLVM and others). //! This crate contains codegen code that is used by all codegen backends (LLVM and others).
//! The backend-agnostic functions of this crate use functions defined in various traits that //! The backend-agnostic functions of this crate use functions defined in various traits that

View file

@ -641,67 +641,89 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
return; return;
} }
if intrinsic.is_some() && intrinsic != Some(sym::drop_in_place) { match intrinsic {
let intrinsic = intrinsic.unwrap(); None | Some(sym::drop_in_place) => {}
let dest = match ret_dest { Some(sym::copy_nonoverlapping) => {
_ if fn_abi.ret.is_indirect() => llargs[0], bx = self.codegen_statement(
ReturnDest::Nothing => { bx,
bx.const_undef(bx.type_ptr_to(bx.arg_memory_ty(&fn_abi.ret))) &rustc_middle::mir::Statement {
} source_info: rustc_middle::mir::SourceInfo::outermost(span),
ReturnDest::IndirectOperand(dst, _) | ReturnDest::Store(dst) => dst.llval, kind: rustc_middle::mir::StatementKind::CopyNonOverlapping(
ReturnDest::DirectOperand(_) => { box rustc_middle::mir::CopyNonOverlapping {
bug!("Cannot use direct operand with an intrinsic call") src: args[0].clone(),
} dst: args[1].clone(),
}; count: args[2].clone(),
},
let args: Vec<_> = args ),
.iter() },
.enumerate() );
.map(|(i, arg)| { helper.funclet_br(self, &mut bx, destination.unwrap().1);
// The indices passed to simd_shuffle* in the return;
// third argument must be constant. This is }
// checked by const-qualification, which also Some(intrinsic) => {
// promotes any complex rvalues to constants. let dest = match ret_dest {
if i == 2 && intrinsic.as_str().starts_with("simd_shuffle") { _ if fn_abi.ret.is_indirect() => llargs[0],
if let mir::Operand::Constant(constant) = arg { ReturnDest::Nothing => {
let c = self.eval_mir_constant(constant); bx.const_undef(bx.type_ptr_to(bx.arg_memory_ty(&fn_abi.ret)))
let (llval, ty) = self.simd_shuffle_indices(
&bx,
constant.span,
constant.literal.ty,
c,
);
return OperandRef { val: Immediate(llval), layout: bx.layout_of(ty) };
} else {
span_bug!(span, "shuffle indices must be constant");
}
} }
ReturnDest::IndirectOperand(dst, _) | ReturnDest::Store(dst) => dst.llval,
ReturnDest::DirectOperand(_) => {
bug!("Cannot use direct operand with an intrinsic call")
}
};
self.codegen_operand(&mut bx, arg) let args: Vec<_> = args
}) .iter()
.collect(); .enumerate()
.map(|(i, arg)| {
// The indices passed to simd_shuffle* in the
// third argument must be constant. This is
// checked by const-qualification, which also
// promotes any complex rvalues to constants.
if i == 2 && intrinsic.as_str().starts_with("simd_shuffle") {
if let mir::Operand::Constant(constant) = arg {
let c = self.eval_mir_constant(constant);
let (llval, ty) = self.simd_shuffle_indices(
&bx,
constant.span,
constant.literal.ty,
c,
);
return OperandRef {
val: Immediate(llval),
layout: bx.layout_of(ty),
};
} else {
span_bug!(span, "shuffle indices must be constant");
}
}
Self::codegen_intrinsic_call( self.codegen_operand(&mut bx, arg)
&mut bx, })
*instance.as_ref().unwrap(), .collect();
&fn_abi,
&args,
dest,
span,
);
if let ReturnDest::IndirectOperand(dst, _) = ret_dest { self.codegen_intrinsic_call(
self.store_return(&mut bx, ret_dest, &fn_abi.ret, dst.llval); &mut bx,
*instance.as_ref().unwrap(),
&fn_abi,
&args,
dest,
span,
);
if let ReturnDest::IndirectOperand(dst, _) = ret_dest {
self.store_return(&mut bx, ret_dest, &fn_abi.ret, dst.llval);
}
if let Some((_, target)) = *destination {
helper.maybe_sideeffect(self.mir, &mut bx, &[target]);
helper.funclet_br(self, &mut bx, target);
} else {
bx.unreachable();
}
return;
} }
if let Some((_, target)) = *destination {
helper.maybe_sideeffect(self.mir, &mut bx, &[target]);
helper.funclet_br(self, &mut bx, target);
} else {
bx.unreachable();
}
return;
} }
// Split the rust-call tupled arguments off. // Split the rust-call tupled arguments off.

View file

@ -49,6 +49,7 @@ fn memset_intrinsic<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
pub fn codegen_intrinsic_call( pub fn codegen_intrinsic_call(
&self,
bx: &mut Bx, bx: &mut Bx,
instance: ty::Instance<'tcx>, instance: ty::Instance<'tcx>,
fn_abi: &FnAbi<'tcx, Ty<'tcx>>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
@ -127,16 +128,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
} }
sym::copy_nonoverlapping => { sym::copy_nonoverlapping => {
copy_intrinsic( // handled explicitly in compiler/rustc_codegen_ssa/src/mir/block.rs
bx, unreachable!();
false,
false,
substs.type_at(0),
args[1].immediate(),
args[0].immediate(),
args[2].immediate(),
);
return;
} }
sym::copy => { sym::copy => {
copy_intrinsic( copy_intrinsic(

View file

@ -123,20 +123,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
let dst_val = self.codegen_operand(&mut bx, dst); let dst_val = self.codegen_operand(&mut bx, dst);
let src_val = self.codegen_operand(&mut bx, src); let src_val = self.codegen_operand(&mut bx, src);
let count = self.codegen_operand(&mut bx, count).immediate(); let count = self.codegen_operand(&mut bx, count).immediate();
let get_val_align = |oper_ref: crate::mir::OperandRef<'_, _>| match oper_ref.val {
OperandValue::Ref(val, _, align) => (val, align),
_ => unreachable!(),
};
let pointee_layout = dst_val let pointee_layout = dst_val
.layout .layout
.pointee_info_at(&mut bx, rustc_target::abi::Size::ZERO) .pointee_info_at(&mut bx, rustc_target::abi::Size::ZERO)
.expect("Expected pointer"); .expect("Expected pointer");
let elem_size = bx.const_u64(pointee_layout.size.bytes()); let bytes = bx.mul(count, bx.const_usize(pointee_layout.size.bytes()));
let byte_count = bx.mul(count, elem_size);
let (dst, dst_align) = get_val_align(dst_val); let align = pointee_layout.align;
let (src, src_align) = get_val_align(src_val); let dst = dst_val.immediate();
bx.memcpy(dst, dst_align, src, src_align, byte_count, crate::MemFlags::empty()); let src = src_val.immediate();
bx.memcpy(dst, align, src, align, bytes, crate::MemFlags::empty());
bx bx
} }
mir::StatementKind::FakeRead(..) mir::StatementKind::FakeRead(..)