Fil-C on Nix

Filnix wiki

mbrock/filnix/nanofil

alias.pl

Address expressions for milestone 5: alias_facts/2 writes each address of a strict SSA function as a base plus a constant offset. The facts are not a no-alias or bounds proof.

Address facts

A fact addrClass, Base, Offset says the address is Base + Offset modulo 2^64, with Offset the signed 64-bit representative. In class p the capability is also the base's.

BaseNames
allocTempthe current execution of that alloc's SSA definition, not all its loop iterations
paramTempa parameter
symbolNamea symbol
valueTempan opaque SSA value: a load, call, cast, phi, or any other computed value

Only same-class copies and additions and subtractions of a constant are followed. A w copy is not an address alias, even when its operand was an l.

What the facts do not say

Different bases may alias: parameters, symbols and opaque values need not name different objects. These facts alone justify neither removing a bounds check nor moving an access or allocation across control flow.

modulealias
useslists
usesassoc
usespairs
usescfg
usespromotestrict_ssa/3
usesirop_kind/2
alias_facts+Func, -Factsdet

Facts is the assoc Temp -> addr(Class, Base, Offset), for the l/p values of Func if it is in strict SSA form, and otherwise empty. Base is alloc(Temp), param(Temp), symbol(Name), or value(Temp) for an opaque SSA value (including loads, calls, casts and phis). A missing fact means unknown, e.g. a cycle in unreachable code with no base to start from.

47alias_factsF, Facts ←
F = func_, _, _, _, Blocks
func_cfgBlocks, Cfg
cfg_idomsCfg, Idom
strict_ssaF, Cfg, Idom
→
findallD−defK, Source, address_defF, D, K, Source, Defs
list_to_assocDefs, ByTemp
findallD−addrK, Base, 0,
memberD−defK, Source, Defs
address_baseSource, D, K, ByTemp, Base
,
Seeds
list_to_assocSeeds, Initial
findallS−edgeD, Delta,
memberD−defK, Source, Defs
address_offsetSource, K, ByTemp, S, Delta
,
Edges0
keysortEdges0, Edges1
group_pairs_by_keyEdges1, Edges
list_to_assocEdges, Users
pending_factsSeeds, Users, Initial, Facts
else
empty_assocFacts
address_def+F, -D, -K, -Source

temp D of address class K is a parameter (param), an instruction (let(Op, Args)) or opaque.

72address_deffunc_, _, _, Params, _, D, K, param ←
memberparamK, tmpD, Params
75address_deffunc_, _, _, _, Blocks, D, K, Source ←
memberblock_, Phis, Insts, _, Blocks
memberphitmpD, K, _, Phis
Source = opaque
or
memberlettmpD, K, Op, Args, Insts
Source = letOp, Args
or
membercallresulttmpD, K, _, _, Insts
Source = opaque
or
membercalltupleTos, _, _, Insts
memberresulttmpD, K, Tos
Source = opaque
86address_classl
87address_classp
address_base+Source, +D, +K, +Defs, -Base

D starts a base of its own; it fails for a definition that offsets another address.

91address_baseparam, D, _, _, paramD
92address_baseopaque, D, _, _, valueD
93address_baseletOp, Args, D, K, Defs, Base ←
ins_baseOp, Args, D, K, Defs, Base
ins_base+Op, +Args, +D, +K, +Defs, -Base

as address_base/5, for an instruction.

98ins_baseOp, Args, D, K, Defs, Base ←
op_kindOp, Kind
kind_baseKind, Op, Args, D, K, Defs, Base
kind_base+Kind, +Op, +Args, +D, +K, +Defs, -Base

as ins_base/6, for Op of Kind. An alloc and the copy of a symbol start their own bases, an add, sub or copy that offsets an address (address_offset/5) starts none, and every other instruction starts a value base.

106kind_baseadditive, Op, Args, D, K, Defs, valueD ←
¬address_offsetletOp, Args, K, Defs, _, _
108kind_basealu, _, _, D, _, _, valueD
109kind_baseshift, _, _, D, _, _, valueD
110kind_baseneg, _, _, D, _, _, valueD
111kind_basecopy, _, V, D, K, Defs, Base ←
copy_baseV, D, K, Defs, Base
112kind_baseptoi, _, _, D, _, _, valueD
113kind_baseitop, _, _, D, _, _, valueD
114kind_baseva_args, _, _, D, _, _, valueD
115kind_baseva_arg, _, _, D, _, _, valueD
116kind_basecmp, _, _, D, _, _, valueD
117kind_baseext, _, _, D, _, _, valueD
118kind_baseload, _, _, D, _, _, valueD
119kind_basealloc, _, _, D, _, _, allocD
copy_base+V, +D, +K, +Defs, -Base

as kind_base/7, for D a copy of V.

122copy_baseglobalS, _, _, _, symbolS
123copy_basetmpS, D, K, Defs, valueD ←
¬address_offsetletcopy, tmpS, K, Defs, _, _
125copy_baseconst_, D, _, _, valueD
address_offset+Source, +K, +Defs, -S, -Delta

Source computes the same-class temp S plus Delta.

129address_offsetletcopy, tmpS, K, Defs, S, 0 ←
get_assocS, Defs, defK, _
131address_offsetletadd, tmpS, constN, K, Defs, S, N ←
get_assocS, Defs, defK, _
133address_offsetletadd, constN, tmpS, l, Defs, S, N ←
get_assocS, Defs, defl, _
135address_offsetletsub, tmpS, constN, K, Defs, S, Delta ←
get_assocS, Defs, defK, _
Delta is −N
pending_facts+Pending, +Users, +Facts0, -Facts

Facts is Facts0 with the addresses derived, directly or not, from Pending, the list of S-Addr whose users are still to be derived. Every derived definition has one source, so a definition is reached only once its source is known, regardless of layout. Phis are roots rather than followed around their cycles: they select a value from an earlier dynamic execution.

146pending_facts[], _, Facts, Facts
147pending_factsS−Addr|Pending0, Users, Facts0, Facts ←
get_assocS, Users, Edges
→
true
else
Edges = []
foldladdr_edge_stateAddr, Edges, Facts0−Pending0, Facts1−Pending
pending_factsPending, Users, Facts1, Facts
addr_edge_state+Addr, +Edge, +Facts0−Pending0, −Facts−Pending

the user D of Edge has the address Addr plus Delta, in Facts and in front of Pending0. The offset wraps modulo 2^64 to its signed 64-bit representative.

157addr_edge_stateaddrK, Base, Off, edgeD, Delta, Facts0−Pending, Facts−D−Addr|Pending ←
U is Off + Delta mod 18446744073709551616
U ≥ 9223372036854775808
→
O is U−18446744073709551616
else
O = U
Addr = addrK, Base, O
put_assocD, Facts0, Addr, Facts