Skip to content
Merged
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
2 changes: 1 addition & 1 deletion compiler/rustc_borrowck/src/dataflow.rs
Original file line number Diff line number Diff line change
@@ -391,7 +391,7 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
| mir::StatementKind::Retag { .. }
| mir::StatementKind::AscribeUserType(..)
| mir::StatementKind::Coverage(..)
| mir::StatementKind::CopyNonOverlapping(..)
| mir::StatementKind::Intrinsic(..)
| mir::StatementKind::Nop => {}
}
}
26 changes: 15 additions & 11 deletions compiler/rustc_borrowck/src/invalidation.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use rustc_data_structures::graph::dominators::Dominators;
use rustc_middle::mir::visit::Visitor;
use rustc_middle::mir::{BasicBlock, Body, Location, Place, Rvalue};
use rustc_middle::mir::{self, BasicBlock, Body, Location, NonDivergingIntrinsic, Place, Rvalue};
use rustc_middle::mir::{BorrowKind, Mutability, Operand};
use rustc_middle::mir::{InlineAsmOperand, Terminator, TerminatorKind};
use rustc_middle::mir::{Statement, StatementKind};
@@ -63,23 +63,24 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
StatementKind::FakeRead(box (_, _)) => {
// Only relevant for initialized/liveness/safety checks.
}
StatementKind::CopyNonOverlapping(box rustc_middle::mir::CopyNonOverlapping {
StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(op)) => {
self.consume_operand(location, op);
}
StatementKind::Intrinsic(box NonDivergingIntrinsic::CopyNonOverlapping(mir::CopyNonOverlapping {
ref src,
ref dst,
ref count,
}) => {
})) => {
self.consume_operand(location, src);
self.consume_operand(location, dst);
self.consume_operand(location, count);
}
StatementKind::Nop
// Only relevant for mir typeck
StatementKind::AscribeUserType(..)
// Doesn't have any language semantics
| StatementKind::Coverage(..)
| StatementKind::AscribeUserType(..)
| StatementKind::Retag { .. }
| StatementKind::StorageLive(..) => {
// `Nop`, `AscribeUserType`, `Retag`, and `StorageLive` are irrelevant
// to borrow check.
}
// Does not actually affect borrowck
| StatementKind::StorageLive(..) => {}
StatementKind::StorageDead(local) => {
self.access_place(
location,
@@ -88,7 +89,10 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
LocalMutationIsAllowed::Yes,
);
}
StatementKind::Deinit(..) | StatementKind::SetDiscriminant { .. } => {
StatementKind::Nop
| StatementKind::Retag { .. }
| StatementKind::Deinit(..)
| StatementKind::SetDiscriminant { .. } => {
bug!("Statement not allowed in this MIR phase")
}
}
28 changes: 14 additions & 14 deletions compiler/rustc_borrowck/src/lib.rs
Original file line number Diff line number Diff line change
@@ -26,8 +26,8 @@ use rustc_index::bit_set::ChunkedBitSet;
use rustc_index::vec::IndexVec;
use rustc_infer::infer::{DefiningAnchor, InferCtxt, TyCtxtInferExt};
use rustc_middle::mir::{
traversal, Body, ClearCrossCrate, Local, Location, Mutability, Operand, Place, PlaceElem,
PlaceRef, VarDebugInfoContents,
traversal, Body, ClearCrossCrate, Local, Location, Mutability, NonDivergingIntrinsic, Operand,
Place, PlaceElem, PlaceRef, VarDebugInfoContents,
};
use rustc_middle::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind};
use rustc_middle::mir::{Field, ProjectionElem, Promoted, Rvalue, Statement, StatementKind};
@@ -591,22 +591,19 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
flow_state,
);
}
StatementKind::CopyNonOverlapping(box rustc_middle::mir::CopyNonOverlapping {
..
}) => {
span_bug!(
StatementKind::Intrinsic(box ref kind) => match kind {
NonDivergingIntrinsic::Assume(op) => self.consume_operand(location, (op, span), flow_state),
NonDivergingIntrinsic::CopyNonOverlapping(..) => span_bug!(
span,
"Unexpected CopyNonOverlapping, should only appear after lower_intrinsics",
)
}
StatementKind::Nop
// Only relevant for mir typeck
StatementKind::AscribeUserType(..)
// Doesn't have any language semantics
| StatementKind::Coverage(..)
| StatementKind::AscribeUserType(..)
| StatementKind::Retag { .. }
| StatementKind::StorageLive(..) => {
// `Nop`, `AscribeUserType`, `Retag`, and `StorageLive` are irrelevant
// to borrow check.
}
// Does not actually affect borrowck
| StatementKind::StorageLive(..) => {}
StatementKind::StorageDead(local) => {
self.access_place(
location,
@@ -616,7 +613,10 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
flow_state,
);
}
StatementKind::Deinit(..) | StatementKind::SetDiscriminant { .. } => {
StatementKind::Nop
| StatementKind::Retag { .. }
| StatementKind::Deinit(..)
| StatementKind::SetDiscriminant { .. } => {
bug!("Statement not allowed in this MIR phase")
}
}
13 changes: 7 additions & 6 deletions compiler/rustc_borrowck/src/type_check/mod.rs
Original file line number Diff line number Diff line change
@@ -1302,12 +1302,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
);
}
}
StatementKind::CopyNonOverlapping(box rustc_middle::mir::CopyNonOverlapping {
..
}) => span_bug!(
stmt.source_info.span,
"Unexpected StatementKind::CopyNonOverlapping, should only appear after lowering_intrinsics",
),
StatementKind::Intrinsic(box ref kind) => match kind {
NonDivergingIntrinsic::Assume(op) => self.check_operand(op, location),
NonDivergingIntrinsic::CopyNonOverlapping(..) => span_bug!(
stmt.source_info.span,
"Unexpected NonDivergingIntrinsic::CopyNonOverlapping, should only appear after lowering_intrinsics",
),
},
StatementKind::FakeRead(..)
| StatementKind::StorageLive(..)
| StatementKind::StorageDead(..)
39 changes: 25 additions & 14 deletions compiler/rustc_codegen_cranelift/src/base.rs
Original file line number Diff line number Diff line change
@@ -794,20 +794,31 @@ fn codegen_stmt<'tcx>(
| StatementKind::AscribeUserType(..) => {}

