The input will be provided in form of the intermediate language described below. Therefore the first task you must carry out is to read the program written in this intermediate language and construct the program's control flow graph.
You are also provided with an interpreter for this intermediate language using which you can verify the correctness of the optimized code and a translator to generate intermediate code for programs written in a subset of C. By computing the number of expression evaluations performed during execution of a set of programs optimized by each of the above two optimizations, you will be able to compare their relative effectiveness in optimizing the programs.
More details about the languages, tools, and output requirements can be found in the following:
#define read(x) scanf("%d", &(x))
#define print(x) printf("%d\n", (x))
in the beginning of a C file and use a standard C compiler to compile it.
In this way, you can debug the C code using your familiar/favorite tools
before using the translator to get an intermediate representation.
#define read(x) scanf("%d", &(x))
#define print(x) printf("%d\n", (x))
int main()
{
int a, n, m, k, j, i, s0, s1, s2, s3, s4;
read(a);
n = a;
m = a;
k = a;
while ( n > 0 ) {
s3 = k + a;
a = a + 1;
s1 = a + m;
if ( n % 2 == 0 ) {
m = -m;
s0 = a + m;
}
else {
s0 = a + m;
m = -m;
}
s2 = a + m;
n = n - 1;
a = a + 1;
s4 = k + a;
}
s4 = k + a;
print(s0);
print(s1);
print(s2);
print(s3);
print(s4);
}
The following is the IR code for the above example:
. _a . _n . _m . _k . _j . _i . _s0 . _s1 . _s2 . _s3 . _s4 . t0 . t1 . t2 . t3 . t4 . t5 . t6 . t7 . t8 . t9 . t10 . t11 . t12 . p0 : START .< _a = _n, _a = _m, _a = _k, _a : L2 <= p0, _n, 0 ?:= L3, p0 + t0, _k, _a = _s3, t0 + t1, _a, 1 = _a, t1 + t2, _a, _m = _s1, t2 % t3, _n, 2 != p0, t3, 0 ?:= L0, p0 - t4, 0, _m = _m, t4 + t5, _a, _m = _s0, t5 := L1 : L0 + t6, _a, _m = _s0, t6 - t7, 0, _m = _m, t7 : L1 + t8, _a, _m = _s2, t8 - t9, _n, 1 = _n, t9 + t10, _a, 1 = _a, t10 + t11, _k, _a = _s4, t11 := L2 : L3 + t12, _k, _a = _s4, t12 .> _s0 .> _s1 .> _s2 .> _s3 .> _s4
| Syntax | Semantics |
|---|---|
| Variable declaration statements: | |
| . name | declares a name for a scalar variable |
| .[] name, n | declares a name for a vector/array variable consisting of n (must be a positive whole number) elements, with name[0] being the first element |
| Copy statements: | |
| = dst, src | dst = src, src can be an immediate |
| array access statements: | |
| =[] dst, src, index | dst = src[index], index can be an immediate |
| []= dst, index, src | dst[index] = src, index can be an immediate |
| Input/Output statements: | |
| .< dst | read a value into dst from the standard input |
| .[]< dst, index | read a value into dst[index] from the standard input |
| .> src | write the value of src into the standard output |
| .[]> src, index | write the value of src[index] into the standard output |
| fixed-point arithmetic op statements(one or both source operands can be immediates): | |
| + dst, src1, src2 | dst = src1 + src2 |
| - dst, src1, src2 | dst = src1 - src2 |
| * dst, src1, src2 | dst = src1 * src2 |
| / dst, src1, src2 | dst = src1 / src2 |
| % dst, src1, src2 | dst = src1 % src2 |
| comparison statements(one or both source operands can be immediates): | |
| < dst, src1, src2 | dst = src1 < src2 |
| <= dst, src1, src2 | dst = src1 <= src2 |
| != dst, src1, src2 | dst = src1 != src2 |
| == dst, src1, src2 | dst = src1 == src2 |
| >= dst, src1, src2 | dst = src1 >= src2 |
| > dst, src1, src2 | dst = src1 > src2 |
| logical-op statements(one or both source operands can be immediates): | |
| || dst, src1, src2 | logical OR, dst = src1 || src2 |
| && dst, src1, src2 | logical AND, dst = src1 && src2 |
| ! dst, src | logical NOT, dst = ! src |
| label declaration statements: | |
| : label | declares a label |
| branch statements: | |
| := label | goto label |
| ?:= label, predicate | if predicate is true(1) goto label |
Download the front end (c2ir) which turns Mini C code into IR code.
Download the interpreter (irRun) which executes IR code. The interpreter executes code written in the mini-intermediate-represeantation language. It assumes that
Download test cases in pp_test.tar.gz and use them to test/debug your program.
. _a . _n . _m . _k . _j . _i . _s0 . _s1 . _s2 . _s3 . _s4 . t0 . t1 . t2 . t3 . t4 . t5 . t6 . t7 . t8 . t9 . t10 . t11 . t12 . p0 . count BB1 : START = count, 1 .< _a = _n, _a = _m, _a = _k, _a + t11, _k, _a BB2 : L2 + count, count, 1 <= p0, _n, 0 ?:= L3, p0 BB3 + count, count, 5 = _s3, t11 + t1, _a, 1 = _a, t1 + t2, _a, _m = _s1, t2 - t4, 0, _m % t3, _n, 2 != p0, t3, 0 ?:= L0, p0 BB4 + count, count, 1 = _m, t4 + t5, _a, _m = _s0, t5 := L1 BB5 : L0 + count, count, 1 = _s0, t2 = _m, t4 + t5, _a, _m BB6 : L1 + count, count, 3 = _s2, t5 - t9, _n, 1 = _n, t9 + t10, _a, 1 = _a, t10 + t11, _k, _a = _s4, t11 := L2 BB7 : L3 = _s4, t11 .> _s0 .> _s1 .> _s2 .> _s3 .> _s4 .> count Blue denotes the instrumented code used to calculate the number of performed expression evaluation. Red denotes the part of code which is modified due to expression elimination.