Skip to content

Commit d524df9

Browse files
authored
Argument Mutability Analysis - and its applications (#7368)
This PR also includes a major rewrite of the pass manager algorithm.
1 parent 5e22d64 commit d524df9

File tree

30 files changed

+1065
-617
lines changed

30 files changed

+1065
-617
lines changed

sway-core/src/ir_generation/function.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1977,6 +1977,7 @@ impl<'a> FnCompiler<'a> {
19771977
block: merge_block,
19781978
idx: 0,
19791979
ty: ptr_ty,
1980+
is_immutable: false,
19801981
},
19811982
);
19821983
merge_block.add_arg(context, merge_block_ptr);
@@ -1986,6 +1987,7 @@ impl<'a> FnCompiler<'a> {
19861987
block: merge_block,
19871988
idx: 1,
19881989
ty: Type::get_uint64(context),
1990+
is_immutable: false,
19891991
},
19901992
);
19911993
merge_block.add_arg(context, merge_block_cap);

sway-core/src/lib.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,9 @@ use sway_error::warning::{CollectedTraitImpl, CompileInfo, CompileWarning, Info,
5858
use sway_features::ExperimentalFeatures;
5959
use sway_ir::{
6060
create_o1_pass_group, register_known_passes, Context, Kind, Module, PassGroup, PassManager,
61-
PrintPassesOpts, ARG_DEMOTION_NAME, CONST_DEMOTION_NAME, DCE_NAME, FN_DEDUP_DEBUG_PROFILE_NAME,
62-
FN_INLINE_NAME, GLOBALS_DCE_NAME, MEM2REG_NAME, MEMCPYOPT_NAME, MISC_DEMOTION_NAME,
63-
RET_DEMOTION_NAME, SIMPLIFY_CFG_NAME, SROA_NAME,
61+
PrintPassesOpts, ARG_DEMOTION_NAME, ARG_POINTEE_MUTABILITY_TAGGER_NAME, CONST_DEMOTION_NAME,
62+
DCE_NAME, FN_DEDUP_DEBUG_PROFILE_NAME, FN_INLINE_NAME, GLOBALS_DCE_NAME, MEM2REG_NAME,
63+
MEMCPYOPT_NAME, MISC_DEMOTION_NAME, RET_DEMOTION_NAME, SIMPLIFY_CFG_NAME, SROA_NAME,
6464
};
6565
use sway_types::span::Source;
6666
use sway_types::{SourceEngine, SourceLocation, Span};
@@ -1256,6 +1256,7 @@ pub(crate) fn compile_ast_to_ir_to_asm(
12561256
pass_group.append_pass(MISC_DEMOTION_NAME);
12571257

12581258
// Convert loads and stores to mem_copies where possible.
1259+
pass_group.append_pass(ARG_POINTEE_MUTABILITY_TAGGER_NAME);
12591260
pass_group.append_pass(MEMCPYOPT_NAME);
12601261

12611262
// Run a DCE and simplify-cfg to clean up any obsolete instructions.

sway-ir/src/analysis.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,3 @@ pub mod dominator;
44
pub use dominator::*;
55
pub mod memory_utils;
66
pub use memory_utils::*;
7-
pub mod arg_mutability;
8-
pub use arg_mutability::*;

sway-ir/src/analysis/arg_mutability.rs

Lines changed: 0 additions & 62 deletions
This file was deleted.

sway-ir/src/analysis/memory_utils.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -391,13 +391,13 @@ impl AnalysisResultT for EscapedSymbols {}
391391

392392
pub fn compute_escaped_symbols_pass(
393393
context: &Context,
394-
_: &AnalysisResults,
394+
_analyses: &AnalysisResults,
395395
function: Function,
396396
) -> Result<AnalysisResult, IrError> {
397397
Ok(Box::new(compute_escaped_symbols(context, &function)))
398398
}
399399

400-
pub fn compute_escaped_symbols(context: &Context, function: &Function) -> EscapedSymbols {
400+
fn compute_escaped_symbols(context: &Context, function: &Function) -> EscapedSymbols {
401401
let add_from_val = |result: &mut FxHashSet<Symbol>, val: &Value, is_complete: &mut bool| {
402402
let (complete, syms) = get_referred_symbols(context, *val).consume();
403403

@@ -422,9 +422,14 @@ pub fn compute_escaped_symbols(context: &Context, function: &Function) -> Escape
422422
InstOp::BinaryOp { .. } => (),
423423
InstOp::BitCast(_, _) => (),
424424
InstOp::Branch(_) => (),
425-
InstOp::Call(_, args) => args
425+
InstOp::Call(callee, args) => args
426426
.iter()
427-
.for_each(|v| add_from_val(&mut result, v, &mut is_complete)),
427+
.enumerate()
428+
.filter(|(arg_idx, _arg)| {
429+
// Immutable arguments are not considered as escaping symbols.
430+
!callee.is_arg_immutable(context, *arg_idx)
431+
})
432+
.for_each(|(_, v)| add_from_val(&mut result, v, &mut is_complete)),
428433
InstOp::CastPtr(ptr, _) => add_from_val(&mut result, ptr, &mut is_complete),
429434
InstOp::Cmp(_, _, _) => (),
430435
InstOp::ConditionalBranch { .. } => (),

sway-ir/src/block.rs

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ pub struct BlockArgument {
5555
/// idx'th argument of the block.
5656
pub idx: usize,
5757
pub ty: Type,
58+
/// Is this known to be immutable?
59+
pub is_immutable: bool,
5860
}
5961

6062
impl BlockArgument {
@@ -144,6 +146,7 @@ impl Block {
144146
block: *self,
145147
idx,
146148
ty,
149+
is_immutable: false,
147150
},
148151
);
149152
context.blocks[self.0].args.push(arg_val);
@@ -152,9 +155,12 @@ impl Block {
152155

153156
pub fn set_arg(&self, context: &mut Context, arg: Value) {
154157
match context.values[arg.0].value {
155-
ValueDatum::Argument(BlockArgument { block, idx, ty: _ })
156-
if block == *self && idx < context.blocks[self.0].args.len() =>
157-
{
158+
ValueDatum::Argument(BlockArgument {
159+
block,
160+
idx,
161+
ty: _,
162+
is_immutable: _,
163+
}) if block == *self && idx < context.blocks[self.0].args.len() => {
158164
context.blocks[self.0].args[idx] = arg;
159165
}
160166
_ => panic!("Inconsistent block argument being set"),
@@ -164,9 +170,12 @@ impl Block {
164170
/// Add a block argument, asserts that `arg` is suitable here.
165171
pub fn add_arg(&self, context: &mut Context, arg: Value) {
166172
match context.values[arg.0].value {
167-
ValueDatum::Argument(BlockArgument { block, idx, ty: _ })
168-
if block == *self && idx == context.blocks[self.0].args.len() =>
169-
{
173+
ValueDatum::Argument(BlockArgument {
174+
block,
175+
idx,
176+
ty: _,
177+
is_immutable: _,
178+
}) if block == *self && idx == context.blocks[self.0].args.len() => {
170179
context.blocks[self.0].args.push(arg);
171180
}
172181
_ => panic!("Inconsistent block argument being added"),
@@ -518,6 +527,7 @@ impl Block {
518527
block,
519528
idx: _,
520529
ty: _,
530+
is_immutable: _,
521531
}) => {
522532
// We modify the Value in place to be a BlockArgument for the new block.
523533
*block = new_block;

sway-ir/src/function.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ impl Function {
114114
block: entry_block,
115115
idx,
116116
ty,
117+
is_immutable: false,
117118
},
118119
)
119120
.add_metadatum(context, arg_metadata),
@@ -385,6 +386,16 @@ impl Function {
385386
context.functions[self.0].arguments.iter()
386387
}
387388

389+
/// Is argument `i` marked immutable?
390+
pub fn is_arg_immutable(&self, context: &Context, i: usize) -> bool {
391+
if let Some((_, val)) = context.functions[self.0].arguments.get(i) {
392+
if let ValueDatum::Argument(arg) = &context.values[val.0].value {
393+
return arg.is_immutable;
394+
}
395+
}
396+
false
397+
}
398+
388399
/// Get a pointer to a local value by name, if found.
389400
pub fn get_local_var(&self, context: &Context, name: &str) -> Option<LocalVar> {
390401
context.functions[self.0].local_storage.get(name).copied()

sway-ir/src/optimize.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
1616
pub mod arg_demotion;
1717
pub use arg_demotion::*;
18+
pub mod arg_mutability_tagger;
19+
pub use arg_mutability_tagger::*;
1820
pub mod const_demotion;
1921
pub use const_demotion::*;
2022
pub mod constants;

0 commit comments

Comments
 (0)