StatementKind::Coverage { .. } => fx.tcx.sess.fatal("-Zcoverage is unimplemented"),
StatementKind::CopyNonOverlapping(inner) => {
let dst = codegen_operand(fx, &inner.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, &inner.src).load_scalar(fx);
let count = codegen_operand(fx, &inner.count).load_scalar(fx);
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.target_config, dst, src, bytes);
}
StatementKind::Intrinsic(ref intrinsic) => match &**intrinsic {
// We ignore `assume` intrinsics, they are only useful for optimizations
NonDivergingIntrinsic::Assume(_) => {}
NonDivergingIntrinsic::CopyNonOverlapping(mir::CopyNonOverlapping {
src,
dst,
count,
}) => {
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 count = codegen_operand(fx, count).load_scalar(fx);
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.target_config, dst, src, bytes);
}
},
}
}

8 changes: 5 additions & 3 deletions compiler/rustc_codegen_cranelift/src/constant.rs
Original file line number Diff line number Diff line change
@@ -536,9 +536,11 @@ pub(crate) fn mir_operand_get_const_val<'tcx>(
{
return None;
}
StatementKind::CopyNonOverlapping(_) => {
return None;
} // conservative handling
StatementKind::Intrinsic(ref intrinsic) => match **intrinsic {
NonDivergingIntrinsic::CopyNonOverlapping(..) => return None,
NonDivergingIntrinsic::Assume(..) => {}
},
// conservative handling
StatementKind::Assign(_)
| StatementKind::FakeRead(_)
| StatementKind::SetDiscriminant { .. }
3 changes: 0 additions & 3 deletions compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
Original file line number Diff line number Diff line change
@@ -357,9 +357,6 @@ fn codegen_regular_intrinsic_call<'tcx>(
let usize_layout = fx.layout_of(fx.tcx.types.usize);

