ISLE: Lowering of multi-output instructions (#3783)
This changes the output of the `lower` constructor from a `ValueRegs` to a new `InstOutput` type, which is a vector of `ValueRegs`. Code in `lower_common` is updated to use this new type to handle instructions with multiple outputs. All back-ends are updated to use the new type.
This commit is contained in:
@@ -38,6 +38,11 @@
|
||||
(type ValueList (primitive ValueList))
|
||||
(type ValueRegs (primitive ValueRegs))
|
||||
|
||||
;; Instruction lowering result: a vector of `ValueRegs`.
|
||||
(type InstOutput (primitive InstOutput))
|
||||
;; (Mutable) builder to incrementally construct an `InstOutput`.
|
||||
(type InstOutputBuilder extern (enum))
|
||||
|
||||
(decl u32_add (u32 u32) u32)
|
||||
(extern constructor u32_add u32_add)
|
||||
|
||||
@@ -64,6 +69,38 @@
|
||||
(decl value_regs_invalid () ValueRegs)
|
||||
(extern constructor value_regs_invalid value_regs_invalid)
|
||||
|
||||
;; Construct an empty `InstOutput`.
|
||||
(decl output_none () InstOutput)
|
||||
(extern constructor output_none output_none)
|
||||
|
||||
;; Construct a single-element `InstOutput`.
|
||||
(decl output (ValueRegs) InstOutput)
|
||||
(extern constructor output output)
|
||||
|
||||
;; Construct a two-element `InstOutput`.
|
||||
(decl output_pair (ValueRegs ValueRegs) InstOutput)
|
||||
(extern constructor output_pair output_pair)
|
||||
|
||||
;; Construct a single-element `InstOutput` from a single register.
|
||||
(decl output_reg (Reg) InstOutput)
|
||||
(rule (output_reg reg) (output (value_reg reg)))
|
||||
|
||||
;; Construct a single-element `InstOutput` from a value.
|
||||
(decl output_value (Value) InstOutput)
|
||||
(rule (output_value val) (output (put_in_regs val)))
|
||||
|
||||
;; Initially empty `InstOutput` builder.
|
||||
(decl output_builder_new () InstOutputBuilder)
|
||||
(extern constructor output_builder_new output_builder_new)
|
||||
|
||||
;; Append a `ValueRegs` to an `InstOutput` under construction.
|
||||
(decl output_builder_push (InstOutputBuilder ValueRegs) Unit)
|
||||
(extern constructor output_builder_push output_builder_push)
|
||||
|
||||
;; Finish building an `InstOutput` incrementally.
|
||||
(decl output_builder_finish (InstOutputBuilder) InstOutput)
|
||||
(extern constructor output_builder_finish output_builder_finish)
|
||||
|
||||
;; Get a temporary register for writing.
|
||||
(decl temp_writable_reg (Type) WritableReg)
|
||||
(extern constructor temp_writable_reg temp_writable_reg)
|
||||
@@ -307,18 +344,18 @@
|
||||
|
||||
(type SideEffectNoResult (enum (Inst (inst MInst))))
|
||||
|
||||
;; Create an empty `ValueRegs`, but do emit the given side-effectful
|
||||
;; Create an empty `InstOutput`, but do emit the given side-effectful
|
||||
;; instruction.
|
||||
(decl value_regs_none (SideEffectNoResult) ValueRegs)
|
||||
(rule (value_regs_none (SideEffectNoResult.Inst inst))
|
||||
(decl side_effect (SideEffectNoResult) InstOutput)
|
||||
(rule (side_effect (SideEffectNoResult.Inst inst))
|
||||
(let ((_ Unit (emit inst)))
|
||||
(value_regs_invalid)))
|
||||
(output_none)))
|
||||
|
||||
;; Similarly, but emit the side-effectful instruction as a safepoint.
|
||||
(decl safepoint (SideEffectNoResult) ValueRegs)
|
||||
(decl safepoint (SideEffectNoResult) InstOutput)
|
||||
(rule (safepoint (SideEffectNoResult.Inst inst))
|
||||
(let ((_ Unit (emit_safepoint inst)))
|
||||
(value_regs_invalid)))
|
||||
(output_none)))
|
||||
|
||||
;;;; Helpers for Working with Flags ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
@@ -438,3 +475,6 @@
|
||||
(convert Value Reg put_in_reg)
|
||||
(convert Value ValueRegs put_in_regs)
|
||||
(convert WritableReg Reg writable_reg_to_reg)
|
||||
(convert ValueRegs InstOutput output)
|
||||
(convert Reg InstOutput output_reg)
|
||||
(convert Value InstOutput output_value)
|
||||
|
||||
Reference in New Issue
Block a user