~ubuntu-branches/ubuntu/precise/mesa-lts-quantal/precise-updates

« back to all changes in this revision

Viewing changes to src/gallium/drivers/r300/compiler/radeon_program.c

  • Committer: Package Import Robot
  • Author(s): Maarten Lankhorst
  • Date: 2012-11-30 20:58:34 UTC
  • Revision ID: package-import@ubuntu.com-20121130205834-gazuvne3fpwlf012
Tags: upstream-9.0
ImportĀ upstreamĀ versionĀ 9.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2008 Nicolai Haehnle.
 
3
 *
 
4
 * All Rights Reserved.
 
5
 *
 
6
 * Permission is hereby granted, free of charge, to any person obtaining
 
7
 * a copy of this software and associated documentation files (the
 
8
 * "Software"), to deal in the Software without restriction, including
 
9
 * without limitation the rights to use, copy, modify, merge, publish,
 
10
 * distribute, sublicense, and/or sell copies of the Software, and to
 
11
 * permit persons to whom the Software is furnished to do so, subject to
 
12
 * the following conditions:
 
13
 *
 
14
 * The above copyright notice and this permission notice (including the
 
15
 * next paragraph) shall be included in all copies or substantial
 
16
 * portions of the Software.
 
17
 *
 
18
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 
19
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 
20
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 
21
 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
 
22
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 
23
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 
24
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
25
 *
 
26
 */
 
27
 
 
28
#include "radeon_program.h"
 
29
 
 
30
#include <stdio.h>
 
31
 
 
32
#include "radeon_compiler.h"
 
33
#include "radeon_dataflow.h"
 
34
 
 
35
 
 
36
/**
 
37
 * Transform the given clause in the following way:
 
38
 *  1. Replace it with an empty clause
 
39
 *  2. For every instruction in the original clause, try the given
 
40
 *     transformations in order.
 
41
 *  3. If one of the transformations returns GL_TRUE, assume that it
 
42
 *     has emitted the appropriate instruction(s) into the new clause;
 
43
 *     otherwise, copy the instruction verbatim.
 
44
 *
 
45
 * \note The transformation is currently not recursive; in other words,
 
46
 * instructions emitted by transformations are not transformed.
 
47
 *
 
48
 * \note The transform is called 'local' because it can only look at
 
49
 * one instruction at a time.
 
50
 */
 
51
void rc_local_transform(
 
52
        struct radeon_compiler * c,
 
53
        void *user)
 
54
{
 
55
        struct radeon_program_transformation *transformations =
 
56
                (struct radeon_program_transformation*)user;
 
57
        struct rc_instruction * inst = c->Program.Instructions.Next;
 
58
 
 
59
        while(inst != &c->Program.Instructions) {
 
60
                struct rc_instruction * current = inst;
 
61
                int i;
 
62
 
 
63
                inst = inst->Next;
 
64
 
 
65
                for(i = 0; transformations[i].function; ++i) {
 
66
                        struct radeon_program_transformation* t = transformations + i;
 
67
 
 
68
                        if (t->function(c, current, t->userData))
 
69
                                break;
 
70
                }
 
71
        }
 
72
}
 
73
 
 
74
struct get_used_temporaries_data {
 
75
        unsigned char * Used;
 
76
        unsigned int UsedLength;
 
77
};
 
78
 
 
79
static void get_used_temporaries_cb(
 
80
        void * userdata,
 
81
        struct rc_instruction * inst,
 
82
        rc_register_file file,
 
83
        unsigned int index,
 
84
        unsigned int mask)
 
85
{
 
86
        struct get_used_temporaries_data * d = userdata;
 
87
 
 
88
        if (file != RC_FILE_TEMPORARY)
 
89
                return;
 
90
 
 
91
        if (index >= d->UsedLength)
 
92
                return;
 
93
 
 
94
        d->Used[index] |= mask;
 
95
}
 
96
 
 
97
/**
 
98
 * This function fills in the parameter 'used' with a writemask that
 
99
 * represent which components of each temporary register are used by the
 
100
 * program.  This is meant to be combined with rc_find_free_temporary_list as a
 
101
 * more efficient version of rc_find_free_temporary.
 
102
 * @param used The function does not initialize this parameter.
 
103
 */
 
104
void rc_get_used_temporaries(
 
105
        struct radeon_compiler * c,
 
106
        unsigned char * used,
 
107
        unsigned int used_length)
 
