Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backwards reaching definitions #726

Merged
merged 21 commits into from
Sep 21, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
6326445
Improved liveness detection for store exclusives (#722)
ThomasHaas Sep 3, 2024
5e10cda
Renamed Location to FinalMemoryValue. (#725)
ThomasHaas Sep 3, 2024
2d5695e
Add ReachingDefinitionsAnalysis
xeren Aug 11, 2024
27cee4f
Add BackwardsReachingDefinitionsAnalysis
xeren Sep 2, 2024
c12af07
Replace Dependency with BackwardsReachingDefinitionsAnalysis
xeren Sep 2, 2024
ae5c2bc
Replace UseDefAnalysis with BackwardsReachingDefinitionsAnalysis
xeren Sep 2, 2024
38bd709
Add AnalysisTest.reachingDefinitionSupportsLoops
xeren Sep 2, 2024
494ebb7
Suggested changes
xeren Sep 4, 2024
7887589
Add support to CAAT for SyncBar, SyncFence and Vloc relations (#724)
ThomasHaas Sep 5, 2024
1bd4bd0
Add unrolling bound to program spec encoding (#727)
natgavrilenko Sep 5, 2024
ecd5d7e
Merge branch 'development' into backwards-reaching-definitions
xeren Sep 5, 2024
3e6f247
Add option to dump encoding to smtlib2 file (#721)
hernanponcedeleon Sep 6, 2024
669e83a
Use correct smtlib2 syntax for push/pop (#728)
hernanponcedeleon Sep 6, 2024
28bbd11
Add options to access previous implementations.
xeren Sep 9, 2024
78c0f90
Merge remote-tracking branch 'refs/remotes/origin/development' into b…
xeren Sep 9, 2024
c0d8a38
Refactor
xeren Sep 10, 2024
bf0c691
Refactor
xeren Sep 10, 2024
fdcc9c2
Merge remote-tracking branch 'refs/remotes/origin/development' into b…
xeren Sep 20, 2024
0db0bb7
fixup! Merge remote-tracking branch 'refs/remotes/origin/development'…
xeren Sep 20, 2024
b8f136f
Remove option program.processing.loopBounds.useDefAnalysis
xeren Sep 20, 2024
e91f205
Small reformat
xeren Sep 20, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,19 @@
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
* Collects all direct usage relationships between {@link RegWriter} and {@link RegReader}.
* <p>
* In contrast to a usual Reaching-Definitions-Analysis,
* this implementation analyzes the program from back to front,
* assigning each program point the set of readers,
* who may still require a register initialization.
* In contrast to a usual Reaching-Definitions-Analysis, this implementation analyzes the program from back to front,
* assigning each program point the set of readers, who may still require a register initialization.
* This means that it does not collect definitions for unused registers.
* Especially, it does not collect last writers for all registers.
* <p>
* This analysis is control-flow-sensitive;
* that is, {@link Label} splits the information among the jumps to it
* and {@link CondJump} merges the information.
* that is, {@link Label} splits the information among the jumps to it and {@link CondJump} merges the information.
* <p>
* This analysis supports loops;
* that is, backward jumps cause re-evaluation of the loop body until convergence.
Expand All @@ -45,6 +43,8 @@ public class BackwardsReachingDefinitionsAnalysis implements ReachingDefinitions

private final Map<RegReader, ReaderInfo> readerMap = new HashMap<>();
private final Map<RegWriter, Readers> writerMap = new HashMap<>();
private final RegWriter INITIAL_WRITER = null;
private final RegReader FINAL_READER = null;

@Override
public Writers getWriters(RegReader reader) {
Expand All @@ -56,7 +56,7 @@ public Writers getWriters(RegReader reader) {

@Override
public Writers getFinalWriters() {
final ReaderInfo result = readerMap.get(null);
final ReaderInfo result = readerMap.get(FINAL_READER);
Preconditions.checkState(result != null, "final state has not been analyzed.");
return result;
}
Expand All @@ -77,7 +77,7 @@ public Readers getReaders(RegWriter writer) {
* Lists all potential users of uninitialized registers.
*/
public Readers getInitialReaders() {
final Readers result = writerMap.get(null);
final Readers result = writerMap.get(INITIAL_WRITER);
Preconditions.checkState(result != null, "initial state has not been analyzed.");
return result;
}
Expand All @@ -89,8 +89,10 @@ public Readers getInitialReaders() {
public static BackwardsReachingDefinitionsAnalysis forFunction(Function function) {
final var analysis = new BackwardsReachingDefinitionsAnalysis();
final Set<Register> finalRegisters = new HashSet<>();
analysis.initialize(function, finalRegisters);
analysis.run(function, finalRegisters);
final List<Event> events = function.getEvents();
analysis.initializeWriterMap(events);
analysis.initializeReaderMap(events, finalRegisters);
analysis.run(events, finalRegisters);
analysis.postProcess();
return analysis;
}
Expand All @@ -109,8 +111,10 @@ public static BackwardsReachingDefinitionsAnalysis fromConfig(Program program, C
final Set<Register> finalRegisters = finalRegisters(program);
for (Function function : program.isUnrolled() ? program.getThreads() :
Iterables.concat(program.getThreads(), program.getFunctions())) {
analysis.initialize(function, finalRegisters);
analysis.run(function, finalRegisters);
final List<Event> events = function.getEvents();
analysis.initializeWriterMap(events);
analysis.initializeReaderMap(events, finalRegisters);
analysis.run(events, finalRegisters);
}
analysis.postProcess();
if (exec != null && program.isUnrolled()) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can exec really be null?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The analysis can be run during processing where ExecutionAnalysis is not available, but it can also be run afterwards. In the former case it should subsume UseDefAnalysis and in the latter case Dependency.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Btw. do we get no must information at all without the ExecutionAnalysis?
Would a dominator tree analysis suffice to generate must information?

Expand Down Expand Up @@ -209,14 +213,17 @@ public boolean mayBeFinal() {

private BackwardsReachingDefinitionsAnalysis() {}

private void initialize(Function function, Set<Register> finalRegisters) {
for (Event event : function.getEvents()) {
private void initializeWriterMap(Collection<Event> events) {
for (Event event : events) {
if (event instanceof RegWriter writer) {
writerMap.put(writer, new Readers());
}
}
writerMap.put(null, new Readers());
for (Event event : function.getEvents()) {
writerMap.put(INITIAL_WRITER, new Readers());
}
ThomasHaas marked this conversation as resolved.
Show resolved Hide resolved

private void initializeReaderMap(Collection<Event> events, Set<Register> finalRegisters) {
for (Event event : events) {
if (event instanceof RegReader reader) {
final Set<Register> usedRegisters = new HashSet<>();
for (Register.Read read : reader.getRegisterReads()) {
Expand All @@ -225,20 +232,19 @@ private void initialize(Function function, Set<Register> finalRegisters) {
readerMap.put(reader, new ReaderInfo(usedRegisters));
}
}
readerMap.put(null, new ReaderInfo(finalRegisters));
readerMap.put(FINAL_READER, new ReaderInfo(finalRegisters));
}

private void run(Function function, Set<Register> finalRegisters) {
private void run(List<Event> events, Set<Register> finalRegisters) {
//For each register used after this state, all future users.
final State currentState = new State();
for (Register finalRegister : finalRegisters) {
final var info = new StateInfo();
info.mayReaders.add(null);
info.mayReaders.add(FINAL_READER);
currentState.put(finalRegister, info);
}
final Map<CondJump, State> trueStates = new HashMap<>();
final Map<CondJump, State> falseStates = new HashMap<>();
final List<Event> events = function.getEvents();
for (int i = events.size() - 1; i >= 0; i--) {
final CondJump loop = runLocal(events.get(i), currentState, trueStates, falseStates);
if (loop != null) {
Expand All @@ -248,7 +254,7 @@ private void run(Function function, Set<Register> finalRegisters) {
}
}
// set the uninitialized flags
final Readers uninitialized = writerMap.get(null);
final Readers uninitialized = writerMap.get(INITIAL_WRITER);
for (Map.Entry<Register, StateInfo> entry : currentState.entrySet()) {
uninitialized.readers.addAll(entry.getValue().mayReaders);
for (RegReader reader : entry.getValue().mayReaders) {
Expand All @@ -260,7 +266,7 @@ private void run(Function function, Set<Register> finalRegisters) {
private void postProcess() {
// build the reverse association
for (Map.Entry<RegWriter, Readers> entry : writerMap.entrySet()) {
if (entry.getKey() == null) {
if (Objects.equals(entry.getKey(), INITIAL_WRITER)) {
continue;
}
for (RegReader reader : entry.getValue().readers) {
Expand All @@ -275,7 +281,7 @@ private void postProcess() {
}
// set the final flag
for (Readers writer : writerMap.values()) {
writer.mayBeFinal = writer.readers.remove(null);
writer.mayBeFinal = writer.readers.remove(FINAL_READER);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ interface Writers {
}

/**
* Instances of this class are associated with a {@link Register} and either a {@link RegReader} or the final state of the program or function.
* Instances of this class are associated with a {@link Register}
* and either a {@link RegReader} or the final state of the program or function.
*/
interface RegisterWriters {

Expand All @@ -63,19 +64,22 @@ interface RegisterWriters {
boolean mustBeInitialized();

/**
* Lists writers s.t. there may be executions, where some instance of the associated reader directly uses the result of an instance of that writer.
* Lists writers s.t. there may be executions, where some instance of the associated reader directly uses the
* result of an instance of that writer.
* @return Writers in program order.
*/
List<RegWriter> getMayWriters();

/**
* Lists writers s.t. all event instances of the associated reader in any execution read from all instances of that writer in that execution.
* Lists writers s.t. all event instances of the associated reader in any execution read from all instances of
* that writer in that execution.
* @return Writers in program order.
*/
List<RegWriter> getMustWriters();
}

static ReachingDefinitionsAnalysis fromConfig(Program program, Context analysisContext, Configuration config) throws InvalidConfigurationException {
static ReachingDefinitionsAnalysis fromConfig(Program program, Context analysisContext, Configuration config)
throws InvalidConfigurationException {
var c = new Config();
config.inject(c);
ReachingDefinitionsAnalysis analysis = switch (c.method) {
Expand Down
Loading