match intrinsic {
sym::assume => {
intrinsic_args!(fx, args => (_a); intrinsic);
}
sym::likely | sym::unlikely => {
intrinsic_args!(fx, args => (a); intrinsic);

4 changes: 0 additions & 4 deletions compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
Original file line number Diff line number Diff line change
@@ -77,10 +77,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
let result = PlaceRef::new_sized(llresult, fn_abi.ret.layout);

let llval = match name {
sym::assume => {
bx.assume(args[0].immediate());
return;
}
sym::abort => {
bx.abort();
return;
14 changes: 9 additions & 5 deletions compiler/rustc_codegen_ssa/src/mir/statement.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use rustc_middle::mir;
use rustc_middle::mir::NonDivergingIntrinsic;

use super::FunctionCx;
use super::LocalRef;
@@ -73,11 +74,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
self.codegen_coverage(&mut bx, coverage.clone(), statement.source_info.scope);
bx
}
mir::StatementKind::CopyNonOverlapping(box mir::CopyNonOverlapping {
ref src,
ref dst,
ref count,
}) => {
mir::StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(ref op)) => {
let op_val = self.codegen_operand(&mut bx, op);
bx.assume(op_val.immediate());
bx
}
mir::StatementKind::Intrinsic(box NonDivergingIntrinsic::CopyNonOverlapping(
mir::CopyNonOverlapping { ref count, ref src, ref dst },
)) => {
let dst_val = self.codegen_operand(&mut bx, dst);
let src_val = self.codegen_operand(&mut bx, src);
let count = self.codegen_operand(&mut bx, count).immediate();
34 changes: 27 additions & 7 deletions compiler/rustc_const_eval/src/interpret/intrinsics.rs
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@ use rustc_hir::def_id::DefId;
use rustc_middle::mir::{
self,
interpret::{ConstValue, GlobalId, InterpResult, PointerArithmetic, Scalar},
BinOp,
BinOp, NonDivergingIntrinsic,
};
use rustc_middle::ty;
use rustc_middle::ty::layout::LayoutOf as _;
@@ -506,12 +506,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// These just return their argument
self.copy_op(&args[0], dest, /*allow_transmute*/ false)?;
}
sym::assume => {
let cond = self.read_scalar(&args[0])?.to_bool()?;
if !cond {
throw_ub_format!("`assume` intrinsic called with `false`");
}
}
sym::raw_eq => {
let result = self.raw_eq_intrinsic(&args[0], &args[1])?;
self.write_scalar(result, dest)?;
@@ -536,6 +530,32 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
Ok(true)
}

pub(super) fn emulate_nondiverging_intrinsic(
&mut self,
intrinsic: &NonDivergingIntrinsic<'tcx>,
) -> InterpResult<'tcx> {
match intrinsic {
NonDivergingIntrinsic::Assume(op) => {
let op = self.eval_operand(op, None)?;
let cond = self.read_scalar(&op)?.to_bool()?;
if !cond {
throw_ub_format!("`assume` called with `false`");
}
Ok(())
}
NonDivergingIntrinsic::CopyNonOverlapping(mir::CopyNonOverlapping {
count,
src,
dst,
}) => {
let src = self.eval_operand(src, None)?;
let dst = self.eval_operand(dst, None)?;
let count = self.eval_operand(count, None)?;
self.copy_intrinsic(&src, &dst, &count, /* nonoverlapping */ true)
}
}
}

pub fn exact_div(
&mut self,
a: &ImmTy<'tcx, M::Provenance>,
8 changes: 1 addition & 7 deletions compiler/rustc_const_eval/src/interpret/step.rs
Original file line number Diff line number Diff line change
@@ -114,13 +114,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
M::retag(self, *kind, &dest)?;
}

// Call CopyNonOverlapping
CopyNonOverlapping(box rustc_middle::mir::CopyNonOverlapping { src, dst, count }) => {
let src = self.eval_operand(src, None)?;
let dst = self.eval_operand(dst, None)?;
let count = self.eval_operand(count, None)?;
self.copy_intrinsic(&src, &dst, &count, /* nonoverlapping */ true)?;
}
Intrinsic(box ref intrinsic) => self.emulate_nondiverging_intrinsic(intrinsic)?,

// Statements we do not track.
AscribeUserType(..) => {}
Original file line number Diff line number Diff line change
@@ -678,7 +678,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
| StatementKind::Retag { .. }
| StatementKind::AscribeUserType(..)
| StatementKind::Coverage(..)
| StatementKind::CopyNonOverlapping(..)
| StatementKind::Intrinsic(..)
| StatementKind::Nop => {}
}
}
24 changes: 16 additions & 8 deletions compiler/rustc_const_eval/src/transform/validate.rs
Original file line number Diff line number Diff line change
@@ -7,9 +7,10 @@ use rustc_middle::mir::interpret::Scalar;
use rustc_middle::mir::visit::NonUseContext::VarDebugInfo;
use rustc_middle::mir::visit::{PlaceContext, Visitor};
use rustc_middle::mir::{
traversal, AggregateKind, BasicBlock, BinOp, Body, BorrowKind, CastKind, Local, Location,
MirPass, MirPhase, Operand, Place, PlaceElem, PlaceRef, ProjectionElem, RuntimePhase, Rvalue,
SourceScope, Statement, StatementKind, Terminator, TerminatorKind, UnOp, START_BLOCK,
traversal, AggregateKind, BasicBlock, BinOp, Body, BorrowKind, CastKind, CopyNonOverlapping,
Local, Location, MirPass, MirPhase, NonDivergingIntrinsic, Operand, Place, PlaceElem, PlaceRef,
ProjectionElem, RuntimePhase, Rvalue, SourceScope, Statement, StatementKind, Terminator,
TerminatorKind, UnOp, START_BLOCK,
};
use rustc_middle::ty::fold::BottomUpFolder;
use rustc_middle::ty::subst::Subst;
@@ -636,11 +637,18 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
);
}
}
StatementKind::CopyNonOverlapping(box rustc_middle::mir::CopyNonOverlapping {
ref src,
ref dst,
ref count,
}) => {
StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(op)) => {
let ty = op.ty(&self.body.local_decls, self.tcx);
if !ty.is_bool() {
self.fail(
location,
format!("`assume` argument must be `bool`, but got: `{}`", ty),
);
}
}
StatementKind::Intrinsic(box NonDivergingIntrinsic::CopyNonOverlapping(
CopyNonOverlapping { src, dst, count },
)) => {
let src_ty = src.ty(&self.body.local_decls, self.tcx);
let op_src_ty = if let Some(src_deref) = src_ty.builtin_deref(true) {
src_deref.ty
8 changes: 1 addition & 7 deletions compiler/rustc_middle/src/mir/mod.rs
Original file line number Diff line number Diff line change
@@ -1370,13 +1370,7 @@ impl Debug for Statement<'_> {
write!(fmt, "Coverage::{:?} for {:?}", kind, rgn)
}
Coverage(box ref coverage) => write!(fmt, "Coverage::{:?}", coverage.kind),
CopyNonOverlapping(box crate::mir::CopyNonOverlapping {
ref src,
ref dst,
ref count,
}) => {
write!(fmt, "copy_nonoverlapping(src={:?}, dst={:?}, count={:?})", src, dst, count)
}
Intrinsic(box ref intrinsic) => write!(fmt, "{intrinsic}"),
Nop => write!(fmt, "nop"),
}
}
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/mir/spanview.rs
Original file line number Diff line number Diff line change
@@ -249,7 +249,7 @@ pub fn statement_kind_name(statement: &Statement<'_>) -> &'static str {
Retag(..) => "Retag",
AscribeUserType(..) => "AscribeUserType",
Coverage(..) => "Coverage",
CopyNonOverlapping(..) => "CopyNonOverlapping",
Intrinsic(..) => "Intrinsic",
Nop => "Nop",
}
}
42 changes: 39 additions & 3 deletions compiler/rustc_middle/src/mir/syntax.rs
Original file line number Diff line number Diff line change
@@ -327,6 +327,34 @@ pub enum StatementKind<'tcx> {
/// executed.
Coverage(Box<Coverage>),