108
{
 
109
        struct rc_instruction * inst;
 
110
        struct get_used_temporaries_data d;
 
111
        d.Used = used;
 
112
        d.UsedLength = used_length;
 
113
 
 
114
        for(inst = c->Program.Instructions.Next;
 
115
                        inst != &c->Program.Instructions; inst = inst->Next) {
 
116
 
 
117
                rc_for_all_reads_mask(inst, get_used_temporaries_cb, &d);
 
118
                rc_for_all_writes_mask(inst, get_used_temporaries_cb, &d);
 
119
        }
 
120
}
 
121
 
 
122
/* Search a list of used temporaries for a free one
 
123
 * \sa rc_get_used_temporaries
 
124
 * @note If this functions finds a free temporary, it will mark it as used
 
125
 * in the used temporary list (param 'used')
 
126
 * @param used list of used temporaries
 
127
 * @param used_length number of items in param 'used'
 
128
 * @param mask which components must be free in the temporary index that is
 
129
 * returned.
 
130
 * @return -1 If there are no more free temporaries, otherwise the index of
 
131
 * a temporary register where the components specified in param 'mask' are
 
132
 * not being used.
 
133
 */
 
134
int rc_find_free_temporary_list(
 
135
        struct radeon_compiler * c,
 
136
        unsigned char * used,
 
137
        unsigned int used_length,
 
138
        unsigned int mask)
 
139
{
 
140
        int i;
 
141
        for(i = 0; i < used_length; i++) {
 
142
                if ((~used[i] & mask) == mask) {
 
143
                        used[i] |= mask;
 
144
                        return i;
 
145
                }
 
146
        }
 
147
        return -1;
 
148
}
 
149
 
 
150
unsigned int rc_find_free_temporary(struct radeon_compiler * c)
 
151
{
 
152
        unsigned char used[RC_REGISTER_MAX_INDEX];
 
153
        int free;
 
154
 
 
155
        memset(used, 0, sizeof(used));
 
156
 
 
157
        rc_get_used_temporaries(c, used, RC_REGISTER_MAX_INDEX);
 
158
 
 
159
        free = rc_find_free_temporary_list(c, used, RC_REGISTER_MAX_INDEX,
 
160
                                                                RC_MASK_XYZW);
 
161
        if (free < 0) {
 
162
                rc_error(c, "Ran out of temporary registers\n");
 
163
                return 0;
 
164
        }
 
165
        return free;
 
166
}
 
167
 
 
168
 
 
169
struct rc_instruction *rc_alloc_instruction(struct radeon_compiler * c)
 
170
{
 
171
        struct rc_instruction * inst = memory_pool_malloc(&c->Pool, sizeof(struct rc_instruction));
 
172
 
 
173
        memset(inst, 0, sizeof(struct rc_instruction));
 
174
 
 
175
        inst->U.I.Opcode = RC_OPCODE_ILLEGAL_OPCODE;
 
176
        inst->U.I.DstReg.WriteMask = RC_MASK_XYZW;
 
177
        inst->U.I.SrcReg[0].Swizzle = RC_SWIZZLE_XYZW;
 
178
        inst->U.I.SrcReg[1].Swizzle = RC_SWIZZLE_XYZW;
 
179
        inst->U.I.SrcReg[2].Swizzle = RC_SWIZZLE_XYZW;
 
180
 
 
181
        return inst;
 
182
}
 
183
 
 
184
void rc_insert_instruction(struct rc_instruction * after, struct rc_instruction * inst)
 
185
{
 
186
        inst->Prev = after;
 
187
        inst->Next = after->Next;
 
188
 
 
189
        inst->Prev->Next = inst;
 
190
        inst->Next->Prev = inst;
 
191
}
 
192
 
 
193
struct rc_instruction *rc_insert_new_instruction(struct radeon_compiler * c, struct rc_instruction * after)
 
194
{
 
195
        struct rc_instruction * inst = rc_alloc_instruction(c);
 
196
 
 
197
        rc_insert_instruction(after, inst);
 
198
 
 
199
        return inst;
 
200
}
 
201
 
 
202
void rc_remove_instruction(struct rc_instruction * inst)
 
203
{
 
204
        inst->Prev->Next = inst->Next;
 
205
        inst->Next->Prev = inst->Prev;
 
206
}
 
207
 
 
208
/**
 
209
 * Return the number of instructions in the program.
 
210
 */
 
211
unsigned int rc_recompute_ips(struct radeon_compiler * c)
 
212
{
 
213
        unsigned int ip = 0;
 
214
        struct rc_instruction * inst;
 
215
 
 
216
        for(inst = c->Program.Instructions.Next;
 
217
            inst != &c->Program.Instructions;
 
218
            inst = inst->Next) {
 
219
                inst->IP = ip++;
 
220
        }
 
221
 
 
222
        c->Program.Instructions.IP = 0xcafedead;
 
223
 
 
224
        return ip;
 
225
}