Skip to content

Commit 29354cb

Browse files
committed
Auto merge of #66294 - davidhewitt:const_fn_memoization, r=<try>
Add memoization for const function evaluations When a const function is being evaluated, as long as all its arguments are zero-sized-types (or it has no arguments) then we can trivially memoize the evaluation result using the existing query mechanism. With thanks to @oli-obk for mentoring me through this at RustFest Barcelona. r? @oli-obk
2 parents 9248b01 + 30cef9b commit 29354cb

File tree

2 files changed

+30
-2
lines changed

2 files changed

+30
-2
lines changed

src/librustc/mir/interpret/mod.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,10 @@ use rustc_data_structures::tiny_list::TinyList;
123123
use rustc_macros::HashStable;
124124
use byteorder::{WriteBytesExt, ReadBytesExt, LittleEndian, BigEndian};
125125

126-
/// Uniquely identifies a specific constant or static.
126+
/// Uniquely identifies one of the following:
127+
/// - A constant
128+
/// - A static
129+
/// - A const fn where all arguments (if any) are zero-sized types
127130
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, RustcEncodable, RustcDecodable, HashStable)]
128131
pub struct GlobalId<'tcx> {
129132
/// For a constant or static, the `Instance` of the item itself.

src/librustc_mir/interpret/terminator.rs

+26-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use syntax::source_map::Span;
77
use rustc_target::spec::abi::Abi;
88

99
use super::{
10-
InterpResult, PointerArithmetic,
10+
GlobalId, InterpResult, PointerArithmetic,
1111
InterpCx, Machine, OpTy, ImmTy, PlaceTy, MPlaceTy, StackPopCleanup, FnVal,
1212
};
1313

@@ -293,6 +293,31 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
293293
}
294294
}
295295

296+
// If this function is a const function then as an optimisation we can query this
297+
// evaluation immediately.
298+
//
299+
// For the moment we only do this for functions which take no arguments
300+
// (or all arguments are ZSTs) so that we don't memoize too much.
301+
if self.tcx.is_const_fn_raw(instance.def.def_id()) &&
302+
args.iter().all(|a| a.layout.is_zst())
303+
{
304+
let gid = GlobalId { instance, promoted: None };
305+
let place = self.const_eval_raw(gid)?;
306+
307+
let dest = match dest {
308+
Some(dest) => dest,
309+
None => throw_ub!(Unreachable)
310+
};
311+
312+
self.copy_op(place.into(), dest)?;
313+
314+
// No stack frame gets pushed, the main loop will just act as if the
315+
// call completed.
316+
self.goto_block(ret)?;
317+
self.dump_place(*dest);
318+
return Ok(())
319+
}
320+
296321
// We need MIR for this fn
297322
let body = match M::find_fn(self, instance, args, dest, ret)? {
298323
Some(body) => body,

0 commit comments

Comments
 (0)