//! Performs various peephole optimizations.

use rustc_abi::ExternAbi;
use rustc_ast::attr;
use rustc_hir::LangItem;
use rustc_middle::bug;
use rustc_middle::mir::*;
use rustc_middle::ty::layout::ValidityRequirement;
use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, layout};
use rustc_span::{DUMMY_SP, Symbol, sym};

use crate::simplify::simplify_duplicate_switch_targets;

pub(super) enum InstSimplify {
    BeforeInline,
    AfterSimplifyCfg,
}

impl<'tcx> crate::MirPass<'tcx> for InstSimplify {
    fn name(&self) -> &'static str {
        match self {
            InstSimplify::BeforeInline => "InstSimplify-before-inline",
            InstSimplify::AfterSimplifyCfg => "InstSimplify-after-simplifycfg",
        }
    }

    fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
        sess.mir_opt_level() > 0
    }

    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
        let ctx = InstSimplifyContext {
            tcx,
            local_decls: &body.local_decls,
            typing_env: body.typing_env(tcx),
        };
        let preserve_ub_checks =
            attr::contains_name(tcx.hir_krate_attrs(), sym::rustc_preserve_ub_checks);
        for block in body.basic_blocks.as_mut() {
            for statement in block.statements.iter_mut() {
                let StatementKind::Assign(box (.., rvalue)) = &mut statement.kind else {
                    continue;
                };

                if !preserve_ub_checks {
                    ctx.simplify_ub_check(rvalue);
                }
                ctx.simplify_bool_cmp(rvalue);
                ctx.simplify_ref_deref(rvalue);
                ctx.simplify_ptr_aggregate(rvalue);
                ctx.simplify_cast(rvalue);
                ctx.simplify_repeated_aggregate(rvalue);
                ctx.simplify_repeat_once(rvalue);
            }

            let terminator = block.terminator.as_mut().unwrap();
            ctx.simplify_primitive_clone(terminator, &mut block.statements);
            ctx.simplify_align_of_slice_val(terminator, &mut block.statements);
            ctx.simplify_intrinsic_assert(terminator);
            ctx.simplify_nounwind_call(terminator);
            simplify_duplicate_switch_targets(terminator);
        }
    }

    fn is_required(&self) -> bool {
        false
    }
}

struct InstSimplifyContext<'a, 'tcx> {
    tcx: TyCtxt<'tcx>,
    local_decls: &'a LocalDecls<'tcx>,
    typing_env: ty::TypingEnv<'tcx>,
}

