Commit 9bcf64aa authored by Kunshan Wang's avatar Kunshan Wang

Fixed phi-nodes and landingpads.

Phi-nodes and landingpads, which are now collectively called
"edge-assigned" instructions, in the basic block are now evaluated
together in the loop backedge rather than evaluated one at a time. This
mirrors the LLVM's behaviour.
parent ca9e751e
...@@ -44,17 +44,17 @@ class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: Interpreter ...@@ -44,17 +44,17 @@ class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: Interpreter
/** Write the return value of futex. May be written from FutexManager */ /** Write the return value of futex. May be written from FutexManager */
def futexReturn(rv: Int): Unit = { def futexReturn(rv: Int): Unit = {
// val validInst = curInst match { // val validInst = curInst match {
// case ci: InstCommInst => ci.inst.name.get match { // case ci: InstCommInst => ci.inst.name.get match {
// case "@uvm.futex.wait" => true // case "@uvm.futex.wait" => true
// case "@uvm.futex.wait_timeout" => true // case "@uvm.futex.wait_timeout" => true
// case _ => false // case _ => false
// } // }
// case _ => false // case _ => false
// } // }
// //
// if (!validInst) throw new UvmRefImplException(ctx + "The current instruction is not @uvm.futex.wait or wait_timeout.") // if (!validInst) throw new UvmRefImplException(ctx + "The current instruction is not @uvm.futex.wait or wait_timeout.")
// //
logger.debug(ctx + "Setting futex return value") logger.debug(ctx + "Setting futex return value")
writeIntResult(32, rv, boxOf(curInst)) writeIntResult(32, rv, boxOf(curInst))
continueNormally() continueNormally()
...@@ -81,6 +81,12 @@ class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: Interpreter ...@@ -81,6 +81,12 @@ class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: Interpreter
/** Get the value box of an SSA variable in the current stack. */ /** Get the value box of an SSA variable in the current stack. */
private def boxOf(v: SSAVariable): ValueBox = boxOf(curStack, v) private def boxOf(v: SSAVariable): ValueBox = boxOf(curStack, v)
/** Get the edge-assigned value box of an edge-assigned instruction in a stack. */
private def edgeAssignedBoxOf(s: InterpreterStack, ea: EdgeAssigned): ValueBox = s.top.edgeAssignedBoxes(ea)
/** Get the edge-assigned value box of an edge-assigned instruction in the current stack. */
private def edgeAssignedBoxOf(ea: EdgeAssigned): ValueBox = edgeAssignedBoxOf(curStack, ea)
// Context printing for debugging // Context printing for debugging
/** Make a string to identify the current function version, basic block and instruction for debugging. */ /** Make a string to identify the current function version, basic block and instruction for debugging. */
...@@ -1005,6 +1011,8 @@ class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: Interpreter ...@@ -1005,6 +1011,8 @@ class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: Interpreter
val curBB = this.curBB val curBB = this.curBB
var cont = true var cont = true
var i = 0 var i = 0
// Determine the value of edge-assigned instructions (phis and landingpads), but keep them in their temporary boxes.
while (cont) { while (cont) {
dest.insts(i) match { dest.insts(i) match {
case phi @ InstPhi(opndTy, cases) => { case phi @ InstPhi(opndTy, cases) => {
...@@ -1012,18 +1020,28 @@ class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: Interpreter ...@@ -1012,18 +1020,28 @@ class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: Interpreter
throw new UvmRuntimeException(s"Phi node ${phi.repr} does not include the case for source basic block ${curBB.repr}") throw new UvmRuntimeException(s"Phi node ${phi.repr} does not include the case for source basic block ${curBB.repr}")
} }
val vb = boxOf(caseVal) val vb = boxOf(caseVal)
val db = boxOf(phi) val db = edgeAssignedBoxOf(phi)
db.copyFrom(vb) db.copyFrom(vb)
i += 1 i += 1
} }
case lp: InstLandingPad => { case lp: InstLandingPad => {
val db = boxOf(lp).asInstanceOf[BoxRef] val db = edgeAssignedBoxOf(lp).asInstanceOf[BoxRef]
db.objRef = excAddr db.objRef = excAddr
i += 1 i += 1
} }
case _ => cont = false case _ => cont = false
} }
} }
// Copy the values of edge-assigned instructions (phis and landingpads) to their canonical boxes.
for (j <- 0 until i) {
val destInst = dest.insts(j)
val sb = edgeAssignedBoxOf(destInst.asInstanceOf[EdgeAssigned])
val db = boxOf(destInst)
db.copyFrom(sb)
}
// Continue execution
jump(dest, i) jump(dest, i)
} }
......
...@@ -56,6 +56,9 @@ class InterpreterStack(val id: Int, val stackMemory: StackMemory, stackBottomFun ...@@ -56,6 +56,9 @@ class InterpreterStack(val id: Int, val stackMemory: StackMemory, stackBottomFun
class InterpreterFrame(val funcVer: FuncVer, val prev: Option[InterpreterFrame]) { class InterpreterFrame(val funcVer: FuncVer, val prev: Option[InterpreterFrame]) {
val boxes = new HashMap[LocalVariable, ValueBox]() val boxes = new HashMap[LocalVariable, ValueBox]()
/** Edge-assigned instructions take values determined at look backedges */
val edgeAssignedBoxes = new HashMap[EdgeAssigned, ValueBox]()
/** Current basic block */ /** Current basic block */
var curBB: BasicBlock = funcVer.entry var curBB: BasicBlock = funcVer.entry
...@@ -101,6 +104,9 @@ class InterpreterFrame(val funcVer: FuncVer, val prev: Option[InterpreterFrame]) ...@@ -101,6 +104,9 @@ class InterpreterFrame(val funcVer: FuncVer, val prev: Option[InterpreterFrame])
private def putBox(lv: LocalVariable) { private def putBox(lv: LocalVariable) {
val ty = TypeInferer.inferType(lv) val ty = TypeInferer.inferType(lv)
boxes.put(lv, ValueBox.makeBoxForType(ty)) boxes.put(lv, ValueBox.makeBoxForType(ty))
if (lv.isInstanceOf[EdgeAssigned]) {
edgeAssignedBoxes.put(lv.asInstanceOf[EdgeAssigned], ValueBox.makeBoxForType(ty))
}
} }
def curInst: Instruction = try { def curInst: Instruction = try {
......
...@@ -148,6 +148,12 @@ case class PassValue(var argTy: Type, var arg: SSAVariable) extends NewStackActi ...@@ -148,6 +148,12 @@ case class PassValue(var argTy: Type, var arg: SSAVariable) extends NewStackActi
case class PassVoid() extends NewStackAction case class PassVoid() extends NewStackAction
case class ThrowExc(var exc: SSAVariable) extends NewStackAction case class ThrowExc(var exc: SSAVariable) extends NewStackAction
/**
* An EdgeAssigned instruction is evaluated at control flow edges rather than sequentially when the PC
* reaches that instruction. Currently PHI and LANDINGPAD are the only two such instructions.
*/
trait EdgeAssigned extends Instruction
/// Concrete instructions /// Concrete instructions
case class InstBinOp(var op: BinOptr, var opndTy: Type, var op1: SSAVariable, var op2: SSAVariable, case class InstBinOp(var op: BinOptr, var opndTy: Type, var op1: SSAVariable, var op2: SSAVariable,
var excClause: Option[ExcClause]) extends HasExcClause var excClause: Option[ExcClause]) extends HasExcClause
...@@ -166,7 +172,7 @@ case class InstBranch2(var cond: SSAVariable, var ifTrue: BasicBlock, var ifFals ...@@ -166,7 +172,7 @@ case class InstBranch2(var cond: SSAVariable, var ifTrue: BasicBlock, var ifFals
case class InstSwitch(var opndTy: Type, var opnd: SSAVariable, var defDest: BasicBlock, case class InstSwitch(var opndTy: Type, var opnd: SSAVariable, var defDest: BasicBlock,
var cases: Seq[(SSAVariable, BasicBlock)]) extends Instruction var cases: Seq[(SSAVariable, BasicBlock)]) extends Instruction
case class InstPhi(var opndTy: Type, var cases: Seq[(BasicBlock, SSAVariable)]) extends Instruction case class InstPhi(var opndTy: Type, var cases: Seq[(BasicBlock, SSAVariable)]) extends Instruction with EdgeAssigned
case class InstCall(var sig: FuncSig, var callee: SSAVariable, var argList: Seq[SSAVariable], case class InstCall(var sig: FuncSig, var callee: SSAVariable, var argList: Seq[SSAVariable],
var excClause: Option[ExcClause], var keepAlives: Seq[LocalVariable] var excClause: Option[ExcClause], var keepAlives: Seq[LocalVariable]
...@@ -180,7 +186,7 @@ case class InstRetVoid() extends AbstractRet ...@@ -180,7 +186,7 @@ case class InstRetVoid() extends AbstractRet
case class InstThrow(var excVal: SSAVariable) extends Instruction case class InstThrow(var excVal: SSAVariable) extends Instruction
case class InstLandingPad() extends Instruction case class InstLandingPad() extends Instruction with EdgeAssigned
case class InstExtractValue(var strTy: TypeStruct, var index: Int, var opnd: SSAVariable) extends Instruction case class InstExtractValue(var strTy: TypeStruct, var index: Int, var opnd: SSAVariable) extends Instruction
......
...@@ -706,6 +706,23 @@ class UvmInterpreterSpec extends UvmBundleTesterBase { ...@@ -706,6 +706,23 @@ class UvmInterpreterSpec extends UvmBundleTesterBase {
ca.close() ca.close()
} }
"PHI instructions in a basic block" should "be assigned at the same time in CFG edges" in {
val ca = microVM.newClientAgent()
val func = ca.putFunction("@phi_cyclic_dep_test")
testFunc(ca, func, Seq()) { (ca, th, st, wp) =>
val Seq(x, y) = ca.dumpKeepalives(st, 0)
ca.toInt(x, signExt=true) shouldEqual 2
ca.toInt(y, signExt=true) shouldEqual 1
TrapRebindPassVoid(st)
}
ca.close()
}
"CALL and RET" should "work for normal returns" in { "CALL and RET" should "work for normal returns" in {
val ca = microVM.newClientAgent() val ca = microVM.newClientAgent()
......
...@@ -408,6 +408,23 @@ ...@@ -408,6 +408,23 @@
COMMINST @uvm.thread_exit COMMINST @uvm.thread_exit
} }
.funcdef @phi_cyclic_dep_test VERSION @phi_cyclic_dep_test_v1 <@noparamsnoret> () {
%entry:
BRANCH %head
%head:
%x = PHI <@i64> { %entry: @I64_1; %head: %y; }
%y = PHI <@i64> { %entry: @I64_2; %head: %x; }
%i = PHI <@i64> { %entry: @I64_0; %head: %i2; }
%i2 = ADD <@i64> %i @I64_1
%lt = SLT <@i64> %i @I64_1
BRANCH2 %lt %head %end
%end:
%trap = TRAP <@void> KEEPALIVE (%x %y)
COMMINST @uvm.thread_exit
}
.funcdef @square_sum VERSION @square_sum_v1 <@i_ii> (%a %b) { .funcdef @square_sum VERSION @square_sum_v1 <@i_ii> (%a %b) {
%entry: %entry:
%a2 = MUL <@i64> %a %a %a2 = MUL <@i64> %a %a
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment