xref: /aosp_15_r20/external/mesa3d/src/asahi/compiler/agx_opt_compact_constants.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright 2024 Alyssa Rosenzweig
3  * SPDX-License-Identifier: MIT
4  */
5 
6 #include "util/bitset.h"
7 #include "util/half_float.h"
8 #include "agx_builder.h"
9 #include "agx_compiler.h"
10 #include "agx_opcodes.h"
11 
12 /*
13  * AGX can convert 16-bit sources to 32-bit for free, so it's beneficial to
14  * compact 32-bit constants down to 16-bit when doing so is lossless. This
15  * reduces register pressure (GPR or uniform, depending on whether the constant
16  * is promoted).
17  */
18 void
agx_opt_compact_constants(agx_context * ctx)19 agx_opt_compact_constants(agx_context *ctx)
20 {
21    /* TODO: Handle ints too */
22    BITSET_WORD *src_float = calloc(ctx->alloc, sizeof(BITSET_WORD));
23    BITSET_WORD *src_other = calloc(ctx->alloc, sizeof(BITSET_WORD));
24    BITSET_WORD *replaced = calloc(ctx->alloc, sizeof(BITSET_WORD));
25 
26    /* Analyze the types that we read constants as */
27    agx_foreach_instr_global(ctx, I) {
28       agx_foreach_ssa_src(I, s) {
29          if (agx_is_float_src(I, s))
30             BITSET_SET(src_float, I->src[s].value);
31          else
32             BITSET_SET(src_other, I->src[s].value);
33       }
34    }
35 
36    agx_foreach_instr_global(ctx, I) {
37       if (I->op == AGX_OPCODE_MOV_IMM && I->dest[0].size == AGX_SIZE_32) {
38          unsigned v = I->dest[0].value;
39 
40          if (BITSET_TEST(src_float, v) && !BITSET_TEST(src_other, v)) {
41             /* Try to compact to f16 */
42             uint16_t compact = _mesa_float_to_half(uif(I->imm));
43 
44             if (I->imm == fui(_mesa_half_to_float(compact))) {
45                I->dest[0].size = AGX_SIZE_16;
46                I->imm = compact;
47                BITSET_SET(replaced, v);
48             }
49          }
50       } else {
51          agx_foreach_ssa_src(I, s) {
52             if (BITSET_TEST(replaced, I->src[s].value)) {
53                I->src[s].size = AGX_SIZE_16;
54             }
55          }
56       }
57    }
58 
59    free(replaced);
60    free(src_float);
61    free(src_other);
62 }
63