xref: /aosp_15_r20/external/mesa3d/src/panfrost/compiler/bi_builder.h.py (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker# Copyright (C) 2020 Collabora, Ltd.
2*61046927SAndroid Build Coastguard Worker#
3*61046927SAndroid Build Coastguard Worker# Permission is hereby granted, free of charge, to any person obtaining a
4*61046927SAndroid Build Coastguard Worker# copy of this software and associated documentation files (the "Software"),
5*61046927SAndroid Build Coastguard Worker# to deal in the Software without restriction, including without limitation
6*61046927SAndroid Build Coastguard Worker# the rights to use, copy, modify, merge, publish, distribute, sublicense,
7*61046927SAndroid Build Coastguard Worker# and/or sell copies of the Software, and to permit persons to whom the
8*61046927SAndroid Build Coastguard Worker# Software is furnished to do so, subject to the following conditions:
9*61046927SAndroid Build Coastguard Worker#
10*61046927SAndroid Build Coastguard Worker# The above copyright notice and this permission notice (including the next
11*61046927SAndroid Build Coastguard Worker# paragraph) shall be included in all copies or substantial portions of the
12*61046927SAndroid Build Coastguard Worker# Software.
13*61046927SAndroid Build Coastguard Worker#
14*61046927SAndroid Build Coastguard Worker# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15*61046927SAndroid Build Coastguard Worker# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16*61046927SAndroid Build Coastguard Worker# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17*61046927SAndroid Build Coastguard Worker# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18*61046927SAndroid Build Coastguard Worker# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19*61046927SAndroid Build Coastguard Worker# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20*61046927SAndroid Build Coastguard Worker# IN THE SOFTWARE.
21*61046927SAndroid Build Coastguard Worker
22*61046927SAndroid Build Coastguard WorkerSKIP = set(["lane", "lane_dest", "lanes", "lanes", "replicate", "swz", "widen",
23*61046927SAndroid Build Coastguard Worker    "swap", "neg", "abs", "not", "sign", "extend", "divzero", "clamp", "sem",
24*61046927SAndroid Build Coastguard Worker    "not_result", "skip", "round", "ftz"])
25*61046927SAndroid Build Coastguard Worker
26*61046927SAndroid Build Coastguard WorkerTEMPLATE = """
27*61046927SAndroid Build Coastguard Worker#ifndef _BI_BUILDER_H_
28*61046927SAndroid Build Coastguard Worker#define _BI_BUILDER_H_
29*61046927SAndroid Build Coastguard Worker
30*61046927SAndroid Build Coastguard Worker#include "compiler.h"
31*61046927SAndroid Build Coastguard Worker
32*61046927SAndroid Build Coastguard Worker<%
33*61046927SAndroid Build Coastguard Worker# For <32-bit loads/stores, the default extend `none` with a natural sized
34*61046927SAndroid Build Coastguard Worker# input is not encodeable! To avoid a footgun, swap the default to `zext` which
35*61046927SAndroid Build Coastguard Worker# will work as expected
36*61046927SAndroid Build Coastguard WorkerZEXT_DEFAULT = set(["LOAD.i8", "LOAD.i16", "LOAD.i24", "STORE.i8", "STORE.i16", "STORE.i24"])
37*61046927SAndroid Build Coastguard Worker
38*61046927SAndroid Build Coastguard Workerdef nirtypes(opcode):
39*61046927SAndroid Build Coastguard Worker    split = opcode.split('.', 1)
40*61046927SAndroid Build Coastguard Worker    if len(split) < 2:
41*61046927SAndroid Build Coastguard Worker        split = opcode.split('_')
42*61046927SAndroid Build Coastguard Worker
43*61046927SAndroid Build Coastguard Worker    if len(split) <= 1:
44*61046927SAndroid Build Coastguard Worker        return None
45*61046927SAndroid Build Coastguard Worker
46*61046927SAndroid Build Coastguard Worker    assert len(split) > 1
47*61046927SAndroid Build Coastguard Worker
48*61046927SAndroid Build Coastguard Worker    type = split[1]
49*61046927SAndroid Build Coastguard Worker    if type[0] == 'v':
50*61046927SAndroid Build Coastguard Worker        type = type[2:]
51*61046927SAndroid Build Coastguard Worker
52*61046927SAndroid Build Coastguard Worker    if type[0] == 'f':
53*61046927SAndroid Build Coastguard Worker        return ['nir_type_float']
54*61046927SAndroid Build Coastguard Worker    elif type[0] == 's':
55*61046927SAndroid Build Coastguard Worker        return ['nir_type_int']
56*61046927SAndroid Build Coastguard Worker    elif type[0] == 'u':
57*61046927SAndroid Build Coastguard Worker        return ['nir_type_uint']
58*61046927SAndroid Build Coastguard Worker    elif type[0] == 'i':
59*61046927SAndroid Build Coastguard Worker        return ['nir_type_uint', 'nir_type_int']
60*61046927SAndroid Build Coastguard Worker    else:
61*61046927SAndroid Build Coastguard Worker        return None
62*61046927SAndroid Build Coastguard Worker
63*61046927SAndroid Build Coastguard Workerdef condition(opcode, typecheck, sizecheck):
64*61046927SAndroid Build Coastguard Worker    cond = ''
65*61046927SAndroid Build Coastguard Worker    if typecheck == True:
66*61046927SAndroid Build Coastguard Worker        cond += '('
67*61046927SAndroid Build Coastguard Worker        types = nirtypes(opcode)
68*61046927SAndroid Build Coastguard Worker        assert types != None
69*61046927SAndroid Build Coastguard Worker        for T in types:
70*61046927SAndroid Build Coastguard Worker            cond += "{}type == {}".format(' || ' if cond[-1] != '(' else '', T)
71*61046927SAndroid Build Coastguard Worker        cond += ')'
72*61046927SAndroid Build Coastguard Worker
73*61046927SAndroid Build Coastguard Worker    if sizecheck == True:
74*61046927SAndroid Build Coastguard Worker        cond += "{}bitsize == {}".format(' && ' if cond != '' else '', typesize(opcode))
75*61046927SAndroid Build Coastguard Worker
76*61046927SAndroid Build Coastguard Worker    cmpf_mods = ops[opcode]["modifiers"]["cmpf"] if "cmpf" in ops[opcode]["modifiers"] else None
77*61046927SAndroid Build Coastguard Worker    if "cmpf" in ops[opcode]["modifiers"]:
78*61046927SAndroid Build Coastguard Worker        cond += "{}(".format(' && ' if cond != '' else '')
79*61046927SAndroid Build Coastguard Worker        for cmpf in ops[opcode]["modifiers"]["cmpf"]:
80*61046927SAndroid Build Coastguard Worker            if cmpf != 'reserved':
81*61046927SAndroid Build Coastguard Worker                cond += "{}cmpf == BI_CMPF_{}".format(' || ' if cond[-1] != '(' else '', cmpf.upper())
82*61046927SAndroid Build Coastguard Worker        cond += ')'
83*61046927SAndroid Build Coastguard Worker
84*61046927SAndroid Build Coastguard Worker    return 'true' if cond == '' else cond
85*61046927SAndroid Build Coastguard Worker
86*61046927SAndroid Build Coastguard Workerdef to_suffix(op):
87*61046927SAndroid Build Coastguard Worker    return "_to" if op["dests"] > 0 else ""
88*61046927SAndroid Build Coastguard Worker
89*61046927SAndroid Build Coastguard Worker%>
90*61046927SAndroid Build Coastguard Worker
91*61046927SAndroid Build Coastguard Worker% for opcode in ops:
92*61046927SAndroid Build Coastguard Workerstatic inline
93*61046927SAndroid Build Coastguard Workerbi_instr * bi_${opcode.replace('.', '_').lower()}${to_suffix(ops[opcode])}(${signature(ops[opcode], modifiers)})
94*61046927SAndroid Build Coastguard Worker{
95*61046927SAndroid Build Coastguard Worker<%
96*61046927SAndroid Build Coastguard Worker    op = ops[opcode]
97*61046927SAndroid Build Coastguard Worker    nr_dests = "nr_dests" if op["variable_dests"] else op["dests"]
98*61046927SAndroid Build Coastguard Worker    nr_srcs = "nr_srcs" if op["variable_srcs"] else src_count(op)
99*61046927SAndroid Build Coastguard Worker%>
100*61046927SAndroid Build Coastguard Worker    size_t size = sizeof(bi_instr) + sizeof(bi_index) * (${nr_dests} + ${nr_srcs});
101*61046927SAndroid Build Coastguard Worker    bi_instr *I = (bi_instr *) rzalloc_size(b->shader, size);
102*61046927SAndroid Build Coastguard Worker
103*61046927SAndroid Build Coastguard Worker    I->op = BI_OPCODE_${opcode.replace('.', '_').upper()};
104*61046927SAndroid Build Coastguard Worker    I->nr_dests = ${nr_dests};
105*61046927SAndroid Build Coastguard Worker    I->nr_srcs = ${nr_srcs};
106*61046927SAndroid Build Coastguard Worker    I->dest = (bi_index *) (&I[1]);
107*61046927SAndroid Build Coastguard Worker    I->src = I->dest + ${nr_dests};
108*61046927SAndroid Build Coastguard Worker
109*61046927SAndroid Build Coastguard Worker% if not op["variable_dests"]:
110*61046927SAndroid Build Coastguard Worker% for dest in range(op["dests"]):
111*61046927SAndroid Build Coastguard Worker    I->dest[${dest}] = dest${dest};
112*61046927SAndroid Build Coastguard Worker% endfor
113*61046927SAndroid Build Coastguard Worker%endif
114*61046927SAndroid Build Coastguard Worker
115*61046927SAndroid Build Coastguard Worker% if not op["variable_srcs"]:
116*61046927SAndroid Build Coastguard Worker% for src in range(src_count(op)):
117*61046927SAndroid Build Coastguard Worker    I->src[${src}] = src${src};
118*61046927SAndroid Build Coastguard Worker% endfor
119*61046927SAndroid Build Coastguard Worker% endif
120*61046927SAndroid Build Coastguard Worker
121*61046927SAndroid Build Coastguard Worker% for mod in ops[opcode]["modifiers"]:
122*61046927SAndroid Build Coastguard Worker% if not should_skip(mod, opcode):
123*61046927SAndroid Build Coastguard Worker    I->${mod} = ${mod};
124*61046927SAndroid Build Coastguard Worker% endif
125*61046927SAndroid Build Coastguard Worker% endfor
126*61046927SAndroid Build Coastguard Worker% if ops[opcode]["rtz"]:
127*61046927SAndroid Build Coastguard Worker    I->round = BI_ROUND_RTZ;
128*61046927SAndroid Build Coastguard Worker% endif
129*61046927SAndroid Build Coastguard Worker% for imm in ops[opcode]["immediates"]:
130*61046927SAndroid Build Coastguard Worker    I->${imm} = ${imm};
131*61046927SAndroid Build Coastguard Worker% endfor
132*61046927SAndroid Build Coastguard Worker% if opcode in ZEXT_DEFAULT:
133*61046927SAndroid Build Coastguard Worker    I->extend = BI_EXTEND_ZEXT;
134*61046927SAndroid Build Coastguard Worker% endif
135*61046927SAndroid Build Coastguard Worker    bi_builder_insert(&b->cursor, I);
136*61046927SAndroid Build Coastguard Worker    return I;
137*61046927SAndroid Build Coastguard Worker}
138*61046927SAndroid Build Coastguard Worker
139*61046927SAndroid Build Coastguard Worker% if ops[opcode]["dests"] == 1 and not ops[opcode]["variable_dests"]:
140*61046927SAndroid Build Coastguard Workerstatic inline
141*61046927SAndroid Build Coastguard Workerbi_index bi_${opcode.replace('.', '_').lower()}(${signature(ops[opcode], modifiers, no_dests=True)})
142*61046927SAndroid Build Coastguard Worker{
143*61046927SAndroid Build Coastguard Worker    return (bi_${opcode.replace('.', '_').lower()}_to(${arguments(ops[opcode])}))->dest[0];
144*61046927SAndroid Build Coastguard Worker}
145*61046927SAndroid Build Coastguard Worker
146*61046927SAndroid Build Coastguard Worker%endif
147*61046927SAndroid Build Coastguard Worker<%
148*61046927SAndroid Build Coastguard Worker    common_op = opcode.split('.')[0]
149*61046927SAndroid Build Coastguard Worker    variants = [a for a in ops.keys() if a.split('.')[0] == common_op]
150*61046927SAndroid Build Coastguard Worker    signatures = [signature(ops[op], modifiers, no_dests=True) for op in variants]
151*61046927SAndroid Build Coastguard Worker    homogenous = all([sig == signatures[0] for sig in signatures])
152*61046927SAndroid Build Coastguard Worker    types = [nirtypes(x) for x in variants]
153*61046927SAndroid Build Coastguard Worker    typeful = False
154*61046927SAndroid Build Coastguard Worker    for t in types:
155*61046927SAndroid Build Coastguard Worker        if t != types[0]:
156*61046927SAndroid Build Coastguard Worker            typeful = True
157*61046927SAndroid Build Coastguard Worker
158*61046927SAndroid Build Coastguard Worker    sizes = [typesize(x) for x in variants]
159*61046927SAndroid Build Coastguard Worker    sized = False
160*61046927SAndroid Build Coastguard Worker    for size in sizes:
161*61046927SAndroid Build Coastguard Worker        if size != sizes[0]:
162*61046927SAndroid Build Coastguard Worker            sized = True
163*61046927SAndroid Build Coastguard Worker
164*61046927SAndroid Build Coastguard Worker    last = opcode == variants[-1]
165*61046927SAndroid Build Coastguard Worker%>
166*61046927SAndroid Build Coastguard Worker% if homogenous and len(variants) > 1 and last:
167*61046927SAndroid Build Coastguard Worker% for (suffix, temp, dests, ret) in (('_to', False, 1, 'instr *'), ('', True, 0, 'index')):
168*61046927SAndroid Build Coastguard Worker% if not temp or ops[opcode]["dests"] > 0:
169*61046927SAndroid Build Coastguard Workerstatic inline
170*61046927SAndroid Build Coastguard Workerbi_${ret} bi_${common_op.replace('.', '_').lower()}${suffix if ops[opcode]['dests'] > 0 else ''}(${signature(ops[opcode], modifiers, typeful=typeful, sized=sized, no_dests=not dests)})
171*61046927SAndroid Build Coastguard Worker{
172*61046927SAndroid Build Coastguard Worker% for i, variant in enumerate(variants):
173*61046927SAndroid Build Coastguard Worker    ${"{}if ({})".format("else " if i > 0 else "", condition(variant, typeful, sized))}
174*61046927SAndroid Build Coastguard Worker        return (bi_${variant.replace('.', '_').lower()}${to_suffix(ops[opcode])}(${arguments(ops[opcode], temp_dest = temp)}))${"->dest[0]" if temp else ""};
175*61046927SAndroid Build Coastguard Worker% endfor
176*61046927SAndroid Build Coastguard Worker    else
177*61046927SAndroid Build Coastguard Worker        unreachable("Invalid parameters for ${common_op}");
178*61046927SAndroid Build Coastguard Worker}
179*61046927SAndroid Build Coastguard Worker
180*61046927SAndroid Build Coastguard Worker%endif
181*61046927SAndroid Build Coastguard Worker%endfor
182*61046927SAndroid Build Coastguard Worker%endif
183*61046927SAndroid Build Coastguard Worker%endfor
184*61046927SAndroid Build Coastguard Worker#endif"""
185*61046927SAndroid Build Coastguard Worker
186*61046927SAndroid Build Coastguard Workerimport sys
187*61046927SAndroid Build Coastguard Workerfrom bifrost_isa import *
188*61046927SAndroid Build Coastguard Workerfrom mako.template import Template
189*61046927SAndroid Build Coastguard Worker
190*61046927SAndroid Build Coastguard Workerinstructions = {}
191*61046927SAndroid Build Coastguard Workerfor arg in sys.argv[1:]:
192*61046927SAndroid Build Coastguard Worker    new_instructions = parse_instructions(arg, include_pseudo = True)
193*61046927SAndroid Build Coastguard Worker    instructions.update(new_instructions)
194*61046927SAndroid Build Coastguard Worker
195*61046927SAndroid Build Coastguard Workerir_instructions = partition_mnemonics(instructions)
196*61046927SAndroid Build Coastguard Workermodifier_lists = order_modifiers(ir_instructions)
197*61046927SAndroid Build Coastguard Worker
198*61046927SAndroid Build Coastguard Worker# Generate type signature for a builder routine
199*61046927SAndroid Build Coastguard Worker
200*61046927SAndroid Build Coastguard Workerdef should_skip(mod, op):
201*61046927SAndroid Build Coastguard Worker    # FROUND and HADD only make sense in context of a round mode, so override
202*61046927SAndroid Build Coastguard Worker    # the usual skip
203*61046927SAndroid Build Coastguard Worker    if mod == "round" and ("FROUND" in op or "HADD" in op):
204*61046927SAndroid Build Coastguard Worker        return False
205*61046927SAndroid Build Coastguard Worker
206*61046927SAndroid Build Coastguard Worker    return mod in SKIP or mod[0:-1] in SKIP
207*61046927SAndroid Build Coastguard Worker
208*61046927SAndroid Build Coastguard Workerdef modifier_signature(op):
209*61046927SAndroid Build Coastguard Worker    return sorted([m for m in op["modifiers"].keys() if not should_skip(m, op["key"])])
210*61046927SAndroid Build Coastguard Worker
211*61046927SAndroid Build Coastguard Workerdef signature(op, modifiers, typeful = False, sized = False, no_dests = False):
212*61046927SAndroid Build Coastguard Worker    return ", ".join(
213*61046927SAndroid Build Coastguard Worker        ["bi_builder *b"] +
214*61046927SAndroid Build Coastguard Worker        (["nir_alu_type type"] if typeful == True else []) +
215*61046927SAndroid Build Coastguard Worker        (["unsigned bitsize"] if sized == True else []) +
216*61046927SAndroid Build Coastguard Worker        (["unsigned nr_dests"] if op["variable_dests"] else
217*61046927SAndroid Build Coastguard Worker            ["bi_index dest{}".format(i) for i in range(0 if no_dests else op["dests"])]) +
218*61046927SAndroid Build Coastguard Worker        (["unsigned nr_srcs"] if op["variable_srcs"] else
219*61046927SAndroid Build Coastguard Worker            ["bi_index src{}".format(i) for i in range(src_count(op))]) +
220*61046927SAndroid Build Coastguard Worker        ["{} {}".format(
221*61046927SAndroid Build Coastguard Worker        "bool" if len(modifiers[T[0:-1]] if T[-1] in "0123" else modifiers[T]) == 2 else
222*61046927SAndroid Build Coastguard Worker        "enum bi_" + T[0:-1] if T[-1] in "0123" else
223*61046927SAndroid Build Coastguard Worker        "enum bi_" + T,
224*61046927SAndroid Build Coastguard Worker        T) for T in modifier_signature(op)] +
225*61046927SAndroid Build Coastguard Worker        ["uint32_t {}".format(imm) for imm in op["immediates"]])
226*61046927SAndroid Build Coastguard Worker
227*61046927SAndroid Build Coastguard Workerdef arguments(op, temp_dest = True):
228*61046927SAndroid Build Coastguard Worker    dest_pattern = "bi_temp(b->shader)" if temp_dest else 'dest{}'
229*61046927SAndroid Build Coastguard Worker    dests = [dest_pattern.format(i) for i in range(op["dests"])]
230*61046927SAndroid Build Coastguard Worker    srcs = ["src{}".format(i) for i in range(src_count(op))]
231*61046927SAndroid Build Coastguard Worker
232*61046927SAndroid Build Coastguard Worker    # Variable source/destinations just pass in the count
233*61046927SAndroid Build Coastguard Worker    if op["variable_dests"]:
234*61046927SAndroid Build Coastguard Worker        dests = ["nr_dests"]
235*61046927SAndroid Build Coastguard Worker
236*61046927SAndroid Build Coastguard Worker    if op["variable_srcs"]:
237*61046927SAndroid Build Coastguard Worker        srcs = ["nr_srcs"]
238*61046927SAndroid Build Coastguard Worker
239*61046927SAndroid Build Coastguard Worker    return ", ".join(["b"] + dests + srcs + modifier_signature(op) + op["immediates"])
240*61046927SAndroid Build Coastguard Worker
241*61046927SAndroid Build Coastguard Workerprint(Template(COPYRIGHT + TEMPLATE).render(ops = ir_instructions, modifiers =
242*61046927SAndroid Build Coastguard Worker    modifier_lists, signature = signature, arguments = arguments, src_count =
243*61046927SAndroid Build Coastguard Worker    src_count, typesize = typesize, should_skip = should_skip))
244