Skip to content

Theory test — Chapter 19

59 questions; you pass at 80 %. This page shows the questions only: take the test in the terminal, where every answer is graded and explained.

./course quiz 19                                   # interactive
./course quiz template 19 -o answers/ch19.yaml  # or fill in a file ...
./course quiz grade 19                             # ... and grade it
Question 1 alias-answers-table · mapping · 1 pt · 01-memory-and-alias-queries

In one function, %p4 = getelementptr i8, ptr %p, i64 4, %p0 = getelementptr i8, ptr %p, i64 0,
%buf = alloca [16 x i8], %b8 = getelementptr i8, ptr %buf, i64 8; %p, %q are ordinary
pointer arguments. Accesses: store i64 to %p (8 bytes), store i32 to %p0, store i32 to %p4,
store i32 to %q, store i64 to %b8. Give the alias answer (no, may, partial or must) for each pair.

Keys: p-p0, p-p4, p0-p4, p-q, b8-q
Answer format: pair: no/may/partial/must
Question 2 alias-partial-offset · number · 1 pt · 01-memory-and-alias-queries

aa-eval prints PartialAlias (off N): i64* %p, i32* %p4 for %p4 = getelementptr i8, ptr %p, i64 4.
What is N?

Answer format: a number
Question 3 modref-calls · mapping · 1 pt · 01-memory-and-alias-queries

%q is a pointer argument that has already been passed to earlier calls. Give the mod/ref answer
(nomodref, ref, mod or modref) of each call for the location %q:
@pure(i32) declared memory(none); @reader(ptr %q) declared memory(read);
@argwriter(ptr %q) declared memory(argmem: write); @unknown() with no attributes.

Keys: pure, reader, argwriter, unknown
Answer format: call: nomodref/ref/mod/modref
Question 4 modref-lattice-meet · single · 1 pt · 01-memory-and-alias-queries

Two alias analyses answer Ref and Mod for the same call and location. What does LLVM's AAResults return?

  1. ModRef, the join of the two answers
  2. NoModRef, the intersection of the two answers
  3. Ref, the first member's answer
  4. Mod, because writes are more important than reads
Answer format: one letter
Question 5 aa-chain-answers · mapping · 1 pt · 01-memory-and-alias-queries

int f(int *restrict a, float *b, int *c) { *a = 1; *b = 2.0f; *c = 3; return *a; } compiled by clang
with TBAA. With -aa-pipeline=basic-aa,tbaa, which member gives the (NoAlias) answer for each pair of stores?
Write basicaa or tbaa.

Keys: a-b, a-c, b-c
Answer format: one value per key
Question 6 llvm-where-aa-chain · single · 1 pt · 01-memory-and-alias-queries

In llvm/lib/Analysis/AliasAnalysis.cpp (LLVM 23.1.2), when does the loop over AAs in AAResults::alias stop early?

  1. When a member returns NoAlias
  2. When a member returns anything other than MayAlias
  3. When a member returns MustAlias
  4. Never; it intersects all answers
Answer format: one letter
Question 7 basicaa-kernel-answers · mapping · 1 pt · 02-local-alias-rules

void kern(int *a, struct pt *s, int i) { int local[4]; a[i] = 1; a[i + 1] = 2; s->x = 3; s->y = 4; local[i] = 5; g = …; }
with struct pt { int x, y; }, a global int g, and 4-byte accesses. Give BasicAA's answer (no or may) for:
a[i] vs a[i+1] (key ai-ai1), local[i] vs local[0] (li-l0), s->y vs g (sy-g), s->x vs g (sx-g),
a[i] vs s->x (ai-sx).

Keys: ai-ai1, li-l0, sy-g, sx-g, ai-sx
Answer format: one value per key
Question 8 llvm-where-object-size · text · 1 pt · 02-local-alias-rules

In BasicAliasAnalysis.cpp (LLVM 23.1.2), which static helper does aliasCheck call to return NoAlias when an access is larger than the entire object on the other side?

Answer format: a short answer
Question 9 capture-uses · set · 1 pt · 02-local-alias-rules

Which of these uses capture the pointer %x (Definition 19.2.6, with returns counted as captures)?
a) store ptr %x, ptr %p b) store i32 0, ptr %x c) call void @f(ptr captures(none) %x)
d) %i = ptrtoint ptr %x to i64 e) ret ptr %x f) %c = icmp eq ptr %x, null

