- 38 Views
- Uploaded on
- Presentation posted in: General

Value Numbering

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.

- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -

a = x + y

b = x + y

x = m + n

c = x + y

d = x + y

e = x

f = y

g = e + f

a = x + y

b = x + y

x = m + n

c = x + y

d = x + y

e = x

f = y

g = e + f

a

x has been re-assigned!

c

c

2

0

1

a = x + y

b = x + y

x = m + n

c = x + y

d = x + y

e = x

f = y

g = e + f

2

0

1

0

x

1

y

5

3

4

2

x+y

2

a

6

5

1

2

b

3

6

5

1

m

4

n

5

5

5

m+n

5

x

1

1

What’s a good data structure for this?

6

5

1

- The algorithm is in Tiger 17.4
- This is a deep semantic property of expressions
- In deciding whether “x+y” has been calculated and thus can be avoided, one can NOT just search the expression (by syntax), but some semantic property (here, the value number of “x+y”)
- x+y == a+b <==> V(x)=V(a) /\ V(y)=V(b)

- A form of abstract interpretation

- In deciding whether “x+y” has been calculated and thus can be avoided, one can NOT just search the expression (by syntax), but some semantic property (here, the value number of “x+y”)

- The goals of both of the two algorithms is to perform redundancy elimination
- how to detect redundancy:
- VN: value number
- CSE: available expression analysis

- how to detect redundancy:
- The key difference is the viewpoint to define “redundancy”
- VN: semantics
- CSE: syntax

x = a+b

VN: Yes!

CSE: No!

t = a

s = b

y = t+s

But research has revealed that

each of them come with pros and cons. So most compilers contain both of them.

z = a+b

h = a+b

Is this a redundancy computation?

VN

CSE

- VN can be extended to extended basic block (EBB) easily (recall that EBBs form a local tree):
- Do a preorder walk of the EBB tree;
- Maintain a scoped table along the way (just as we did with the scoped declarations of variables when we discuss elaboration)

a = x + y

b = x + y

x = 2

a = 3

a?

d = x + y

a? b?

Available expression +

Reaching expression

0

x

1

y

2

x+y

2

a = x + y

a

2

b

b = x + y

x = 2

a = 3

a

d = x + y

0

x

1

y

2

x+y

2

a = x + y

a

3

x

4

a

b = x + y

x = 2

a = 3

d = x + y

- It’s hard to do global value numbering for general CFG
- But for SSA, there are good algorithms:
- 1988: partition-based algorithm
- Alpern ‘88

- 1997: dominator-based algorithm
- Kooper ‘97

- 2004: GVN-PRE
- implemented in GCC

- 1988: partition-based algorithm

Partition-based GVN

L1:

a = x + y

L2:

L3:

x = x + y

x = x + y

L4:

d = x + y

L1:

- Key observations:
- Variables defined with different operators can not be equal (arity), thus we group them in different congruent classes;
- for variables with same definition operator, they are equal iff the corresponding operands are from the same congruent classes.

a = x + y

L2:

L3:

x1 = x + y

x2 = x + y

L4:

x3=ϕ(x1, x2)

d = x3 + y

L1:

Initial partitions:

{a, x1, x2, d} {x3} {x} {y}

this partition is based on the

expression operators.

a = x + y

L2:

L3:

x1 = x + y

x2 = x + y

a = x+y

x1 = x+y

x2 = x+y

d = x3+y

x3 = ϕ(x1, x2)

x = ?

y = ?

L4:

x3=ϕ(x1, x2)

d = x3 + y

In the same set <==> take good chance of equality.

L1:

{a, x1, x2, d} {x3} {x} {y}

a = x + y

Now, consider {x}:

There are 3 uses of x, but not

x3!

L2:

L3:

x1 = x + y

x2 = x + y

a = x+y

x1 = x+y

x2 = x+y

d = x3+y

x3 = ϕ(x1, x2)

x = ?

y = ?

L4:

x3=ϕ(x1, x2)

d = x3 + y

L1:

{a, x1, x2, d} {x3} {x} {y}

a = x + y

Final partitions:

{a, x1, x2} {d} {x3} {x} {y}

L2:

L3:

x1 = x + y

x2 = x + y

a = x+y

x1 = x+y

x2 = x+y

d = x3+y

x3 = ϕ(x1, x2)

x = ?

y = ?

L4:

x3=ϕ(x1, x2)

d = x3 + y

a

a

a

As “a” dominates both x1 and x2, so all uses of x1 and x2 can be replaced by “a”.

partition()

P = all initial partitions (a queue of sets)

while (!empty(P))

S = deQueue(P) // suppose S is an array

n = arity(S[0]) // example: + ==> n == 2

for (i=0 to n-1)

use_v[i] = S[0][i]; // calculate use sets

T = {S[0]}

foreach (x \in s[1]…s[k-1]) // k=|s|

for (i=0 to n-1)

if (use[x_i]!=use_v[i]) break;

T \/= {x}

if (T!=S)

enQueue (T); enQueue (S-T);

L1:

i = 1

j = 1

L1:

i1 = 1

j1 = 1

L2:

L2:

i3 = ϕ(i1, i2)

j3 = ϕ (j1, j2)

L4:

L4:

L3:

L3:

i = i+1

j = j+1

i = i+3

j = j+3

i4 = i3+1

j4 = j3+1

i5 = i3+3

j5 = j3+3

L5:

L5:

i2 = ϕ(i4, i5)

j2 = ϕ (j4, j5)

CFG

SSA

L1:

i1 = 1

j1 = 1

{i1, j1} {i3, j3} {i4, j4, i5, j5} {i2, j2}

// Be partitioned into:

{i1, j1} {i3, j3} {i4, j4} {i5, j5} {i2, j2}

L2:

i3 = ϕ(i1, i2)

j3 = ϕ (j1, j2)

L4:

L3:

i4 = i3+1

j4 = j3+1

i5 = i3+3

j5 = j3+3

L5:

i2 = ϕ(i4, i5)

j2 = ϕ (j4, j5)

SSA

L1:

i = 1

j = 1

L1:

i1 = 1

j1 = 1

L2:

L2:

i3 = ϕ(i1, i2)

j3 = ϕ (j1, j2)

L4:

L4:

L3:

L3:

i = i+1

j = j+1

i = i+3

j = j+3

i4 = i3+1

j4 = j3+1

i5 = i3+3

j5 = j3+3

L5:

L5:

i2 = ϕ(i4, i5)

j2 = ϕ (j4, j5)

CFG

SSA

Dominator-based GVN

- VN can be extended to GVN
- on dominator trees:
- Do a (what order?) walk of the dominator tree;
- Maintain a scoped table along the way (just as we did with the scope declarations of variables)
- for each block B, do VN as before, for a successor S of B, modify the ϕarguments

L1:

2

0

1

a = x + y

L2:

L3:

x1 = x + y

x2 = x + y

2

2

0

1

0

1

L4:

2

2

L1

2

x3=ϕ(x1, x2)

d = x3 + y

3

2

1

L2

L4

L3

- VN can be extended to GVN
- on dominator trees:
- Do a (what order?) walk of the dominator tree;
- Maintain a scoped table along the way (just as we did with the scope declarations of variables)
- for each block B, do VN as before, for a successor S of B, modify the ϕarguments.

L1:

2

0

1

a = x + y

L2:

L3:

b = x + y

x1 = 2

a1 = 3

3

3

2

0

1

4

4

L4:

L1

5

3

0

x2=ϕ(x, x1)

d = x2 + y

6

5

1

L2

L4

L3