Commit b80efcce authored by Kunshan Wang's avatar Kunshan Wang

CALL, RET and some fac and fib programs.

parent 952d4eea
...@@ -57,8 +57,6 @@ class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: Interpreter ...@@ -57,8 +57,6 @@ class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: Interpreter
} }
private def interpretCurrentInstruction(): Unit = try { private def interpretCurrentInstruction(): Unit = try {
val curInst = this.curInst
logger.debug(ctx + "Executing instruction...") logger.debug(ctx + "Executing instruction...")
curInst match { curInst match {
...@@ -345,13 +343,50 @@ class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: Interpreter ...@@ -345,13 +343,50 @@ class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: Interpreter
val dest = cases.find(pair => boxOf(pair._1).asInstanceOf[BoxInt].value == ov).map(_._2).getOrElse(defDest) val dest = cases.find(pair => boxOf(pair._1).asInstanceOf[BoxInt].value == ov).map(_._2).getOrElse(defDest)
branchAndMovePC(dest) branchAndMovePC(dest)
} }
case _ => throw new UvmRefImplException("Operand type must be integer. %s found.".format(opndTy)) case _ => throw new UvmRefImplException(ctx + "Operand type must be integer. %s found.".format(opndTy))
} }
} }
case i @ InstPhi(_, _) => throw new UvmRefImplException("PHI instructions reached in normal execution, " + case i @ InstPhi(_, _) => throw new UvmRefImplException(ctx + "PHI instructions reached in normal execution, " +
"but PHI must only appear in the beginning of basic blocks and not in the entry block.") "but PHI must only appear in the beginning of basic blocks and not in the entry block.")
case i @ InstCall(sig, callee, argList, excClause, keepAlives) => {
val calleeFunc = boxOf(callee).asInstanceOf[BoxFunc].func.getOrElse {
throw new UvmRuntimeException(ctx + "Callee must not be NULL")
}
val funcVer = getFuncDefOrTriggerCallback(calleeFunc)
val argBoxes = argList.map(boxOf)
curStack.pushFrame(funcVer, argBoxes)
}
case i @ InstTailCall(sig, callee, argList) => {
val calleeFunc = boxOf(callee).asInstanceOf[BoxFunc].func.getOrElse {
throw new UvmRuntimeException(ctx + "Callee must not be NULL")
}
val funcVer = getFuncDefOrTriggerCallback(calleeFunc)
val argBoxes = argList.map(boxOf)
curStack.replaceTop(funcVer, argBoxes)
}
case i @ InstRet(retTy, retVal) => {
val rvb = boxOf(retVal)
curStack.popFrame()
val newCurInst = curInst // in the parent frame of the RET
boxOf(newCurInst).copyFrom(rvb)
continueNormally()
}
case i @ InstRetVoid() => {
curStack.popFrame()
continueNormally()
}
// Indentation guide: Insert more instructions here. // Indentation guide: Insert more instructions here.
case i @ InstTrap(retTy, excClause, keepAlives) => { case i @ InstTrap(retTy, excClause, keepAlives) => {
...@@ -406,7 +441,7 @@ class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: Interpreter ...@@ -406,7 +441,7 @@ class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: Interpreter
} }
} catch { } catch {
case e: Exception => { case e: Exception => {
logger.debug(ctx + "Exception thrown while interpreting instruction.") logger.error(ctx + "Exception thrown while interpreting instruction.")
throw e throw e
} }
} }
...@@ -531,8 +566,20 @@ class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: Interpreter ...@@ -531,8 +566,20 @@ class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: Interpreter
case i: InstWatchPoint => i.exc case i: InstWatchPoint => i.exc
case i: InstSwapStack => i.excClause.map(_.exc) case i: InstSwapStack => i.excClause.map(_.exc)
case _ => { case _ => {
throw new UvmRefImplException("Instruction %s (%s) is in a stack frame when an exception is thrown.".format(inst.repr, inst.getClass.getName)) throw new UvmRefImplException(ctx + "Instruction %s (%s) is in a stack frame when an exception is thrown.".format(inst.repr, inst.getClass.getName))
} }
} }
} }
@tailrec
private def getFuncDefOrTriggerCallback(f: Function): FuncVer = {
f.versions.headOption match {
case Some(v) => v
case None =>
logger.debug(ctx + "Function %s is undefined. Trigger undefined function event.".format(f.repr))
microVM.trapManager.undefinedFunctionHandler.handleUndefinedFunction(f.id)
getFuncDefOrTriggerCallback(f)
}
}
} }
...@@ -30,6 +30,22 @@ class InterpreterStack(val id: Int, val stackMemory: StackMemory, stackBottomFun ...@@ -30,6 +30,22 @@ class InterpreterStack(val id: Int, val stackMemory: StackMemory, stackBottomFun
res res
} }
} }
def pushFrame(funcVer: FuncVer, args: Seq[ValueBox]): Unit = {
val newFrame = InterpreterFrame.frameForCall(funcVer, args, Some(top))
top = newFrame
}
def replaceTop(funcVer: FuncVer, args: Seq[ValueBox]): Unit = {
val newFrame = InterpreterFrame.frameForCall(funcVer, args, top.prev)
top = newFrame
}
def popFrame(): Unit = {
top = top.prev.getOrElse {
throw new UvmRuntimeException("Attemting to pop the last frame of a stack. Stack ID: %d.".format(id))
}
}
} }
class InterpreterFrame(val funcVer: FuncVer, val prev: Option[InterpreterFrame]) { class InterpreterFrame(val funcVer: FuncVer, val prev: Option[InterpreterFrame]) {
......
...@@ -4,7 +4,9 @@ import uvm._ ...@@ -4,7 +4,9 @@ import uvm._
import uvm.comminsts._ import uvm.comminsts._
import uvm.types._ import uvm.types._
abstract class SSAVariable extends IdentifiedSettable abstract class SSAVariable extends IdentifiedSettable {
override def hashCode(): Int = id
}
// Global variables: Constants, Global Cells and Functions (Function is defined in controlFlow.scala) // Global variables: Constants, Global Cells and Functions (Function is defined in controlFlow.scala)
......
package uvm.refimpl.itpr
import org.scalatest._
import java.io.FileReader
import uvm._
import uvm.types._
import uvm.ssavariables._
import uvm.refimpl._
import uvm.refimpl.itpr._
import MemoryOrder._
import AtomicRMWOptr._
import uvm.refimpl.mem.TypeSizes.Word
class UvmInterpreterSimpleTests extends FlatSpec with Matchers {
{ // Configure logger
import org.slf4j.LoggerFactory
import org.slf4j.{ Logger => SLogger }
import ch.qos.logback.classic.{ Logger => LLogger, Level }
import ch.qos.logback.classic.Level._
def setLevel(name: String, level: Level): Unit = {
LoggerFactory.getLogger(name).asInstanceOf[LLogger].setLevel(level)
}
setLevel(SLogger.ROOT_LOGGER_NAME, INFO)
setLevel("uvm.refimpl.itpr", DEBUG)
}
val microVM = new MicroVM();
implicit def idOf(name: String): Int = microVM.globalBundle.allNs(name).id
implicit def nameOf(id: Int): String = microVM.globalBundle.allNs(id).name.get
{
val ca = microVM.newClientAgent()
val r = new FileReader("tests/uvm-refimpl-test/primitives.uir")
ca.loadBundle(r)
r.close()
val r2 = new FileReader("tests/uvm-refimpl-test/simple-tests.uir")
ca.loadBundle(r2)
r2.close()
ca.close()
}
type TrapHandlerFunction = (ClientAgent, Handle, Handle, Int) => TrapHandlerResult
class MockTrapHandler(thf: TrapHandlerFunction) extends TrapHandler {
def handleTrap(ca: ClientAgent, thread: Handle, stack: Handle, watchPointID: Int): TrapHandlerResult = {
thf(ca, thread, stack, watchPointID)
}
}
def testFunc(ca: ClientAgent, func: Handle, args: Seq[Handle])(handler: TrapHandlerFunction): Unit = {
microVM.trapManager.trapHandler = new MockTrapHandler(handler)
val hStack = ca.newStack(func, args)
val hThread = ca.newThread(hStack)
microVM.threadStackManager.joinAll()
}
implicit class MagicalBox(vb: ValueBox) {
def asInt: BigInt = vb.asInstanceOf[BoxInt].value
def asSInt(l: Int): BigInt = OpHelper.prepareSigned(vb.asInstanceOf[BoxInt].value, l)
def asUInt(l: Int): BigInt = OpHelper.prepareUnsigned(vb.asInstanceOf[BoxInt].value, l)
def asFloat: Float = vb.asInstanceOf[BoxFloat].value
def asDouble: Double = vb.asInstanceOf[BoxDouble].value
def asRef: Word = vb.asInstanceOf[BoxRef].objRef
def asIRef: (Word, Word) = { val b = vb.asInstanceOf[BoxIRef]; (b.objRef, b.offset) }
def asIRefAddr: Word = { val b = vb.asInstanceOf[BoxIRef]; b.objRef + b.offset }
def asStruct: Seq[ValueBox] = vb.asInstanceOf[BoxStruct].values
def asFunc: Option[Function] = vb.asInstanceOf[BoxFunc].func
def asThread: Option[InterpreterThread] = vb.asInstanceOf[BoxThread].thread
def asStack: Option[InterpreterStack] = vb.asInstanceOf[BoxStack].stack
def asTR64Box: BoxTagRef64 = vb.asInstanceOf[BoxTagRef64]
def asTR64Raw: Long = vb.asInstanceOf[BoxTagRef64].raw
def asVec: Seq[ValueBox] = vb.asInstanceOf[BoxVector].values
}
"Factorial functions" should "work" in {
val ca = microVM.newClientAgent()
val func = ca.putFunction("@test_fac")
testFunc(ca, func, Seq()) { (ca, th, st, wp) =>
val Seq(r1, r2, r3) = ca.dumpKeepalives(st, 0)
r1.vb.asInt shouldEqual 3628800
r2.vb.asInt shouldEqual 3628800
r3.vb.asInt shouldEqual 3628800
TrapRebindPassVoid(st)
}
ca.close()
}
"Fibonacci functions" should "work" in {
val ca = microVM.newClientAgent()
val func = ca.putFunction("@test_fib")
val watch = true
testFunc(ca, func, Seq()) { (ca, th, st, wp) =>
val trapName = nameOf(ca.currentInstruction(st, 0))
trapName match {
case "@fibonacci_mat_v1.watch" => {
if (watch) {
val vhs = ca.dumpKeepalives(st, 0)
val vs = vhs.map(_.vb.asInt)
println("watch " + vs)
}
TrapRebindPassVoid(st)
}
case "@test_fib_v1.checktrap" => {
val Seq(r1, r2) = ca.dumpKeepalives(st, 0)
r1.vb.asInt shouldEqual 55
r2.vb.asInt shouldEqual 55
TrapRebindPassVoid(st)
}
case _ => fail("Should not hit " + trapName)
}
}
ca.close()
}
}
\ No newline at end of file
...@@ -757,4 +757,22 @@ class UvmInterpreterSpec extends FlatSpec with Matchers { ...@@ -757,4 +757,22 @@ class UvmInterpreterSpec extends FlatSpec with Matchers {
ca.close() ca.close()
} }
"CALL and RET" should "work for normal returns" in {
val ca = microVM.newClientAgent()
val func = ca.putFunction("@call_ret")
val a0 = ca.putInt("@i64", 3)
val a1 = ca.putInt("@i64", 4)
testFunc(ca, func, Seq(a0, a1)) { (ca, th, st, wp) =>
val Seq(ss) = ca.dumpKeepalives(st, 0)
ss.vb.asInt shouldEqual 25
TrapRebindPassVoid(st)
}
ca.close()
}
} }
\ No newline at end of file
...@@ -405,24 +405,21 @@ ...@@ -405,24 +405,21 @@
COMMINST @uvm.thread_exit COMMINST @uvm.thread_exit
} }
// .funcsig @square_sum_sig = @i_ii .funcdef @square_sum VERSION @square_sum_v1 <@i_ii> (%a %b) {
// .funcdef @square_sum VERSION @square_sum_v1 <@square_sum_sig> (%a %b) { %entry:
// %entry: %a2 = MUL <@i64> %a %a
// %a2 = MUL <@i64> %a %a %b2 = MUL <@i64> %b %b
// %b2 = MUL <@i64> %b %b %s = ADD <@i64> %a2 %b2
// %s = ADD <@i64> %a2 %b2 RET <@i64> %s
// RET <@i64> %s }
// }
// .funcdef @call_ret VERSION @call_ret_v1 <@i_ii> (%a %b) {
// .funcsig @call_ret_sig = @i_ii %entry:
// .funcdef @call_ret VERSION @call_ret_v1 <@call_ret_sig> (%a %b) { %ss = CALL <@i_ii> @square_sum (%a %b)
// %entry: %trap = TRAP <@void> KEEPALIVE (%ss)
// %ss = CALL <@i_ii> @square_sum (%a %b) COMMINST @uvm.thread_exit
// %trap = TRAP <@void> KEEPALIVE (%ss) }
// %exit:
// COMMINST @uvm.thread_exit
// }
//
// .funcsig @thrower_sig = @noparamsnoret // .funcsig @thrower_sig = @noparamsnoret
// .funcdef @thrower VERSION @thrower_v1 <@thrower_sig> () { // .funcdef @thrower VERSION @thrower_v1 <@thrower_sig> () {
// %entry: // %entry:
......
...@@ -12,25 +12,17 @@ ...@@ -12,25 +12,17 @@
.const @TRUE <@i64> = 1 .const @TRUE <@i64> = 1
.const @FALSE <@i64> = 0 .const @FALSE <@i64> = 0
.funcsig @i_i = @i64 (@i64)
.funcsig @i_ii = @i64 (@i64 @i64) .funcsig @i_ii = @i64 (@i64 @i64)
.typedef @refvoid = ref<@void> .typedef @refvoid = ref<@void>
.const @NULLREF <@refvoid> = NULL .const @NULLREF <@refvoid> = NULL
.typedef @StructFoo = struct <@i32 @i64 @float @double>
.const @STRUCT_FOO <@StructFoo> = {1 2 3.0f 4.0d}
.typedef @refi64 = ref<@i64> .typedef @refi64 = ref<@i64>
.typedef @irefi64 = iref<@i64> .typedef @irefi64 = iref<@i64>
.typedef @weakrefi64 = weakref<@i64> .typedef @weakrefi64 = weakref<@i64>
.typedef @StructBar = struct < .const @I64_0 <@i64> = 0
@i64 @i32 @i16 @i8 @float @double .const @I64_1 <@i64> = 1
@refi64 @irefi64 @weakrefi64 .const @I64_2 <@i64> = 2
> .const @I64_10 <@i64> = 10
.typedef @refBar = ref<@StructBar>
.typedef @irefBar = iref<@StructBar>
.typedef @hCharArray = hybrid<@i64 @i8>
// require primitives.uir // require primitives.uir
.funcdef @factorial_rec <@i64 (@i64)> (%n) { .funcdef @factorial_rec VERSION @factorial_rec_v1 <@i_i> (%n) {
%zero = EQ <@i64> %n 0 %entry:
BRANCH2 %zero %iszero %notzero %zero = EQ <@i64> %n @I64_0
BRANCH2 %zero %iszero %notzero
%iszero:
RET <@i64> 1 %iszero:
RET <@i64> @I64_1
%notzero:
%nm1 = SUB <@i64> %n 1 %notzero:
%rec = CALL <@i64 (@i64)> @factorial_rec (%nm1) %nm1 = SUB <@i64> %n @I64_1
%result = MUL <@i64> %n %rec %rec = CALL <@i_i> @factorial_rec (%nm1)
RET <@i64> %result %result = MUL <@i64> %n %rec
RET <@i64> %result
} }
.funcdef @factorial_iter <@i64 (@i64)> (%n) { .funcdef @factorial_iter VERSION @factorial_iter_v1 <@i_i> (%n) {
%entry: %entry:
BRANCH %head BRANCH %head
%head: %head:
%i = PHI <@i64> { %entry: 1; %next: %i2; } %i = PHI <@i64> { %entry: @I64_1; %next: %i2; }
%prod = PHI <@i64> { %entry: 1; %next: %prod2; } %prod = PHI <@i64> { %entry: @I64_1; %next: %prod2; }
%cmp = SLE <@i64> %i %n %cmp = SLE <@i64> %i %n
BRANCH2 %cmp %body %exit BRANCH2 %cmp %body %exit
%body: %body:
%prod2 = MUL <@i64> %prod %i %prod2 = MUL <@i64> %prod %i
%i2 = ADD <@i64> %i 1 %i2 = ADD <@i64> %i @I64_1
BRANCH %next BRANCH %next
%next: %next:
BRANCH %head BRANCH %head
%exit: %exit:
RET <@i64> %prod RET <@i64> %prod
} }
.funcdef @factorial_tailrec <@i64 (@i64 @i64)> (%n %prod) { .funcdef @factorial_tailrec VERSION @factorial_tailrec_v1 <@i_ii> (%n %prod) {
%zero = EQ <@i64> %n 0 %entry:
BRANCH2 %zero %iszero %notzero %zero = EQ <@i64> %n @I64_1
BRANCH2 %zero %iszero %notzero
%iszero:
RET <@i64> %prod %iszero:
RET <@i64> %prod
%notzero:
%nm1 = SUB <@i64> %n 1 %notzero:
%mul = MUL <@i64> %n %prod %nm1 = SUB <@i64> %n @I64_1
TAILCALL <@i64 (@i64 @i64)> @factorial_tailrec (%nm1 %mul) %mul = MUL <@i64> %n %prod
TAILCALL <@i_ii> @factorial_tailrec (%nm1 %mul)
} }
.funcdef @test_fac <@noparamsnoret> () { .funcdef @test_fac VERSION @test_fac_v1 <@noparamsnoret> () {
%r1 = CALL <@i64 (@i64)> @factorial_rec (10) %entry:
%r2 = CALL <@i64 (@i64)> @factorial_iter (10) %r1 = CALL <@i_i> @factorial_rec (@I64_10)
%r3 = CALL <@i64 (@i64 @i64)> @factorial_tailrec (10 1) %r2 = CALL <@i_i> @factorial_iter (@I64_10)
%checktrap = TRAP <@void> %exit %exit KEEPALIVE (%r1 %r2 %r3) %r3 = CALL <@i_ii> @factorial_tailrec (@I64_10 @I64_1)
%exit: %checktrap = TRAP <@void> KEEPALIVE (%r1 %r2 %r3)
ICALL @uvm.thread_exit() COMMINST @uvm.thread_exit
THROW @NULLREF
} }
.funcdef @fibonacci_rec <@i64 (@i64)> (%n) { .funcdef @fibonacci_rec VERSION @fibonacci_rec_v1 <@i_i> (%n) {
%zero = EQ <@i64> %n 0 %entry:
BRANCH2 %zero %iszero %notzero %zero = EQ <@i64> %n @I64_0
BRANCH2 %zero %iszero %notzero
%iszero:
RET <@i64> 0 %iszero:
RET <@i64> @I64_0
%notzero:
%one = EQ <@i64> %n 1 %notzero:
BRANCH2 %one %isone %notone %one = EQ <@i64> %n @I64_1
BRANCH2 %one %isone %notone
%isone:
RET <@i64> 1 %isone:
RET <@i64> @I64_1
%notone:
%nm1 = SUB <@i64> %n 1 %notone:
%nm2 = SUB <@i64> %n 2 %nm1 = SUB <@i64> %n @I64_1
%rec1 = CALL <@i64 (@i64)> @fibonacci_rec (%nm1) %nm2 = SUB <@i64> %n @I64_2
%rec2 = CALL <@i64 (@i64)> @fibonacci_rec (%nm2) %rec1 = CALL <@i_i> @fibonacci_rec (%nm1)
%result = ADD <@i64> %rec1 %rec2 %rec2 = CALL <@i_i> @fibonacci_rec (%nm2)
RET <@i64> %result %result = ADD <@i64> %rec1 %rec2
RET <@i64> %result
} }
// M(n) = [F_{n+1} F_n ; // M(n) = [F_{n+1} F_n ;
...@@ -89,77 +91,79 @@ ...@@ -89,77 +91,79 @@
// 1 0] // 1 0]
// M(0) = [1 0; // M(0) = [1 0;
// 0 1] // 0 1]
.funcdef @fibonacci_mat <@i64 (@i64)> (%n) { .funcdef @fibonacci_mat VERSION @fibonacci_mat_v1 <@i_i> (%n) {
%entry: %entry:
BRANCH %head BRANCH %head
%head: %head:
%a = PHI <@i64> { %entry: 1; %next: %a2; } %a = PHI <@i64> { %entry: @I64_1; %next: %a2; }
%b = PHI <@i64> { %entry: 1; %next: %b2; } %b = PHI <@i64> { %entry: @I64_1; %next: %b2; }
%c = PHI <@i64> { %entry: 1; %next: %c2; } %c = PHI <@i64> { %entry: @I64_1; %next: %c2; }
%d = PHI <@i64> { %entry: 0; %next: %d2; } %d = PHI <@i64> { %entry: @I64_0; %next: %d2; }
%aa = PHI <@i64> { %entry: 1; %next: %aa2; } %aa = PHI <@i64> { %entry: @I64_1; %next: %aa2; }
%bb = PHI <@i64> { %entry: 0; %next: %bb2; } %bb = PHI <@i64> { %entry: @I64_0; %next: %bb2; }
%cc = PHI <@i64> { %entry: 0; %next: %cc2; } %cc = PHI <@i64> { %entry: @I64_0; %next: %cc2; }
%dd = PHI <@i64> { %entry: 1; %next: %dd2; } %dd = PHI <@i64> { %entry: @I64_1; %next: %dd2; }
%nn = PHI <@i64> { %entry: %n; %next: %nn2; } %nn = PHI <@i64> { %entry: %n; %next: %nn2; }
%watch = TRAP <@void> %head2 %head2 KEEPALIVE (%a %b %c %d %aa %bb %cc %dd %nn) %watch = TRAP <@void> KEEPALIVE (%a %b %c %d %aa %bb %cc %dd %nn)
%head2: %nn0 = EQ <@i64> %nn @I64_0
%nn0 = EQ <@i64> %nn 0 BRANCH2 %nn0 %exit %body
BRANCH2 %nn0 %exit %body
%body:
%body: %nnm2 = AND <@i64> %nn @I64_1
%nodd = AND <@i64> %nn 1 %nodd = EQ <@i64> %nnm2 @I64_1
BRANCH2 %nodd %odd %even BRANCH2 %nodd %odd %even
%odd: %odd:
%aa_a = MUL <@i64> %aa %a %aa_a = MUL <@i64> %aa %a
%bb_c = MUL <@i64> %bb %c %bb_c = MUL <@i64> %bb %c
%aa_b = MUL <@i64> %aa %b %aa_b = MUL <@i64> %aa %b
%bb_d = MUL <@i64> %bb %d %bb_d = MUL <@i64> %bb %d
%cc_a = MUL <@i64> %cc %a %cc_a = MUL <@i64> %cc %a
%dd_c = MUL <@i64> %dd %c %dd_c = MUL <@i64> %dd %c
%cc_b = MUL <@i64> %cc %b %cc_b = MUL <@i64> %cc %b
%dd_d = MUL <@i64> %dd %d %dd_d = MUL <@i64> %dd %d
%aa3 = ADD <@i64> %aa_a %bb_c %aa3 = ADD <@i64> %aa_a %bb_c
%bb3 = ADD <@i64> %aa_b %bb_d %bb3 = ADD <@i64> %aa_b %bb_d
%cc3 = ADD <@i64> %cc_a %dd_c %cc3 = ADD <@i64> %cc_a %dd_c
%dd3 = ADD <@i64> %cc_b %dd_d %dd3 = ADD <@i64> %cc_b %dd_d
BRANCH %next BRANCH %next
%even: %even:
BRANCH %next BRANCH %next
%next: %next:
%aa2 = PHI <@i64> { %odd: %aa3; %even: %aa; } %aa2 = PHI <@i64> { %odd: %aa3; %even: %aa; }
%bb2 = PHI <@i64> { %odd: %bb3; %even: %bb; } %bb2 = PHI <@i64> { %odd: %bb3; %even: %bb; }
%cc2 = PHI <@i64> { %odd: %cc3; %even: %cc; } %cc2 = PHI <@i64> { %odd: %cc3; %even: %cc; }
%dd2 = PHI <@i64> { %odd: %dd3; %even: %dd; } %dd2 = PHI <@i64> { %odd: %dd3; %even: %dd; }
%a_a = MUL <@i64> %a %a %a_a = MUL <@i64> %a %a
%a_b = MUL <@i64> %a %b %a_b = MUL <@i64> %a %b
%a_c = MUL <@i64> %a %c %a_c = MUL <@i64> %a %c
%b_c = MUL <@i64> %b %c %b_c = MUL <@i64> %b %c
%b_d = MUL <@i64> %b %d %b_d = MUL <@i64> %b %d
%c_d = MUL <@i64> %c %d %c_d = MUL <@i64> %c %d
%d_d = MUL <@i64> %d %d %d_d = MUL <@i64> %d %d
%a2 = ADD <@i64> %a_a %b_c %a2 = ADD <@i64> %a_a %b_c
%b2 = ADD <@i64> %a_b %b_d %b2 = ADD <@i64> %a_b %b_d
%c2 = ADD <@i64> %a_c %c_d %c2 = ADD <@i64> %a_c %c_d
%d2 = ADD <@i64> %b_c %d_d %d2 = ADD <@i64> %b_c %d_d
%nn2 = ASHR <@i64> %nn 1 %nn2 = ASHR <@i64> %nn @I64_1
BRANCH %head BRANCH %head
%exit: %exit:
RET <@i64> %bb RET <@i64> %bb
} }
.funcdef @test_fib <@noparamsnoret> () { .funcdef @test_fib VERSION @test_fib_v1 <@noparamsnoret> () {
%r1 = CALL <@i64 (@i64)> @fibonacci_rec (10) %entry:
%r2 = CALL <@i64 (@i64)> @fibonacci_mat (10) %r1 = CALL <@i_i> @fibonacci_rec (@I64_10)
%checktrap = TRAP <@void> %exit %exit KEEPALIVE (%r1 %r2) %r2 = CALL <@i_i> @fibonacci_mat (@I64_10)
%exit: %checktrap = TRAP <@void> KEEPALIVE (
ICALL @uvm.thread_exit() %r1
THROW @NULLREF %r2
} )
\ No newline at end of file COMMINST @uvm.thread_exit
}
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