compiler: support disabling now-pinning

This commit is contained in:
Sebastien Bourdeauducq 2020-04-26 12:38:43 +08:00
parent d19f28fa84
commit 251a0101a6
2 changed files with 48 additions and 25 deletions

View File

@ -78,13 +78,15 @@ class Target:
:var little_endian: (boolean) :var little_endian: (boolean)
Whether the code will be executed on a little-endian machine. This cannot be always Whether the code will be executed on a little-endian machine. This cannot be always
determined from data_layout due to JIT. determined from data_layout due to JIT.
:var now_pinning: (boolean)
Whether the target implements the now-pinning RTIO optimization.
""" """
triple = "unknown" triple = "unknown"
data_layout = "" data_layout = ""
features = [] features = []
print_function = "printf" print_function = "printf"
little_endian = False little_endian = False
now_pinning = True
def __init__(self): def __init__(self):
self.llcontext = ll.Context() self.llcontext = ll.Context()
@ -254,6 +256,7 @@ class OR1KTarget(Target):
features = ["mul", "div", "ffl1", "cmov", "addc"] features = ["mul", "div", "ffl1", "cmov", "addc"]
print_function = "core_log" print_function = "core_log"
little_endian = False little_endian = False
now_pinning = True
class CortexA9Target(Target): class CortexA9Target(Target):
triple = "armv7-unknown-linux-gnueabihf" triple = "armv7-unknown-linux-gnueabihf"
@ -261,3 +264,4 @@ class CortexA9Target(Target):
features = ["dsp", "fp16", "neon", "vfp3"] features = ["dsp", "fp16", "neon", "vfp3"]
print_function = "core_log" print_function = "core_log"
little_endian = True little_endian = True
now_pinning = False

View File