/// Denotes a call to an intrinsic that does not require an unwind path and always returns.
/// This avoids adding a new block and a terminator for simple intrinsics.
Intrinsic(Box<NonDivergingIntrinsic<'tcx>>),

/// No-op. Useful for deleting instructions without affecting statement indices.
Nop,
}

#[derive(
Clone,
TyEncodable,
TyDecodable,
Debug,
PartialEq,
Hash,
HashStable,
TypeFoldable,
TypeVisitable
)]
pub enum NonDivergingIntrinsic<'tcx> {
/// Denotes a call to the intrinsic function `assume`.
///
/// The operand must be a boolean. Optimizers may use the value of the boolean to backtrack its
/// computation to infer information about other variables. So if the boolean came from a
/// `x < y` operation, subsequent operations on `x` and `y` could elide various bound checks.
/// If the argument is `false`, this operation is equivalent to `TerminatorKind::Unreachable`.
Assume(Operand<'tcx>),

/// Denotes a call to the intrinsic function `copy_nonoverlapping`.
///
/// First, all three operands are evaluated. `src` and `dest` must each be a reference, pointer,
@@ -340,10 +368,18 @@ pub enum StatementKind<'tcx> {
///
/// **Needs clarification**: Is this typed or not, ie is there a typed load and store involved?
/// I vaguely remember Ralf saying somewhere that he thought it should not be.
CopyNonOverlapping(Box<CopyNonOverlapping<'tcx>>),
CopyNonOverlapping(CopyNonOverlapping<'tcx>),
}

/// No-op. Useful for deleting instructions without affecting statement indices.
Nop,
impl std::fmt::Display for NonDivergingIntrinsic<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Assume(op) => write!(f, "assume({op:?})"),
Self::CopyNonOverlapping(CopyNonOverlapping { src, dst, count }) => {
write!(f, "copy_nonoverlapping(dst = {dst:?}, src = {src:?}, count = {count:?})")
}
}
}
}

