C++, C# IR: Stabilize sort order for basic blocks.

This commit is contained in:
Cornelius Riemenschneider
2020-11-04 12:35:41 +01:00
parent 6ff939db5c
commit a13947424a
18 changed files with 213 additions and 127 deletions

View File

@@ -26,15 +26,6 @@ class IRBlockBase extends TIRBlock {
/** Gets the source location of the first non-`Phi` instruction in this block. */
final Language::Location getLocation() { result = getFirstInstruction().getLocation() }
/**
* INTERNAL: Do not use.
*
* Gets a string that uniquely identifies this block within its enclosing function.
*
* This predicate is used by debugging and printing code only.
*/
final string getUniqueId() { result = getFirstInstruction(this).getUniqueId() }
/**
* INTERNAL: Do not use.
*
@@ -47,14 +38,15 @@ class IRBlockBase extends TIRBlock {
config.shouldEvaluateDebugStringsForFunction(this.getEnclosingFunction())
) and
this =
rank[result + 1](IRBlock funcBlock, int sortOverride |
rank[result + 1](IRBlock funcBlock, int sortOverride, int sortKey1, int sortKey2 |
funcBlock.getEnclosingFunction() = getEnclosingFunction() and
funcBlock.getFirstInstruction().hasSortKeys(sortKey1, sortKey2) and
// Ensure that the block containing `EnterFunction` always comes first.
if funcBlock.getFirstInstruction() instanceof EnterFunctionInstruction
then sortOverride = 0
else sortOverride = 1
|
funcBlock order by sortOverride, funcBlock.getUniqueId()
funcBlock order by sortOverride, sortKey1, sortKey2
)
}

View File

@@ -171,6 +171,16 @@ class Instruction extends Construction::TStageInstruction {
*/
final string getUniqueId() { result = Construction::getInstructionUniqueId(this) }
/**
* INTERNAL: Do not use.
*
* Gets two sort keys for this instruction - used to order instructions for printing
* in test outputs.
*/
final predicate hasSortKeys(int key1, int key2) {
Construction::instructionHasSortKeys(this, key1, key2)
}
/**
* Gets the basic block that contains this instruction.
*/

View File

@@ -856,7 +856,7 @@ private module CachedForDebugging {
exists(Alias::MemoryLocation location, OldBlock phiBlock, string specificity |
instr = getPhi(phiBlock, location) and
result =
"Phi Block(" + phiBlock.getUniqueId() + ")[" + specificity + "]: " + location.getUniqueId() and
"Phi Block(" + phiBlock.getFirstInstruction().getUniqueId() + ")[" + specificity + "]: " + location.getUniqueId() and
if location instanceof Alias::VirtualVariable
then
// Sort Phi nodes for virtual variables before Phi nodes for member locations.
@@ -873,6 +873,24 @@ private module CachedForDebugging {
result.getAST() = var.getAST() and
result.getTag() = var.getTag()
}
cached
predicate instructionHasSortKeys(Instruction instr, int key1, int key2) {
exists(OldInstruction oldInstr |
oldInstr = getOldInstruction(instr) and
oldInstr.hasSortKeys(key1, key2)
)
or
instr instanceof TUnreachedInstruction and
key1 = maxValue() and
key2 = maxValue()
}
/**
* Returns the value of the maximum representable integer.
*/
cached
int maxValue() { result = 2147483647 }
}
module SSAConsistency {

View File

@@ -26,15 +26,6 @@ class IRBlockBase extends TIRBlock {
/** Gets the source location of the first non-`Phi` instruction in this block. */
final Language::Location getLocation() { result = getFirstInstruction().getLocation() }
/**
* INTERNAL: Do not use.
*
* Gets a string that uniquely identifies this block within its enclosing function.
*
* This predicate is used by debugging and printing code only.
*/
final string getUniqueId() { result = getFirstInstruction(this).getUniqueId() }
/**
* INTERNAL: Do not use.
*
@@ -47,14 +38,15 @@ class IRBlockBase extends TIRBlock {
config.shouldEvaluateDebugStringsForFunction(this.getEnclosingFunction())
) and
this =
rank[result + 1](IRBlock funcBlock, int sortOverride |
rank[result + 1](IRBlock funcBlock, int sortOverride, int sortKey1, int sortKey2 |
funcBlock.getEnclosingFunction() = getEnclosingFunction() and
funcBlock.getFirstInstruction().hasSortKeys(sortKey1, sortKey2) and
// Ensure that the block containing `EnterFunction` always comes first.
if funcBlock.getFirstInstruction() instanceof EnterFunctionInstruction
then sortOverride = 0
else sortOverride = 1
|
funcBlock order by sortOverride, funcBlock.getUniqueId()
funcBlock order by sortOverride, sortKey1, sortKey2
)
}

View File

@@ -171,6 +171,16 @@ class Instruction extends Construction::TStageInstruction {
*/
final string getUniqueId() { result = Construction::getInstructionUniqueId(this) }
/**
* INTERNAL: Do not use.
*
* Gets two sort keys for this instruction - used to order instructions for printing
* in test outputs.
*/
final predicate hasSortKeys(int key1, int key2) {
Construction::instructionHasSortKeys(this, key1, key2)
}
/**
* Gets the basic block that contains this instruction.
*/

View File

@@ -380,10 +380,21 @@ private module CachedForDebugging {
string getTempVariableUniqueId(IRTempVariable var) {
exists(TranslatedElement element |
var = element.getTempVariable(_) and
result = element.getId() + ":" + getTempVariableTagId(var.getTag())
result = element.getId().toString() + ":" + getTempVariableTagId(var.getTag())
)
}
cached
predicate instructionHasSortKeys(Instruction instruction, int key1, int key2) {
key1 = getInstructionTranslatedElement(instruction).getId() and
getInstructionTag(instruction) =
rank[key2](InstructionTag tag, string tagId |
tagId = getInstructionTagId(tag)
|
tag order by tagId
)
}
cached
string getInstructionUniqueId(Instruction instruction) {
result =

View File

@@ -752,10 +752,10 @@ abstract class TranslatedElement extends TTranslatedElement {
abstract TranslatedElement getChild(int id);
/**
* Gets the an identifier string for the element. This string is unique within
* Gets the an identifier string for the element. This id is unique within
* the scope of the element's function.
*/
final string getId() { result = getUniqueId().toString() }
final int getId() { result = getUniqueId() }
private TranslatedElement getChildByRank(int rankIndex) {
result =

View File

@@ -26,15 +26,6 @@ class IRBlockBase extends TIRBlock {
/** Gets the source location of the first non-`Phi` instruction in this block. */
final Language::Location getLocation() { result = getFirstInstruction().getLocation() }
/**
* INTERNAL: Do not use.
*
* Gets a string that uniquely identifies this block within its enclosing function.
*
* This predicate is used by debugging and printing code only.
*/
final string getUniqueId() { result = getFirstInstruction(this).getUniqueId() }
/**
* INTERNAL: Do not use.
*
@@ -47,14 +38,15 @@ class IRBlockBase extends TIRBlock {
config.shouldEvaluateDebugStringsForFunction(this.getEnclosingFunction())
) and
this =
rank[result + 1](IRBlock funcBlock, int sortOverride |
rank[result + 1](IRBlock funcBlock, int sortOverride, int sortKey1, int sortKey2 |
funcBlock.getEnclosingFunction() = getEnclosingFunction() and
funcBlock.getFirstInstruction().hasSortKeys(sortKey1, sortKey2) and
// Ensure that the block containing `EnterFunction` always comes first.
if funcBlock.getFirstInstruction() instanceof EnterFunctionInstruction
then sortOverride = 0
else sortOverride = 1
|
funcBlock order by sortOverride, funcBlock.getUniqueId()
funcBlock order by sortOverride, sortKey1, sortKey2
)
}

View File

@@ -171,6 +171,16 @@ class Instruction extends Construction::TStageInstruction {
*/
final string getUniqueId() { result = Construction::getInstructionUniqueId(this) }
/**
* INTERNAL: Do not use.
*
* Gets two sort keys for this instruction - used to order instructions for printing
* in test outputs.
*/
final predicate hasSortKeys(int key1, int key2) {
Construction::instructionHasSortKeys(this, key1, key2)
}
/**
* Gets the basic block that contains this instruction.
*/

View File

@@ -856,7 +856,7 @@ private module CachedForDebugging {
exists(Alias::MemoryLocation location, OldBlock phiBlock, string specificity |
instr = getPhi(phiBlock, location) and
result =
"Phi Block(" + phiBlock.getUniqueId() + ")[" + specificity + "]: " + location.getUniqueId() and
"Phi Block(" + phiBlock.getFirstInstruction().getUniqueId() + ")[" + specificity + "]: " + location.getUniqueId() and
if location instanceof Alias::VirtualVariable
then
// Sort Phi nodes for virtual variables before Phi nodes for member locations.
@@ -873,6 +873,24 @@ private module CachedForDebugging {
result.getAST() = var.getAST() and
result.getTag() = var.getTag()
}
cached
predicate instructionHasSortKeys(Instruction instr, int key1, int key2) {
exists(OldInstruction oldInstr |
oldInstr = getOldInstruction(instr) and
oldInstr.hasSortKeys(key1, key2)
)
or
instr instanceof TUnreachedInstruction and
key1 = maxValue() and
key2 = maxValue()
}
/**
* Returns the value of the maximum representable integer.
*/
cached
int maxValue() { result = 2147483647 }
}
module SSAConsistency {

View File

@@ -26,15 +26,6 @@ class IRBlockBase extends TIRBlock {
/** Gets the source location of the first non-`Phi` instruction in this block. */
final Language::Location getLocation() { result = getFirstInstruction().getLocation() }
/**
* INTERNAL: Do not use.
*
* Gets a string that uniquely identifies this block within its enclosing function.
*
* This predicate is used by debugging and printing code only.
*/
final string getUniqueId() { result = getFirstInstruction(this).getUniqueId() }
/**
* INTERNAL: Do not use.
*
@@ -47,14 +38,15 @@ class IRBlockBase extends TIRBlock {
config.shouldEvaluateDebugStringsForFunction(this.getEnclosingFunction())
) and
this =
rank[result + 1](IRBlock funcBlock, int sortOverride |
rank[result + 1](IRBlock funcBlock, int sortOverride, int sortKey1, int sortKey2 |
funcBlock.getEnclosingFunction() = getEnclosingFunction() and
funcBlock.getFirstInstruction().hasSortKeys(sortKey1, sortKey2) and
// Ensure that the block containing `EnterFunction` always comes first.
if funcBlock.getFirstInstruction() instanceof EnterFunctionInstruction
then sortOverride = 0
else sortOverride = 1
|
funcBlock order by sortOverride, funcBlock.getUniqueId()
funcBlock order by sortOverride, sortKey1, sortKey2
)
}

View File

@@ -171,6 +171,16 @@ class Instruction extends Construction::TStageInstruction {
*/
final string getUniqueId() { result = Construction::getInstructionUniqueId(this) }
/**
* INTERNAL: Do not use.
*
* Gets two sort keys for this instruction - used to order instructions for printing
* in test outputs.
*/
final predicate hasSortKeys(int key1, int key2) {
Construction::instructionHasSortKeys(this, key1, key2)
}
/**
* Gets the basic block that contains this instruction.
*/

View File

@@ -411,10 +411,21 @@ private module CachedForDebugging {
string getTempVariableUniqueId(IRTempVariable var) {
exists(TranslatedElement element |
var = element.getTempVariable(_) and
result = element.getId() + ":" + getTempVariableTagId(var.getTag())
result = element.getId().toString() + ":" + getTempVariableTagId(var.getTag())
)
}
cached
predicate instructionHasSortKeys(Instruction instruction, int key1, int key2) {
key1 = getInstructionTranslatedElement(instruction).getId() and
getInstructionTag(instruction) =
rank[key2](InstructionTag tag, string tagId |
tagId = getInstructionTagId(tag)
|
tag order by tagId
)
}
cached
string getInstructionUniqueId(Instruction instruction) {
result =

View File

@@ -384,10 +384,10 @@ abstract class TranslatedElement extends TTranslatedElement {
abstract TranslatedElement getChild(int id);
/**
* Gets the an identifier string for the element. This string is unique within
* Gets the an identifier string for the element. This id is unique within
* the scope of the element's function.
*/
final string getId() { result = this.getUniqueId().toString() }
int getId() { result = this.getUniqueId() }
private TranslatedElement getChildByRank(int rankIndex) {
result =

View File

@@ -26,15 +26,6 @@ class IRBlockBase extends TIRBlock {
/** Gets the source location of the first non-`Phi` instruction in this block. */
final Language::Location getLocation() { result = getFirstInstruction().getLocation() }
/**
* INTERNAL: Do not use.
*
* Gets a string that uniquely identifies this block within its enclosing function.
*
* This predicate is used by debugging and printing code only.
*/
final string getUniqueId() { result = getFirstInstruction(this).getUniqueId() }
/**
* INTERNAL: Do not use.
*
@@ -47,14 +38,15 @@ class IRBlockBase extends TIRBlock {
config.shouldEvaluateDebugStringsForFunction(this.getEnclosingFunction())
) and
this =
rank[result + 1](IRBlock funcBlock, int sortOverride |
rank[result + 1](IRBlock funcBlock, int sortOverride, int sortKey1, int sortKey2 |
funcBlock.getEnclosingFunction() = getEnclosingFunction() and
funcBlock.getFirstInstruction().hasSortKeys(sortKey1, sortKey2) and
// Ensure that the block containing `EnterFunction` always comes first.
if funcBlock.getFirstInstruction() instanceof EnterFunctionInstruction
then sortOverride = 0
else sortOverride = 1
|
funcBlock order by sortOverride, funcBlock.getUniqueId()
funcBlock order by sortOverride, sortKey1, sortKey2
)
}

View File

@@ -171,6 +171,16 @@ class Instruction extends Construction::TStageInstruction {
*/
final string getUniqueId() { result = Construction::getInstructionUniqueId(this) }
/**
* INTERNAL: Do not use.
*
* Gets two sort keys for this instruction - used to order instructions for printing
* in test outputs.
*/
final predicate hasSortKeys(int key1, int key2) {
Construction::instructionHasSortKeys(this, key1, key2)
}
/**
* Gets the basic block that contains this instruction.
*/

View File

@@ -856,7 +856,7 @@ private module CachedForDebugging {
exists(Alias::MemoryLocation location, OldBlock phiBlock, string specificity |
instr = getPhi(phiBlock, location) and
result =
"Phi Block(" + phiBlock.getUniqueId() + ")[" + specificity + "]: " + location.getUniqueId() and
"Phi Block(" + phiBlock.getFirstInstruction().getUniqueId() + ")[" + specificity + "]: " + location.getUniqueId() and
if location instanceof Alias::VirtualVariable
then
// Sort Phi nodes for virtual variables before Phi nodes for member locations.
@@ -873,6 +873,24 @@ private module CachedForDebugging {
result.getAST() = var.getAST() and
result.getTag() = var.getTag()
}
cached
predicate instructionHasSortKeys(Instruction instr, int key1, int key2) {
exists(OldInstruction oldInstr |
oldInstr = getOldInstruction(instr) and
oldInstr.hasSortKeys(key1, key2)
)
or
instr instanceof TUnreachedInstruction and
key1 = maxValue() and
key2 = maxValue()
}
/**
* Returns the value of the maximum representable integer.
*/
cached
int maxValue() { result = 2147483647 }
}
module SSAConsistency {

View File

@@ -1018,87 +1018,95 @@ jumps.cs:
# 7| r7_1(glval<Int32>) = VariableAddress[i] :
# 7| r7_2(Int32) = Constant[1] :
# 7| mu7_3(Int32) = Store[i] : &:r7_1, r7_2
#-----| Goto -> Block 1
#-----| Goto -> Block 2
# 7| Block 1
# 7| r7_4(glval<Int32>) = VariableAddress[i] :
# 7| r7_5(Int32) = Load[i] : &:r7_4, ~m?
# 7| r7_6(Int32) = Constant[10] :
# 7| r7_7(Boolean) = CompareLE : r7_5, r7_6
# 7| v7_8(Void) = ConditionalBranch : r7_7
#-----| False -> Block 7
#-----| True -> Block 2
# 7| r7_6(Int32) = Constant[1] :
# 7| r7_7(Int32) = Add : r7_5, r7_6
# 7| mu7_8(Int32) = Store[i] : &:r7_4, r7_7
#-----| Goto (back edge) -> Block 2
# 9| Block 2
# 7| Block 2
# 7| r7_9(glval<Int32>) = VariableAddress[i] :
# 7| r7_10(Int32) = Load[i] : &:r7_9, ~m?
# 7| r7_11(Int32) = Constant[10] :
# 7| r7_12(Boolean) = CompareLE : r7_10, r7_11
# 7| v7_13(Void) = ConditionalBranch : r7_12
#-----| False -> Block 8
#-----| True -> Block 3
# 9| Block 3
# 9| r9_1(glval<Int32>) = VariableAddress[i] :
# 9| r9_2(Int32) = Load[i] : &:r9_1, ~m?
# 9| r9_3(Int32) = Constant[3] :
# 9| r9_4(Boolean) = CompareEQ : r9_2, r9_3
# 9| v9_5(Void) = ConditionalBranch : r9_4
#-----| False -> Block 4
#-----| True -> Block 3
#-----| False -> Block 5
#-----| True -> Block 4
# 10| Block 3
# 10| Block 4
# 10| v10_1(Void) = NoOp :
#-----| Goto -> Block 19
#-----| Goto -> Block 1
# 11| Block 4
# 11| Block 5
# 11| r11_1(glval<Int32>) = VariableAddress[i] :
# 11| r11_2(Int32) = Load[i] : &:r11_1, ~m?
# 11| r11_3(Int32) = Constant[5] :
# 11| r11_4(Boolean) = CompareEQ : r11_2, r11_3
# 11| v11_5(Void) = ConditionalBranch : r11_4
#-----| False -> Block 6
#-----| True -> Block 5
#-----| False -> Block 7
#-----| True -> Block 6
# 12| Block 5
# 12| Block 6
# 12| v12_1(Void) = NoOp :
#-----| Goto -> Block 7
#-----| Goto -> Block 8
# 13| Block 6
# 13| Block 7
# 13| r13_1(<funcaddr>) = FunctionAddress[WriteLine] :
# 13| r13_2(String) = StringConstant["BreakAndContinue"] :
# 13| v13_3(Void) = Call[WriteLine] : func:r13_1, 0:r13_2
# 13| mu13_4(<unknown>) = ^CallSideEffect : ~m?
#-----| Goto -> Block 19
#-----| Goto -> Block 1
# 16| Block 7
# 16| Block 8
# 16| r16_1(glval<Int32>) = VariableAddress[i] :
# 16| r16_2(Int32) = Constant[0] :
# 16| mu16_3(Int32) = Store[i] : &:r16_1, r16_2
#-----| Goto -> Block 8
#-----| Goto -> Block 9
# 16| Block 8
# 16| Block 9
# 16| r16_4(glval<Int32>) = VariableAddress[i] :
# 16| r16_5(Int32) = Load[i] : &:r16_4, ~m?
# 16| r16_6(Int32) = Constant[10] :
# 16| r16_7(Boolean) = CompareLT : r16_5, r16_6
# 16| v16_8(Void) = ConditionalBranch : r16_7
#-----| False -> Block 10
#-----| True -> Block 9
#-----| False -> Block 11
#-----| True -> Block 10
# 18| Block 9
# 18| Block 10
# 18| r18_1(glval<Int32>) = VariableAddress[i] :
# 18| r18_2(Int32) = Load[i] : &:r18_1, ~m?
# 18| r18_3(Int32) = Constant[1] :
# 18| r18_4(Int32) = Add : r18_2, r18_3
# 18| mu18_5(Int32) = Store[i] : &:r18_1, r18_4
# 19| v19_1(Void) = NoOp :
#-----| Goto (back edge) -> Block 8
#-----| Goto (back edge) -> Block 9
# 22| Block 10
# 22| Block 11
# 22| r22_1(glval<Int32>) = VariableAddress[a] :
# 22| r22_2(Int32) = Constant[0] :
# 22| mu22_3(Int32) = Store[a] : &:r22_1, r22_2
#-----| Goto -> Block 11
#-----| Goto -> Block 12
# 23| Block 11
# 23| Block 12
# 23| r23_1(Boolean) = Constant[true] :
# 23| v23_2(Void) = ConditionalBranch : r23_1
#-----| False -> Block 16
#-----| True -> Block 12
#-----| False -> Block 17
#-----| True -> Block 13
# 25| Block 12
# 25| Block 13
# 25| r25_1(glval<Int32>) = VariableAddress[a] :
# 25| r25_2(Int32) = Load[a] : &:r25_1, ~m?
# 25| r25_3(Int32) = Constant[1] :
@@ -1109,41 +1117,41 @@ jumps.cs:
# 26| r26_3(Int32) = Constant[5] :
# 26| r26_4(Boolean) = CompareEQ : r26_2, r26_3
# 26| v26_5(Void) = ConditionalBranch : r26_4
#-----| False -> Block 14
#-----| True -> Block 13
#-----| False -> Block 15
#-----| True -> Block 14
# 27| Block 13
# 27| Block 14
# 27| v27_1(Void) = NoOp :
#-----| Goto (back edge) -> Block 11
#-----| Goto (back edge) -> Block 12
# 28| Block 14
# 28| Block 15
# 28| r28_1(glval<Int32>) = VariableAddress[a] :
# 28| r28_2(Int32) = Load[a] : &:r28_1, ~m?
# 28| r28_3(Int32) = Constant[10] :
# 28| r28_4(Boolean) = CompareEQ : r28_2, r28_3
# 28| v28_5(Void) = ConditionalBranch : r28_4
#-----| False (back edge) -> Block 11
#-----| True -> Block 15
#-----| False (back edge) -> Block 12
#-----| True -> Block 16
# 29| Block 15
# 29| Block 16
# 29| v29_1(Void) = NoOp :
#-----| Goto -> Block 16
#-----| Goto -> Block 17
# 32| Block 16
# 32| Block 17
# 32| r32_1(glval<Int32>) = VariableAddress[i] :
# 32| r32_2(Int32) = Constant[1] :
# 32| mu32_3(Int32) = Store[i] : &:r32_1, r32_2
#-----| Goto -> Block 18
#-----| Goto -> Block 19
# 32| Block 17
# 32| Block 18
# 32| r32_4(glval<Int32>) = VariableAddress[i] :
# 32| r32_5(Int32) = Load[i] : &:r32_4, ~m?
# 32| r32_6(Int32) = Constant[1] :
# 32| r32_7(Int32) = Add : r32_5, r32_6
# 32| mu32_8(Int32) = Store[i] : &:r32_4, r32_7
#-----| Goto (back edge) -> Block 18
#-----| Goto (back edge) -> Block 19
# 32| Block 18
# 32| Block 19
# 32| r32_9(glval<Int32>) = VariableAddress[i] :
# 32| r32_10(Int32) = Load[i] : &:r32_9, ~m?
# 32| r32_11(Int32) = Constant[10] :
@@ -1152,21 +1160,13 @@ jumps.cs:
#-----| False -> Block 22
#-----| True -> Block 20
# 7| Block 19
# 7| r7_9(glval<Int32>) = VariableAddress[i] :
# 7| r7_10(Int32) = Load[i] : &:r7_9, ~m?
# 7| r7_11(Int32) = Constant[1] :
# 7| r7_12(Int32) = Add : r7_10, r7_11
# 7| mu7_13(Int32) = Store[i] : &:r7_9, r7_12
#-----| Goto (back edge) -> Block 1
# 34| Block 20
# 34| r34_1(glval<Int32>) = VariableAddress[i] :
# 34| r34_2(Int32) = Load[i] : &:r34_1, ~m?
# 34| r34_3(Int32) = Constant[5] :
# 34| r34_4(Boolean) = CompareEQ : r34_2, r34_3
# 34| v34_5(Void) = ConditionalBranch : r34_4
#-----| False -> Block 17
#-----| False -> Block 18
#-----| True -> Block 21
# 35| Block 21
@@ -1562,8 +1562,8 @@ stmts.cs:
# 7| r7_3(Int32) = Constant[5] :
# 7| r7_4(Boolean) = CompareEQ : r7_2, r7_3
# 7| v7_5(Void) = ConditionalBranch : r7_4
#-----| False -> Block 2
#-----| True -> Block 3
#-----| False -> Block 3
#-----| True -> Block 2
# 5| Block 1
# 5| r5_5(glval<Int32>) = VariableAddress[#return] :
@@ -1571,18 +1571,18 @@ stmts.cs:
# 5| v5_7(Void) = AliasedUse : ~m?
# 5| v5_8(Void) = ExitFunction :
# 10| Block 2
# 10| r10_1(glval<Int32>) = VariableAddress[#return] :
# 10| r10_2(Int32) = Constant[1] :
# 10| mu10_3(Int32) = Store[#return] : &:r10_1, r10_2
#-----| Goto -> Block 1
# 8| Block 3
# 8| Block 2
# 8| r8_1(glval<Int32>) = VariableAddress[#return] :
# 8| r8_2(Int32) = Constant[0] :
# 8| mu8_3(Int32) = Store[#return] : &:r8_1, r8_2
#-----| Goto -> Block 1
# 10| Block 3
# 10| r10_1(glval<Int32>) = VariableAddress[#return] :
# 10| r10_2(Int32) = Constant[1] :
# 10| mu10_3(Int32) = Store[#return] : &:r10_1, r10_2
#-----| Goto -> Block 1
# 13| System.Void test_stmts.whileStmt(System.Int32)
# 13| Block 0
# 13| v13_1(Void) = EnterFunction :