Skip to content

Commit 1b6be0b

Browse files
authored
Merge pull request #197 from sbillig/sccp-ptr
mem optimizations, sccp ptr fix
2 parents 983c303 + e885228 commit 1b6be0b

File tree

63 files changed

+6076
-722
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+6076
-722
lines changed

crates/codegen/src/isa/evm/malloc_plan.rs

Lines changed: 102 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,31 @@ use super::{
2020
ptr_escape::PtrEscapeSummary,
2121
};
2222

23+
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
24+
pub(crate) struct MallocEscapeKind(u8);
25+
26+
impl MallocEscapeKind {
27+
pub(crate) const RETURNS_TO_CALLER: Self = Self(1 << 0);
28+
pub(crate) const STORED_NON_LOCAL: Self = Self(1 << 1);
29+
pub(crate) const UNKNOWN: Self = Self(1 << 2);
30+
31+
pub(crate) fn has_global_or_unknown(self) -> bool {
32+
self.contains(Self::STORED_NON_LOCAL) || self.contains(Self::UNKNOWN)
33+
}
34+
35+
pub(crate) fn is_return_only(self) -> bool {
36+
self.contains(Self::RETURNS_TO_CALLER) && !self.has_global_or_unknown()
37+
}
38+
39+
fn contains(self, other: Self) -> bool {
40+
self.0 & other.0 != 0
41+
}
42+
43+
fn union(self, other: Self) -> Self {
44+
Self(self.0 | other.0)
45+
}
46+
}
47+
2348
pub(crate) fn should_restore_free_ptr_on_internal_returns(
2449
function: &Function,
2550
module: &ModuleCtx,
@@ -202,7 +227,7 @@ pub(crate) fn compute_transient_mallocs(
202227
let local_mem = &prov_info.local_mem;
203228

204229
let block_malloc_in = compute_block_malloc_in(function, isa);
205-
let escaping = compute_escaping_mallocs(
230+
let escape_kinds = compute_malloc_escape_kinds(
206231
function,
207232
module,
208233
isa,
@@ -212,8 +237,8 @@ pub(crate) fn compute_transient_mallocs(
212237
&block_malloc_in,
213238
);
214239

215-
for base in escaping {
216-
mallocs.remove(&base);
240+
for malloc in escape_kinds.keys() {
241+
mallocs.remove(malloc);
217242
}
218243

219244
for block in function.layout.iter_block() {
@@ -269,12 +294,12 @@ pub(crate) fn compute_transient_mallocs(
269294
mallocs
270295
}
271296

272-
pub(crate) fn compute_escaping_mallocs_for_function(
297+
pub(crate) fn compute_malloc_escape_kinds_for_function(
273298
function: &Function,
274299
module: &ModuleCtx,
275300
isa: &Evm,
276301
ptr_escape: &FxHashMap<FuncRef, PtrEscapeSummary>,
277-
) -> FxHashSet<InstId> {
302+
) -> FxHashMap<InstId, MallocEscapeKind> {
278303
let prov_info = compute_provenance(function, module, isa, |callee| {
279304
ptr_escape
280305
.get(&callee)
@@ -285,7 +310,7 @@ pub(crate) fn compute_escaping_mallocs_for_function(
285310
let prov = &prov_info.value;
286311
let local_mem = &prov_info.local_mem;
287312
let block_malloc_in = compute_block_malloc_in(function, isa);
288-
compute_escaping_mallocs(
313+
compute_malloc_escape_kinds(
289314
function,
290315
module,
291316
isa,
@@ -385,24 +410,50 @@ fn compute_block_malloc_in(
385410
}
386411

387412
fn record_escaping_mallocs(
388-
escaping: &mut FxHashSet<InstId>,
413+
escape_kinds: &mut FxHashMap<InstId, MallocEscapeKind>,
389414
value: ValueId,
390415
prov: &SecondaryMap<ValueId, Provenance>,
391416
seen_mallocs: &BitSet<InstId>,
417+
direct_kind: MallocEscapeKind,
392418
) {
393419
let p = &prov[value];
394-
record_escaping_provenance(escaping, p, seen_mallocs);
420+
record_escaping_provenance(escape_kinds, p, seen_mallocs, direct_kind);
395421
}
396422

397423
fn record_escaping_provenance(
398-
escaping: &mut FxHashSet<InstId>,
424+
escape_kinds: &mut FxHashMap<InstId, MallocEscapeKind>,
399425
p: &Provenance,
400426
seen_mallocs: &BitSet<InstId>,
427+
direct_kind: MallocEscapeKind,
401428
) {
402429
if p.is_unknown_ptr() {
403-
escaping.extend(seen_mallocs.iter());
430+
for malloc in seen_mallocs.iter() {
431+
record_escape_kind(escape_kinds, malloc, MallocEscapeKind::UNKNOWN);
432+
}
433+
}
434+
for malloc in p.malloc_insts() {
435+
record_escape_kind(escape_kinds, malloc, direct_kind);
436+
}
437+
}
438+
439+
fn record_escape_kind(
440+
escape_kinds: &mut FxHashMap<InstId, MallocEscapeKind>,
441+
malloc: InstId,
442+
kind: MallocEscapeKind,
443+
) {
444+
escape_kinds
445+
.entry(malloc)
446+
.and_modify(|cur| *cur = cur.union(kind))
447+
.or_insert(kind);
448+
}
449+
450+
fn record_unknown_seen_mallocs(
451+
escape_kinds: &mut FxHashMap<InstId, MallocEscapeKind>,
452+
seen_mallocs: &BitSet<InstId>,
453+
) {
454+
for malloc in seen_mallocs.iter() {
455+
record_escape_kind(escape_kinds, malloc, MallocEscapeKind::UNKNOWN);
404456
}
405-
escaping.extend(p.malloc_insts());
406457
}
407458

408459
fn local_copy_source_may_be_heap_derived(
@@ -428,16 +479,16 @@ fn local_copy_source_may_be_heap_derived(
428479
!any
429480
}
430481

431-
fn compute_escaping_mallocs(
482+
fn compute_malloc_escape_kinds(
432483
function: &Function,
433484
module: &ModuleCtx,
434485
isa: &Evm,
435486
ptr_escape: &FxHashMap<FuncRef, PtrEscapeSummary>,
436487
prov: &SecondaryMap<ValueId, Provenance>,
437488
local_mem: &FxHashMap<InstId, Provenance>,
438489
block_malloc_in: &SecondaryMap<BlockId, BitSet<InstId>>,
439-
) -> FxHashSet<InstId> {
440-
let mut escaping: FxHashSet<InstId> = FxHashSet::default();
490+
) -> FxHashMap<InstId, MallocEscapeKind> {
491+
let mut escape_kinds: FxHashMap<InstId, MallocEscapeKind> = FxHashMap::default();
441492

442493
for block in function.layout.iter_block() {
443494
let mut seen_mallocs = block_malloc_in[block].clone();
@@ -448,7 +499,13 @@ fn compute_escaping_mallocs(
448499
let Some(ret_val) = *ret.arg() else {
449500
continue;
450501
};
451-
record_escaping_mallocs(&mut escaping, ret_val, prov, &seen_mallocs);
502+
record_escaping_mallocs(
503+
&mut escape_kinds,
504+
ret_val,
505+
prov,
506+
&seen_mallocs,
507+
MallocEscapeKind::RETURNS_TO_CALLER,
508+
);
452509
}
453510
EvmInstKind::Mstore(mstore) => {
454511
let addr = *mstore.addr();
@@ -457,7 +514,13 @@ fn compute_escaping_mallocs(
457514
}
458515

459516
let val = *mstore.value();
460-
record_escaping_mallocs(&mut escaping, val, prov, &seen_mallocs);
517+
record_escaping_mallocs(
518+
&mut escape_kinds,
519+
val,
520+
prov,
521+
&seen_mallocs,
522+
MallocEscapeKind::STORED_NON_LOCAL,
523+
);
461524
}
462525
EvmInstKind::EvmMstore8(mstore8) => {
463526
let addr = *mstore8.addr();
@@ -466,7 +529,13 @@ fn compute_escaping_mallocs(
466529
}
467530

468531
let val = *mstore8.val();
469-
record_escaping_mallocs(&mut escaping, val, prov, &seen_mallocs);
532+
record_escaping_mallocs(
533+
&mut escape_kinds,
534+
val,
535+
prov,
536+
&seen_mallocs,
537+
MallocEscapeKind::STORED_NON_LOCAL,
538+
);
470539
}
471540
EvmInstKind::EvmMcopy(mcopy) => {
472541
let dest = *mcopy.dest();
@@ -481,16 +550,21 @@ fn compute_escaping_mallocs(
481550
for base in src_prov.alloca_insts() {
482551
any = true;
483552
if let Some(stored) = local_mem.get(&base) {
484-
record_escaping_provenance(&mut escaping, stored, &seen_mallocs);
553+
record_escaping_provenance(
554+
&mut escape_kinds,
555+
stored,
556+
&seen_mallocs,
557+
MallocEscapeKind::STORED_NON_LOCAL,
558+
);
485559
}
486560
}
487561
if !any {
488-
escaping.extend(seen_mallocs.iter());
562+
record_unknown_seen_mallocs(&mut escape_kinds, &seen_mallocs);
489563
}
490564
} else {
491565
// Unknown source bytes copied to non-local memory may include malloc-derived
492566
// pointers from this function.
493-
escaping.extend(seen_mallocs.iter());
567+
record_unknown_seen_mallocs(&mut escape_kinds, &seen_mallocs);
494568
}
495569
}
496570
EvmInstKind::Call(call) => {
@@ -501,7 +575,13 @@ fn compute_escaping_mallocs(
501575
.unwrap_or_else(|| conservative_unknown_ptr_summary(module, callee));
502576
for (idx, &arg) in call.args().iter().enumerate() {
503577
if idx < callee_sum.arg_may_escape.len() && callee_sum.arg_may_escape[idx] {
504-
record_escaping_mallocs(&mut escaping, arg, prov, &seen_mallocs);
578+
record_escaping_mallocs(
579+
&mut escape_kinds,
580+
arg,
581+
prov,
582+
&seen_mallocs,
583+
MallocEscapeKind::STORED_NON_LOCAL,
584+
);
505585
}
506586
}
507587
}
@@ -514,7 +594,7 @@ fn compute_escaping_mallocs(
514594
}
515595
}
516596

517-
escaping
597+
escape_kinds
518598
}
519599

520600
fn conservative_unknown_ptr_summary(module: &ModuleCtx, func_ref: FuncRef) -> PtrEscapeSummary {

crates/codegen/src/isa/evm/memory_plan.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use crate::{
1212
#[cfg(debug_assertions)]
1313
use super::static_arena_alloc::verify_object_packing;
1414
use super::{
15+
malloc_plan::MallocEscapeKind,
1516
ptr_escape::PtrEscapeSummary,
1617
static_arena_alloc::{
1718
FuncObjectLayout, FuncStackObjects, StackObjId, StaticArenaAllocCtx,
@@ -60,7 +61,8 @@ pub struct FuncMemPlan {
6061

6162
pub malloc_future_static_words: FxHashMap<InstId, u32>,
6263
pub transient_mallocs: FxHashSet<InstId>,
63-
pub escaping_mallocs: FxHashSet<InstId>,
64+
pub malloc_escape_kinds: FxHashMap<InstId, MallocEscapeKind>,
65+
pub return_escape_caller_clamp_words: u32,
6466
}
6567

6668
#[derive(Clone, Debug)]
@@ -269,7 +271,8 @@ pub(crate) fn compute_program_memory_plan(
269271
locals_words: layout.locals_words,
270272
malloc_future_static_words: FxHashMap::default(),
271273
transient_mallocs: FxHashSet::default(),
272-
escaping_mallocs: FxHashSet::default(),
274+
malloc_escape_kinds: FxHashMap::default(),
275+
return_escape_caller_clamp_words: 0,
273276
},
274277
);
275278
}
@@ -311,7 +314,8 @@ pub(crate) fn compute_program_memory_plan(
311314
locals_words: planned_func.layout.locals_words,
312315
malloc_future_static_words: FxHashMap::default(),
313316
transient_mallocs: FxHashSet::default(),
314-
escaping_mallocs: FxHashSet::default(),
317+
malloc_escape_kinds: FxHashMap::default(),
318+
return_escape_caller_clamp_words: 0,
315319
},
316320
);
317321
}

0 commit comments

Comments
 (0)