Skip to content

Commit

Permalink
[BoundsWidening] Use invertibility to support bounds widening in loops (
Browse files Browse the repository at this point in the history
#1137)

An expression that modifies an LValue is said to be invertible w.r.t. the
LValue if we can write an expression in terms of the original value of the
LValue before the modification. For example, the expression x + 1 is invertible
w.r.t x because we can write this expression in terms of the original value of
x which is (x - 1) + 1.

In this PR, we use invertibility of statements to support bounds widening in
loops. More specifically, if a statement modifies a variable that occurs in the
bounds expression of a null-terminated array then instead of killing its bounds
at that statement we use invertibility of the statement to try to write the
widened bounds in terms of the original value of the variable.
  • Loading branch information
Mandeep Singh Grang authored Jul 27, 2021
1 parent 8d3c184 commit 088d45f
Show file tree
Hide file tree
Showing 5 changed files with 516 additions and 56 deletions.
59 changes: 49 additions & 10 deletions clang/include/clang/Sema/BoundsWideningAnalysis.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "clang/AST/ExprUtils.h"
#include "clang/AST/PrettyPrinter.h"
#include "clang/Analysis/Analyses/PostOrderCFGView.h"
#include "clang/Sema/BoundsUtils.h"
#include "clang/Sema/CheckedCAnalysesPrepass.h"
#include "clang/Sema/Sema.h"

Expand Down Expand Up @@ -54,6 +55,14 @@ namespace clang {
// for printing the blocks in a deterministic order.
using OrderedBlocksTy = std::vector<const CFGBlock *>;

// A tuple (Tup) of three elements such that we need to replace Tup[0] with
// Tup[1] in the bounds of every pointer in Tup[3].
using LValuesToReplaceInBoundsTy = std::tuple<Expr *, Expr *, VarSetTy>;

// A mapping of invertible statements to LValuesToReplaceInBoundsTy.
using InvertibleStmtMapTy = llvm::DenseMap<const Stmt *,
LValuesToReplaceInBoundsTy>;

} // end namespace clang

namespace clang {
Expand Down Expand Up @@ -128,20 +137,20 @@ namespace clang {
// Get the set of variables that are pointers to null-terminated arrays and
// in whose lower bounds expressions the variables in Vars occur.
// @param[in] Vars is a set of variables.
// @param[out] NullTermPtrsWithVarsInLowerBounds is a set of variables that
// are pointers to null-terminated arrays and in whose lower bounds
// expressions the variables in Vars occur.
void GetNullTermPtrsWithVarsInLowerBounds(
VarSetTy &Vars, VarSetTy &NullTermPtrsWithVarsInLowerBounds) const;
// @param[out] PtrsWithVarsInLowerBounds is a set of variables that are
// pointers to null-terminated arrays and in whose lower bounds expressions
// the variables in Vars occur.
void GetPtrsWithVarsInLowerBounds(
VarSetTy &Vars, VarSetTy &PtrsWithVarsInLowerBounds) const;

// Get the set of variables that are pointers to null-terminated arrays and
// in whose upper bounds expressions the variables in Vars occur.
// @param[in] Vars is a set of variables.
// @param[out] NullTermPtrsWithVarsInLowerBounds is a set of variables that
// are pointers to null-terminated arrays and in whose upper bounds
// expressions the variables in Vars occur.
void GetNullTermPtrsWithVarsInUpperBounds(
VarSetTy &Vars, VarSetTy &NullTermPtrsWithVarsInUpperBounds) const;
// @param[out] PtrsWithVarsInLowerBounds is a set of variables that are
// pointers to null-terminated arrays and in whose upper bounds expressions
// the variables in Vars occur.
void GetPtrsWithVarsInUpperBounds(
VarSetTy &Vars, VarSetTy &PtrsWithVarsInUpperBounds) const;

// Add an offset to a given expression.
// @param[in] E is the given expression.
Expand Down Expand Up @@ -287,6 +296,14 @@ namespace clang {
// The Out set of the previous statement of a statement in a block.
BoundsMapTy OutOfPrevStmt;

// This stores the adjusted bounds after we have determined the
// invertibility of the current statement that modifies variables
// occurring in bounds expressions.
StmtBoundsMapTy AdjustedBounds;

// A mapping of invertible statements to LValuesToReplaceInBoundsTy.
InvertibleStmtMapTy InvertibleStmts;

ElevatedCFGBlock(const CFGBlock *B) : Block(B) {}

}; // end of ElevatedCFGBlock class.
Expand Down Expand Up @@ -492,6 +509,28 @@ namespace clang {
const Stmt *CurrStmt,
BoundsMapTy &VarsAndBounds);

// Check if CurrStmt is invertible w.r.t. the variables modified by
// CurrStmt.
// Note: This function modifies the set EB->InvertibleStmts.
// @param[in] EB is the current ElevatedCFGBlock.
// @param[in] CurrStmt is the current statement.
// @param[in] PtrsWithAffectedBounds is the set of variables that are
// pointers to null-terminated arrays whose bounds are affected by
// modification to variables that occur in their bounds expressions by
// CurrStmt.
void CheckStmtInvertibility(ElevatedCFGBlock *EB,
const Stmt *CurrStmt,
VarSetTy PtrsWithAffectedBounds) const;

// Update the bounds in StmtOut with the adjusted bounds for the current
// statement, if they exist.
// @param[in] EB is the current ElevatedCFGBlock.
// @param[in] CurrStmt is the current statement.
// @param[out] StmtOut is updated with the adjusted bounds for CurrStmt, if
// they exist.
void UpdateAdjustedBounds(ElevatedCFGBlock *EB, const Stmt *CurrStmt,
BoundsMapTy &StmtOut) const;

// Order the blocks by block number to get a deterministic iteration order
// for the blocks.
// @return Blocks ordered by block number from higher to lower since block
Expand Down
Loading

0 comments on commit 088d45f

Please sign in to comment.