Skip to content

Commit ed22bdc

Browse files
authored
Rollup merge of #104605 - RalfJung:clf_consts, r=bjorn3
deduplicate constant evaluation in cranelift backend The cranelift backend had two matches on `ConstantKind`, which can be avoided, and used this `eval_for_mir` that nothing else uses... this makes things more consistent with the (better-tested) LLVM backend. I noticed this because cranelift was the only user of `eval_for_mir`. However `try_eval_for_mir` still has one other user in `eval`... the odd thing is that the interpreter has its own `eval_mir_constant` which seems to duplicate the same functionality and does not use `try_eval_for_mir`. No idea what is happening here. r? ``@bjorn3`` Cc ``@lcnr``
2 parents 844e3fb + 3338244 commit ed22bdc

File tree

3 files changed

+31
-51
lines changed

3 files changed

+31
-51
lines changed

Diff for: compiler/rustc_codegen_cranelift/src/constant.rs

+23-35
Original file line numberDiff line numberDiff line change
@@ -38,22 +38,8 @@ impl ConstantCx {
3838
pub(crate) fn check_constants(fx: &mut FunctionCx<'_, '_, '_>) -> bool {
3939
let mut all_constants_ok = true;
4040
for constant in &fx.mir.required_consts {
41-
let unevaluated = match fx.monomorphize(constant.literal) {
42-
ConstantKind::Ty(_) => unreachable!(),
43-
ConstantKind::Unevaluated(uv, _) => uv,
44-
ConstantKind::Val(..) => continue,
45-
};
46-
47-
if let Err(err) = fx.tcx.const_eval_resolve(ParamEnv::reveal_all(), unevaluated, None) {
41+
if eval_mir_constant(fx, constant).is_none() {
4842
all_constants_ok = false;
49-
match err {
50-
ErrorHandled::Reported(_) => {
51-
fx.tcx.sess.span_err(constant.span, "erroneous constant encountered");
52-
}
53-
ErrorHandled::TooGeneric => {
54-
span_bug!(constant.span, "codegen encountered polymorphic constant: {:?}", err);
55-
}
56-
}
5743
}
5844
}
5945
all_constants_ok
@@ -80,15 +66,15 @@ pub(crate) fn codegen_tls_ref<'tcx>(
8066
}
8167

8268
pub(crate) fn eval_mir_constant<'tcx>(
83-
fx: &mut FunctionCx<'_, '_, 'tcx>,
69+
fx: &FunctionCx<'_, '_, 'tcx>,
8470
constant: &Constant<'tcx>,
85-
) -> (ConstValue<'tcx>, Ty<'tcx>) {
71+
) -> Option<(ConstValue<'tcx>, Ty<'tcx>)> {
8672
let constant_kind = fx.monomorphize(constant.literal);
8773
let uv = match constant_kind {
8874
ConstantKind::Ty(const_) => match const_.kind() {
8975
ty::ConstKind::Unevaluated(uv) => uv.expand(),
9076
ty::ConstKind::Value(val) => {
91-
return (fx.tcx.valtree_to_const_val((const_.ty(), val)), const_.ty());
77+
return Some((fx.tcx.valtree_to_const_val((const_.ty(), val)), const_.ty()));
9278
}
9379
err => span_bug!(
9480
constant.span,
@@ -102,22 +88,31 @@ pub(crate) fn eval_mir_constant<'tcx>(
10288
span_bug!(constant.span, "MIR constant refers to static");
10389
}
10490
ConstantKind::Unevaluated(uv, _) => uv,
105-
ConstantKind::Val(val, _) => return (val, constant_kind.ty()),
91+
ConstantKind::Val(val, _) => return Some((val, constant_kind.ty())),
10692
};
10793

108-
(
109-
fx.tcx.const_eval_resolve(ty::ParamEnv::reveal_all(), uv, None).unwrap_or_else(|_err| {
110-
span_bug!(constant.span, "erroneous constant not captured by required_consts");
111-
}),
112-
constant_kind.ty(),
113-
)
94+
let val = fx
95+
.tcx
96+
.const_eval_resolve(ty::ParamEnv::reveal_all(), uv, None)
97+
.map_err(|err| match err {
98+
ErrorHandled::Reported(_) => {
99+
fx.tcx.sess.span_err(constant.span, "erroneous constant encountered");
100+
}
101+
ErrorHandled::TooGeneric => {
102+
span_bug!(constant.span, "codegen encountered polymorphic constant: {:?}", err);
103+
}
104+
})
105+
.ok();
106+
val.map(|val| (val, constant_kind.ty()))
114107
}
115108

116109
pub(crate) fn codegen_constant_operand<'tcx>(
117110
fx: &mut FunctionCx<'_, '_, 'tcx>,
118111
constant: &Constant<'tcx>,
119112
) -> CValue<'tcx> {
120-
let (const_val, ty) = eval_mir_constant(fx, constant);
113+
let (const_val, ty) = eval_mir_constant(fx, constant).unwrap_or_else(|| {
114+
span_bug!(constant.span, "erroneous constant not captured by required_consts")
115+
});
121116

122117
codegen_const_value(fx, const_val, ty)
123118
}
@@ -453,20 +448,13 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
453448
assert!(cx.todo.is_empty(), "{:?}", cx.todo);
454449
}
455450