@ -380,8 +380,19 @@ class LLVMIRGenerator:
llty = ll.FunctionType(llvoid, [lli32, llsliceptr, llptrptr]) llty = ll.FunctionType(llvoid, [lli32, llsliceptr, llptrptr])
elif name == "rpc_recv": elif name == "rpc_recv":
llty = ll.FunctionType(lli32, [llptr]) llty = ll.FunctionType(lli32, [llptr])
# with now-pinning
elif name == "now": elif name == "now":
llty = lli64 llty = lli64
# without now-pinning
elif name == "now_mu":
llty = ll.FunctionType(lli64, [])
elif name == "at_mu":
llty = ll.FunctionType(llvoid, [lli64])
elif name == "delay_mu":
llty = ll.FunctionType(llvoid, [lli64])
elif name == "watchdog_set": elif name == "watchdog_set":
llty = ll.FunctionType(lli32, [lli64]) llty = ll.FunctionType(lli32, [lli64])
elif name == "watchdog_clear": elif name == "watchdog_clear":
@ -1174,35 +1185,43 @@ class LLVMIRGenerator:
# This is an identity cast at LLVM IR level. # This is an identity cast at LLVM IR level.
return self.map(insn.operands[0]) return self.map(insn.operands[0])
elif insn.op == "now_mu": elif insn.op == "now_mu":
llnow = self.llbuilder.load(self.llbuiltin("now"), name=insn.name) if self.target.now_pinning:
return llnow return self.llbuilder.load(self.llbuiltin("now"), name=insn.name)
else:
return self.llbuilder.call(self.llbuiltin("now_mu"), [])
elif insn.op == "at_mu": elif insn.op == "at_mu":
time, = insn.operands time, = insn.operands
lltime = self.map(time) lltime = self.map(time)
lltime_hi = self.llbuilder.trunc(self.llbuilder.lshr(lltime, ll.Constant(lli64, 32)), lli32) if self.target.now_pinning:
lltime_lo = self.llbuilder.trunc(lltime, lli32) lltime_hi = self.llbuilder.trunc(self.llbuilder.lshr(lltime, ll.Constant(lli64, 32)), lli32)
llnow_hiptr = self.llbuilder.bitcast(self.llbuiltin("now"), lli32.as_pointer()) lltime_lo = self.llbuilder.trunc(lltime, lli32)
llnow_loptr = self.llbuilder.gep(llnow_hiptr, [self.llindex(1)]) llnow_hiptr = self.llbuilder.bitcast(self.llbuiltin("now"), lli32.as_pointer())
if self.target.little_endian: llnow_loptr = self.llbuilder.gep(llnow_hiptr, [self.llindex(1)])
lltime_hi, lltime_lo = lltime_lo, lltime_hi if self.target.little_endian:
llstore_hi = self.llbuilder.store_atomic(lltime_hi, llnow_hiptr, ordering="seq_cst", align=4) lltime_hi, lltime_lo = lltime_lo, lltime_hi
llstore_lo = self.llbuilder.store_atomic(lltime_lo, llnow_loptr, ordering="seq_cst", align=4) llstore_hi = self.llbuilder.store_atomic(lltime_hi, llnow_hiptr, ordering="seq_cst", align=4)
return llstore_lo llstore_lo = self.llbuilder.store_atomic(lltime_lo, llnow_loptr, ordering="seq_cst", align=4)
return llstore_lo
else:
return self.llbuilder.call(self.llbuiltin("at_mu"), [lltime])
elif insn.op == "delay_mu": elif insn.op == "delay_mu":
interval, = insn.operands interval, = insn.operands
llnowptr = self.llbuiltin("now") llinterval = self.map(interval)
llnow = self.llbuilder.load(llnowptr, name="now.old") if self.target.now_pinning:
lladjusted = self.llbuilder.add(llnow, self.map(interval), name="now.new") llnowptr = self.llbuiltin("now")
llnow = self.llbuilder.load(llnowptr, name="now.old")
lladjusted_hi = self.llbuilder.trunc(self.llbuilder.lshr(lladjusted, ll.Constant(lli64, 32)), lli32) lladjusted = self.llbuilder.add(llnow, llinterval, name="now.new")
lladjusted_lo = self.llbuilder.trunc(lladjusted, lli32) lladjusted_hi = self.llbuilder.trunc(self.llbuilder.lshr(lladjusted, ll.Constant(lli64, 32)), lli32)
llnow_hiptr = self.llbuilder.bitcast(llnowptr, lli32.as_pointer()) lladjusted_lo = self.llbuilder.trunc(lladjusted, lli32)
llnow_loptr = self.llbuilder.gep(llnow_hiptr, [self.llindex(1)]) llnow_hiptr = self.llbuilder.bitcast(llnowptr, lli32.as_pointer())
if self.target.little_endian: llnow_loptr = self.llbuilder.gep(llnow_hiptr, [self.llindex(1)])
lladjusted_hi, lladjusted_lo = lladjusted_lo, lladjusted_hi if self.target.little_endian:
llstore_hi = self.llbuilder.store_atomic(lladjusted_hi, llnow_hiptr, ordering="seq_cst", align=4) lladjusted_hi, lladjusted_lo = lladjusted_lo, lladjusted_hi
llstore_lo = self.llbuilder.store_atomic(lladjusted_lo, llnow_loptr, ordering="seq_cst", align=4) llstore_hi = self.llbuilder.store_atomic(lladjusted_hi, llnow_hiptr, ordering="seq_cst", align=4)
return llstore_lo llstore_lo = self.llbuilder.store_atomic(lladjusted_lo, llnow_loptr, ordering="seq_cst", align=4)
return llstore_lo
else:
return self.llbuilder.call(self.llbuiltin("delay_mu"), [llinterval])
elif insn.op == "watchdog_set": elif insn.op == "watchdog_set":
interval, = insn.operands interval, = insn.operands
return self.llbuilder.call(self.llbuiltin("watchdog_set"), [self.map(interval)]) return self.llbuilder.call(self.llbuiltin("watchdog_set"), [self.map(interval)])