Answer format: letters, e.g. {a, b}
Question 10 capture-private-load · single · 1 pt · 02-local-alias-rules

In int f(void) { int p = 1, l = 2; keep(&l); opaque(); return p + l; }, after clang -O1 which loads remain after the call to opaque()?

  1. Both p and l are reloaded
  2. Only l is reloaded; p's value 1 is folded
  3. Only p is reloaded
  4. Neither: both values are folded
Answer format: one letter
Question 11 globalsaa-summary · mapping · 1 pt · 02-local-alias-rules

static int counter; int shared; — set_shared(x) writes only shared; bump() does counter++;
log_it(int) is an external function with no attributes. f calls all three. With
-aa-pipeline=globals-aa,basic-aa, give the mod/ref answer (nomodref or modref) for @counter at each call.

Keys: set_shared, bump, log_it
Answer format: one value per key
Question 12 globalsaa-callback · single · 1 pt · 02-local-alias-rules

For an external declaration, which attributes let GlobalsAA assume it cannot access the module's non-address-taken internal globals?

  1. readonly alone
  2. nocallback and nosync
  3. nounwind and willreturn
  4. noinline
Answer format: one letter
Question 13 tbaa-pairs · mapping · 1 pt · 03-type-and-scope-rules

struct A { short s; int i; }; struct B { int k; struct A a; }; (offsets B.k 0, B.a 4, A.s 0, A.i 4), clang TBAA.
Tags: b->a.i = (B, int, 8), b->a.s = (B, short, 4), b->k = (B, int, 0), *p = (int, int, 0) for int *p,
*q = (short, short, 0), a->i = (A, int, 4). Give TBAA's answer (no or may) for the pairs
bai-bk, bai-bas, bai-p, bai-ai, bai-q, bk-ai.

Keys: bai-bk, bai-bas, bai-p, bai-ai, bai-q, bk-ai
Answer format: one value per key
Question 14 tbaa-char-exemption · single · 1 pt · 03-type-and-scope-rules

Why does TBAA never answer NoAlias for a char access against anything in clang's type tree?

  1. Because char accesses are always 1 byte
  2. Because omnipotent char is an ancestor of every scalar type, so a char tag accesses the whole common type
  3. Because clang does not attach TBAA tags to char accesses
  4. Because char is in a different type tree
Answer format: one letter
Question 15 llvm-where-tbaa-lca · text · 1 pt · 03-type-and-scope-rules

In TypeBasedAliasAnalysis.cpp (LLVM 23.1.2), which function computes the least common ancestor of two access types (and makes matchAccessTags answer MayAlias when it returns null)?

Answer format: a short answer
Question 16 scoped-noalias-query · mapping · 1 pt · 03-type-and-scope-rules

Scopes s1, s2 in one domain. Access I: alias.scope {s1}, noalias {s2}. Access J: alias.scope {s2}, no noalias list.
Access K: no alias.scope list, noalias {s1}. Give ScopedNoAliasAA's answer (no or may) for I-J, I-K, J-K.

Keys: i-j, i-k, j-k
Answer format: one value per key
Question 17 restrict-semantics · single · 1 pt · 03-type-and-scope-rules

What does restrict on a parameter int *restrict p promise in C11?

  1. p is never null
  2. p points to a fresh heap object
  3. During the function, an object accessed through p and modified is accessed only through pointers based on p
  4. No other pointer of the same type exists anywhere in the program
Answer format: one letter
Question 18 andersen-running-pts · mapping · 1 pt · 04-andersen

Andersen's analysis on: p = &a; q = &b; r = &p; s = q; *r = s; t = *r; u = &c; q = u; b = t; q = b.
Give pts(q), pts(u), pts(a), pts(r) (write {} for empty).

Keys: q, u, a, r
Answer format: one value per key (a set: {x, y})
Question 19 andersen-edges-step3 · set · 1 pt · 04-andersen

Same program, worklist started with p, q, r, u in that order (FIFO). Which new constraint-graph edges are
added when r is popped (step 3)? Write edges as x->y.

Answer format: edges as x->y, e.g. {a->b, c->d}
Question 20 cycle-collapse-online · set · 1 pt · 04-andersen

Same program with online cycle detection. Which nodes are collapsed into one when the edge s → p is added?

Answer format: items separated by commas or spaces, e.g. {a, b}
Question 21 cycle-lazy-trigger · number · 1 pt · 04-andersen