451+
/// Used only for intrinsic implementations that need a compile-time constant
456452
pub(crate) fn mir_operand_get_const_val<'tcx>(
457453
fx: &FunctionCx<'_, '_, 'tcx>,
458454
operand: &Operand<'tcx>,
459455
) -> Option<ConstValue<'tcx>> {
460456
match operand {
461-
Operand::Constant(const_) => match fx.monomorphize(const_.literal) {
462-
ConstantKind::Ty(const_) => Some(
463-
const_.eval_for_mir(fx.tcx, ParamEnv::reveal_all()).try_to_value(fx.tcx).unwrap(),
464-
),
465-
ConstantKind::Val(val, _) => Some(val),
466-
ConstantKind::Unevaluated(uv, _) => {
467-
Some(fx.tcx.const_eval_resolve(ParamEnv::reveal_all(), uv, None).unwrap())
468-
}
469-
},
457+
Operand::Constant(const_) => Some(eval_mir_constant(fx, const_).unwrap().0),
470458
// FIXME(rust-lang/rust#85105): Casts like `IMM8 as u32` result in the const being stored
471459
// inside a temporary before being passed to the intrinsic requiring the const argument.
472460
// This code tries to find a single constant defining definition of the referenced local.

Diff for: compiler/rustc_codegen_ssa/src/mir/constant.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
4242
};
4343

4444
self.cx.tcx().const_eval_resolve(ty::ParamEnv::reveal_all(), uv, None).map_err(|err| {
45-
self.cx.tcx().sess.span_err(constant.span, "erroneous constant encountered");
45+
match err {
46+
ErrorHandled::Reported(_) => {
47+
self.cx.tcx().sess.span_err(constant.span, "erroneous constant encountered");
48+
}
49+
ErrorHandled::TooGeneric => {
50+
span_bug!(constant.span, "codegen encountered polymorphic constant: {:?}", err);
51+
}
52+
}
4653
err
4754
})
4855
}

Diff for: compiler/rustc_middle/src/ty/consts.rs

-15
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
use crate::mir::interpret::LitToConstInput;
2-
use crate::mir::ConstantKind;
32
use crate::ty::{self, DefIdTree, InternalSubsts, ParamEnv, ParamEnvAnd, Ty, TyCtxt};
43
use rustc_data_structures::intern::Interned;
54
use rustc_hir as hir;
@@ -230,20 +229,6 @@ impl<'tcx> Const<'tcx> {
230229
}
231230
}
232231

233-
#[inline]
234-
/// Tries to evaluate the constant if it is `Unevaluated` and creates a ConstValue if the
235-
/// evaluation succeeds. If it doesn't succeed, returns the unevaluated constant.
236-
pub fn eval_for_mir(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> ConstantKind<'tcx> {
237-
if let Some(val) = self.kind().try_eval_for_mir(tcx, param_env) {
238-
match val {
239-
Ok(const_val) => ConstantKind::from_value(const_val, self.ty()),
240-
Err(guar) => ConstantKind::Ty(tcx.const_error_with_guaranteed(self.ty(), guar)),
241-
}
242-
} else {
243-
ConstantKind::Ty(self)
244-
}
245-
}
246-
247232
#[inline]
248233
/// Panics if the value cannot be evaluated or doesn't contain a valid integer of the given type.
249234
pub fn eval_bits(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: Ty<'tcx>) -> u128 {

0 commit comments

Comments
 (0)