[llvm] [Utils][SPIR-V] Adding spirv-sim to LLVM (PR #104020)
Michal Paszkowski via llvm-commits
llvm-commits at lists.llvm.org
Mon Aug 19 23:02:00 PDT 2024
Nathan =?utf-8?q?Gauër?= <brioche at google.com>,
Nathan =?utf-8?q?Gauër?= <brioche at google.com>
Message-ID:
In-Reply-To: <llvm.org/llvm/llvm-project/pull/104020 at github.com>
================
@@ -0,0 +1,387 @@
+# Base class for an instruction. To implement a basic instruction that doesn't
+# impact the control-flow, create a new class inheriting from this.
+class Instruction:
+ _result: str
+
+ def __init__(self, line: str):
+ # Contains the name of the output register, if any.
+ self._result: str = None
+ # Contains the instruction opcode.
+ self._opcode: str = None
+ # Contains all the instruction operands, except result and opcode.
+ self._operands: list[str] = []
+
+ self.line = line
+ tokens = line.split()
+ if len(tokens) > 1 and tokens[1] == "=":
+ self._result = tokens[0]
+ self._opcode = tokens[2]
+ self._operands = tokens[3:] if len(tokens) > 2 else []
+ else:
+ self._result = None
+ self._opcode = tokens[0]
+ self._operands = tokens[1:] if len(tokens) > 1 else []
+
+ def __str__(self):
+ if self._result is None:
+ return f" {self._opcode} {self._operands}"
+ return f"{self._result:3} = {self._opcode} {self._operands}"
+
+ # Returns the instruction opcode.
+ def opcode(self) -> str:
+ return self._opcode
+
+ # Returns the instruction operands.
+ def operands(self) -> list[str]:
+ return self._operands
+
+ # Returns the instruction output register. Calling this function is
+ # only allowed if has_output_register() is true.
+ def output_register(self) -> str:
+ assert self.has_output_register()
+ return self._result
+
+ # Returns true if this function has an output register. False otherwise.
+ def has_output_register(self) -> bool:
+ return self._result is not None
+
+ # This function is used to initialize state related to this instruction
+ # before module execution begins. For example, global Input variables
+ # can use this to store the lane ID into the register.
+ def static_execution(self, lane):
+ pass
+
+ # This function is called everytime this instruction is executed by a
+ # tangle. This function should not be directly overriden, instead see
+ # _impl and _advance_ip.
+ def runtime_execution(self, module, lane):
+ self._impl(module, lane)
+ self._advance_ip(module, lane)
+
+ # This function needs to be overriden if your instruction can be executed.
+ # It implements the logic of the instruction.
+ # 'Static' instructions like OpConstant should not override this since
+ # they are not supposed to be executed at runtime.
+ def _impl(self, module, lane):
+ raise RuntimeError(f"Unimplemented instruction {self}")
+
+ # By default, IP is incremented to point to the next instruction.
+ # If the instruction modifies IP (like OpBranch), this must be overridden.
+ def _advance_ip(self, module, lane):
+ lane.set_ip(lane.ip() + 1)
+
+
+# Those are parsed, but never executed.
+class OpEntryPoint(Instruction):
+ pass
+
+
+class OpFunction(Instruction):
+ pass
+
+
+class OpFunctionEnd(Instruction):
+ pass
+
+
+class OpLabel(Instruction):
+ pass
+
+
+class OpVariable(Instruction):
+ pass
+
+
+class OpName(Instruction):
+ def name(self) -> str:
+ return self._operands[1][1:-1]
+
+ def decoratedRegister(self) -> str:
+ return self._operands[0]
+
+
+# The only decoration we use if the BuilIn one to initialize the values.
+class OpDecorate(Instruction):
+ def static_execution(self, lane):
+ if self._operands[1] == "LinkageAttributes":
+ return
+
+ assert (
+ self._operands[1] == "BuiltIn"
+ and self._operands[2] == "SubgroupLocalInvocationId"
+ )
+ lane.set_register(self._operands[0], lane.tid())
+
+
+# Constants
+class OpConstant(Instruction):
+ def static_execution(self, lane):
+ lane.set_register(self._result, int(self._operands[1]))
+
+
+class OpConstantTrue(OpConstant):
+ def static_execution(self, lane):
+ lane.set_register(self._result, True)
+
+
+class OpConstantFalse(OpConstant):
+ def static_execution(self, lane):
+ lane.set_register(self._result, False)
+
+
+class OpConstantComposite(OpConstant):
+ def static_execution(self, lane):
+ result = []
+ length = self.get_register(self._operands[0])
+ for op in self._operands[1:]:
+ result.append(self.get_register(op))
+ lane.set_register(self._result, result)
+
+
+class OpConstantComposite(OpConstant):
----------------
michalpaszkowski wrote:
`OpConstantComposite` is defined twice
https://github.com/llvm/llvm-project/pull/104020
More information about the llvm-commits
mailing list