With lazy cycle detection (and the same FIFO order), at which worklist step is the cycle collapsed — the first step whose propagation along an edge finds two equal non-empty sets?

Answer format: a number
Question 22 gcc-where-hcd · text · 1 pt · 04-andersen

In GCC 14's tree-ssa-structalias.cc, which function implements the phase printed as "Finding indirect cycles" (hybrid cycle detection)?

Answer format: a short answer
Question 23 wave-rounds · number · 1 pt · 04-andersen

How many rounds does wave propagation (Algorithm 19.4.9) need on the running example, counting the final round that adds no edge?

Answer format: a number
Question 24 wave-topo · single · 1 pt · 04-andersen

Why does one wave in topological order satisfy every edge present at the start of the round?

  1. Because points-to sets never exceed the number of objects
  2. Because after collapsing cycles the graph is acyclic, so every node's predecessors are final before it propagates
  3. Because loads and stores are handled before copies
  4. Because the worklist is FIFO
Answer format: one letter
Question 25 steens-running-pts · mapping · 1 pt · 05-unification

Steensgaard's analysis on the same running example. Give pts(u), pts(a), pts(r).

Keys: u, a, r
Answer format: one value per key (a set: {x, y})
Question 26 steens-join-step5 · set · 1 pt · 05-unification

Which program variables are in the class unified at step 5 (*r = s) of Steensgaard's trace (ignore fresh τ cells)?

Answer format: items separated by commas or spaces, e.g. {a, b}
Question 27 llvm-where-cfl-steens · single · 1 pt · 05-unification

What does the header comment of llvm/lib/Analysis/CFLSteensAliasAnalysis.cpp at llvmorg-15.0.0 compare its precision to?

  1. Andersen's analysis
  2. Roughly a one-level context-sensitive Steensgaard's algorithm
  3. Type-based alias analysis
  4. Flow-sensitive points-to analysis
Answer format: one letter
Question 28 das-u · set · 1 pt · 05-unification

Das's one-level flow on the running example. What is pts(u)?

Answer format: items separated by commas or spaces, e.g. {a, b}
Question 29 das-between · multi · 1 pt · 05-unification

Which statements about Das's one-level flow are true?

  1. Its sets contain Andersen's sets
  2. Its sets are contained in Steensgaard's sets
  3. It uses inclusion at every level of indirection
  4. Every flow edge a → b keeps D(a) = D(b)
Answer format: letters, e.g. a, c
Question 30 fs-strong-update · mapping · 1 pt · 06-flow-and-field-sensitivity

s = &o; *s = &a; x = *s; *s = &b; y = *s (o a singleton global). Give pts(x) and pts(y) flow-sensitively
(keys x, y) and flow-insensitively (keys x-fi, y-fi).

Keys: x, y, x-fi, y-fi
Answer format: one value per key (a set: {x, y})
Question 31 sfs-stages · sequence · 1 pt · 06-flow-and-field-sensitivity

Put the steps of staged sparse flow-sensitive analysis (SFS) in order:
a) sparse flow-sensitive propagation along def-use edges; b) an auxiliary flow-insensitive analysis;
c) memory SSA (def-use chains) per object from the auxiliary sets.

Answer format: items in order, e.g. A B C
Question 32 field-models-table · mapping · 1 pt · 06-flow-and-field-sensitivity

struct pair { int *first; int *second; } s; s.first = &x; s.second = &y; ps = &s; if (k) ps->first = ps->second;
What may the second field (s.second) point to under the field-insensitive (insensitive), field-based (based)
and field-sensitive (sensitive) models?

Keys: insensitive, based, sensitive
Answer format: one value per key (a set: {x, y})
Question 33 field-based-unsound · single · 1 pt · 06-flow-and-field-sensitivity

Why can a field-based analysis be unsound for C?

  1. Because it has too many locations
  2. Because a pointer to one field can be produced by arithmetic or casts from a pointer to another field, so the accessed field is not always the named one
  3. Because it ignores allocation sites
  4. Because it cannot handle recursion
Answer format: one letter
Question 34 kcfa-wrapper · mapping · 1 pt · 07-context-sensitivity

int *id(int *v) { return v; } int *w(int *v) { return id(v); /* site d */ } and in main
x = w(&a); /* c1 */ y = w(&b); /* c2 */. Give pts(x) and pts(y) under 1-CFA (keys x1, y1) and 2-CFA (x2, y2).

