Pseudocode: Consume value of true condition in while-loop

This commit is contained in:
Alexey Sedunov
2014-07-23 12:47:01 +04:00
parent e11ffb8542
commit b0bf11c51e
5 changed files with 72 additions and 57 deletions
@@ -802,6 +802,13 @@ public class JetControlFlowProcessor {
if (!conditionIsTrueConstant) { if (!conditionIsTrueConstant) {
builder.jumpOnFalse(loopInfo.getExitPoint(), expression, builder.getBoundValue(condition)); builder.jumpOnFalse(loopInfo.getExitPoint(), expression, builder.getBoundValue(condition));
} }
else {
assert condition != null : "Invalid while condition: " + expression.getText();
List<PseudoValue> values = ContainerUtil.createMaybeSingletonList(builder.getBoundValue(condition));
Map<PseudoValue, TypePredicate> typePredicates =
PseudocodePackage.expectedTypeFor(new SingleType(KotlinBuiltIns.getInstance().getBooleanType()), values);
builder.magic(condition, null, values, typePredicates, MagicKind.VALUE_CONSUMER);
}
builder.bindLabel(loopInfo.getBodyEntryPoint()); builder.bindLabel(loopInfo.getBodyEntryPoint());
JetExpression body = expression.getBody(); JetExpression body = expression.getBody();
@@ -16,14 +16,15 @@ L2 [loop entry point]:
L5 [condition entry point]: L5 [condition entry point]:
r(true) -> <v1> r(true) -> <v1>
mark(while (true) { val a: Int }) mark(while (true) { val a: Int })
magic[VALUE_CONSUMER](true|<v1>) -> <v2>
L4 [body entry point]: L4 [body entry point]:
3 mark({ val a: Int }) 3 mark({ val a: Int })
v(val a: Int) INIT: in: {} out: {a=D} v(val a: Int) INIT: in: {} out: {a=D}
2 jmp(L2 [loop entry point]) INIT: in: {} out: {} USE: in: {} out: {} 2 jmp(L2 [loop entry point]) INIT: in: {} out: {} USE: in: {} out: {}
L3 [loop exit point]: L3 [loop exit point]:
- read (Unit) - read (Unit) -> <v3>
- mark("after") - mark("after")
- r("after") -> <v2> - r("after") -> <v4>
L1: L1:
1 <END> INIT: in: {} out: {} 1 <END> INIT: in: {} out: {}
error: error:
@@ -7,8 +7,9 @@ fun foo() {
"after" "after"
} }
--------------------- ---------------------
"before" <v0>: * NEW: r("before") -> <v0> <v2>: * NEW: magic[VALUE_CONSUMER](true|<v1>) -> <v2>
true <v1>: * NEW: r(true) -> <v1> "before" <v0>: * NEW: r("before") -> <v0>
"after" <v2>: * NEW: r("after") -> <v2> true <v1>: Boolean NEW: r(true) -> <v1>
{ "before" while (true) { val a: Int } "after" } <v2>: * COPY "after" <v3>: * NEW: r("after") -> <v3>
{ "before" while (true) { val a: Int } "after" } <v3>: * COPY
===================== =====================
@@ -256,36 +256,37 @@ L2 [loop entry point]:
L5 [condition entry point]: L5 [condition entry point]:
r(true) -> <v0> PREV:[mark(@l while(true) { try { 1 if (2 > 3) { break @l } } finally { 2 } }), jmp(L2 [loop entry point])] r(true) -> <v0> PREV:[mark(@l while(true) { try { 1 if (2 > 3) { break @l } } finally { 2 } }), jmp(L2 [loop entry point])]
mark(while(true) { try { 1 if (2 > 3) { break @l } } finally { 2 } }) mark(while(true) { try { 1 if (2 > 3) { break @l } } finally { 2 } })
magic[VALUE_CONSUMER](true|<v0>) -> <v1>
L4 [body entry point]: L4 [body entry point]:
3 mark({ try { 1 if (2 > 3) { break @l } } finally { 2 } }) 3 mark({ try { 1 if (2 > 3) { break @l } } finally { 2 } })
mark(try { 1 if (2 > 3) { break @l } } finally { 2 }) mark(try { 1 if (2 > 3) { break @l } } finally { 2 })
jmp?(L6 [onExceptionToFinallyBlock]) NEXT:[mark({ 2 }), mark({ 1 if (2 > 3) { break @l } })] jmp?(L6 [onExceptionToFinallyBlock]) NEXT:[mark({ 2 }), mark({ 1 if (2 > 3) { break @l } })]
4 mark({ 1 if (2 > 3) { break @l } }) 4 mark({ 1 if (2 > 3) { break @l } })
r(1) -> <v1> r(1) -> <v2>
mark(if (2 > 3) { break @l }) mark(if (2 > 3) { break @l })
r(2) -> <v2> r(2) -> <v3>
r(3) -> <v3> r(3) -> <v4>
mark(2 > 3) mark(2 > 3)
call(2 > 3, compareTo|<v2>, <v3>) -> <v4> call(2 > 3, compareTo|<v3>, <v4>) -> <v5>
jf(L7|<v4>) NEXT:[read (Unit), mark({ break @l })] jf(L7|<v5>) NEXT:[read (Unit), mark({ break @l })]
5 mark({ break @l }) 5 mark({ break @l })
L8 [start finally]: L8 [start finally]:
6 mark({ 2 }) 6 mark({ 2 })
r(2) -> <v5> r(2) -> <v6>
L9 [finish finally]: L9 [finish finally]:
5 jmp(L3 [loop exit point]) NEXT:[read (Unit)] 5 jmp(L3 [loop exit point]) NEXT:[read (Unit)]
- 4 jmp(L10) NEXT:[jmp(L11 [skipFinallyToErrorBlock])] PREV:[] - 4 jmp(L10) NEXT:[jmp(L11 [skipFinallyToErrorBlock])] PREV:[]
L7: L7:
read (Unit) PREV:[jf(L7|<v4>)] read (Unit) PREV:[jf(L7|<v5>)]
L10: L10:
3 jmp(L11 [skipFinallyToErrorBlock]) NEXT:[mark({ 2 })] 3 jmp(L11 [skipFinallyToErrorBlock]) NEXT:[mark({ 2 })]
L6 [onExceptionToFinallyBlock]: L6 [onExceptionToFinallyBlock]:
6 mark({ 2 }) PREV:[jmp?(L6 [onExceptionToFinallyBlock])] 6 mark({ 2 }) PREV:[jmp?(L6 [onExceptionToFinallyBlock])]
r(2) -> <v5> r(2) -> <v6>
3 jmp(error) NEXT:[<ERROR>] 3 jmp(error) NEXT:[<ERROR>]
L11 [skipFinallyToErrorBlock]: L11 [skipFinallyToErrorBlock]:
6 mark({ 2 }) PREV:[jmp(L11 [skipFinallyToErrorBlock])] 6 mark({ 2 }) PREV:[jmp(L11 [skipFinallyToErrorBlock])]
r(2) -> <v5> r(2) -> <v6>
2 jmp(L2 [loop entry point]) NEXT:[r(true) -> <v0>] 2 jmp(L2 [loop entry point]) NEXT:[r(true) -> <v0>]
L3 [loop exit point]: L3 [loop exit point]:
read (Unit) PREV:[jmp(L3 [loop exit point])] read (Unit) PREV:[jmp(L3 [loop exit point])]
@@ -322,35 +323,36 @@ L3 [loop entry point]:
L6 [condition entry point]: L6 [condition entry point]:
r(true) -> <v0> PREV:[mark(@l while(true) { 1 if (2 > 3) { break @l } }), jmp(L3 [loop entry point])] r(true) -> <v0> PREV:[mark(@l while(true) { 1 if (2 > 3) { break @l } }), jmp(L3 [loop entry point])]
mark(while(true) { 1 if (2 > 3) { break @l } }) mark(while(true) { 1 if (2 > 3) { break @l } })
magic[VALUE_CONSUMER](true|<v0>) -> <v1>
L5 [body entry point]: L5 [body entry point]:
4 mark({ 1 if (2 > 3) { break @l } }) 4 mark({ 1 if (2 > 3) { break @l } })
r(1) -> <v1> r(1) -> <v2>
mark(if (2 > 3) { break @l }) mark(if (2 > 3) { break @l })
r(2) -> <v2> r(2) -> <v3>
r(3) -> <v3> r(3) -> <v4>
mark(2 > 3) mark(2 > 3)
call(2 > 3, compareTo|<v2>, <v3>) -> <v4> call(2 > 3, compareTo|<v3>, <v4>) -> <v5>
jf(L7|<v4>) NEXT:[read (Unit), mark({ break @l })] jf(L7|<v5>) NEXT:[read (Unit), mark({ break @l })]
5 mark({ break @l }) 5 mark({ break @l })
jmp(L4 [loop exit point]) NEXT:[read (Unit)] jmp(L4 [loop exit point]) NEXT:[read (Unit)]
- 4 jmp(L8) NEXT:[jmp(L3 [loop entry point])] PREV:[] - 4 jmp(L8) NEXT:[jmp(L3 [loop entry point])] PREV:[]
L7: L7:
read (Unit) PREV:[jf(L7|<v4>)] read (Unit) PREV:[jf(L7|<v5>)]
L8: L8:
3 jmp(L3 [loop entry point]) NEXT:[r(true) -> <v0>] 3 jmp(L3 [loop entry point]) NEXT:[r(true) -> <v0>]
L4 [loop exit point]: L4 [loop exit point]:
read (Unit) PREV:[jmp(L4 [loop exit point])] read (Unit) PREV:[jmp(L4 [loop exit point])]
r(5) -> <v5> r(5) -> <v6>
2 jmp(L9 [skipFinallyToErrorBlock]) NEXT:[mark({ 2 })] 2 jmp(L9 [skipFinallyToErrorBlock]) NEXT:[mark({ 2 })]
L2 [onExceptionToFinallyBlock]: L2 [onExceptionToFinallyBlock]:
L10 [start finally]: L10 [start finally]:
3 mark({ 2 }) PREV:[jmp?(L2 [onExceptionToFinallyBlock])] 3 mark({ 2 }) PREV:[jmp?(L2 [onExceptionToFinallyBlock])]
r(2) -> <v6> r(2) -> <v7>
L11 [finish finally]: L11 [finish finally]:
2 jmp(error) NEXT:[<ERROR>] 2 jmp(error) NEXT:[<ERROR>]
L9 [skipFinallyToErrorBlock]: L9 [skipFinallyToErrorBlock]:
3 mark({ 2 }) PREV:[jmp(L9 [skipFinallyToErrorBlock])] 3 mark({ 2 }) PREV:[jmp(L9 [skipFinallyToErrorBlock])]
r(2) -> <v6> r(2) -> <v7>
L1: L1:
1 <END> NEXT:[<SINK>] 1 <END> NEXT:[<SINK>]
error: error:
@@ -383,20 +385,21 @@ L3 [loop entry point]:
L6 [condition entry point]: L6 [condition entry point]:
r(true) -> <v0> PREV:[mark(@l while(true) { 1 if (2 > 3) { break @l } }), jmp(L3 [loop entry point])] r(true) -> <v0> PREV:[mark(@l while(true) { 1 if (2 > 3) { break @l } }), jmp(L3 [loop entry point])]
mark(while(true) { 1 if (2 > 3) { break @l } }) mark(while(true) { 1 if (2 > 3) { break @l } })
magic[VALUE_CONSUMER](true|<v0>) -> <v1>
L5 [body entry point]: L5 [body entry point]:
4 mark({ 1 if (2 > 3) { break @l } }) 4 mark({ 1 if (2 > 3) { break @l } })
r(1) -> <v1> r(1) -> <v2>
mark(if (2 > 3) { break @l }) mark(if (2 > 3) { break @l })
r(2) -> <v2> r(2) -> <v3>
r(3) -> <v3> r(3) -> <v4>
mark(2 > 3) mark(2 > 3)
call(2 > 3, compareTo|<v2>, <v3>) -> <v4> call(2 > 3, compareTo|<v3>, <v4>) -> <v5>
jf(L7|<v4>) NEXT:[read (Unit), mark({ break @l })] jf(L7|<v5>) NEXT:[read (Unit), mark({ break @l })]
5 mark({ break @l }) 5 mark({ break @l })
jmp(L4 [loop exit point]) NEXT:[read (Unit)] jmp(L4 [loop exit point]) NEXT:[read (Unit)]
- 4 jmp(L8) NEXT:[jmp(L3 [loop entry point])] PREV:[] - 4 jmp(L8) NEXT:[jmp(L3 [loop entry point])] PREV:[]
L7: L7:
read (Unit) PREV:[jf(L7|<v4>)] read (Unit) PREV:[jf(L7|<v5>)]
L8: L8:
3 jmp(L3 [loop entry point]) NEXT:[r(true) -> <v0>] 3 jmp(L3 [loop entry point]) NEXT:[r(true) -> <v0>]
L4 [loop exit point]: L4 [loop exit point]:
@@ -405,12 +408,12 @@ L4 [loop exit point]:
L2 [onExceptionToFinallyBlock]: L2 [onExceptionToFinallyBlock]:
L10 [start finally]: L10 [start finally]:
3 mark({ 2 }) PREV:[jmp?(L2 [onExceptionToFinallyBlock])] 3 mark({ 2 }) PREV:[jmp?(L2 [onExceptionToFinallyBlock])]
r(2) -> <v5> r(2) -> <v6>
L11 [finish finally]: L11 [finish finally]:
2 jmp(error) NEXT:[<ERROR>] 2 jmp(error) NEXT:[<ERROR>]
L9 [skipFinallyToErrorBlock]: L9 [skipFinallyToErrorBlock]:
3 mark({ 2 }) PREV:[jmp(L9 [skipFinallyToErrorBlock])] 3 mark({ 2 }) PREV:[jmp(L9 [skipFinallyToErrorBlock])]
r(2) -> <v5> r(2) -> <v6>
L1: L1:
1 <END> NEXT:[<SINK>] 1 <END> NEXT:[<SINK>]
error: error:
@@ -118,13 +118,14 @@ fun t5() {
} }
} }
--------------------- ---------------------
true <v0>: * NEW: r(true) -> <v0> <v1>: * NEW: magic[VALUE_CONSUMER](true|<v0>) -> <v1>
1 <v1>: * NEW: r(1) -> <v1> true <v0>: Boolean NEW: r(true) -> <v0>
2 <v2>: {<: Comparable<Int>} NEW: r(2) -> <v2> 1 <v2>: * NEW: r(1) -> <v2>
3 <v3>: Int NEW: r(3) -> <v3> 2 <v3>: {<: Comparable<Int>} NEW: r(2) -> <v3>
2 > 3 <v4>: Boolean NEW: call(2 > 3, compareTo|<v2>, <v3>) -> <v4> 3 <v4>: Int NEW: r(3) -> <v4>
2 <v5>: * NEW: r(2) -> <v5> 2 > 3 <v5>: Boolean NEW: call(2 > 3, compareTo|<v3>, <v4>) -> <v5>
{ 2 } <v5>: * COPY 2 <v6>: * NEW: r(2) -> <v6>
{ 2 } <v6>: * COPY
===================== =====================
== t6 == == t6 ==
fun t6() { fun t6() {
@@ -141,17 +142,18 @@ fun t6() {
} }
} }
--------------------- ---------------------
true <v0>: * NEW: r(true) -> <v0> <v1>: * NEW: magic[VALUE_CONSUMER](true|<v0>) -> <v1>
1 <v1>: * NEW: r(1) -> <v1> true <v0>: Boolean NEW: r(true) -> <v0>
2 <v2>: {<: Comparable<Int>} NEW: r(2) -> <v2> 1 <v2>: * NEW: r(1) -> <v2>
3 <v3>: Int NEW: r(3) -> <v3> 2 <v3>: {<: Comparable<Int>} NEW: r(2) -> <v3>
2 > 3 <v4>: Boolean NEW: call(2 > 3, compareTo|<v2>, <v3>) -> <v4> 3 <v4>: Int NEW: r(3) -> <v4>
5 <v5>: * NEW: r(5) -> <v5> 2 > 3 <v5>: Boolean NEW: call(2 > 3, compareTo|<v3>, <v4>) -> <v5>
{ @l while(true) { 1 if (2 > 3) { break @l } } 5 } <v5>: * COPY 5 <v6>: * NEW: r(5) -> <v6>
2 <v6>: * NEW: r(2) -> <v6> { @l while(true) { 1 if (2 > 3) { break @l } } 5 } <v6>: * COPY
{ 2 } <v6>: * COPY 2 <v7>: * NEW: r(2) -> <v7>
try { @l while(true) { 1 if (2 > 3) { break @l } } 5 } finally { 2 } <v5>: * COPY { 2 } <v7>: * COPY
{ try { @l while(true) { 1 if (2 > 3) { break @l } } 5 } finally { 2 } } <v5>: * COPY try { @l while(true) { 1 if (2 > 3) { break @l } } 5 } finally { 2 } <v6>: * COPY
{ try { @l while(true) { 1 if (2 > 3) { break @l } } 5 } finally { 2 } } <v6>: * COPY
===================== =====================
== t7 == == t7 ==
fun t7() { fun t7() {
@@ -167,13 +169,14 @@ fun t7() {
} }
} }
--------------------- ---------------------
true <v0>: * NEW: r(true) -> <v0> <v1>: * NEW: magic[VALUE_CONSUMER](true|<v0>) -> <v1>
1 <v1>: * NEW: r(1) -> <v1> true <v0>: Boolean NEW: r(true) -> <v0>
2 <v2>: {<: Comparable<Int>} NEW: r(2) -> <v2> 1 <v2>: * NEW: r(1) -> <v2>
3 <v3>: Int NEW: r(3) -> <v3> 2 <v3>: {<: Comparable<Int>} NEW: r(2) -> <v3>
2 > 3 <v4>: Boolean NEW: call(2 > 3, compareTo|<v2>, <v3>) -> <v4> 3 <v4>: Int NEW: r(3) -> <v4>
2 <v5>: * NEW: r(2) -> <v5> 2 > 3 <v5>: Boolean NEW: call(2 > 3, compareTo|<v3>, <v4>) -> <v5>
{ 2 } <v5>: * COPY 2 <v6>: * NEW: r(2) -> <v6>
{ 2 } <v6>: * COPY
===================== =====================
== t8 == == t8 ==
fun t8(a : Int) { fun t8(a : Int) {