impl<'tcx> InstSimplifyContext<'_, 'tcx> {
    /// Transform aggregates like [0, 0, 0, 0, 0] into [0; 5].
    /// GVN can also do this optimization, but GVN is only run at mir-opt-level 2 so having this in
    /// InstSimplify helps unoptimized builds.
    fn simplify_repeated_aggregate(&self, rvalue: &mut Rvalue<'tcx>) {
        let Rvalue::Aggregate(box AggregateKind::Array(_), fields) = &*rvalue else {
            return;
        };
        if fields.len() < 5 {
            return;
        }
        let (first, rest) = fields[..].split_first().unwrap();
        let Operand::Constant(first) = first else {
            return;
        };
        let Ok(first_val) = first.const_.eval(self.tcx, self.typing_env, first.span) else {
            return;
        };
        if rest.iter().all(|field| {
            let Operand::Constant(field) = field else {
                return false;
            };
            let field = field.const_.eval(self.tcx, self.typing_env, field.span);
            field == Ok(first_val)
        }) {
            let len = ty::Const::from_target_usize(self.tcx, fields.len().try_into().unwrap());
            *rvalue = Rvalue::Repeat(Operand::Constant(first.clone()), len);
        }
    }

    /// Transform boolean comparisons into logical operations.
    fn simplify_bool_cmp(&self, rvalue: &mut Rvalue<'tcx>) {
        let Rvalue::BinaryOp(op @ (BinOp::Eq | BinOp::Ne), box (a, b)) = &*rvalue else { return };
        *rvalue = match (op, self.try_eval_bool(a), self.try_eval_bool(b)) {
            // Transform "Eq(a, true)" ==> "a"
            (BinOp::Eq, _, Some(true)) => Rvalue::Use(a.clone()),

            // Transform "Ne(a, false)" ==> "a"
            (BinOp::Ne, _, Some(false)) => Rvalue::Use(a.clone()),

            // Transform "Eq(true, b)" ==> "b"
            (BinOp::Eq, Some(true), _) => Rvalue::Use(b.clone()),

            // Transform "Ne(false, b)" ==> "b"
            (BinOp::Ne, Some(false), _) => Rvalue::Use(b.clone()),

            // Transform "Eq(false, b)" ==> "Not(b)"
            (BinOp::Eq, Some(false), _) => Rvalue::UnaryOp(UnOp::Not, b.clone()),

            // Transform "Ne(true, b)" ==> "Not(b)"
            (BinOp::Ne, Some(true), _) => Rvalue::UnaryOp(UnOp::Not, b.clone()),

            // Transform "Eq(a, false)" ==> "Not(a)"
            (BinOp::Eq, _, Some(false)) => Rvalue::UnaryOp(UnOp::Not, a.clone()),

            // Transform "Ne(a, true)" ==> "Not(a)"
            (BinOp::Ne, _, Some(true)) => Rvalue::UnaryOp(UnOp::Not, a.clone()),

            _ => return,
        };
    }

    fn try_eval_bool(&self, a: &Operand<'_>) -> Option<bool> {
        let a = a.constant()?;
        if a.const_.ty().is_bool() { a.const_.try_to_bool() } else { None }
    }

    /// Transform `&(*a)` ==> `a`.
    fn simplify_ref_deref(&self, rvalue: &mut Rvalue<'tcx>) {
        if let Rvalue::Ref(_, _, place) | Rvalue::RawPtr(_, place) = rvalue
            && let Some((base, ProjectionElem::Deref)) = place.as_ref().last_projection()
            && rvalue.ty(self.local_decls, self.tcx) == base.ty(self.local_decls, self.tcx).ty
        {
            *rvalue = Rvalue::Use(Operand::Copy(Place {
                local: base.local,
                projection: self.tcx.mk_place_elems(base.projection),
            }));
        }
    }

    /// Transform `Aggregate(RawPtr, [p, ()])` ==> `Cast(PtrToPtr, p)`.
    fn simplify_ptr_aggregate(&self, rvalue: &mut Rvalue<'tcx>) {
        if let Rvalue::Aggregate(box AggregateKind::RawPtr(pointee_ty, mutability), fields) = rvalue
            && let meta_ty = fields.raw[1].ty(self.local_decls, self.tcx)
            && meta_ty.is_unit()
        {
            // The mutable borrows we're holding prevent printing `rvalue` here
            let mut fields = std::mem::take(fields);
            let _meta = fields.pop().unwrap();
            let data = fields.pop().unwrap();
            let ptr_ty = Ty::new_ptr(self.tcx, *pointee_ty, *mutability);
            *rvalue = Rvalue::Cast(CastKind::PtrToPtr, data, ptr_ty);
        }
    }

    fn simplify_ub_check(&self, rvalue: &mut Rvalue<'tcx>) {
        let Rvalue::NullaryOp(NullOp::UbChecks, _) = *rvalue else { return };

        let const_ = Const::from_bool(self.tcx, self.tcx.sess.ub_checks());
        let constant = ConstOperand { span: DUMMY_SP, const_, user_ty: None };
        *rvalue = Rvalue::Use(Operand::Constant(Box::new(constant)));
    }

    fn simplify_cast(&self, rvalue: &mut Rvalue<'tcx>) {
        let Rvalue::Cast(kind, operand, cast_ty) = rvalue else { return };

        let operand_ty = operand.ty(self.local_decls, self.tcx);
        if operand_ty == *cast_ty {
            *rvalue = Rvalue::Use(operand.clone());
        } else if *kind == CastKind::Transmute
            // Transmuting an integer to another integer is just a signedness cast
            && let (ty::Int(int), ty::Uint(uint)) | (ty::Uint(uint), ty::Int(int)) =
                (operand_ty.kind(), cast_ty.kind())
            && int.bit_width() == uint.bit_width()
        {
            // The width check isn't strictly necessary, as different widths
            // are UB and thus we'd be allowed to turn it into a cast anyway.
            // But let's keep the UB around for codegen to exploit later.
            // (If `CastKind::Transmute` ever becomes *not* UB for mismatched sizes,
            // then the width check is necessary for big-endian correctness.)
            *kind = CastKind::IntToInt;
        }
    }

    /// Simplify `[x; 1]` to just `[x]`.
    fn simplify_repeat_once(&self, rvalue: &mut Rvalue<'tcx>) {
        if let Rvalue::Repeat(operand, count) = rvalue
            && let Some(1) = count.try_to_target_usize(self.tcx)
        {
            *rvalue = Rvalue::Aggregate(
                Box::new(AggregateKind::Array(operand.ty(self.local_decls, self.tcx))),
                [operand.clone()].into(),
            );
        }
    }

    fn simplify_primitive_clone(
        &self,
        terminator: &mut Terminator<'tcx>,
        statements: &mut Vec<Statement<'tcx>>,
    ) {
        let TerminatorKind::Call {
            func, args, destination, target: Some(destination_block), ..
        } = &terminator.kind
        else {
            return;
        };

        // It's definitely not a clone if there are multiple arguments
        let [arg] = &args[..] else { return };

        // Only bother looking more if it's easy to know what we're calling
        let Some((fn_def_id, ..)) = func.const_fn_def() else { return };

        // These types are easily available from locals, so check that before
        // doing DefId lookups to figure out what we're actually calling.
        let arg_ty = arg.node.ty(self.local_decls, self.tcx);

        let ty::Ref(_region, inner_ty, Mutability::Not) = *arg_ty.kind() else { return };

        if !self.tcx.is_lang_item(fn_def_id, LangItem::CloneFn)
            || !inner_ty.is_trivially_pure_clone_copy()
        {
            return;
        }

        let Some(arg_place) = arg.node.place() else { return };

        statements.push(Statement::new(
            terminator.source_info,
            StatementKind::Assign(Box::new((
                *destination,
                Rvalue::Use(Operand::Copy(
                    arg_place.project_deeper(&[ProjectionElem::Deref], self.tcx),
                )),
            ))),
        ));
        terminator.kind = TerminatorKind::Goto { target: *destination_block };
    }

    // Convert `align_of_val::<[T]>(ptr)` to `align_of::<T>()`, since the
    // alignment of a slice doesn't actually depend on metadata at all
    // and the element type is always `Sized`.
    //
    // This is here so it can run after inlining, where it's more useful.
    // (LowerIntrinsics is done in cleanup, before the optimization passes.)
    fn simplify_align_of_slice_val(
        &self,
        terminator: &mut Terminator<'tcx>,
        statements: &mut Vec<Statement<'tcx>>,
    ) {
        let source_info = terminator.source_info;
        if let TerminatorKind::Call {
            func, args, destination, target: Some(destination_block), ..
        } = &terminator.kind
            && args.len() == 1
            && let Some((fn_def_id, generics)) = func.const_fn_def()
            && self.tcx.is_intrinsic(fn_def_id, sym::align_of_val)
            && let ty::Slice(elem_ty) = *generics.type_at(0).kind()
        {
            let align_def_id = self.tcx.require_lang_item(LangItem::AlignOf, source_info.span);
            let align_const = Operand::unevaluated_constant(
                self.tcx,
                align_def_id,
                &[elem_ty.into()],
                source_info.span,
            );
            statements.push(Statement::new(
                source_info,
                StatementKind::Assign(Box::new((*destination, Rvalue::Use(align_const)))),
            ));
            terminator.kind = TerminatorKind::Goto { target: *destination_block };
        }
    }

    fn simplify_nounwind_call(&self, terminator: &mut Terminator<'tcx>) {
        let TerminatorKind::Call { ref func, ref mut unwind, .. } = terminator.kind else {
            return;
        };

        let Some((def_id, _)) = func.const_fn_def() else {
            return;
        };

        let body_ty = self.tcx.type_of(def_id).skip_binder();
        let body_abi = match body_ty.kind() {
            ty::FnDef(..) => body_ty.fn_sig(self.tcx).abi(),
            ty::Closure(..) => ExternAbi::RustCall,
            ty::Coroutine(..) => ExternAbi::Rust,
            _ => bug!("unexpected body ty: {body_ty:?}"),
        };

        if !layout::fn_can_unwind(self.tcx, Some(def_id), body_abi) {
            *unwind = UnwindAction::Unreachable;
        }
    }

    fn simplify_intrinsic_assert(&self, terminator: &mut Terminator<'tcx>) {
        let TerminatorKind::Call { ref func, target: ref mut target @ Some(target_block), .. } =
            terminator.kind
        else {
            return;
        };
        let func_ty = func.ty(self.local_decls, self.tcx);
        let Some((intrinsic_name, args)) = resolve_rust_intrinsic(self.tcx, func_ty) else {
            return;
        };
        // The intrinsics we are interested in have one generic parameter
        let [arg, ..] = args[..] else { return };

        let known_is_valid =
            intrinsic_assert_panics(self.tcx, self.typing_env, arg, intrinsic_name);
        match known_is_valid {
            // We don't know the layout or it's not validity assertion at all, don't touch it
            None => {}
            Some(true) => {
                // If we know the assert panics, indicate to later opts that the call diverges
                *target = None;
            }
            Some(false) => {
                // If we know the assert does not panic, turn the call into a Goto
                terminator.kind = TerminatorKind::Goto { target: target_block };
            }
        }
    }
}

fn intrinsic_assert_panics<'tcx>(
    tcx: TyCtxt<'tcx>,
    typing_env: ty::TypingEnv<'tcx>,
    arg: ty::GenericArg<'tcx>,
    intrinsic_name: Symbol,
) -> Option<bool> {
    let requirement = ValidityRequirement::from_intrinsic(intrinsic_name)?;
    let ty = arg.expect_ty();
    Some(!tcx.check_validity_requirement((requirement, typing_env.as_query_input(ty))).ok()?)
}

fn resolve_rust_intrinsic<'tcx>(
    tcx: TyCtxt<'tcx>,
    func_ty: Ty<'tcx>,
) -> Option<(Symbol, GenericArgsRef<'tcx>)> {
    let ty::FnDef(def_id, args) = *func_ty.kind() else { return None };
    let intrinsic = tcx.intrinsic(def_id)?;
    Some((intrinsic.name, args))
}