Keys: x1, y1, x2, y2
Answer format: one value per key (a set: {x, y})
Question 35 kcfa-contexts-count · number · 1 pt · 07-context-sensitivity

A function h is called only from w (one call site d); w is called from three call sites c1, c2, c3 in main. How many contexts does 2-CFA create for h?

Answer format: a number
Question 36 summary-id · set · 1 pt · 07-context-sensitivity

With the summary Summary(id) = {ret ↦ P1} instantiated at y = id(&b), what does y point to?

Answer format: items separated by commas or spaces, e.g. {a, b}
Question 37 llvm-where-function-attrs · single · 1 pt · 07-context-sensitivity

In llvm/lib/Transforms/IPO/FunctionAttrs.cpp, over what unit does the pass that adds memory(...) (addMemoryAttrs) work, so that callee summaries are available?

  1. One basic block at a time
  2. Strongly connected components of the call graph, bottom-up
  3. The whole module in one pass, top-down
  4. Loops of each function
Answer format: one letter
Question 38 objsens-box · mapping · 1 pt · 07-context-sensitivity

b1 = new Box /*h1*/; b1.set(new A /*hA*/); x = b1.get(); b2 = new Box /*h2*/; b2.set(new B /*hB*/); y = b2.get();
with set(v) { this.f = v; }, get() { return this.f; }. Give pts(x), pts(y) under 1-object sensitivity
(keys x, y) and context-insensitively (x-ci, y-ci).

Keys: x, y, x-ci, y-ci
Answer format: one value per key (a set: {x, y})
Question 39 typesens-merge · single · 1 pt · 07-context-sensitivity

In the Box program both Box objects are allocated in class Main. What does 1-type sensitivity give for x?

  1. {hA}
  2. {hA, hB}
  3. {}
  4. {hB}
Answer format: one letter
Question 40 datalog-rounds · number · 1 pt · 08-declarative-and-demand-driven

Semi-naive evaluation of the four points-to rules on the running example. After round 0 (the addr facts), how many rounds derive at least one new fact?

Answer format: a number
Question 41 datalog-rule-store · single · 1 pt · 08-declarative-and-demand-driven

Which Datalog rule encodes the store *p = q?

  1. pts(p, o) :- store(p, q), pts(q, o).
  2. pts(r, o) :- store(p, q), pts(p, r), pts(q, o).
  3. pts(q, o) :- store(p, q), pts(p, o).
  4. pts(p, o) :- store(p, q), pts(q, r), pts(r, o).
Answer format: one letter
Question 42 demand-relevant-set · set · 1 pt · 08-declarative-and-demand-driven

The demand-driven query pts(t) on the running example. Which variables end in the relevant set R?

Answer format: items separated by commas or spaces, e.g. {a, b}
Question 43 demand-budget · single · 1 pt · 08-declarative-and-demand-driven

What does SVF's ContextDDA do when a context-sensitive query exceeds its budget?

  1. It returns an empty set
  2. It aborts the analysis
  3. It downgrades the query to the flow-sensitive answer
  4. It increases the budget until the query finishes
Answer format: one letter
Question 44 escape-go-decisions · mapping · 1 pt · 09-escape-and-shape

Go 1.24: sum uses p := &point{1, 2} only locally; leak returns &q for a local q; store assigns
&point{n, n} to a global; slice uses make([]int, 8) only locally. Stack or heap for each allocation?

Keys: sum, leak, store, slice
Answer format: one value per key
Question 45 escape-lattice · single · 1 pt · 09-escape-and-shape

An object allocated in method m is reachable from m's return value but from no global or other thread. Its escape state?

  1. NoEscape
  2. ArgEscape
  3. GlobalEscape
  4. ThreadEscape
Answer format: one letter
Question 46 shape-lseg-fixpoint · number · 1 pt · 09-escape-and-shape

Separation-logic shape analysis of x = null; while (c) { t = malloc(); t->next = x; x = t; } (Lesson 19.9 §3): how many symbolic heaps are in the loop head's set at the fixed point?

Answer format: a number
Question 47 shape-vs-pointsto · single · 1 pt · 09-escape-and-shape

Why can Andersen's analysis not prove that the list built by that loop is acyclic?

  1. Because it is flow-insensitive only
  2. Because all nodes come from one allocation site, a single abstract object that points to itself
  3. Because it does not handle malloc
  4. Because it is context-insensitive
