panfrost/midgard: Refactor schedule/emit pipeline
First, this moves the scheduler and emitter out of midgard_compile.c
into their own dedicated files.
More interestingly, this slims down midgard_bundle to be essentially an
array of _pointers_ to midgard_instructions (plus some bundling
metadata), rather than the instructions and packing themselves. The
difference is critical, as it means that (within reason, i.e. as long as
it doesn't affect the schedule) midgard_instrucitons can now be modified
_after_ scheduling while having changes updated in the final binary.
On a more philosophical level, this removes an IR. Previously, the IR
before scheduling (MIR) was separate from the IR after scheduling
(post-schedule MIR), requiring a separate set of utilities to traverse,
using different idioms. There was no good reason for this, and it
restricts our flexibility with the RA. So unify all the things!
Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Reviewed-by: Ryan Houdek <Sonicadvance1@gmail.com>
2019-05-22 05:33:21 +01:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2018-2019 Alyssa Rosenzweig <alyssa@rosenzweig.io>
|
|
|
|
*
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
|
|
* to deal in the Software without restriction, including without limitation
|
|
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
|
|
*
|
|
|
|
* The above copyright notice and this permission notice (including the next
|
|
|
|
* paragraph) shall be included in all copies or substantial portions of the
|
|
|
|
* Software.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
|
|
* SOFTWARE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "compiler.h"
|
|
|
|
#include "midgard_ops.h"
|
|
|
|
|
2020-05-21 17:38:27 +01:00
|
|
|
static midgard_int_mod
|
|
|
|
mir_get_imod(bool shift, nir_alu_type T, bool half, bool scalar)
|
|
|
|
{
|
|
|
|
if (!half) {
|
|
|
|
assert(!shift);
|
|
|
|
/* Sign-extension, really... */
|
|
|
|
return scalar ? 0 : midgard_int_normal;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (shift)
|
|
|
|
return midgard_int_shift;
|
|
|
|
|
|
|
|
if (nir_alu_type_get_base_type(T) == nir_type_int)
|
|
|
|
return midgard_int_sign_extend;
|
|
|
|
else
|
|
|
|
return midgard_int_zero_extend;
|
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned
|
|
|
|
mir_pack_mod(midgard_instruction *ins, unsigned i, bool scalar)
|
|
|
|
{
|
|
|
|
bool integer = midgard_is_integer_op(ins->alu.op);
|
|
|
|
unsigned base_size = (8 << ins->alu.reg_mode);
|
|
|
|
unsigned sz = nir_alu_type_get_type_size(ins->src_types[i]);
|
|
|
|
bool half = (sz == (base_size >> 1));
|
|
|
|
|
|
|
|
return integer ?
|
|
|
|
mir_get_imod(ins->src_shift[i], ins->src_types[i], half, scalar) :
|
|
|
|
((ins->src_abs[i] << 0) |
|
|
|
|
((ins->src_neg[i] << 1)));
|
|
|
|
}
|
|
|
|
|
panfrost/midgard: Refactor schedule/emit pipeline
First, this moves the scheduler and emitter out of midgard_compile.c
into their own dedicated files.
More interestingly, this slims down midgard_bundle to be essentially an
array of _pointers_ to midgard_instructions (plus some bundling
metadata), rather than the instructions and packing themselves. The
difference is critical, as it means that (within reason, i.e. as long as
it doesn't affect the schedule) midgard_instrucitons can now be modified
_after_ scheduling while having changes updated in the final binary.
On a more philosophical level, this removes an IR. Previously, the IR
before scheduling (MIR) was separate from the IR after scheduling
(post-schedule MIR), requiring a separate set of utilities to traverse,
using different idioms. There was no good reason for this, and it
restricts our flexibility with the RA. So unify all the things!
Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Reviewed-by: Ryan Houdek <Sonicadvance1@gmail.com>
2019-05-22 05:33:21 +01:00
|
|
|
/* Midgard IR only knows vector ALU types, but we sometimes need to actually
|
|
|
|
* use scalar ALU instructions, for functional or performance reasons. To do
|
|
|
|
* this, we just demote vector ALU payloads to scalar. */
|
|
|
|
|
|
|
|
static int
|
2019-07-02 02:51:48 +01:00
|
|
|
component_from_mask(unsigned mask)
|
panfrost/midgard: Refactor schedule/emit pipeline
First, this moves the scheduler and emitter out of midgard_compile.c
into their own dedicated files.
More interestingly, this slims down midgard_bundle to be essentially an
array of _pointers_ to midgard_instructions (plus some bundling
metadata), rather than the instructions and packing themselves. The
difference is critical, as it means that (within reason, i.e. as long as
it doesn't affect the schedule) midgard_instrucitons can now be modified
_after_ scheduling while having changes updated in the final binary.
On a more philosophical level, this removes an IR. Previously, the IR
before scheduling (MIR) was separate from the IR after scheduling
(post-schedule MIR), requiring a separate set of utilities to traverse,
using different idioms. There was no good reason for this, and it
restricts our flexibility with the RA. So unify all the things!
Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Reviewed-by: Ryan Houdek <Sonicadvance1@gmail.com>
2019-05-22 05:33:21 +01:00
|
|
|
{
|
2019-07-02 02:35:28 +01:00
|
|
|
for (int c = 0; c < 8; ++c) {
|
|
|
|
if (mask & (1 << c))
|
panfrost/midgard: Refactor schedule/emit pipeline
First, this moves the scheduler and emitter out of midgard_compile.c
into their own dedicated files.
More interestingly, this slims down midgard_bundle to be essentially an
array of _pointers_ to midgard_instructions (plus some bundling
metadata), rather than the instructions and packing themselves. The
difference is critical, as it means that (within reason, i.e. as long as
it doesn't affect the schedule) midgard_instrucitons can now be modified
_after_ scheduling while having changes updated in the final binary.
On a more philosophical level, this removes an IR. Previously, the IR
before scheduling (MIR) was separate from the IR after scheduling
(post-schedule MIR), requiring a separate set of utilities to traverse,
using different idioms. There was no good reason for this, and it
restricts our flexibility with the RA. So unify all the things!
Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Reviewed-by: Ryan Houdek <Sonicadvance1@gmail.com>
2019-05-22 05:33:21 +01:00
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
|
|
|
assert(0);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned
|
2020-05-21 17:38:27 +01:00
|
|
|
mir_pack_scalar_source(unsigned mod, bool is_full, unsigned component)
|
panfrost/midgard: Refactor schedule/emit pipeline
First, this moves the scheduler and emitter out of midgard_compile.c
into their own dedicated files.
More interestingly, this slims down midgard_bundle to be essentially an
array of _pointers_ to midgard_instructions (plus some bundling
metadata), rather than the instructions and packing themselves. The
difference is critical, as it means that (within reason, i.e. as long as
it doesn't affect the schedule) midgard_instrucitons can now be modified
_after_ scheduling while having changes updated in the final binary.
On a more philosophical level, this removes an IR. Previously, the IR
before scheduling (MIR) was separate from the IR after scheduling
(post-schedule MIR), requiring a separate set of utilities to traverse,
using different idioms. There was no good reason for this, and it
restricts our flexibility with the RA. So unify all the things!
Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Reviewed-by: Ryan Houdek <Sonicadvance1@gmail.com>
2019-05-22 05:33:21 +01:00
|
|
|
{
|
2020-05-21 17:38:27 +01:00
|
|
|
midgard_scalar_alu_src s = {
|
|
|
|
.mod = mod,
|
|
|
|
.full = is_full,
|
|
|
|
.component = component << (is_full ? 1 : 0)
|
|
|
|
};
|
panfrost/midgard: Refactor schedule/emit pipeline
First, this moves the scheduler and emitter out of midgard_compile.c
into their own dedicated files.
More interestingly, this slims down midgard_bundle to be essentially an
array of _pointers_ to midgard_instructions (plus some bundling
metadata), rather than the instructions and packing themselves. The
difference is critical, as it means that (within reason, i.e. as long as
it doesn't affect the schedule) midgard_instrucitons can now be modified
_after_ scheduling while having changes updated in the final binary.
On a more philosophical level, this removes an IR. Previously, the IR
before scheduling (MIR) was separate from the IR after scheduling
(post-schedule MIR), requiring a separate set of utilities to traverse,
using different idioms. There was no good reason for this, and it
restricts our flexibility with the RA. So unify all the things!
Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Reviewed-by: Ryan Houdek <Sonicadvance1@gmail.com>
2019-05-22 05:33:21 +01:00
|
|
|
|
|
|
|
unsigned o;
|
|
|
|
memcpy(&o, &s, sizeof(s));
|
|
|
|
|
|
|
|
return o & ((1 << 6) - 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static midgard_scalar_alu
|
|
|
|
vector_to_scalar_alu(midgard_vector_alu v, midgard_instruction *ins)
|
|
|
|
{
|
2020-05-21 17:38:27 +01:00
|
|
|
bool is_full = nir_alu_type_get_type_size(ins->dest_type) == 32;
|
panfrost/midgard: Refactor schedule/emit pipeline
First, this moves the scheduler and emitter out of midgard_compile.c
into their own dedicated files.
More interestingly, this slims down midgard_bundle to be essentially an
array of _pointers_ to midgard_instructions (plus some bundling
metadata), rather than the instructions and packing themselves. The
difference is critical, as it means that (within reason, i.e. as long as
it doesn't affect the schedule) midgard_instrucitons can now be modified
_after_ scheduling while having changes updated in the final binary.
On a more philosophical level, this removes an IR. Previously, the IR
before scheduling (MIR) was separate from the IR after scheduling
(post-schedule MIR), requiring a separate set of utilities to traverse,
using different idioms. There was no good reason for this, and it
restricts our flexibility with the RA. So unify all the things!
Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Reviewed-by: Ryan Houdek <Sonicadvance1@gmail.com>
2019-05-22 05:33:21 +01:00
|
|
|
|
2020-05-21 17:38:27 +01:00
|
|
|
bool half_0 = nir_alu_type_get_type_size(ins->src_types[0]) == 16;
|
|
|
|
bool half_1 = nir_alu_type_get_type_size(ins->src_types[1]) == 16;
|
2019-07-26 14:30:16 +01:00
|
|
|
unsigned comp = component_from_mask(ins->mask);
|
|
|
|
|
2020-05-21 17:38:27 +01:00
|
|
|
unsigned packed_src[2] = {
|
|
|
|
mir_pack_scalar_source(mir_pack_mod(ins, 0, true), !half_0, ins->swizzle[0][comp]),
|
|
|
|
mir_pack_scalar_source(mir_pack_mod(ins, 1, true), !half_1, ins->swizzle[1][comp])
|
|
|
|
};
|
|
|
|
|
panfrost/midgard: Refactor schedule/emit pipeline
First, this moves the scheduler and emitter out of midgard_compile.c
into their own dedicated files.
More interestingly, this slims down midgard_bundle to be essentially an
array of _pointers_ to midgard_instructions (plus some bundling
metadata), rather than the instructions and packing themselves. The
difference is critical, as it means that (within reason, i.e. as long as
it doesn't affect the schedule) midgard_instrucitons can now be modified
_after_ scheduling while having changes updated in the final binary.
On a more philosophical level, this removes an IR. Previously, the IR
before scheduling (MIR) was separate from the IR after scheduling
(post-schedule MIR), requiring a separate set of utilities to traverse,
using different idioms. There was no good reason for this, and it
restricts our flexibility with the RA. So unify all the things!
Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Reviewed-by: Ryan Houdek <Sonicadvance1@gmail.com>
2019-05-22 05:33:21 +01:00
|
|
|
/* The output component is from the mask */
|
|
|
|
midgard_scalar_alu s = {
|
|
|
|
.op = v.op,
|
2020-05-21 17:38:27 +01:00
|
|
|
.src1 = packed_src[0],
|
|
|
|
.src2 = packed_src[1],
|
panfrost/midgard: Refactor schedule/emit pipeline
First, this moves the scheduler and emitter out of midgard_compile.c
into their own dedicated files.
More interestingly, this slims down midgard_bundle to be essentially an
array of _pointers_ to midgard_instructions (plus some bundling
metadata), rather than the instructions and packing themselves. The
difference is critical, as it means that (within reason, i.e. as long as
it doesn't affect the schedule) midgard_instrucitons can now be modified
_after_ scheduling while having changes updated in the final binary.
On a more philosophical level, this removes an IR. Previously, the IR
before scheduling (MIR) was separate from the IR after scheduling
(post-schedule MIR), requiring a separate set of utilities to traverse,
using different idioms. There was no good reason for this, and it
restricts our flexibility with the RA. So unify all the things!
Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Reviewed-by: Ryan Houdek <Sonicadvance1@gmail.com>
2019-05-22 05:33:21 +01:00
|
|
|
.unknown = 0,
|
|
|
|
.outmod = v.outmod,
|
2019-07-02 02:35:28 +01:00
|
|
|
.output_full = is_full,
|
2019-07-26 14:30:16 +01:00
|
|
|
.output_component = comp
|
panfrost/midgard: Refactor schedule/emit pipeline
First, this moves the scheduler and emitter out of midgard_compile.c
into their own dedicated files.
More interestingly, this slims down midgard_bundle to be essentially an
array of _pointers_ to midgard_instructions (plus some bundling
metadata), rather than the instructions and packing themselves. The
difference is critical, as it means that (within reason, i.e. as long as
it doesn't affect the schedule) midgard_instrucitons can now be modified
_after_ scheduling while having changes updated in the final binary.
On a more philosophical level, this removes an IR. Previously, the IR
before scheduling (MIR) was separate from the IR after scheduling
(post-schedule MIR), requiring a separate set of utilities to traverse,
using different idioms. There was no good reason for this, and it
restricts our flexibility with the RA. So unify all the things!
Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Reviewed-by: Ryan Houdek <Sonicadvance1@gmail.com>
2019-05-22 05:33:21 +01:00
|
|
|
};
|
|
|
|
|
2019-07-02 02:51:48 +01:00
|
|
|
/* Full components are physically spaced out */
|
|
|
|
if (is_full) {
|
|
|
|
assert(s.output_component < 4);
|
|
|
|
s.output_component <<= 1;
|
|
|
|
}
|
|
|
|
|
panfrost/midgard: Refactor schedule/emit pipeline
First, this moves the scheduler and emitter out of midgard_compile.c
into their own dedicated files.
More interestingly, this slims down midgard_bundle to be essentially an
array of _pointers_ to midgard_instructions (plus some bundling
metadata), rather than the instructions and packing themselves. The
difference is critical, as it means that (within reason, i.e. as long as
it doesn't affect the schedule) midgard_instrucitons can now be modified
_after_ scheduling while having changes updated in the final binary.
On a more philosophical level, this removes an IR. Previously, the IR
before scheduling (MIR) was separate from the IR after scheduling
(post-schedule MIR), requiring a separate set of utilities to traverse,
using different idioms. There was no good reason for this, and it
restricts our flexibility with the RA. So unify all the things!
Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Reviewed-by: Ryan Houdek <Sonicadvance1@gmail.com>
2019-05-22 05:33:21 +01:00
|
|
|
/* Inline constant is passed along rather than trying to extract it
|
|
|
|
* from v */
|
|
|
|
|
2019-08-26 19:58:27 +01:00
|
|
|
if (ins->has_inline_constant) {
|
panfrost/midgard: Refactor schedule/emit pipeline
First, this moves the scheduler and emitter out of midgard_compile.c
into their own dedicated files.
More interestingly, this slims down midgard_bundle to be essentially an
array of _pointers_ to midgard_instructions (plus some bundling
metadata), rather than the instructions and packing themselves. The
difference is critical, as it means that (within reason, i.e. as long as
it doesn't affect the schedule) midgard_instrucitons can now be modified
_after_ scheduling while having changes updated in the final binary.
On a more philosophical level, this removes an IR. Previously, the IR
before scheduling (MIR) was separate from the IR after scheduling
(post-schedule MIR), requiring a separate set of utilities to traverse,
using different idioms. There was no good reason for this, and it
restricts our flexibility with the RA. So unify all the things!
Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Reviewed-by: Ryan Houdek <Sonicadvance1@gmail.com>
2019-05-22 05:33:21 +01:00
|
|
|
uint16_t imm = 0;
|
|
|
|
int lower_11 = ins->inline_constant & ((1 << 12) - 1);
|
|
|
|
imm |= (lower_11 >> 9) & 3;
|
|
|
|
imm |= (lower_11 >> 6) & 4;
|
|
|
|
imm |= (lower_11 >> 2) & 0x38;
|
|
|
|
imm |= (lower_11 & 63) << 6;
|
|
|
|
|
|
|
|
s.src2 = imm;
|
|
|
|
}
|
|
|
|
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
2019-11-05 13:50:29 +00:00
|
|
|
/* 64-bit swizzles are super easy since there are 2 components of 2 components
|
|
|
|
* in an 8-bit field ... lots of duplication to go around!
|
|
|
|
*
|
|
|
|
* Swizzles of 32-bit vectors accessed from 64-bit instructions are a little
|
|
|
|
* funny -- pack them *as if* they were native 64-bit, using rep_* flags to
|
|
|
|
* flag upper. For instance, xy would become 64-bit XY but that's just xyzw
|
|
|
|
* native. Likewise, zz would become 64-bit XX with rep* so it would be xyxy
|
|
|
|
* with rep. Pretty nifty, huh? */
|
|
|
|
|
|
|
|
static unsigned
|
|
|
|
mir_pack_swizzle_64(unsigned *swizzle, unsigned max_component)
|
|
|
|
{
|
|
|
|
unsigned packed = 0;
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < 2; ++i) {
|
|
|
|
assert(swizzle[i] <= max_component);
|
|
|
|
|
2019-12-13 15:13:24 +00:00
|
|
|
unsigned a = (swizzle[i] & 1) ?
|
2019-11-05 13:50:29 +00:00
|
|
|
(COMPONENT_W << 2) | COMPONENT_Z :
|
|
|
|
(COMPONENT_Y << 2) | COMPONENT_X;
|
|
|
|
|
|
|
|
packed |= a << (i * 4);
|
|
|
|
}
|
|
|
|
|
|
|
|
return packed;
|
|
|
|
}
|
|
|
|
|
2019-11-13 12:58:48 +00:00
|
|
|
static void
|
|
|
|
mir_pack_mask_alu(midgard_instruction *ins)
|
|
|
|
{
|
|
|
|
unsigned effective = ins->mask;
|
|
|
|
|
|
|
|
/* If we have a destination override, we need to figure out whether to
|
|
|
|
* override to the lower or upper half, shifting the effective mask in
|
|
|
|
* the latter, so AAAA.... becomes AAAA */
|
|
|
|
|
2020-05-08 22:41:49 +01:00
|
|
|
unsigned inst_size = 8 << ins->alu.reg_mode;
|
|
|
|
signed upper_shift = mir_upper_override(ins, inst_size);
|
2019-11-13 12:58:48 +00:00
|
|
|
|
2020-05-08 22:41:49 +01:00
|
|
|
if (upper_shift >= 0) {
|
2019-11-13 12:58:48 +00:00
|
|
|
effective >>= upper_shift;
|
2020-05-08 22:41:49 +01:00
|
|
|
ins->alu.dest_override = upper_shift ?
|
|
|
|
midgard_dest_override_upper :
|
|
|
|
midgard_dest_override_lower;
|
|
|
|
} else {
|
|
|
|
ins->alu.dest_override = midgard_dest_override_none;
|
2019-11-13 12:58:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (ins->alu.reg_mode == midgard_reg_mode_32)
|
|
|
|
ins->alu.mask = expand_writemask(effective, 2);
|
2020-05-21 23:04:36 +01:00
|
|
|
else if (ins->alu.reg_mode == midgard_reg_mode_64)
|
|
|
|
ins->alu.mask = expand_writemask(effective, 1);
|
2019-11-13 12:58:48 +00:00
|
|
|
else
|
|
|
|
ins->alu.mask = effective;
|
|
|
|
}
|
|
|
|
|
2020-05-21 17:38:27 +01:00
|
|
|
static unsigned
|
|
|
|
mir_pack_swizzle(unsigned mask, unsigned *swizzle,
|
|
|
|
nir_alu_type T, midgard_reg_mode reg_mode,
|
|
|
|
bool op_channeled, bool *rep_low, bool *rep_high)
|
2019-10-26 19:06:17 +01:00
|
|
|
{
|
2020-05-21 17:38:27 +01:00
|
|
|
unsigned packed = 0;
|
|
|
|
unsigned sz = nir_alu_type_get_type_size(T);
|
2019-10-26 19:06:17 +01:00
|
|
|
|
2020-05-21 17:38:27 +01:00
|
|
|
if (reg_mode == midgard_reg_mode_64) {
|
2020-05-21 23:05:29 +01:00
|
|
|
assert(sz == 64 || sz == 32);
|
|
|
|
unsigned components = (sz == 32) ? 4 : 2;
|
2019-10-31 18:56:45 +00:00
|
|
|
|
2020-05-21 17:38:27 +01:00
|
|
|
packed = mir_pack_swizzle_64(swizzle, components);
|
2019-10-31 18:56:45 +00:00
|
|
|
|
2020-05-21 17:38:27 +01:00
|
|
|
if (sz == 32) {
|
|
|
|
bool lo = swizzle[0] >= COMPONENT_Z;
|
|
|
|
bool hi = swizzle[1] >= COMPONENT_Z;
|
2020-02-04 14:29:59 +00:00
|
|
|
|
2020-05-21 17:38:27 +01:00
|
|
|
if (mask & 0x1) {
|
|
|
|
/* We can't mix halves... */
|
|
|
|
if (mask & 2)
|
|
|
|
assert(lo == hi);
|
2020-02-04 14:29:59 +00:00
|
|
|
|
2020-05-21 17:38:27 +01:00
|
|
|
*rep_low = lo;
|
|
|
|
} else {
|
|
|
|
*rep_low = hi;
|
2019-11-05 13:50:29 +00:00
|
|
|
}
|
2020-05-21 17:38:27 +01:00
|
|
|
} else if (sz < 32) {
|
|
|
|
unreachable("Cannot encode 8/16 swizzle in 64-bit");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* For 32-bit, swizzle packing is stupid-simple. For 16-bit,
|
|
|
|
* the strategy is to check whether the nibble we're on is
|
|
|
|
* upper or lower. We need all components to be on the same
|
|
|
|
* "side"; that much is enforced by the ISA and should have
|
|
|
|
* been lowered. TODO: 8-bit packing. TODO: vec8 */
|
2019-10-31 18:56:45 +00:00
|
|
|
|
2020-05-21 17:38:27 +01:00
|
|
|
unsigned first = mask ? ffs(mask) - 1 : 0;
|
|
|
|
bool upper = swizzle[first] > 3;
|
2019-10-26 19:06:17 +01:00
|
|
|
|
2020-05-21 17:38:27 +01:00
|
|
|
if (upper && mask)
|
|
|
|
assert(sz <= 16);
|
2019-10-31 18:56:45 +00:00
|
|
|
|
2020-05-21 17:38:27 +01:00
|
|
|
bool dest_up = !op_channeled && (first >= 4);
|
2020-05-07 21:09:47 +01:00
|
|
|
|
2020-05-21 17:38:27 +01:00
|
|
|
for (unsigned c = (dest_up ? 4 : 0); c < (dest_up ? 8 : 4); ++c) {
|
|
|
|
unsigned v = swizzle[c];
|
2019-10-31 18:56:45 +00:00
|
|
|
|
2020-05-21 17:38:27 +01:00
|
|
|
bool t_upper = v > 3;
|
2019-10-31 18:56:45 +00:00
|
|
|
|
2020-05-21 17:38:27 +01:00
|
|
|
/* Ensure we're doing something sane */
|
2019-10-26 19:06:17 +01:00
|
|
|
|
2020-05-21 17:38:27 +01:00
|
|
|
if (mask & (1 << c)) {
|
|
|
|
assert(t_upper == upper);
|
|
|
|
assert(v <= 7);
|
|
|
|
}
|
2019-11-05 13:50:29 +00:00
|
|
|
|
2020-05-21 17:38:27 +01:00
|
|
|
/* Use the non upper part */
|
|
|
|
v &= 0x3;
|
2019-11-05 13:50:29 +00:00
|
|
|
|
2020-05-21 17:38:27 +01:00
|
|
|
packed |= v << (2 * (c % 4));
|
|
|
|
}
|
2019-11-05 13:50:29 +00:00
|
|
|
|
2020-04-28 22:44:39 +01:00
|
|
|
|
2020-05-21 17:38:27 +01:00
|
|
|
/* Replicate for now.. should really pick a side for
|
|
|
|
* dot products */
|
2020-04-28 22:44:39 +01:00
|
|
|
|
2020-05-13 23:24:25 +01:00
|
|
|
if (reg_mode == midgard_reg_mode_16 && sz == 16) {
|
2020-05-21 17:38:27 +01:00
|
|
|
*rep_low = !upper;
|
|
|
|
*rep_high = upper;
|
2020-05-13 23:24:25 +01:00
|
|
|
} else if (reg_mode == midgard_reg_mode_16 && sz == 8) {
|
|
|
|
*rep_low = upper;
|
|
|
|
*rep_high = upper;
|
2020-05-21 17:38:27 +01:00
|
|
|
} else if (reg_mode == midgard_reg_mode_32) {
|
|
|
|
*rep_low = upper;
|
|
|
|
} else {
|
|
|
|
unreachable("Unhandled reg mode");
|
2019-10-26 19:06:17 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-21 17:38:27 +01:00
|
|
|
return packed;
|
|
|
|
}
|
2019-10-26 19:06:17 +01:00
|
|
|
|
2020-05-21 17:38:27 +01:00
|
|
|
static void
|
|
|
|
mir_pack_vector_srcs(midgard_instruction *ins)
|
|
|
|
{
|
|
|
|
bool channeled = GET_CHANNEL_COUNT(alu_opcode_props[ins->alu.op].props);
|
|
|
|
|
|
|
|
midgard_reg_mode mode = ins->alu.reg_mode;
|
|
|
|
unsigned base_size = (8 << mode);
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < 2; ++i) {
|
|
|
|
if (ins->has_inline_constant && (i == 1))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (ins->src[i] == ~0)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
bool rep_lo = false, rep_hi = false;
|
|
|
|
unsigned sz = nir_alu_type_get_type_size(ins->src_types[i]);
|
|
|
|
bool half = (sz == (base_size >> 1));
|
|
|
|
|
|
|
|
assert((sz == base_size) || half);
|
|
|
|
|
|
|
|
unsigned swizzle = mir_pack_swizzle(ins->mask, ins->swizzle[i],
|
|
|
|
ins->src_types[i], ins->alu.reg_mode,
|
|
|
|
channeled, &rep_lo, &rep_hi);
|
|
|
|
|
|
|
|
midgard_vector_alu_src pack = {
|
|
|
|
.mod = mir_pack_mod(ins, i, false),
|
|
|
|
.rep_low = rep_lo,
|
|
|
|
.rep_high = rep_hi,
|
|
|
|
.half = half,
|
|
|
|
.swizzle = swizzle
|
|
|
|
};
|
|
|
|
|
|
|
|
unsigned p = vector_alu_srco_unsigned(pack);
|
|
|
|
|
|
|
|
if (i == 0)
|
|
|
|
ins->alu.src1 = p;
|
|
|
|
else
|
|
|
|
ins->alu.src2 = p;
|
|
|
|
}
|
2019-10-26 19:06:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
mir_pack_swizzle_ldst(midgard_instruction *ins)
|
|
|
|
{
|
|
|
|
/* TODO: non-32-bit, non-vec4 */
|
|
|
|
for (unsigned c = 0; c < 4; ++c) {
|
|
|
|
unsigned v = ins->swizzle[0][c];
|
|
|
|
|
|
|
|
/* Check vec4 */
|
|
|
|
assert(v <= 3);
|
|
|
|
|
|
|
|
ins->load_store.swizzle |= v << (2 * c);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* TODO: arg_1/2 */
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
mir_pack_swizzle_tex(midgard_instruction *ins)
|
|
|
|
{
|
|
|
|
for (unsigned i = 0; i < 2; ++i) {
|
|
|
|
unsigned packed = 0;
|
|
|
|
|
|
|
|
for (unsigned c = 0; c < 4; ++c) {
|
|
|
|
unsigned v = ins->swizzle[i][c];
|
|
|
|
|
|
|
|
/* Check vec4 */
|
|
|
|
assert(v <= 3);
|
|
|
|
|
|
|
|
packed |= v << (2 * c);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (i == 0)
|
|
|
|
ins->texture.swizzle = packed;
|
|
|
|
else
|
|
|
|
ins->texture.in_reg_swizzle = packed;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* TODO: bias component */
|
|
|
|
}
|
|
|
|
|
2019-11-07 13:25:27 +00:00
|
|
|
/* Load store masks are 4-bits. Load/store ops pack for that. vec4 is the
|
|
|
|
* natural mask width; vec8 is constrained to be in pairs, vec2 is duplicated. TODO: 8-bit?
|
|
|
|
*/
|
|
|
|
|
|
|
|
static void
|
|
|
|
mir_pack_ldst_mask(midgard_instruction *ins)
|
|
|
|
{
|
2020-05-07 15:12:38 +01:00
|
|
|
unsigned sz = nir_alu_type_get_type_size(ins->dest_type);
|
2019-11-07 13:25:27 +00:00
|
|
|
unsigned packed = ins->mask;
|
|
|
|
|
2020-05-07 15:12:38 +01:00
|
|
|
if (sz == 64) {
|
2019-11-07 13:25:27 +00:00
|
|
|
packed = ((ins->mask & 0x2) ? (0x8 | 0x4) : 0) |
|
|
|
|
((ins->mask & 0x1) ? (0x2 | 0x1) : 0);
|
2020-05-07 15:12:38 +01:00
|
|
|
} else if (sz == 16) {
|
2019-11-07 13:25:27 +00:00
|
|
|
packed = 0;
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < 4; ++i) {
|
|
|
|
/* Make sure we're duplicated */
|
|
|
|
bool u = (ins->mask & (1 << (2*i + 0))) != 0;
|
|
|
|
bool v = (ins->mask & (1 << (2*i + 1))) != 0;
|
|
|
|
assert(u == v);
|
|
|
|
|
|
|
|
packed |= (u << i);
|
|
|
|
}
|
2020-05-07 15:12:38 +01:00
|
|
|
} else {
|
|
|
|
assert(sz == 32);
|
2019-11-07 13:25:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ins->load_store.mask = packed;
|
|
|
|
}
|
|
|
|
|
2020-04-30 18:46:35 +01:00
|
|
|
static void
|
|
|
|
mir_lower_inverts(midgard_instruction *ins)
|
|
|
|
{
|
|
|
|
bool inv[3] = {
|
|
|
|
ins->src_invert[0],
|
|
|
|
ins->src_invert[1],
|
|
|
|
ins->src_invert[2]
|
|
|
|
};
|
|
|
|
|
|
|
|
switch (ins->alu.op) {
|
|
|
|
case midgard_alu_op_iand:
|
|
|
|
/* a & ~b = iandnot(a, b) */
|
|
|
|
/* ~a & ~b = ~(a | b) = inor(a, b) */
|
|
|
|
|
|
|
|
if (inv[0] && inv[1])
|
|
|
|
ins->alu.op = midgard_alu_op_inor;
|
|
|
|
else if (inv[1])
|
|
|
|
ins->alu.op = midgard_alu_op_iandnot;
|
|
|
|
|
|
|
|
break;
|
|
|
|
case midgard_alu_op_ior:
|
|
|
|
/* a | ~b = iornot(a, b) */
|
|
|
|
/* ~a | ~b = ~(a & b) = inand(a, b) */
|
|
|
|
|
|
|
|
if (inv[0] && inv[1])
|
|
|
|
ins->alu.op = midgard_alu_op_inand;
|
|
|
|
else if (inv[1])
|
|
|
|
ins->alu.op = midgard_alu_op_iornot;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case midgard_alu_op_ixor:
|
|
|
|
/* ~a ^ b = a ^ ~b = ~(a ^ b) = inxor(a, b) */
|
|
|
|
/* ~a ^ ~b = a ^ b */
|
|
|
|
|
|
|
|
if (inv[0] ^ inv[1])
|
|
|
|
ins->alu.op = midgard_alu_op_inxor;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
panfrost/midgard: Refactor schedule/emit pipeline
First, this moves the scheduler and emitter out of midgard_compile.c
into their own dedicated files.
More interestingly, this slims down midgard_bundle to be essentially an
array of _pointers_ to midgard_instructions (plus some bundling
metadata), rather than the instructions and packing themselves. The
difference is critical, as it means that (within reason, i.e. as long as
it doesn't affect the schedule) midgard_instrucitons can now be modified
_after_ scheduling while having changes updated in the final binary.
On a more philosophical level, this removes an IR. Previously, the IR
before scheduling (MIR) was separate from the IR after scheduling
(post-schedule MIR), requiring a separate set of utilities to traverse,
using different idioms. There was no good reason for this, and it
restricts our flexibility with the RA. So unify all the things!
Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Reviewed-by: Ryan Houdek <Sonicadvance1@gmail.com>
2019-05-22 05:33:21 +01:00
|
|
|
static void
|
|
|
|
emit_alu_bundle(compiler_context *ctx,
|
|
|
|
midgard_bundle *bundle,
|
|
|
|
struct util_dynarray *emission,
|
|
|
|
unsigned lookahead)
|
|
|
|
{
|
|
|
|
/* Emit the control word */
|
|
|
|
util_dynarray_append(emission, uint32_t, bundle->control | lookahead);
|
|
|
|
|
|
|
|
/* Next up, emit register words */
|
|
|
|
for (unsigned i = 0; i < bundle->instruction_count; ++i) {
|
|
|
|
midgard_instruction *ins = bundle->instructions[i];
|
|
|
|
|
|
|
|
/* Check if this instruction has registers */
|
2019-12-31 00:02:23 +00:00
|
|
|
if (ins->compact_branch) continue;
|
panfrost/midgard: Refactor schedule/emit pipeline
First, this moves the scheduler and emitter out of midgard_compile.c
into their own dedicated files.
More interestingly, this slims down midgard_bundle to be essentially an
array of _pointers_ to midgard_instructions (plus some bundling
metadata), rather than the instructions and packing themselves. The
difference is critical, as it means that (within reason, i.e. as long as
it doesn't affect the schedule) midgard_instrucitons can now be modified
_after_ scheduling while having changes updated in the final binary.
On a more philosophical level, this removes an IR. Previously, the IR
before scheduling (MIR) was separate from the IR after scheduling
(post-schedule MIR), requiring a separate set of utilities to traverse,
using different idioms. There was no good reason for this, and it
restricts our flexibility with the RA. So unify all the things!
Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Reviewed-by: Ryan Houdek <Sonicadvance1@gmail.com>
2019-05-22 05:33:21 +01:00
|
|
|
|
|
|
|
/* Otherwise, just emit the registers */
|
|
|
|
uint16_t reg_word = 0;
|
|
|
|
memcpy(®_word, &ins->registers, sizeof(uint16_t));
|
|
|
|
util_dynarray_append(emission, uint16_t, reg_word);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Now, we emit the body itself */
|
|
|
|
for (unsigned i = 0; i < bundle->instruction_count; ++i) {
|
|
|
|
midgard_instruction *ins = bundle->instructions[i];
|
|
|
|
|
|
|
|
/* Where is this body */
|
|
|
|
unsigned size = 0;
|
|
|
|
void *source = NULL;
|
|
|
|
|
|
|
|
/* In case we demote to a scalar */
|
|
|
|
midgard_scalar_alu scalarized;
|
|
|
|
|
2020-04-30 18:46:35 +01:00
|
|
|
if (!ins->compact_branch)
|
|
|
|
mir_lower_inverts(ins);
|
|
|
|
|
panfrost/midgard: Refactor schedule/emit pipeline
First, this moves the scheduler and emitter out of midgard_compile.c
into their own dedicated files.
More interestingly, this slims down midgard_bundle to be essentially an
array of _pointers_ to midgard_instructions (plus some bundling
metadata), rather than the instructions and packing themselves. The
difference is critical, as it means that (within reason, i.e. as long as
it doesn't affect the schedule) midgard_instrucitons can now be modified
_after_ scheduling while having changes updated in the final binary.
On a more philosophical level, this removes an IR. Previously, the IR
before scheduling (MIR) was separate from the IR after scheduling
(post-schedule MIR), requiring a separate set of utilities to traverse,
using different idioms. There was no good reason for this, and it
restricts our flexibility with the RA. So unify all the things!
Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Reviewed-by: Ryan Houdek <Sonicadvance1@gmail.com>
2019-05-22 05:33:21 +01:00
|
|
|
if (ins->unit & UNITS_ANY_VECTOR) {
|
2019-11-13 12:58:48 +00:00
|
|
|
mir_pack_mask_alu(ins);
|
2020-05-21 17:38:27 +01:00
|
|
|
mir_pack_vector_srcs(ins);
|
panfrost/midgard: Refactor schedule/emit pipeline
First, this moves the scheduler and emitter out of midgard_compile.c
into their own dedicated files.
More interestingly, this slims down midgard_bundle to be essentially an
array of _pointers_ to midgard_instructions (plus some bundling
metadata), rather than the instructions and packing themselves. The
difference is critical, as it means that (within reason, i.e. as long as
it doesn't affect the schedule) midgard_instrucitons can now be modified
_after_ scheduling while having changes updated in the final binary.
On a more philosophical level, this removes an IR. Previously, the IR
before scheduling (MIR) was separate from the IR after scheduling
(post-schedule MIR), requiring a separate set of utilities to traverse,
using different idioms. There was no good reason for this, and it
restricts our flexibility with the RA. So unify all the things!
Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Reviewed-by: Ryan Houdek <Sonicadvance1@gmail.com>
2019-05-22 05:33:21 +01:00
|
|
|
size = sizeof(midgard_vector_alu);
|
|
|
|
source = &ins->alu;
|
|
|
|
} else if (ins->unit == ALU_ENAB_BR_COMPACT) {
|
|
|
|
size = sizeof(midgard_branch_cond);
|
|
|
|
source = &ins->br_compact;
|
|
|
|
} else if (ins->compact_branch) { /* misnomer */
|
|
|
|
size = sizeof(midgard_branch_extended);
|
|
|
|
source = &ins->branch_extended;
|
|
|
|
} else {
|
|
|
|
size = sizeof(midgard_scalar_alu);
|
|
|
|
scalarized = vector_to_scalar_alu(ins->alu, ins);
|
|
|
|
source = &scalarized;
|
|
|
|
}
|
|
|
|
|
2020-04-01 03:32:19 +01:00
|
|
|
memcpy(util_dynarray_grow_bytes(emission, size, 1), source, size);
|
panfrost/midgard: Refactor schedule/emit pipeline
First, this moves the scheduler and emitter out of midgard_compile.c
into their own dedicated files.
More interestingly, this slims down midgard_bundle to be essentially an
array of _pointers_ to midgard_instructions (plus some bundling
metadata), rather than the instructions and packing themselves. The
difference is critical, as it means that (within reason, i.e. as long as
it doesn't affect the schedule) midgard_instrucitons can now be modified
_after_ scheduling while having changes updated in the final binary.
On a more philosophical level, this removes an IR. Previously, the IR
before scheduling (MIR) was separate from the IR after scheduling
(post-schedule MIR), requiring a separate set of utilities to traverse,
using different idioms. There was no good reason for this, and it
restricts our flexibility with the RA. So unify all the things!
Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Reviewed-by: Ryan Houdek <Sonicadvance1@gmail.com>
2019-05-22 05:33:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Emit padding (all zero) */
|
2020-04-01 03:32:19 +01:00
|
|
|
memset(util_dynarray_grow_bytes(emission, bundle->padding, 1), 0, bundle->padding);
|
panfrost/midgard: Refactor schedule/emit pipeline
First, this moves the scheduler and emitter out of midgard_compile.c
into their own dedicated files.
More interestingly, this slims down midgard_bundle to be essentially an
array of _pointers_ to midgard_instructions (plus some bundling
metadata), rather than the instructions and packing themselves. The
difference is critical, as it means that (within reason, i.e. as long as
it doesn't affect the schedule) midgard_instrucitons can now be modified
_after_ scheduling while having changes updated in the final binary.
On a more philosophical level, this removes an IR. Previously, the IR
before scheduling (MIR) was separate from the IR after scheduling
(post-schedule MIR), requiring a separate set of utilities to traverse,
using different idioms. There was no good reason for this, and it
restricts our flexibility with the RA. So unify all the things!
Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Reviewed-by: Ryan Houdek <Sonicadvance1@gmail.com>
2019-05-22 05:33:21 +01:00
|
|
|
|
|
|
|
/* Tack on constants */
|
|
|
|
|
2020-01-20 14:00:57 +00:00
|
|
|
if (bundle->has_embedded_constants)
|
|
|
|
util_dynarray_append(emission, midgard_constants, bundle->constants);
|
panfrost/midgard: Refactor schedule/emit pipeline
First, this moves the scheduler and emitter out of midgard_compile.c
into their own dedicated files.
More interestingly, this slims down midgard_bundle to be essentially an
array of _pointers_ to midgard_instructions (plus some bundling
metadata), rather than the instructions and packing themselves. The
difference is critical, as it means that (within reason, i.e. as long as
it doesn't affect the schedule) midgard_instrucitons can now be modified
_after_ scheduling while having changes updated in the final binary.
On a more philosophical level, this removes an IR. Previously, the IR
before scheduling (MIR) was separate from the IR after scheduling
(post-schedule MIR), requiring a separate set of utilities to traverse,
using different idioms. There was no good reason for this, and it
restricts our flexibility with the RA. So unify all the things!
Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Reviewed-by: Ryan Houdek <Sonicadvance1@gmail.com>
2019-05-22 05:33:21 +01:00
|
|
|
}
|
|
|
|
|
2019-12-07 20:54:36 +00:00
|
|
|
/* Shift applied to the immediate used as an offset. Probably this is papering
|
|
|
|
* over some other semantic distinction else well, but it unifies things in the
|
|
|
|
* compiler so I don't mind. */
|
|
|
|
|
|
|
|
static unsigned
|
|
|
|
mir_ldst_imm_shift(midgard_load_store_op op)
|
|
|
|
{
|
|
|
|
if (OP_IS_UBO_READ(op))
|
|
|
|
return 3;
|
|
|
|
else
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2020-04-28 00:23:17 +01:00
|
|
|
static enum mali_sampler_type
|
|
|
|
midgard_sampler_type(nir_alu_type t) {
|
|
|
|
switch (nir_alu_type_get_base_type(t))
|
|
|
|
{
|
|
|
|
case nir_type_float:
|
|
|
|
return MALI_SAMPLER_FLOAT;
|
|
|
|
case nir_type_int:
|
|
|
|
return MALI_SAMPLER_SIGNED;
|
|
|
|
case nir_type_uint:
|
|
|
|
return MALI_SAMPLER_UNSIGNED;
|
|
|
|
default:
|
|
|
|
unreachable("Unknown sampler type");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
panfrost/midgard: Refactor schedule/emit pipeline
First, this moves the scheduler and emitter out of midgard_compile.c
into their own dedicated files.
More interestingly, this slims down midgard_bundle to be essentially an
array of _pointers_ to midgard_instructions (plus some bundling
metadata), rather than the instructions and packing themselves. The
difference is critical, as it means that (within reason, i.e. as long as
it doesn't affect the schedule) midgard_instrucitons can now be modified
_after_ scheduling while having changes updated in the final binary.
On a more philosophical level, this removes an IR. Previously, the IR
before scheduling (MIR) was separate from the IR after scheduling
(post-schedule MIR), requiring a separate set of utilities to traverse,
using different idioms. There was no good reason for this, and it
restricts our flexibility with the RA. So unify all the things!
Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Reviewed-by: Ryan Houdek <Sonicadvance1@gmail.com>
2019-05-22 05:33:21 +01:00
|
|
|
/* After everything is scheduled, emit whole bundles at a time */
|
|
|
|
|
|
|
|
void
|
|
|
|
emit_binary_bundle(compiler_context *ctx,
|
2019-07-10 18:00:50 +01:00
|
|
|
midgard_bundle *bundle,
|
|
|
|
struct util_dynarray *emission,
|
|
|
|
int next_tag)
|
panfrost/midgard: Refactor schedule/emit pipeline
First, this moves the scheduler and emitter out of midgard_compile.c
into their own dedicated files.
More interestingly, this slims down midgard_bundle to be essentially an
array of _pointers_ to midgard_instructions (plus some bundling
metadata), rather than the instructions and packing themselves. The
difference is critical, as it means that (within reason, i.e. as long as
it doesn't affect the schedule) midgard_instrucitons can now be modified
_after_ scheduling while having changes updated in the final binary.
On a more philosophical level, this removes an IR. Previously, the IR
before scheduling (MIR) was separate from the IR after scheduling
(post-schedule MIR), requiring a separate set of utilities to traverse,
using different idioms. There was no good reason for this, and it
restricts our flexibility with the RA. So unify all the things!
Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Reviewed-by: Ryan Houdek <Sonicadvance1@gmail.com>
2019-05-22 05:33:21 +01:00
|
|
|
{
|
|
|
|
int lookahead = next_tag << 4;
|
|
|
|
|
|
|
|
switch (bundle->tag) {
|
|
|
|
case TAG_ALU_4:
|
|
|
|
case TAG_ALU_8:
|
|
|
|
case TAG_ALU_12:
|
|
|
|
case TAG_ALU_16:
|
2020-01-02 17:33:25 +00:00
|
|
|
case TAG_ALU_4 + 4:
|
|
|
|
case TAG_ALU_8 + 4:
|
|
|
|
case TAG_ALU_12 + 4:
|
|
|
|
case TAG_ALU_16 + 4:
|
panfrost/midgard: Refactor schedule/emit pipeline
First, this moves the scheduler and emitter out of midgard_compile.c
into their own dedicated files.
More interestingly, this slims down midgard_bundle to be essentially an
array of _pointers_ to midgard_instructions (plus some bundling
metadata), rather than the instructions and packing themselves. The
difference is critical, as it means that (within reason, i.e. as long as
it doesn't affect the schedule) midgard_instrucitons can now be modified
_after_ scheduling while having changes updated in the final binary.
On a more philosophical level, this removes an IR. Previously, the IR
before scheduling (MIR) was separate from the IR after scheduling
(post-schedule MIR), requiring a separate set of utilities to traverse,
using different idioms. There was no good reason for this, and it
restricts our flexibility with the RA. So unify all the things!
Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Reviewed-by: Ryan Houdek <Sonicadvance1@gmail.com>
2019-05-22 05:33:21 +01:00
|
|
|
emit_alu_bundle(ctx, bundle, emission, lookahead);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TAG_LOAD_STORE_4: {
|
|
|
|
/* One or two composing instructions */
|
|
|
|
|
|
|
|
uint64_t current64, next64 = LDST_NOP;
|
|
|
|
|
2019-07-02 02:51:48 +01:00
|
|
|
/* Copy masks */
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < bundle->instruction_count; ++i) {
|
2019-11-07 13:25:27 +00:00
|
|
|
mir_pack_ldst_mask(bundle->instructions[i]);
|
2019-10-26 19:06:17 +01:00
|
|
|
|
|
|
|
mir_pack_swizzle_ldst(bundle->instructions[i]);
|
2019-11-15 19:19:34 +00:00
|
|
|
|
|
|
|
/* Apply a constant offset */
|
2020-01-20 14:00:57 +00:00
|
|
|
unsigned offset = bundle->instructions[i]->constants.u32[0];
|
2019-11-15 19:19:34 +00:00
|
|
|
|
|
|
|
if (offset) {
|
2019-12-07 20:54:36 +00:00
|
|
|
unsigned shift = mir_ldst_imm_shift(bundle->instructions[i]->load_store.op);
|
|
|
|
unsigned upper_shift = 10 - shift;
|
|
|
|
|
|
|
|
bundle->instructions[i]->load_store.varying_parameters |= (offset & ((1 << upper_shift) - 1)) << shift;
|
|
|
|
bundle->instructions[i]->load_store.address |= (offset >> upper_shift);
|
2019-11-15 19:19:34 +00:00
|
|
|
}
|
2019-07-02 02:51:48 +01:00
|
|
|
}
|
|
|
|
|
panfrost/midgard: Refactor schedule/emit pipeline
First, this moves the scheduler and emitter out of midgard_compile.c
into their own dedicated files.
More interestingly, this slims down midgard_bundle to be essentially an
array of _pointers_ to midgard_instructions (plus some bundling
metadata), rather than the instructions and packing themselves. The
difference is critical, as it means that (within reason, i.e. as long as
it doesn't affect the schedule) midgard_instrucitons can now be modified
_after_ scheduling while having changes updated in the final binary.
On a more philosophical level, this removes an IR. Previously, the IR
before scheduling (MIR) was separate from the IR after scheduling
(post-schedule MIR), requiring a separate set of utilities to traverse,
using different idioms. There was no good reason for this, and it
restricts our flexibility with the RA. So unify all the things!
Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Reviewed-by: Ryan Houdek <Sonicadvance1@gmail.com>
2019-05-22 05:33:21 +01:00
|
|
|
memcpy(¤t64, &bundle->instructions[0]->load_store, sizeof(current64));
|
|
|
|
|
|
|
|
if (bundle->instruction_count == 2)
|
|
|
|
memcpy(&next64, &bundle->instructions[1]->load_store, sizeof(next64));
|
|
|
|
|
|
|
|
midgard_load_store instruction = {
|
|
|
|
.type = bundle->tag,
|
|
|
|
.next_type = next_tag,
|
|
|
|
.word1 = current64,
|
|
|
|
.word2 = next64
|
|
|
|
};
|
|
|
|
|
|
|
|
util_dynarray_append(emission, midgard_load_store, instruction);
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2019-06-11 18:24:57 +01:00
|
|
|
case TAG_TEXTURE_4:
|
2020-02-04 01:23:41 +00:00
|
|
|
case TAG_TEXTURE_4_VTX:
|
|
|
|
case TAG_TEXTURE_4_BARRIER: {
|
panfrost/midgard: Refactor schedule/emit pipeline
First, this moves the scheduler and emitter out of midgard_compile.c
into their own dedicated files.
More interestingly, this slims down midgard_bundle to be essentially an
array of _pointers_ to midgard_instructions (plus some bundling
metadata), rather than the instructions and packing themselves. The
difference is critical, as it means that (within reason, i.e. as long as
it doesn't affect the schedule) midgard_instrucitons can now be modified
_after_ scheduling while having changes updated in the final binary.
On a more philosophical level, this removes an IR. Previously, the IR
before scheduling (MIR) was separate from the IR after scheduling
(post-schedule MIR), requiring a separate set of utilities to traverse,
using different idioms. There was no good reason for this, and it
restricts our flexibility with the RA. So unify all the things!
Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Reviewed-by: Ryan Houdek <Sonicadvance1@gmail.com>
2019-05-22 05:33:21 +01:00
|
|
|
/* Texture instructions are easy, since there is no pipelining
|
2019-06-11 18:24:57 +01:00
|
|
|
* nor VLIW to worry about. We may need to set .cont/.last
|
|
|
|
* flags. */
|
panfrost/midgard: Refactor schedule/emit pipeline
First, this moves the scheduler and emitter out of midgard_compile.c
into their own dedicated files.
More interestingly, this slims down midgard_bundle to be essentially an
array of _pointers_ to midgard_instructions (plus some bundling
metadata), rather than the instructions and packing themselves. The
difference is critical, as it means that (within reason, i.e. as long as
it doesn't affect the schedule) midgard_instrucitons can now be modified
_after_ scheduling while having changes updated in the final binary.
On a more philosophical level, this removes an IR. Previously, the IR
before scheduling (MIR) was separate from the IR after scheduling
(post-schedule MIR), requiring a separate set of utilities to traverse,
using different idioms. There was no good reason for this, and it
restricts our flexibility with the RA. So unify all the things!
Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Reviewed-by: Ryan Houdek <Sonicadvance1@gmail.com>
2019-05-22 05:33:21 +01:00
|
|
|
|
|
|
|
midgard_instruction *ins = bundle->instructions[0];
|
|
|
|
|
2019-06-11 18:24:57 +01:00
|
|
|
ins->texture.type = bundle->tag;
|
panfrost/midgard: Refactor schedule/emit pipeline
First, this moves the scheduler and emitter out of midgard_compile.c
into their own dedicated files.
More interestingly, this slims down midgard_bundle to be essentially an
array of _pointers_ to midgard_instructions (plus some bundling
metadata), rather than the instructions and packing themselves. The
difference is critical, as it means that (within reason, i.e. as long as
it doesn't affect the schedule) midgard_instrucitons can now be modified
_after_ scheduling while having changes updated in the final binary.
On a more philosophical level, this removes an IR. Previously, the IR
before scheduling (MIR) was separate from the IR after scheduling
(post-schedule MIR), requiring a separate set of utilities to traverse,
using different idioms. There was no good reason for this, and it
restricts our flexibility with the RA. So unify all the things!
Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Reviewed-by: Ryan Houdek <Sonicadvance1@gmail.com>
2019-05-22 05:33:21 +01:00
|
|
|
ins->texture.next_type = next_tag;
|
2020-05-08 22:41:49 +01:00
|
|
|
|
2020-05-13 16:05:49 +01:00
|
|
|
/* Nothing else to pack for barriers */
|
|
|
|
if (ins->texture.op == TEXTURE_OP_BARRIER) {
|
|
|
|
ins->texture.cont = ins->texture.last = 1;
|
|
|
|
util_dynarray_append(emission, midgard_texture_word, ins->texture);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-05-08 22:41:49 +01:00
|
|
|
signed override = mir_upper_override(ins, 32);
|
|
|
|
|
|
|
|
ins->texture.mask = override > 0 ?
|
|
|
|
ins->mask >> override :
|
|
|
|
ins->mask;
|
|
|
|
|
2019-10-26 19:06:17 +01:00
|
|
|
mir_pack_swizzle_tex(ins);
|
panfrost/midgard: Refactor schedule/emit pipeline
First, this moves the scheduler and emitter out of midgard_compile.c
into their own dedicated files.
More interestingly, this slims down midgard_bundle to be essentially an
array of _pointers_ to midgard_instructions (plus some bundling
metadata), rather than the instructions and packing themselves. The
difference is critical, as it means that (within reason, i.e. as long as
it doesn't affect the schedule) midgard_instrucitons can now be modified
_after_ scheduling while having changes updated in the final binary.
On a more philosophical level, this removes an IR. Previously, the IR
before scheduling (MIR) was separate from the IR after scheduling
(post-schedule MIR), requiring a separate set of utilities to traverse,
using different idioms. There was no good reason for this, and it
restricts our flexibility with the RA. So unify all the things!
Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Reviewed-by: Ryan Houdek <Sonicadvance1@gmail.com>
2019-05-22 05:33:21 +01:00
|
|
|
|
2020-04-28 00:22:06 +01:00
|
|
|
unsigned osz = nir_alu_type_get_type_size(ins->dest_type);
|
|
|
|
unsigned isz = nir_alu_type_get_type_size(ins->src_types[1]);
|
|
|
|
|
|
|
|
assert(osz == 32 || osz == 16);
|
|
|
|
assert(isz == 32 || isz == 16);
|
|
|
|
|
|
|
|
ins->texture.out_full = (osz == 32);
|
2020-05-08 22:41:49 +01:00
|
|
|
ins->texture.out_upper = override > 0;
|
2020-04-28 00:22:06 +01:00
|
|
|
ins->texture.in_reg_full = (isz == 32);
|
2020-04-28 00:23:17 +01:00
|
|
|
ins->texture.sampler_type = midgard_sampler_type(ins->dest_type);
|
2020-04-28 00:22:06 +01:00
|
|
|
|
2019-11-18 13:02:58 +00:00
|
|
|
if (mir_op_computes_derivatives(ctx->stage, ins->texture.op)) {
|
2020-05-12 18:34:52 +01:00
|
|
|
ins->texture.cont = !ins->helper_terminate;
|
|
|
|
ins->texture.last = ins->helper_terminate || ins->helper_execute;
|
2019-06-11 17:43:08 +01:00
|
|
|
} else {
|
|
|
|
ins->texture.cont = ins->texture.last = 1;
|
panfrost/midgard: Refactor schedule/emit pipeline
First, this moves the scheduler and emitter out of midgard_compile.c
into their own dedicated files.
More interestingly, this slims down midgard_bundle to be essentially an
array of _pointers_ to midgard_instructions (plus some bundling
metadata), rather than the instructions and packing themselves. The
difference is critical, as it means that (within reason, i.e. as long as
it doesn't affect the schedule) midgard_instrucitons can now be modified
_after_ scheduling while having changes updated in the final binary.
On a more philosophical level, this removes an IR. Previously, the IR
before scheduling (MIR) was separate from the IR after scheduling
(post-schedule MIR), requiring a separate set of utilities to traverse,
using different idioms. There was no good reason for this, and it
restricts our flexibility with the RA. So unify all the things!
Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Reviewed-by: Ryan Houdek <Sonicadvance1@gmail.com>
2019-05-22 05:33:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
util_dynarray_append(emission, midgard_texture_word, ins->texture);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
unreachable("Unknown midgard instruction type\n");
|
|
|
|
}
|
|
|
|
}
|