/// Describes what kind of retag is to be performed.
17 changes: 9 additions & 8 deletions compiler/rustc_middle/src/mir/visit.rs
Original file line number Diff line number Diff line change
@@ -425,14 +425,15 @@ macro_rules! make_mir_visitor {
location
)
}
StatementKind::CopyNonOverlapping(box crate::mir::CopyNonOverlapping{
src,
dst,
count,
}) => {
self.visit_operand(src, location);
self.visit_operand(dst, location);
self.visit_operand(count, location)
StatementKind::Intrinsic(box ref $($mutability)? intrinsic) => {
match intrinsic {
NonDivergingIntrinsic::Assume(op) => self.visit_operand(op, location),
NonDivergingIntrinsic::CopyNonOverlapping(CopyNonOverlapping { src, dst, count }) => {
self.visit_operand(src, location);
self.visit_operand(dst, location);
self.visit_operand(count, location);
}
}
}
StatementKind::Nop => {}
}
2 changes: 1 addition & 1 deletion compiler/rustc_mir_dataflow/src/impls/liveness.rs
Original file line number Diff line number Diff line change
@@ -270,7 +270,7 @@ impl<'a, 'tcx> Analysis<'tcx> for MaybeTransitiveLiveLocals<'a> {
| StatementKind::Retag(..)
| StatementKind::AscribeUserType(..)
| StatementKind::Coverage(..)
| StatementKind::CopyNonOverlapping(..)
| StatementKind::Intrinsic(..)
| StatementKind::Nop => None,
};
if let Some(destination) = destination {
2 changes: 1 addition & 1 deletion compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs
Original file line number Diff line number Diff line change
@@ -142,7 +142,7 @@ impl<'mir, 'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'mir, 'tc
| StatementKind::FakeRead(..)
| StatementKind::Nop
| StatementKind::Retag(..)
| StatementKind::CopyNonOverlapping(..)
| StatementKind::Intrinsic(..)
| StatementKind::StorageLive(..) => {}
}
}
2 changes: 1 addition & 1 deletion compiler/rustc_mir_dataflow/src/move_paths/builder.rs
Original file line number Diff line number Diff line change
@@ -330,7 +330,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
StatementKind::Retag { .. }
| StatementKind::AscribeUserType(..)
| StatementKind::Coverage(..)
| StatementKind::CopyNonOverlapping(..)
| StatementKind::Intrinsic(..)
| StatementKind::Nop => {}
}
}
3 changes: 2 additions & 1 deletion compiler/rustc_mir_transform/src/check_unsafety.rs
Original file line number Diff line number Diff line change
@@ -105,7 +105,8 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> {
// safe (at least as emitted during MIR construction)
}

