From 9bbfa14c828114fbd4ca9f858d736f2dbc9dd146 Mon Sep 17 00:00:00 2001
From: Valentin Perrelle <valentin.perrelle@cea.fr>
Date: Wed, 19 Jun 2019 17:07:20 +0200
Subject: [PATCH] [Eva] Update section Loop Unrolling

---
 .../parametrizing/loop-unroll-const.c         |  11 +
 .../parametrizing/loop-unroll-const.log       | 222 ++++++++++++++++++
 .../parametrizing/loop-unroll-insuf.c         |   5 +
 .../parametrizing/loop-unroll-insuf.log       |  23 ++
 .../parametrizing/loop-unroll-nested.c        |  13 +
 .../parametrizing/loop-unroll-nested.log      |  43 ++++
 doc/value/examples/parametrizing/makefile     |   5 +-
 doc/value/main.tex                            |  53 +++--
 8 files changed, 348 insertions(+), 27 deletions(-)
 create mode 100644 doc/value/examples/parametrizing/loop-unroll-const.c
 create mode 100644 doc/value/examples/parametrizing/loop-unroll-const.log
 create mode 100644 doc/value/examples/parametrizing/loop-unroll-insuf.c
 create mode 100644 doc/value/examples/parametrizing/loop-unroll-insuf.log
 create mode 100644 doc/value/examples/parametrizing/loop-unroll-nested.c
 create mode 100644 doc/value/examples/parametrizing/loop-unroll-nested.log

