Skip to content

Commit 0c98320

Browse files
Merge pull request #40 from CompilerProgramming/develop
During SSA construction do a liveness check prior to inserting a phi
2 parents 4f3a2ac + ddb5e2c commit 0c98320

File tree

6 files changed

+521
-113
lines changed

6 files changed

+521
-113
lines changed

optvm/src/main/java/com/compilerprogramming/ezlang/compiler/ChaitinGraphColoringRegisterAllocator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public Map<Integer, Integer> assignRegisters(CompiledFunction function, int numR
4545
* Frame size = max number of registers needed to execute the function
4646
*/
4747
private int computeFrameSize(Map<Integer, Integer> assignments) {
48-
return assignments.values().stream().mapToInt(k->k).max().orElse(0);
48+
return assignments.values().stream().mapToInt(k->k).max().orElse(-1)+1;
4949
}
5050

5151
/**

optvm/src/main/java/com/compilerprogramming/ezlang/compiler/CompiledFunction.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public class CompiledFunction {
1717
public BasicBlock currentBlock;
1818
private BasicBlock currentBreakTarget;
1919
private BasicBlock currentContinueTarget;
20-
private Type.TypeFunction functionType;
20+
public Type.TypeFunction functionType;
2121
public final RegisterPool registerPool;
2222
private final TypeDictionary typeDictionary;
2323

optvm/src/main/java/com/compilerprogramming/ezlang/compiler/EnterSSA.java

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ public EnterSSA(CompiledFunction bytecodeFunction, EnumSet<Options> options) {
4343
}
4444
this.blocks = domTree.blocks; // the blocks are ordered reverse post order
4545
findNonLocalNames();
46+
new Liveness(bytecodeFunction); // EWe require liveness info to construct pruned ssa
4647
insertPhis();
4748
renameVars();
4849
bytecodeFunction.isSSA = true;
@@ -94,12 +95,16 @@ void insertPhis() {
9495
while (b != null) {
9596
visited.set(b.bid);
9697
for (BasicBlock d: b.dominationFrontier) {
97-
if (d == function.exit) // The exit block does not need any phis as it has no instructions
98-
continue;
99-
// insert phi for x in d
100-
d.insertPhiFor(x);
101-
if (!visited.get(d.bid))
102-
worklist.push(d);
98+
// Perform a liveness check to avoid inserting
99+
// phi when variable is dead
100+
// Inserting dead phis causes problems during renaming
101+
// because there will not be a definition available
102+
if (d.liveIn.contains(x)) {
103+
// insert phi for x in d
104+
d.insertPhiFor(x);
105+
if (!visited.get(d.bid))
106+
worklist.push(d);
107+
}
103108
}
104109
b = worklist.pop();
105110
}

optvm/src/test/java/com/compilerprogramming/ezlang/compiler/TestIncrementalSSA.java

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -520,5 +520,154 @@ func foo(x: Int,y: Int)->Int
520520
""", result);
521521
}
522522

523+
@Test
524+
public void testSSA10() {
525+
String src = """
526+
func main()->Int {
527+
var sum = 0
528+
var i = 0
529+
var j = 0
530+
while (i < 5) {
531+
j = 0
532+
while (j < 5) {
533+
if (j % 2 == 0)
534+
sum = sum + j
535+
j = j + 1
536+
}
537+
i = i + 1
538+
}
539+
return sum
540+
}
541+
""";
542+
String result = compileSrc(src);
543+
Assert.assertEquals("""
544+
func main()->Int
545+
Reg #0 sum 0
546+
Reg #1 i 1
547+
Reg #2 j 2
548+
Reg #3 %t3 3
549+
Reg #4 i_1 1
550+
Reg #5 j_1 2
551+
Reg #6 %t6 6
552+
Reg #7 j_2 2
553+
Reg #8 %t8 8
554+
Reg #9 %t9 9
555+
Reg #10 %t10 10
556+
Reg #11 sum_1 0
557+
Reg #12 sum_2 0
558+
Reg #13 %t13 13
559+
Reg #14 j_3 2
560+
Reg #15 j_4 2
561+
Reg #16 sum_3 0
562+
Reg #17 sum_4 0
563+
Reg #18 %t18 18
564+
Reg #19 i_2 1
565+
Reg #20 i_3 1
566+
Reg #21 i_4 1
567+
L0:
568+
sum = 0
569+
i = 0
570+
j = 0
571+
goto L2
572+
L2:
573+
sum_3 = phi(sum, sum_1)
574+
i_1 = phi(i, i_4)
575+
%t3 = i_1<5
576+
if %t3 goto L3 else goto L4
577+
L3:
578+
j_1 = 0
579+
goto L5
580+
L5:
581+
sum_1 = phi(sum_3, sum_4)
582+
j_2 = phi(j_1, j_4)
583+
%t6 = j_2<5
584+
if %t6 goto L6 else goto L7
585+
L6:
586+
%t8 = j_2%2
587+
%t9 = %t8==0
588+
if %t9 goto L8 else goto L9
589+
L8:
590+
%t10 = sum_1+j_2
591+
sum_2 = %t10
592+
goto L9
593+
L9:
594+
sum_4 = phi(sum_1, sum_2)
595+
%t13 = j_2+1
596+
j_4 = %t13
597+
goto L5
598+
L7:
599+
%t18 = i_1+1
600+
i_4 = %t18
601+
goto L2
602+
L4:
603+
ret sum_3
604+
goto L1
605+
L1:
606+
""", result);
607+
}
608+
609+
@Test
610+
public void testSSA17() {
611+
String src = """
612+
func merge(begin: Int, middle: Int, end: Int)
613+
{
614+
if (begin < end) {
615+
var cond = 0
616+
if (begin < middle) {
617+
if (begin >= end) cond = 1;
618+
}
619+
if (cond)
620+
{
621+
cond = 0
622+
}
623+
}
624+
}
625+
""";
626+
String result = compileSrc(src);
627+
Assert.assertEquals("""
628+
func merge(begin: Int,middle: Int,end: Int)
629+
Reg #0 begin 0
630+
Reg #1 middle 1
631+
Reg #2 end 2
632+
Reg #3 cond 3
633+
Reg #4 %t4 4
634+
Reg #5 %t5 5
635+
Reg #6 %t6 6
636+
Reg #7 cond_1 3
637+
Reg #8 cond_2 3
638+
Reg #9 cond_3 3
639+
Reg #10 cond_4 3
640+
L0:
641+
arg begin
642+
arg middle
643+
arg end
644+
%t4 = begin<end
645+
if %t4 goto L2 else goto L3
646+
L2:
647+
cond = 0
648+
%t5 = begin<middle
649+
if %t5 goto L4 else goto L5
650+
L4:
651+
%t6 = begin>=end
652+
if %t6 goto L6 else goto L7
653+
L6:
654+
cond_1 = 1
655+
goto L7
656+
L7:
657+
cond_3 = phi(cond, cond_1)
658+
goto L5
659+
L5:
660+
cond_2 = phi(cond, cond_3)
661+
if cond_2 goto L8 else goto L9
662+
L8:
663+
cond_4 = 0
664+
goto L9
665+
L9:
666+
goto L3
667+
L3:
668+
goto L1
669+
L1:
670+
""", result);
671+
}
523672

524673
}

0 commit comments

Comments
 (0)