Answer format: one letter
Question 48 memssa-phis · set · 1 pt · 10-memory-ssa

Blocks (memory ops → successors): A: store a → B; B: none → C, F; C: store b; load a → D, E; D: call → E;
E: load b → B; F: load a; load b → exit. Which blocks get a MemoryPhi?

Answer format: items separated by commas or spaces, e.g. {a, b}
Question 49 memssa-clobber-trace · mapping · 1 pt · 10-memory-ssa

Same function; a and b never alias; the call may write both. Give the clobbering access of each load
(0 for liveOnEntry, a def number with defs 1 = A.1, 2 = C.1, 3 = D.1, or phi@B / phi@E): C.2, E.1, F.1, F.2.

Keys: C.2, E.1, F.1, F.2
Answer format: access: 0, 1, 2, 3, phi@B or phi@E
Question 50 sroa-partitions · number · 1 pt · 11-memory-optimizations

SROA on struct pair q (8 bytes) with uses memcpy(q, p, 8), load i32 q.hi (bytes 4–7) and load i32 q.lo (bytes 0–3). How many partitions (new allocas) does q become?

Answer format: a number
Question 51 sroa-escape · single · 1 pt · 11-memory-optimizations

Which use prevents SROA from splitting an alloca?

  1. A memcpy of the whole alloca into another alloca
  2. A load of an i32 at a constant offset
  3. Passing the alloca's address to an opaque function
  4. A lifetime.start marker
Answer format: one letter
Question 52 dse-table · mapping · 1 pt · 11-memory-optimizations

*p = 1; *p = 2; char buf[64]; memset(buf, 0, 64); memcpy(buf, src, 16); *q = 3; consume(buf); *q = 4; buf[0] = 1;
(p, q arguments). What does LLVM 23's dse do to each: store1 (*p = 1), memset, store3 (*q = 3), storebuf (buf[0] = 1)?
Write deleted, shortened or kept.

Keys: store1, memset, store3, storebuf
Answer format: one value per key
Question 53 llvm-where-dse-shorten · text · 1 pt · 11-memory-optimizations

In DeadStoreElimination.cpp (LLVM 23.1.2), which function shortens a partially overwritten memset or memcpy?

Answer format: a short answer
Question 54 loadpre-insert · number · 1 pt · 11-memory-optimizations

if (c) r = *p + v; else r = v; return r + *p; After GVN's load PRE, how many loads of *p execute on the path
through the then-branch?

Answer format: a number
Question 55 forwarding-conditions · multi · 1 pt · 11-memory-optimizations

pebble-loadfwd (E2) replaces a load L by the value of a store S when…

  1. S is L's clobbering access according to the MemorySSA walker
  2. S dominates L
  3. S MustAliases L and stores a value of L's type
  4. S is in the same basic block as L
  5. S is volatile
Answer format: letters, e.g. a, c
Question 56 memcpyopt-forward · single · 1 pt · 11-memory-optimizations

memcpy(b, a, 16); memcpy(c, b, 16); with nothing in between. What can MemCpyOpt do?

  1. Replace the second copy by memcpy(c, a, 16)
  2. Delete both copies
  3. Replace both by memmove(c, a, 32)
  4. Nothing: memcpy is opaque
Answer format: one letter
Question 57 memcpyopt-memset · number · 1 pt · 11-memory-optimizations

p[0] = 0; p[1] = 0; p[2] = 0; p[3] = 0; with long *p (8-byte longs). MemCpyOpt merges the stores into one memset of how many bytes?

Answer format: a number
Question 58 licm-promotion-kind · mapping · 1 pt · 11-memory-optimizations

int total; void acc(const float *a, int n) { for (i) total += (int)a[i]; }. What kind of promotion does
loop-mssa(licm) perform with -aa-pipeline=basic-aa (key basicaa) and basic-aa,tbaa (key basicaa-tbaa)?
Write load-only or full.

Keys: basicaa, basicaa-tbaa
Answer format: one value per key
Question 59 licm-promotion-safety · multi · 1 pt · 11-memory-optimizations

Which conditions allow LICM to sink the promoted store to the loop exits?

  1. A store to the location is guaranteed to execute on every iteration
  2. The location is a local that is not captured
  3. The loop contains a call
  4. No other access in the loop may read or write the location
Answer format: letters, e.g. a, c