diff --git a/doc/value/examples/parametrizing/loop-unroll-const.c b/doc/value/examples/parametrizing/loop-unroll-const.c
new file mode 100644
index 00000000000..dad47c0b399
--- /dev/null
+++ b/doc/value/examples/parametrizing/loop-unroll-const.c
@@ -0,0 +1,11 @@
+#define NROWS 10
+void main(void) {
+  int a[NROWS][20] = {0};
+  //@ loop unroll NROWS;
+  for (int i = 0; i < 10; i++) {
+    //@ loop unroll (10+10);
+    for (int j = 0; j < 20; j++) {
+      a[i][j] += i + j;
+    }
+  }
+}
diff --git a/doc/value/examples/parametrizing/loop-unroll-const.log b/doc/value/examples/parametrizing/loop-unroll-const.log
new file mode 100644
index 00000000000..9071ef76070
--- /dev/null
+++ b/doc/value/examples/parametrizing/loop-unroll-const.log
@@ -0,0 +1,222 @@
+[kernel] Parsing loop-unroll-const.c (with preprocessing)
+[eva] Analyzing a complete application starting at main
+[eva] Computing initial state
+[eva] Initial state computed
+[eva:initial-state] Values of globals at initialization
+  
+[eva] loop-unroll-const.c:7: Trace partitioning superposing up to 100 states
+[eva] loop-unroll-const.c:7: Trace partitioning superposing up to 200 states
+[eva] done for function main
+[eva] ====== VALUES COMPUTED ======
+[eva:final-states] Values at end of function main:
+  a[0][0] ∈ {0}
+   [0][1] ∈ {1}
+   [0][2] ∈ {2}
+   [0][3] ∈ {3}
+   [0][4] ∈ {4}
+   [0][5] ∈ {5}
+   [0][6] ∈ {6}
+   [0][7] ∈ {7}
+   [0][8] ∈ {8}
+   [0][9] ∈ {9}
+   [0][10] ∈ {10}
+   [0][11] ∈ {11}
+   [0][12] ∈ {12}
+   [0][13] ∈ {13}
+   [0][14] ∈ {14}
+   [0][15] ∈ {15}
+   [0][16] ∈ {16}
+   [0][17] ∈ {17}
+   [0][18] ∈ {18}
+   [0][19] ∈ {19}
+   [1][0] ∈ {1}
+   [1][1] ∈ {2}
+   [1][2] ∈ {3}
+   [1][3] ∈ {4}
+   [1][4] ∈ {5}
+   [1][5] ∈ {6}
+   [1][6] ∈ {7}
+   [1][7] ∈ {8}
+   [1][8] ∈ {9}
+   [1][9] ∈ {10}
+   [1][10] ∈ {11}
+   [1][11] ∈ {12}
+   [1][12] ∈ {13}
+   [1][13] ∈ {14}
+   [1][14] ∈ {15}
+   [1][15] ∈ {16}
+   [1][16] ∈ {17}
+   [1][17] ∈ {18}
+   [1][18] ∈ {19}
+   [1][19] ∈ {20}
+   [2][0] ∈ {2}
+   [2][1] ∈ {3}
+   [2][2] ∈ {4}
+   [2][3] ∈ {5}
+   [2][4] ∈ {6}
+   [2][5] ∈ {7}
+   [2][6] ∈ {8}
+   [2][7] ∈ {9}
+   [2][8] ∈ {10}
+   [2][9] ∈ {11}
+   [2][10] ∈ {12}
+   [2][11] ∈ {13}
+   [2][12] ∈ {14}
+   [2][13] ∈ {15}
+   [2][14] ∈ {16}
+   [2][15] ∈ {17}
+   [2][16] ∈ {18}
+   [2][17] ∈ {19}
+   [2][18] ∈ {20}
+   [2][19] ∈ {21}
+   [3][0] ∈ {3}
+   [3][1] ∈ {4}
+   [3][2] ∈ {5}
+   [3][3] ∈ {6}
+   [3][4] ∈ {7}
+   [3][5] ∈ {8}
+   [3][6] ∈ {9}
+   [3][7] ∈ {10}
+   [3][8] ∈ {11}
+   [3][9] ∈ {12}
+   [3][10] ∈ {13}
+   [3][11] ∈ {14}
+   [3][12] ∈ {15}
+   [3][13] ∈ {16}
+   [3][14] ∈ {17}
+   [3][15] ∈ {18}
+   [3][16] ∈ {19}
+   [3][17] ∈ {20}
+   [3][18] ∈ {21}
+   [3][19] ∈ {22}
+   [4][0] ∈ {4}
+   [4][1] ∈ {5}
+   [4][2] ∈ {6}
+   [4][3] ∈ {7}
+   [4][4] ∈ {8}
+   [4][5] ∈ {9}
+   [4][6] ∈ {10}
+   [4][7] ∈ {11}
+   [4][8] ∈ {12}
+   [4][9] ∈ {13}
+   [4][10] ∈ {14}
+   [4][11] ∈ {15}
+   [4][12] ∈ {16}
+   [4][13] ∈ {17}
+   [4][14] ∈ {18}
+   [4][15] ∈ {19}
+   [4][16] ∈ {20}
+   [4][17] ∈ {21}
+   [4][18] ∈ {22}
+   [4][19] ∈ {23}
+   [5][0] ∈ {5}
+   [5][1] ∈ {6}
+   [5][2] ∈ {7}
+   [5][3] ∈ {8}
+   [5][4] ∈ {9}
+   [5][5] ∈ {10}
+   [5][6] ∈ {11}
+   [5][7] ∈ {12}
+   [5][8] ∈ {13}
+   [5][9] ∈ {14}
+   [5][10] ∈ {15}
+   [5][11] ∈ {16}
+   [5][12] ∈ {17}
+   [5][13] ∈ {18}
+   [5][14] ∈ {19}
+   [5][15] ∈ {20}
+   [5][16] ∈ {21}
+   [5][17] ∈ {22}
+   [5][18] ∈ {23}
+   [5][19] ∈ {24}
+   [6][0] ∈ {6}
+   [6][1] ∈ {7}
+   [6][2] ∈ {8}
+   [6][3] ∈ {9}
+   [6][4] ∈ {10}
+   [6][5] ∈ {11}
+   [6][6] ∈ {12}
+   [6][7] ∈ {13}
+   [6][8] ∈ {14}
+   [6][9] ∈ {15}
+   [6][10] ∈ {16}
+   [6][11] ∈ {17}
+   [6][12] ∈ {18}
+   [6][13] ∈ {19}
+   [6][14] ∈ {20}
+   [6][15] ∈ {21}
+   [6][16] ∈ {22}
+   [6][17] ∈ {23}
+   [6][18] ∈ {24}
+   [6][19] ∈ {25}
+   [7][0] ∈ {7}
+   [7][1] ∈ {8}
+   [7][2] ∈ {9}
+   [7][3] ∈ {10}
+   [7][4] ∈ {11}
+   [7][5] ∈ {12}
+   [7][6] ∈ {13}
+   [7][7] ∈ {14}
+   [7][8] ∈ {15}
+   [7][9] ∈ {16}
+   [7][10] ∈ {17}
+   [7][11] ∈ {18}
+   [7][12] ∈ {19}
+   [7][13] ∈ {20}
+   [7][14] ∈ {21}
+   [7][15] ∈ {22}
+   [7][16] ∈ {23}
+   [7][17] ∈ {24}
+   [7][18] ∈ {25}
+   [7][19] ∈ {26}
+   [8][0] ∈ {8}
+   [8][1] ∈ {9}
+   [8][2] ∈ {10}
+   [8][3] ∈ {11}
+   [8][4] ∈ {12}
+   [8][5] ∈ {13}
+   [8][6] ∈ {14}
+   [8][7] ∈ {15}
+   [8][8] ∈ {16}
+   [8][9] ∈ {17}
+   [8][10] ∈ {18}
+   [8][11] ∈ {19}
+   [8][12] ∈ {20}
+   [8][13] ∈ {21}
+   [8][14] ∈ {22}
+   [8][15] ∈ {23}
+   [8][16] ∈ {24}
+   [8][17] ∈ {25}
+   [8][18] ∈ {26}
+   [8][19] ∈ {27}
+   [9][0] ∈ {9}
+   [9][1] ∈ {10}
+   [9][2] ∈ {11}
+   [9][3] ∈ {12}
+   [9][4] ∈ {13}
+   [9][5] ∈ {14}
+   [9][6] ∈ {15}
+   [9][7] ∈ {16}
+   [9][8] ∈ {17}
+   [9][9] ∈ {18}
+   [9][10] ∈ {19}
+   [9][11] ∈ {20}
+   [9][12] ∈ {21}
+   [9][13] ∈ {22}
+   [9][14] ∈ {23}
+   [9][15] ∈ {24}
+   [9][16] ∈ {25}
+   [9][17] ∈ {26}
+   [9][18] ∈ {27}
+   [9][19] ∈ {28}
+[eva:summary] ====== ANALYSIS SUMMARY ======
+  ----------------------------------------------------------------------------
+  1 function analyzed (out of 1): 100% coverage.
+  In this function, 16 statements reached (out of 16): 100% coverage.
+  ----------------------------------------------------------------------------
+  No errors or warnings raised during the analysis.
+  ----------------------------------------------------------------------------
+  0 alarms generated by the analysis.
+  ----------------------------------------------------------------------------
+  No logical properties have been reached by the analysis.
+  ----------------------------------------------------------------------------
diff --git a/doc/value/examples/parametrizing/loop-unroll-insuf.c b/doc/value/examples/parametrizing/loop-unroll-insuf.c
new file mode 100644
index 00000000000..5058c9d4046
--- /dev/null
+++ b/doc/value/examples/parametrizing/loop-unroll-insuf.c
@@ -0,0 +1,5 @@
+void main() {
+  //@ loop unroll 20; // should be 21
+  for (int i = 0 ; i <= 20 ; i ++) {
+  }
+}
\ No newline at end of file
diff --git a/doc/value/examples/parametrizing/loop-unroll-insuf.log b/doc/value/examples/parametrizing/loop-unroll-insuf.log
new file mode 100644
index 00000000000..7527748a566
--- /dev/null
+++ b/doc/value/examples/parametrizing/loop-unroll-insuf.log
@@ -0,0 +1,23 @@
+[kernel] Parsing loop-unroll-insuf.c (with preprocessing)
+[eva] Analyzing a complete application starting at main
+[eva] Computing initial state
+[eva] Initial state computed
+[eva:initial-state] Values of globals at initialization
+  
+[eva:loop-unroll] loop-unroll-insuf.c:3: loop not completely unrolled
+[eva] loop-unroll-insuf.c:3: starting to merge loop iterations
+[eva] done for function main
+[eva] ====== VALUES COMPUTED ======
+[eva:final-states] Values at end of function main:
+  i ∈ {21}
+[eva:summary] ====== ANALYSIS SUMMARY ======
+  ----------------------------------------------------------------------------
+  1 function analyzed (out of 1): 100% coverage.
+  In this function, 6 statements reached (out of 6): 100% coverage.
+  ----------------------------------------------------------------------------
+  No errors or warnings raised during the analysis.
+  ----------------------------------------------------------------------------
+  0 alarms generated by the analysis.
+  ----------------------------------------------------------------------------
+  No logical properties have been reached by the analysis.
+  ----------------------------------------------------------------------------
diff --git a/doc/value/examples/parametrizing/loop-unroll-nested.c b/doc/value/examples/parametrizing/loop-unroll-nested.c
new file mode 100644
index 00000000000..7205a6d088a
--- /dev/null
+++ b/doc/value/examples/parametrizing/loop-unroll-nested.c
@@ -0,0 +1,13 @@
+int t1[] = {1, 2, 3}, t2[] = {4, 5}, t3[] = {6, 7, 8, 9};
+int *t[] = {t1, t2, t3};
+int sizes[] = {3, 2, 4};
+void main(void) {
+  int S = 0;
+  // loop unroll 3;
+  for (int i = 0 ; i < 3 ; i++) {
+    // loop unroll sizes[i];
+    for (int j = 0 ; j < sizes[i] ; j++) {
+      S += t[i][j];
+    }
+  }
+}
diff --git a/doc/value/examples/parametrizing/loop-unroll-nested.log b/doc/value/examples/parametrizing/loop-unroll-nested.log
new file mode 100644
index 00000000000..5ff936dc948
--- /dev/null
+++ b/doc/value/examples/parametrizing/loop-unroll-nested.log
@@ -0,0 +1,43 @@
+[kernel] Parsing loop-unroll-nested.c (with preprocessing)
+[eva] Analyzing a complete application starting at main
+[eva] Computing initial state
+[eva] Initial state computed
+[eva:initial-state] Values of globals at initialization
+  t1[0] ∈ {1}
+    [1] ∈ {2}
+    [2] ∈ {3}
+  t2[0] ∈ {4}
+    [1] ∈ {5}
+  t3[0] ∈ {6}
+    [1] ∈ {7}
+    [2] ∈ {8}
+    [3] ∈ {9}
+  t[0] ∈ {{ &t1[0] }}
+   [1] ∈ {{ &t2[0] }}
+   [2] ∈ {{ &t3[0] }}
+  sizes[0] ∈ {3}
+       [1] ∈ {2}
+       [2] ∈ {4}
+[eva] loop-unroll-nested.c:9: starting to merge loop iterations
+[eva:alarm] loop-unroll-nested.c:10: Warning: 
+  signed overflow. assert S + *(t[i] + j) ≤ 2147483647;
+[eva] loop-unroll-nested.c:7: starting to merge loop iterations
+[eva:alarm] loop-unroll-nested.c:10: Warning: 
+  out of bounds read. assert \valid_read(t[i] + j);
+[eva] done for function main
+[eva] ====== VALUES COMPUTED ======
+[eva:final-states] Values at end of function main:
+  S ∈ [0..2147483647]
+[eva:summary] ====== ANALYSIS SUMMARY ======
+  ----------------------------------------------------------------------------
+  1 function analyzed (out of 1): 100% coverage.
+  In this function, 16 statements reached (out of 16): 100% coverage.
+  ----------------------------------------------------------------------------
+  No errors or warnings raised during the analysis.
+  ----------------------------------------------------------------------------
+  2 alarms generated by the analysis:
+       1 invalid memory access
+       1 integer overflow
+  ----------------------------------------------------------------------------
+  No logical properties have been reached by the analysis.
+  ----------------------------------------------------------------------------
diff --git a/doc/value/examples/parametrizing/makefile b/doc/value/examples/parametrizing/makefile
index 5c550ea370e..74f6d633930 100644
--- a/doc/value/examples/parametrizing/makefile
+++ b/doc/value/examples/parametrizing/makefile
@@ -14,7 +14,10 @@ TARGETS = \
   nor.1.log \
   nor.2.log \
   ilevel.1.log \
