-
Notifications
You must be signed in to change notification settings - Fork 274
CONTRACTS: represent loop nesting structure as a graph #7631
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
Merged
remi-delmas-3000
merged 1 commit into
diffblue:develop
from
remi-delmas-3000:contracts-loop-nesting-graph
Apr 1, 2023
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
86 changes: 86 additions & 0 deletions
86
src/goto-instrument/contracts/dynamic-frames/dfcc_loop_nesting_graph.cpp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
/*******************************************************************\ | ||
|
||
Module: Dynamic frame condition checking | ||
|
||
Author: Qinheping Hu, [email protected] | ||
|
||
Author: Remi Delmas, [email protected] | ||
|
||
Date: March 2023 | ||
|
||
\*******************************************************************/ | ||
|
||
#include "dfcc_loop_nesting_graph.h" | ||
|
||
#include <util/invariant.h> | ||
#include <util/message.h> | ||
|
||
dfcc_loop_nesting_graph_nodet::dfcc_loop_nesting_graph_nodet( | ||
const goto_programt::targett &head, | ||
const goto_programt::targett &latch, | ||
const loopt &instructions) | ||
: head(head), latch(latch), instructions(instructions) | ||
{ | ||
} | ||
|
||
/// \pre Loop normal form properties must hold. | ||
dfcc_loop_nesting_grapht | ||
build_loop_nesting_graph(goto_programt &goto_program, messaget &log) | ||
{ | ||
natural_loops_mutablet natural_loops(goto_program); | ||
dfcc_loop_nesting_grapht loop_nesting_graph; | ||
// Add a node per natural loop | ||
for(auto &loop : natural_loops.loop_map) | ||
{ | ||
auto loop_head = loop.first; | ||
auto &loop_instructions = loop.second; | ||
|
||
if(loop_instructions.size() <= 1) | ||
{ | ||
// ignore single instruction loops of the form | ||
// LOOP: goto LOOP; | ||
continue; | ||
} | ||
|
||
// Find the instruction that jumps back to `loop_head` and has the | ||
// highest GOTO location number, define it as the latch. | ||
auto loop_latch = loop_head; | ||
for(const auto &t : loop_instructions) | ||
{ | ||
if( | ||
t->is_goto() && t->get_target() == loop_head && | ||
t->location_number > loop_latch->location_number) | ||
loop_latch = t; | ||
} | ||
|
||
DATA_INVARIANT(loop_latch != loop_head, "Natural loop latch is found"); | ||
|
||
loop_nesting_graph.add_node(loop_head, loop_latch, loop_instructions); | ||
} | ||
|
||
// Add edges to the graph, pointing from inner loop to outer loops. | ||
// An `inner` will be considered nested in `outer` iff both its head | ||
// and latch instructions are instructions of `outer`. | ||
for(size_t outer = 0; outer < loop_nesting_graph.size(); ++outer) | ||
{ | ||
const auto &outer_instructions = loop_nesting_graph[outer].instructions; | ||
|
||
for(size_t inner = 0; inner < loop_nesting_graph.size(); ++inner) | ||
{ | ||
if(inner == outer) | ||
continue; | ||
|
||
if(outer_instructions.contains(loop_nesting_graph[inner].head)) | ||
{ | ||
loop_nesting_graph.add_edge(inner, outer); | ||
} | ||
} | ||
} | ||
|
||
auto topsorted_size = loop_nesting_graph.topsort().size(); | ||
INVARIANT( | ||
topsorted_size == loop_nesting_graph.size(), | ||
"loop_nesting_graph must be acyclic"); | ||
|
||
return loop_nesting_graph; | ||
} |
52 changes: 52 additions & 0 deletions
52
src/goto-instrument/contracts/dynamic-frames/dfcc_loop_nesting_graph.h
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
/*******************************************************************\ | ||
|
||
Module: Dynamic frame condition checking | ||
|
||
Author: Qinheping Hu, [email protected] | ||
|
||
Author: Remi Delmas, [email protected] | ||
|
||
Date: March 2023 | ||
|
||
\*******************************************************************/ | ||
|
||
/// \file | ||
/// Builds a graph describing how loops are nested in a GOTO program. | ||
|
||
#ifndef CPROVER_GOTO_INSTRUMENT_CONTRACTS_DYNAMIC_FRAMES_DFCC_LOOP_NESTING_GRAPH_H | ||
#define CPROVER_GOTO_INSTRUMENT_CONTRACTS_DYNAMIC_FRAMES_DFCC_LOOP_NESTING_GRAPH_H | ||
|
||
#include <util/graph.h> | ||
|
||
#include <goto-instrument/loop_utils.h> | ||
|
||
class messaget; | ||
|
||
/// A graph node that stores information about a natural loop. | ||
struct dfcc_loop_nesting_graph_nodet : public graph_nodet<empty_edget> | ||
{ | ||
public: | ||
dfcc_loop_nesting_graph_nodet( | ||
const goto_programt::targett &head, | ||
const goto_programt::targett &latch, | ||
const loopt &instructions); | ||
|
||
/// Loop head instruction | ||
goto_programt::targett head; | ||
|
||
/// Loop latch instruction | ||
goto_programt::targett latch; | ||
|
||
/// Set of loop instructions | ||
loopt instructions; | ||
}; | ||
|
||
typedef grapht<dfcc_loop_nesting_graph_nodet> dfcc_loop_nesting_grapht; | ||
|
||
/// \brief Builds a graph instance describing the nesting structure of natural | ||
/// loops in the given \p goto_program. | ||
/// A loop is considered nested in an outer loop if its head and its latch are | ||
/// both found in the instructions of the outer loop. | ||
dfcc_loop_nesting_grapht | ||
build_loop_nesting_graph(goto_programt &goto_program, messaget &log); | ||
#endif |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.