StatementKind::CopyNonOverlapping(..) => unreachable!(),
// Move to above list once mir construction uses it.
StatementKind::Intrinsic(..) => unreachable!(),
}
self.super_statement(statement, location);
}
2 changes: 1 addition & 1 deletion compiler/rustc_mir_transform/src/coverage/spans.rs
Original file line number Diff line number Diff line change
@@ -825,7 +825,7 @@ pub(super) fn filtered_statement_span(statement: &Statement<'_>) -> Option<Span>

// Retain spans from all other statements
StatementKind::FakeRead(box (_, _)) // Not including `ForGuardBinding`
| StatementKind::CopyNonOverlapping(..)
| StatementKind::Intrinsic(..)
| StatementKind::Assign(_)
| StatementKind::SetDiscriminant { .. }
| StatementKind::Deinit(..)
2 changes: 1 addition & 1 deletion compiler/rustc_mir_transform/src/dead_store_elimination.rs
Original file line number Diff line number Diff line change
@@ -52,7 +52,7 @@ pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, borrowed: &BitS
| StatementKind::StorageLive(_)
| StatementKind::StorageDead(_)
| StatementKind::Coverage(_)
| StatementKind::CopyNonOverlapping(_)
| StatementKind::Intrinsic(_)
| StatementKind::Nop => (),

StatementKind::FakeRead(_) | StatementKind::AscribeUserType(_, _) => {
2 changes: 1 addition & 1 deletion compiler/rustc_mir_transform/src/dest_prop.rs
Original file line number Diff line number Diff line change
@@ -537,7 +537,7 @@ impl<'a> Conflicts<'a> {
| StatementKind::FakeRead(..)
| StatementKind::AscribeUserType(..)
| StatementKind::Coverage(..)
| StatementKind::CopyNonOverlapping(..)
| StatementKind::Intrinsic(..)
| StatementKind::Nop => {}
}
}
2 changes: 1 addition & 1 deletion compiler/rustc_mir_transform/src/generator.rs
Original file line number Diff line number Diff line change
@@ -1452,7 +1452,7 @@ impl<'tcx> Visitor<'tcx> for EnsureGeneratorFieldAssignmentsNeverAlias<'_> {
| StatementKind::Retag(..)
| StatementKind::AscribeUserType(..)
| StatementKind::Coverage(..)
| StatementKind::CopyNonOverlapping(..)
| StatementKind::Intrinsic(..)
| StatementKind::Nop => {}
}
}
31 changes: 25 additions & 6 deletions compiler/rustc_mir_transform/src/lower_intrinsics.rs
Original file line number Diff line number Diff line change
@@ -46,12 +46,31 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
let mut args = args.drain(..);
block.statements.push(Statement {
source_info: terminator.source_info,
kind: StatementKind::CopyNonOverlapping(Box::new(
rustc_middle::mir::CopyNonOverlapping {
src: args.next().unwrap(),
dst: args.next().unwrap(),
count: args.next().unwrap(),
},
kind: StatementKind::Intrinsic(Box::new(
NonDivergingIntrinsic::CopyNonOverlapping(
rustc_middle::mir::CopyNonOverlapping {
src: args.next().unwrap(),
dst: args.next().unwrap(),
count: args.next().unwrap(),
},
),
)),
});
assert_eq!(
args.next(),
None,
"Extra argument for copy_non_overlapping intrinsic"
);
drop(args);
terminator.kind = TerminatorKind::Goto { target };
}
sym::assume => {
let target = target.unwrap();
let mut args = args.drain(..);
block.statements.push(Statement {
source_info: terminator.source_info,
kind: StatementKind::Intrinsic(Box::new(
NonDivergingIntrinsic::Assume(args.next().unwrap()),
)),
});
assert_eq!(
Original file line number Diff line number Diff line change
@@ -51,7 +51,7 @@ impl RemoveNoopLandingPads {
StatementKind::Assign { .. }
| StatementKind::SetDiscriminant { .. }
| StatementKind::Deinit(..)
| StatementKind::CopyNonOverlapping(..)
| StatementKind::Intrinsic(..)
| StatementKind::Retag { .. } => {
return false;
}
4 changes: 2 additions & 2 deletions compiler/rustc_mir_transform/src/separate_const_switch.rs
Original file line number Diff line number Diff line change
@@ -249,7 +249,7 @@ fn is_likely_const<'tcx>(mut tracked_place: Place<'tcx>, block: &BasicBlockData<
| StatementKind::AscribeUserType(_, _)
| StatementKind::Coverage(_)
| StatementKind::StorageDead(_)
| StatementKind::CopyNonOverlapping(_)
| StatementKind::Intrinsic(_)
| StatementKind::Nop => {}
}
}
@@ -317,7 +317,7 @@ fn find_determining_place<'tcx>(
| StatementKind::Retag(_, _)
| StatementKind::AscribeUserType(_, _)
| StatementKind::Coverage(_)
| StatementKind::CopyNonOverlapping(_)
| StatementKind::Intrinsic(_)
| StatementKind::Nop => {}

// If the discriminant is set, it is always set
2 changes: 1 addition & 1 deletion compiler/rustc_mir_transform/src/simplify.rs
Original file line number Diff line number Diff line change
@@ -499,7 +499,7 @@ impl UsedLocals {
impl<'tcx> Visitor<'tcx> for UsedLocals {
fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
match statement.kind {
StatementKind::CopyNonOverlapping(..)
StatementKind::Intrinsic(..)
| StatementKind::Retag(..)
| StatementKind::Coverage(..)
| StatementKind::FakeRead(..)
26 changes: 26 additions & 0 deletions src/test/mir-opt/lower_intrinsics.assume.LowerIntrinsics.diff
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
- // MIR for `assume` before LowerIntrinsics
+ // MIR for `assume` after LowerIntrinsics

fn assume() -> () {
let mut _0: (); // return place in scope 0 at $DIR/lower_intrinsics.rs:+0:17: +0:17
let _1: (); // in scope 0 at $DIR/lower_intrinsics.rs:+2:9: +2:38
scope 1 {
}

bb0: {
StorageLive(_1); // scope 1 at $DIR/lower_intrinsics.rs:+2:9: +2:38
- _1 = std::intrinsics::assume(const true) -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:+2:9: +2:38
- // mir::Constant
- // + span: $DIR/lower_intrinsics.rs:72:9: 72:32
- // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(bool) {std::intrinsics::assume}, val: Value(<ZST>) }
+ assume(const true); // scope 1 at $DIR/lower_intrinsics.rs:+2:9: +2:38
+ goto -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:+2:9: +2:38
}

bb1: {
StorageDead(_1); // scope 1 at $DIR/lower_intrinsics.rs:+2:38: +2:39
_0 = const (); // scope 1 at $DIR/lower_intrinsics.rs:+1:5: +3:6
return; // scope 0 at $DIR/lower_intrinsics.rs:+4:2: +4:2
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
- // MIR for `f_copy_nonoverlapping` before LowerIntrinsics
+ // MIR for `f_copy_nonoverlapping` after LowerIntrinsics

fn f_copy_nonoverlapping() -> () {
let mut _0: (); // return place in scope 0 at $DIR/lower_intrinsics.rs:+0:32: +0:32
let _1: (); // in scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:12
let _3: (); // in scope 0 at $DIR/lower_intrinsics.rs:+4:9: +4:95
let mut _4: *const i32; // in scope 0 at $DIR/lower_intrinsics.rs:+4:29: +4:59
let mut _5: *const (); // in scope 0 at $DIR/lower_intrinsics.rs:+4:29: +4:45
let mut _6: *const (); // in scope 0 at $DIR/lower_intrinsics.rs:+4:29: +4:45
let _7: &(); // in scope 0 at $DIR/lower_intrinsics.rs:+4:29: +4:33
let mut _8: *mut i32; // in scope 0 at $DIR/lower_intrinsics.rs:+4:61: +4:91
let mut _9: *mut (); // in scope 0 at $DIR/lower_intrinsics.rs:+4:61: +4:79
let mut _10: *mut (); // in scope 0 at $DIR/lower_intrinsics.rs:+4:61: +4:79
let mut _11: &mut (); // in scope 0 at $DIR/lower_intrinsics.rs:+4:61: +4:69
scope 1 {
debug src => _1; // in scope 1 at $DIR/lower_intrinsics.rs:+1:9: +1:12
let mut _2: (); // in scope 1 at $DIR/lower_intrinsics.rs:+2:9: +2:16
scope 2 {
debug dst => _2; // in scope 2 at $DIR/lower_intrinsics.rs:+2:9: +2:16
scope 3 {
}
}
}

bb0: {
StorageLive(_1); // scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:12
Deinit(_1); // scope 0 at $DIR/lower_intrinsics.rs:+1:15: +1:17
StorageLive(_2); // scope 1 at $DIR/lower_intrinsics.rs:+2:9: +2:16
Deinit(_2); // scope 1 at $DIR/lower_intrinsics.rs:+2:19: +2:21
StorageLive(_3); // scope 3 at $DIR/lower_intrinsics.rs:+4:9: +4:95
StorageLive(_4); // scope 3 at $DIR/lower_intrinsics.rs:+4:29: +4:59
StorageLive(_5); // scope 3 at $DIR/lower_intrinsics.rs:+4:29: +4:45
StorageLive(_6); // scope 3 at $DIR/lower_intrinsics.rs:+4:29: +4:45
StorageLive(_7); // scope 3 at $DIR/lower_intrinsics.rs:+4:29: +4:33
_7 = &_1; // scope 3 at $DIR/lower_intrinsics.rs:+4:29: +4:33
_6 = &raw const (*_7); // scope 3 at $DIR/lower_intrinsics.rs:+4:29: +4:33
_5 = _6; // scope 3 at $DIR/lower_intrinsics.rs:+4:29: +4:45
_4 = move _5 as *const i32 (Misc); // scope 3 at $DIR/lower_intrinsics.rs:+4:29: +4:59
StorageDead(_5); // scope 3 at $DIR/lower_intrinsics.rs:+4:58: +4:59
StorageLive(_8); // scope 3 at $DIR/lower_intrinsics.rs:+4:61: +4:91
StorageLive(_9); // scope 3 at $DIR/lower_intrinsics.rs:+4:61: +4:79
StorageLive(_10); // scope 3 at $DIR/lower_intrinsics.rs:+4:61: +4:79
StorageLive(_11); // scope 3 at $DIR/lower_intrinsics.rs:+4:61: +4:69
_11 = &mut _2; // scope 3 at $DIR/lower_intrinsics.rs:+4:61: +4:69
_10 = &raw mut (*_11); // scope 3 at $DIR/lower_intrinsics.rs:+4:61: +4:69
_9 = _10; // scope 3 at $DIR/lower_intrinsics.rs:+4:61: +4:79
_8 = move _9 as *mut i32 (Misc); // scope 3 at $DIR/lower_intrinsics.rs:+4:61: +4:91
StorageDead(_9); // scope 3 at $DIR/lower_intrinsics.rs:+4:90: +4:91
- _3 = copy_nonoverlapping::<i32>(move _4, move _8, const 0_usize) -> bb1; // scope 3 at $DIR/lower_intrinsics.rs:+4:9: +4:95
- // mir::Constant
- // + span: $DIR/lower_intrinsics.rs:65:9: 65:28
- // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(*const i32, *mut i32, usize) {copy_nonoverlapping::<i32>}, val: Value(<ZST>) }
+ copy_nonoverlapping(dst = move _8, src = move _4, count = const 0_usize); // scope 3 at $DIR/lower_intrinsics.rs:+4:9: +4:95
+ goto -> bb1; // scope 3 at $DIR/lower_intrinsics.rs:+4:9: +4:95
}

bb1: {
StorageDead(_8); // scope 3 at $DIR/lower_intrinsics.rs:+4:94: +4:95
StorageDead(_4); // scope 3 at $DIR/lower_intrinsics.rs:+4:94: +4:95
StorageDead(_11); // scope 3 at $DIR/lower_intrinsics.rs:+4:95: +4:96
StorageDead(_10); // scope 3 at $DIR/lower_intrinsics.rs:+4:95: +4:96
StorageDead(_7); // scope 3 at $DIR/lower_intrinsics.rs:+4:95: +4:96
StorageDead(_6); // scope 3 at $DIR/lower_intrinsics.rs:+4:95: +4:96
StorageDead(_3); // scope 3 at $DIR/lower_intrinsics.rs:+4:95: +4:96
_0 = const (); // scope 3 at $DIR/lower_intrinsics.rs:+3:5: +5:6
StorageDead(_2); // scope 1 at $DIR/lower_intrinsics.rs:+6:1: +6:2
StorageDead(_1); // scope 0 at $DIR/lower_intrinsics.rs:+6:1: +6:2
return; // scope 0 at $DIR/lower_intrinsics.rs:+6:2: +6:2
}
}

23 changes: 22 additions & 1 deletion src/test/mir-opt/lower_intrinsics.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// unit-test: LowerIntrinsics
// ignore-wasm32 compiled with panic=abort by default

#![feature(core_intrinsics)]
#![feature(core_intrinsics, intrinsics)]
#![crate_type = "lib"]

// EMIT_MIR lower_intrinsics.wrapping.LowerIntrinsics.diff
@@ -51,3 +51,24 @@ pub fn discriminant<T>(t: T) {
core::intrinsics::discriminant_value(&());
core::intrinsics::discriminant_value(&E::B);
}

extern "rust-intrinsic" {
// Cannot use `std::intrinsics::copy_nonoverlapping` as that is a wrapper function
fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
}

// EMIT_MIR lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.diff
pub fn f_copy_nonoverlapping() {
let src = ();
let mut dst = ();
unsafe {
copy_nonoverlapping(&src as *const _ as *const i32, &mut dst as *mut _ as *mut i32, 0);
}
}

// EMIT_MIR lower_intrinsics.assume.LowerIntrinsics.diff
pub fn assume() {
unsafe {
std::intrinsics::assume(true);
}
}
146 changes: 0 additions & 146 deletions src/test/mir-opt/separate_const_switch.identity.ConstProp.diff

This file was deleted.

124 changes: 0 additions & 124 deletions src/test/mir-opt/separate_const_switch.identity.PreCodegen.after.mir

This file was deleted.

103 changes: 0 additions & 103 deletions src/test/mir-opt/separate_const_switch.too_complex.ConstProp.diff

This file was deleted.

This file was deleted.

11 changes: 9 additions & 2 deletions src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@ use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_middle::mir::{
Body, CastKind, NullOp, Operand, Place, ProjectionElem, Rvalue, Statement, StatementKind, Terminator,
TerminatorKind,
TerminatorKind, NonDivergingIntrinsic
};
use rustc_middle::ty::subst::GenericArgKind;
use rustc_middle::ty::{self, adjustment::PointerCast, Ty, TyCtxt};
@@ -212,11 +212,18 @@ fn check_statement<'tcx>(
check_place(tcx, **place, span, body)
},

StatementKind::CopyNonOverlapping(box rustc_middle::mir::CopyNonOverlapping { dst, src, count }) => {
StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(op)) => {
check_operand(tcx, op, span, body)
},

StatementKind::Intrinsic(box NonDivergingIntrinsic::CopyNonOverlapping(
rustc_middle::mir::CopyNonOverlapping { dst, src, count },
)) => {
check_operand(tcx, dst, span, body)?;
check_operand(tcx, src, span, body)?;
check_operand(tcx, count, span, body)
},

// These are all NOPs
StatementKind::StorageLive(_)
| StatementKind::StorageDead(_)