1 /*
2 * Copyright 2008 Nicolai Haehnle.
3 * SPDX-License-Identifier: MIT
4 */
5
6 #include "radeon_program.h"
7
8 #include <stdio.h>
9
10 #include "radeon_compiler.h"
11 #include "radeon_dataflow.h"
12
13 /**
14 * Transform the given clause in the following way:
15 * 1. Replace it with an empty clause
16 * 2. For every instruction in the original clause, try the given
17 * transformations in order.
18 * 3. If one of the transformations returns GL_TRUE, assume that it
19 * has emitted the appropriate instruction(s) into the new clause;
20 * otherwise, copy the instruction verbatim.
21 *
22 * \note The transformation is currently not recursive; in other words,
23 * instructions emitted by transformations are not transformed.
24 *
25 * \note The transform is called 'local' because it can only look at
26 * one instruction at a time.
27 */
28 void
rc_local_transform(struct radeon_compiler * c,void * user)29 rc_local_transform(struct radeon_compiler *c, void *user)
30 {
31 struct radeon_program_transformation *transformations =
32 (struct radeon_program_transformation *)user;
33 struct rc_instruction *inst = c->Program.Instructions.Next;
34
35 while (inst != &c->Program.Instructions) {
36 struct rc_instruction *current = inst;
37 int i;
38
39 inst = inst->Next;
40
41 for (i = 0; transformations[i].function; ++i) {
42 struct radeon_program_transformation *t = transformations + i;
43
44 if (t->function(c, current, t->userData))
45 break;
46 }
47 }
48 }
49
50 unsigned int
rc_find_free_temporary(struct radeon_compiler * c)51 rc_find_free_temporary(struct radeon_compiler *c)
52 {
53 /* Find the largest used temp index when called for the first time. */
54 if (c->max_temp_index == -1) {
55 for (struct rc_instruction *inst = c->Program.Instructions.Next;
56 inst != &c->Program.Instructions; inst = inst->Next) {
57 const struct rc_opcode_info *opcode = rc_get_opcode_info(inst->U.I.Opcode);
58 if (opcode->HasDstReg && inst->U.I.DstReg.File == RC_FILE_TEMPORARY &&
59 inst->U.I.WriteALUResult == RC_ALURESULT_NONE &&
60 inst->U.I.DstReg.Index > c->max_temp_index)
61 c->max_temp_index = inst->U.I.DstReg.Index;
62 }
63 }
64
65 c->max_temp_index++;
66 if (c->max_temp_index > RC_REGISTER_MAX_INDEX) {
67 rc_error(c, "Ran out of temporary registers\n");
68 return 0;
69 }
70 return c->max_temp_index;
71 }
72
73 struct rc_instruction *
rc_alloc_instruction(struct radeon_compiler * c)74 rc_alloc_instruction(struct radeon_compiler *c)
75 {
76 struct rc_instruction *inst = memory_pool_malloc(&c->Pool, sizeof(struct rc_instruction));
77
78 memset(inst, 0, sizeof(struct rc_instruction));
79
80 inst->U.I.Opcode = RC_OPCODE_ILLEGAL_OPCODE;
81 inst->U.I.DstReg.WriteMask = RC_MASK_XYZW;
82 inst->U.I.SrcReg[0].Swizzle = RC_SWIZZLE_XYZW;
83 inst->U.I.SrcReg[1].Swizzle = RC_SWIZZLE_XYZW;
84 inst->U.I.SrcReg[2].Swizzle = RC_SWIZZLE_XYZW;
85
86 return inst;
87 }
88
89 void
rc_insert_instruction(struct rc_instruction * after,struct rc_instruction * inst)90 rc_insert_instruction(struct rc_instruction *after, struct rc_instruction *inst)
91 {
92 inst->Prev = after;
93 inst->Next = after->Next;
94
95 inst->Prev->Next = inst;
96 inst->Next->Prev = inst;
97 }
98
99 struct rc_instruction *
rc_insert_new_instruction(struct radeon_compiler * c,struct rc_instruction * after)100 rc_insert_new_instruction(struct radeon_compiler *c, struct rc_instruction *after)
101 {
102 struct rc_instruction *inst = rc_alloc_instruction(c);
103
104 rc_insert_instruction(after, inst);
105
106 return inst;
107 }
108
109 void
rc_remove_instruction(struct rc_instruction * inst)110 rc_remove_instruction(struct rc_instruction *inst)
111 {
112 inst->Prev->Next = inst->Next;
113 inst->Next->Prev = inst->Prev;
114 }
115
116 /**
117 * Return the number of instructions in the program.
118 */
119 unsigned int
rc_recompute_ips(struct radeon_compiler * c)120 rc_recompute_ips(struct radeon_compiler *c)
121 {
122 unsigned int ip = 0;
123 struct rc_instruction *inst;
124
125 for (inst = c->Program.Instructions.Next; inst != &c->Program.Instructions; inst = inst->Next) {
126 inst->IP = ip++;
127 }
128
129 c->Program.Instructions.IP = 0xcafedead;
130
131 return ip;
132 }
133