1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
//! Which `restrict` scope an access is in, and which pointer inside it the access went through.
//!
//! Design: `spec/optimizer/08-alias-analysis.md` section 8.2 layer 5, and
//! `spec/safe-memory/09-type-init-and-races.md` section 9.6.
//!
//! Two small numbers on every access, a clique and a base, which is the whole of the mechanism and
//! is what gcc calls `MR_DEPENDENCE_CLIQUE` and `MR_DEPENDENCE_BASE`. A clique is one scope that
//! declares `restrict` pointers and a base is one of the pointers it declares. Same clique and
//! different base means the two accesses cannot touch the same byte, because that is exactly what
//! `restrict` promises, and [`rucc_ir::Restrict::disjoint`] is that one line.
//!
//! Layer 5 of the alias analysis has been written and tested since the analysis went in and has
//! never had an access to answer about, because nothing worked out where a pointer came from.
//! This is where it comes from.
//!
//! # What a base is worked out from
//!
//! The names the access was written with, and not the value the pointer turns out to hold. The
//! walk over a place takes the members and the subscripts apart already, so what arrives here is
//! the pointer expression an access is about to be made through, and this follows it down through
//! the casts and the pointer arithmetic to the declaration at the bottom of it. A member of
//! something reached through a `restrict` pointer is reached through it too, which falls out of
//! the place walk rather than being said here. `p->next->value` stops at the inner dereference,
//! because that pointer was read out of memory and where it came from is not a question about
//! names.
//!
//! This is deliberately syntactic. The standard's definition of based on is about what happens to
//! an expression when `P` is changed to point at a copy of the array, which is not a question the
//! front end can answer, and the syntactic reading is what gcc and clang both implement. It is the
//! conservative direction too: an access nothing recognizes carries no clique, and a clique of
//! zero is no information rather than a claim.
//!
//! # Why the clique is numbered per module and not per function
//!
//! Because an inliner is a thing that merges two functions into one, and two functions that each
//! numbered their own parameters clique one would come out of it with four pointers in one clique
//! promising things about each other that nobody promised. gcc renumbers on inlining for exactly
//! this reason. There is no inliner here yet, and numbering from a counter that the whole module
//! shares means there is nothing to renumber when there is one. Merging two modules at link time
//! is the same hazard one level up and is tamnd/rucc#969.
//!
//! # What this does not work out yet
//!
//! A `restrict` pointer declared inside a block rather than as a parameter. The scope it makes is
//! the block, which the walk does not have in hand where the declarations of a function are
//! gathered, and the parameters are where `restrict` is nearly always written: `memcpy`, `strcpy`
//! and the numeric kernels all put it on parameters and all have two. tamnd/rucc#970.
use HashMap;
use ;
use Restrict;
use ;
use ;
/// The `restrict` pointers a function declares, and which scope and number each of them has.
pub
/// Whether a declaration's type is a pointer somebody wrote `restrict` on.
///
/// The adjusted type, which is what a parameter written `int a[restrict]` has by the time it is
/// here: the adjustment to a pointer carries the qualifiers from inside the brackets, which is
/// where C 6.7.6.3 puts them and is the only reason that spelling means anything.