-  ilevel.2.log
+  ilevel.2.log \
+	loop-unroll-const.log \
+	loop-unroll-nested.log \
+	loop-unroll-insuf.log
 
 .SECONDEXPANSION:
 .PHONY: all clean
diff --git a/doc/value/main.tex b/doc/value/main.tex
index a541d32a9a7..62fb14dd0f0 100644
--- a/doc/value/main.tex
+++ b/doc/value/main.tex
@@ -3308,29 +3308,35 @@ iteration, avoiding merging states from different iterations.
 This leads to increased cost in terms of analysis, but usually the cost
 increase is worth the improvement in precision.
 
-Such annotations must be placed before just before the loop (i.e. before the
+Such annotations must be placed just before the loop (i.e. before the
 \lstinline|while|, \lstinline|for| or \lstinline|do| introducing the loop),
 and one annotation is required per loop, including nested ones. For instance:
 
-\begin{lstlisting}
-#define NROWS 10
-void main() {
-  int a[NROWS][20] = {0};
-  //@ loop unroll NROWS;
-  for (int i = 0; i < 10; i++) {
-    //@ loop unroll (10+10);
-    for (int j = 0; j < 20; j++) {
-      a[i][j] += i + j;
-    }
-  }
-}
-\end{lstlisting}
+\lstinputlisting{examples/parametrizing/loop-unroll-const.c}
 
-Note that constants obtained via \lstinline|#define| macros can be used in
-annotations, as well as constant expressions. The annotations above will ensure
+The annotations above will ensure
 that \Eva{} will unroll the loops and keep the analysis precise; otherwise,
 the array access \lstinline|a[i][j]| might generate alarms due to imprecisions.
 
+The \lstinline|loop unroll| parameter can be any C expression such that there
+is only one possible integer value found by \Eva{} for this expression.
+Constants obtained via \lstinline|#define| macros, variables which always have
+a unique value or a combination of these with arithmetic operator are
+suitable. For expressions which do not obviously represent only one integer,
+the acceptability of the annotation depends on the precision of the analyzer.
+Note that there are interesting cases of non-constant expression for
+unrolling annotations. The example below shows a function with two nested loops.
+
+\lstinputlisting{examples/parametrizing/loop-unroll-nested.c}
+
+The number of iterations of the outer one is constant while the number of
+iterations of the inner one is variable but depends on the current iteration of
+the outer loop. However, if we instructs \Eva{} to unroll the outer loop then
+the parameter \lstinline|sizes[i]| of the \lstinline|loop unroll| annotation
+always evaluate to a single possible integer and thus the inner loop annotation
+is accepted. Note that, in this example, it is also possible to use an upper
+bound like $4$.
+
 The unrolling mechanism is independent of \lstinline|-eva-slevel|
 (see next subsection): annotated loops are always unrolled at least the specified
 number of times. If the loop has not been entirely unrolled, however,
@@ -3340,17 +3346,12 @@ While it is sometimes useful to unroll only the first iterations, the usual
 objective is full unrolling; for this reason, the user is informed whenever
 the specified unrolling value is insufficient to unroll the loop entirely:
 
-\begin{lstlisting}
-void main() {
-  //@ loop unroll 20; // should be 21
-  for (int i = 0 ; i <= 20 ; i ++) {
-  }
-}
-\end{lstlisting}
+\begin{minipage}{\linewidth}% prevents page break in listing
+\lstinputlisting{examples/parametrizing/loop-unroll-insuf.c}
+\end{minipage}
 
-\begin{lstlisting}
-[eva:loop-unroll] insuf-loop.c:3: loop not completely unrolled
-\end{lstlisting}
+\lstinputlisting[linerange={7-7}]
+  {examples/parametrizing/loop-unroll-insuf.log}
 
 The message can be deactived via \lstinline|-eva-warn-key loop-unroll=inactive|.
 
-- 
GitLab