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

« back to all changes in this revision

Viewing changes to src/mesa/drivers/dri/r300/compiler/radeon_variable.c

  • Committer: Package Import Robot
  • Author(s): Robert Hooker
  • Date: 2012-02-02 12:05:48 UTC
  • mfrom: (1.7.1) (3.3.27 sid)
  • Revision ID: package-import@ubuntu.com-20120202120548-nvkma85jq0h4coix
Tags: 8.0~rc2-0ubuntu4
Drop drisearchdir handling, it is no longer needed with multiarch
and dri-alternates being removed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright 2011 Tom Stellard <tstellar@gmail.com>
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_variable.h"
29
 
 
30
 
#include "memory_pool.h"
31
 
#include "radeon_compiler_util.h"
32
 
#include "radeon_dataflow.h"
33
 
#include "radeon_list.h"
34
 
#include "radeon_opcodes.h"
35
 
#include "radeon_program.h"
36
 
 
37
 
/**
38
 
 * Rewrite the index and writemask for the destination register of var
39
 
 * and its friends to new_index and new_writemask.  This function also takes
40
 
 * care of rewriting the swizzles for the sources of var.
41
 
 */
42
 
void rc_variable_change_dst(
43
 
        struct rc_variable * var,
44
 
        unsigned int new_index,
45
 
        unsigned int new_writemask)
46
 
{
47
 
        struct rc_variable * var_ptr;
48
 
        struct rc_list * readers;
49
 
        unsigned int old_mask = rc_variable_writemask_sum(var);
50
 
        unsigned int conversion_swizzle =
51
 
                        rc_make_conversion_swizzle(old_mask, new_writemask);
52
 
 
53
 
        for (var_ptr = var; var_ptr; var_ptr = var_ptr->Friend) {
54
 
                if (var_ptr->Inst->Type == RC_INSTRUCTION_NORMAL) {
55
 
                        rc_normal_rewrite_writemask(var_ptr->Inst,
56
 
                                                        conversion_swizzle);
57
 
                        var_ptr->Inst->U.I.DstReg.Index = new_index;
58
 
                } else {
59
 
                        struct rc_pair_sub_instruction * sub;
60
 
                        if (var_ptr->Dst.WriteMask == RC_MASK_W) {
61
 
                                assert(new_writemask & RC_MASK_W);
62
 
                                sub = &var_ptr->Inst->U.P.Alpha;
63
 
                        } else {
64
 
                                sub = &var_ptr->Inst->U.P.RGB;
65
 
                                rc_pair_rewrite_writemask(sub,
66
 
                                                        conversion_swizzle);
67
 
                        }
68
 
                        sub->DestIndex = new_index;
69
 
                }
70
 
        }
71
 
 
72
 
        readers = rc_variable_readers_union(var);
73
 
 
74
 
        for ( ; readers; readers = readers->Next) {
75
 
                struct rc_reader * reader = readers->Item;
76
 
                if (reader->Inst->Type == RC_INSTRUCTION_NORMAL) {
77
 
                        reader->U.I.Src->Index = new_index;
78
 
                        reader->U.I.Src->Swizzle = rc_rewrite_swizzle(
79
 
                                reader->U.I.Src->Swizzle, conversion_swizzle);
80
 
                } else {
81
 
                        struct rc_pair_instruction * pair_inst =
82
 
                                                        &reader->Inst->U.P;
83
 
                        unsigned int src_type = rc_source_type_swz(
84
 
                                                        reader->U.P.Arg->Swizzle);
85
 
 
86
 
                        int src_index = reader->U.P.Arg->Source;
87
 
                        if (src_index == RC_PAIR_PRESUB_SRC) {
88
 
                                src_index = rc_pair_get_src_index(
89
 
                                                pair_inst, reader->U.P.Src);
90
 
                        }
91
 
                        /* Try to delete the old src, it is OK if this fails,
92
 
                         * because rc_pair_alloc_source might be able to
93
 
                         * find a source the ca be reused.
94
 
                         */
95
 
                        if (rc_pair_remove_src(reader->Inst, src_type,
96
 
                                                        src_index, old_mask)) {
97
 
                                /* Reuse the source index of the source that
98
 
                                 * was just deleted and set its register
99
 
                                 * index.  We can't use rc_pair_alloc_source
100
 
                                 * for this becuase it might return a source
101
 
                                 * index that is already being used. */
102
 
                                if (src_type & RC_SOURCE_RGB) {
103
 
                                        pair_inst->RGB.Src[src_index]
104
 
                                                .Used = 1;
105
 
                                        pair_inst->RGB.Src[src_index]
106
 
                                                .Index = new_index;
107
 
                                        pair_inst->RGB.Src[src_index]
108
 
                                                .File = RC_FILE_TEMPORARY;
109
 
                                }
110
 
                                if (src_type & RC_SOURCE_ALPHA) {
111
 
                                        pair_inst->Alpha.Src[src_index]
112
 
                                                .Used = 1;
113
 
                                        pair_inst->Alpha.Src[src_index]
114
 
                                                .Index = new_index;
115
 
                                        pair_inst->Alpha.Src[src_index]
116
 
                                                .File = RC_FILE_TEMPORARY;
117
 
                                }
118
 
                        } else {
119
 
                                src_index = rc_pair_alloc_source(
120
 
                                                &reader->Inst->U.P,
121
 
                                                src_type & RC_SOURCE_RGB,
122
 
                                                src_type & RC_SOURCE_ALPHA,
123
 
                                                RC_FILE_TEMPORARY,
124
 
                                                new_index);
125
 
                                if (src_index < 0) {
126
 
                                        rc_error(var->C, "Rewrite of inst %u failed "
127
 
                                                "Can't allocate source for "
128
 
                                                "Inst %u src_type=%x "
129
 
                                                "new_index=%u new_mask=%u\n",
130
 
                                                var->Inst->IP, reader->Inst->IP, src_type, new_index, new_writemask);
131
 
                                                continue;
132
 
                                }
133
 
                        }
134
 
                        reader->U.P.Arg->Swizzle = rc_rewrite_swizzle(
135
 
                                reader->U.P.Arg->Swizzle, conversion_swizzle);
136
 
                        if (reader->U.P.Arg->Source != RC_PAIR_PRESUB_SRC) {
137
 
                                reader->U.P.Arg->Source = src_index;
138
 
                        }
139
 
                }
140
 
        }
141
 
}
142
 
 
143
 
/**
144
 
 * Compute the live intervals for var and its friends.
145
 
 */
146
 
void rc_variable_compute_live_intervals(struct rc_variable * var)
147
 
{
148
 
        while(var) {
149
 
                unsigned int i;
150
 
                unsigned int start = var->Inst->IP;
151
 
 
152
 
                for (i = 0; i < var->ReaderCount; i++) {
153
 
                        unsigned int chan;
154
 
                        unsigned int chan_start = start;
155
 
                        unsigned int chan_end = var->Readers[i].Inst->IP;
156
 
                        unsigned int mask = var->Readers[i].WriteMask;
157
 
                        struct rc_instruction * inst;
158
 
 
159
 
                        /* Extend the live interval of T0 to the start of the
160
 
                         * loop for sequences like:
161
 
                         * BGNLOOP
162
 
                         * read T0
163
 
                         * ...
164
 
                         * write T0
165
 
                         * ENDLOOP
166
 
                         */
167
 
                        if (var->Readers[i].Inst->IP < start) {
168
 
                                struct rc_instruction * bgnloop =
169
 
                                        rc_match_endloop(var->Readers[i].Inst);
170
 
                                chan_start = bgnloop->IP;
171
 
                        }
172
 
 
173
 
                        /* Extend the live interval of T0 to the start of the
174
 
                         * loop in case there is a BRK instruction in the loop
175
 
                         * (we don't actually check for a BRK instruction we
176
 
                         * assume there is one somewhere in the loop, which
177
 
                         * there usually is) for sequences like:
178
 
                         * BGNLOOP
179
 
                         * ...
180
 
                         * conditional BRK
181
 
                         * ...
182
 
                         * write T0
183
 
                         * ENDLOOP
184
 
                         * read T0
185
 
                         ***************************************************
186
 
                         * Extend the live interval of T0 to the end of the
187
 
                         * loop for sequences like:
188
 
                         * write T0
189
 
                         * BGNLOOP
190
 
                         * ...
191
 
                         * read T0
192
 
                         * ENDLOOP
193
 
                         */
194
 
                        for (inst = var->Inst; inst != var->Readers[i].Inst;
195
 
                                                        inst = inst->Next) {
196
 
                                rc_opcode op = rc_get_flow_control_inst(inst);
197
 
                                if (op == RC_OPCODE_ENDLOOP) {
198
 
                                        struct rc_instruction * bgnloop =
199
 
                                                rc_match_endloop(inst);
200
 
                                        if (bgnloop->IP < chan_start) {
201
 
                                                chan_start = bgnloop->IP;
202
 
                                        }
203
 
                                } else if (op == RC_OPCODE_BGNLOOP) {
204
 
                                        struct rc_instruction * endloop =
205
 
                                                rc_match_bgnloop(inst);
206
 
                                        if (endloop->IP > chan_end) {
207
 
                                                chan_end = endloop->IP;
208
 
                                        }
209
 
                                }
210
 
                        }
211
 
 
212
 
                        for (chan = 0; chan < 4; chan++) {
213
 
                                if ((mask >> chan) & 0x1) {
214
 
                                        if (!var->Live[chan].Used
215
 
                                        || chan_start < var->Live[chan].Start) {
216
 
                                                var->Live[chan].Start =
217
 
                                                                chan_start;
218
 
                                        }
219
 
                                        if (!var->Live[chan].Used
220
 
                                        || chan_end > var->Live[chan].End) {
221
 
                                                var->Live[chan].End = chan_end;
222
 
                                        }
223
 
                                        var->Live[chan].Used = 1;
224
 
                                }
225
 
                        }
226
 
                }
227
 
                var = var->Friend;
228
 
        }
229
 
}
230
 
 
231
 
/**
232
 
 * @return 1 if a and b share a reader
233
 
 * @return 0 if they do not
234
 
 */
235
 
static unsigned int readers_intersect(
236
 
        struct rc_variable * a,
237
 
        struct rc_variable * b)
238
 
{
239
 
        unsigned int a_index, b_index;
240
 
        for (a_index = 0; a_index < a->ReaderCount; a_index++) {
241
 
                struct rc_reader reader_a = a->Readers[a_index];
242
 
                for (b_index = 0; b_index < b->ReaderCount; b_index++) {
243
 
                        struct rc_reader reader_b = b->Readers[b_index];
244
 
                        if (reader_a.Inst->Type == RC_INSTRUCTION_NORMAL
245
 
                                && reader_b.Inst->Type == RC_INSTRUCTION_NORMAL
246
 
                                && reader_a.U.I.Src == reader_b.U.I.Src) {
247
 
 
248
 
                                return 1;
249
 
                        }
250
 
                        if (reader_a.Inst->Type == RC_INSTRUCTION_PAIR
251
 
                                && reader_b.Inst->Type == RC_INSTRUCTION_PAIR
252
 
                                && reader_a.U.P.Src == reader_b.U.P.Src) {
253
 
 
254
 
                                return 1;
255
 
                        }
256
 
                }
257
 
        }
258
 
        return 0;
259
 
}
260
 
 
261
 
void rc_variable_add_friend(
262
 
        struct rc_variable * var,
263
 
        struct rc_variable * friend)
264
 
{
265
 
        assert(var->Dst.Index == friend->Dst.Index);
266
 
        while(var->Friend) {
267
 
                var = var->Friend;
268
 
        }
269
 
        var->Friend = friend;
270
 
}
271
 
 
272
 
struct rc_variable * rc_variable(
273
 
        struct radeon_compiler * c,
274
 
        unsigned int DstFile,
275
 
        unsigned int DstIndex,
276
 
        unsigned int DstWriteMask,
277
 
        struct rc_reader_data * reader_data)
278
 
{
279
 
        struct rc_variable * new =
280
 
                        memory_pool_malloc(&c->Pool, sizeof(struct rc_variable));
281
 
        memset(new, 0, sizeof(struct rc_variable));
282
 
        new->C = c;
283
 
        new->Dst.File = DstFile;
284
 
        new->Dst.Index = DstIndex;
285
 
        new->Dst.WriteMask = DstWriteMask;
286
 
        if (reader_data) {
287
 
                new->Inst = reader_data->Writer;
288
 
                new->ReaderCount = reader_data->ReaderCount;
289
 
                new->Readers = reader_data->Readers;
290
 
        }
291
 
        return new;
292
 
}
293
 
 
294
 
static void get_variable_helper(
295
 
        struct rc_list ** variable_list,
296
 
        struct rc_variable * variable)
297
 
{
298
 
        struct rc_list * list_ptr;
299
 
        for (list_ptr = *variable_list; list_ptr; list_ptr = list_ptr->Next) {
300
 
                if (readers_intersect(variable, list_ptr->Item)) {
301
 
                        rc_variable_add_friend(list_ptr->Item, variable);
302
 
                        return;
303
 
                }
304
 
        }
305
 
        rc_list_add(variable_list, rc_list(&variable->C->Pool, variable));
306
 
}
307
 
 
308
 
static void get_variable_pair_helper(
309
 
        struct rc_list ** variable_list,
310
 
        struct radeon_compiler * c,
311
 
        struct rc_instruction * inst,
312
 
        struct rc_pair_sub_instruction * sub_inst)
313
 
{
314
 
        struct rc_reader_data reader_data;
315
 
        struct rc_variable * new_var;
316
 
        rc_register_file file;
317
 
        unsigned int writemask;
318
 
 
319
 
        if (sub_inst->Opcode == RC_OPCODE_NOP) {
320
 
                return;
321
 
        }
322
 
        memset(&reader_data, 0, sizeof(struct rc_reader_data));
323
 
        rc_get_readers_sub(c, inst, sub_inst, &reader_data, NULL, NULL, NULL);
324
 
 
325
 
        if (reader_data.ReaderCount == 0) {
326
 
                return;
327
 
        }
328
 
 
329
 
        if (sub_inst->WriteMask) {
330
 
                file = RC_FILE_TEMPORARY;
331
 
                writemask = sub_inst->WriteMask;
332
 
        } else if (sub_inst->OutputWriteMask) {
333
 
                file = RC_FILE_OUTPUT;
334
 
                writemask = sub_inst->OutputWriteMask;
335
 
        } else {
336
 
                writemask = 0;
337
 
                file = RC_FILE_NONE;
338
 
        }
339
 
        new_var = rc_variable(c, file, sub_inst->DestIndex, writemask,
340
 
                                                                &reader_data);
341
 
        get_variable_helper(variable_list, new_var);
342
 
}
343
 
 
344
 
/**
345
 
 * Generate a list of variables used by the shader program.  Each instruction
346
 
 * that writes to a register is considered a variable.  The struct rc_variable
347
 
 * data structure includes a list of readers and is essentially a
348
 
 * definition-use chain.  Any two variables that share a reader are considered
349
 
 * "friends" and they are linked together via the Friend attribute.
350
 
 */
351
 
struct rc_list * rc_get_variables(struct radeon_compiler * c)
352
 
{
353
 
        struct rc_instruction * inst;
354
 
        struct rc_list * variable_list = NULL;
355
 
 
356
 
        for (inst = c->Program.Instructions.Next;
357
 
                                        inst != &c->Program.Instructions;
358
 
                                        inst = inst->Next) {
359
 
                struct rc_reader_data reader_data;
360
 
                struct rc_variable * new_var;
361
 
                memset(&reader_data, 0, sizeof(reader_data));
362
 
 
363
 
                if (inst->Type == RC_INSTRUCTION_NORMAL) {
364
 
                        rc_get_readers(c, inst, &reader_data, NULL, NULL, NULL);
365
 
                        if (reader_data.ReaderCount == 0) {
366
 
                                continue;
367
 
                        }
368
 
                        new_var = rc_variable(c, inst->U.I.DstReg.File,
369
 
                                inst->U.I.DstReg.Index,
370
 
                                inst->U.I.DstReg.WriteMask, &reader_data);
371
 
                        get_variable_helper(&variable_list, new_var);
372
 
                } else {
373
 
                        get_variable_pair_helper(&variable_list, c, inst,
374
 
                                                        &inst->U.P.RGB);
375
 
                        get_variable_pair_helper(&variable_list, c, inst,
376
 
                                                        &inst->U.P.Alpha);
377
 
                }
378
 
        }
379
 
 
380
 
        return variable_list;
381
 
}
382
 
 
383
 
/**
384
 
 * @return The bitwise or of the writemasks of a variable and all of its
385
 
 * friends.
386
 
 */
387
 
unsigned int rc_variable_writemask_sum(struct rc_variable * var)
388
 
{
389
 
        unsigned int writemask = 0;
390
 
        while(var) {
391
 
                writemask |= var->Dst.WriteMask;
392
 
                var = var->Friend;
393
 
        }
394
 
        return writemask;
395
 
}
396
 
 
397
 
/*
398
 
 * @return A list of readers for a variable and its friends.  Readers
399
 
 * that read from two different variable friends are only included once in
400
 
 * this list.
401
 
 */
402
 
struct rc_list * rc_variable_readers_union(struct rc_variable * var)
403
 
{
404
 
        struct rc_list * list = NULL;
405
 
        while (var) {
406
 
                unsigned int i;
407
 
                for (i = 0; i < var->ReaderCount; i++) {
408
 
                        struct rc_list * temp;
409
 
                        struct rc_reader * a = &var->Readers[i];
410
 
                        unsigned int match = 0;
411
 
                        for (temp = list; temp; temp = temp->Next) {
412
 
                                struct rc_reader * b = temp->Item;
413
 
                                if (a->Inst->Type != b->Inst->Type) {
414
 
                                        continue;
415
 
                                }
416
 
                                if (a->Inst->Type == RC_INSTRUCTION_NORMAL) {
417
 
                                        if (a->U.I.Src == b->U.I.Src) {
418
 
                                                match = 1;
419
 
                                                break;
420
 
                                        }
421
 
                                }
422
 
                                if (a->Inst->Type == RC_INSTRUCTION_PAIR) {
423
 
                                        if (a->U.P.Arg == b->U.P.Arg
424
 
                                            && a->U.P.Src == b->U.P.Src) {
425
 
                                                match = 1;
426
 
                                                break;
427
 
                                        }
428
 
                                }
429
 
                        }
430
 
                        if (match) {
431
 
                                continue;
432
 
                        }
433
 
                        rc_list_add(&list, rc_list(&var->C->Pool, a));
434
 
                }
435
 
                var = var->Friend;
436
 
        }
437
 
        return list;
438
 
}
439
 
 
440
 
static unsigned int reader_equals_src(
441
 
        struct rc_reader reader,
442
 
        unsigned int src_type,
443
 
        void * src)
444
 
{
445
 
        if (reader.Inst->Type != src_type) {
446
 
                return 0;
447
 
        }
448
 
        if (src_type == RC_INSTRUCTION_NORMAL) {
449
 
                return reader.U.I.Src == src;
450
 
        } else {
451
 
                return reader.U.P.Src == src;
452
 
        }
453
 
}
454
 
 
455
 
static unsigned int variable_writes_src(
456
 
        struct rc_variable * var,
457
 
        unsigned int src_type,
458
 
        void * src)
459
 
{
460
 
        unsigned int i;
461
 
        for (i = 0; i < var->ReaderCount; i++) {
462
 
                if (reader_equals_src(var->Readers[i], src_type, src)) {
463
 
                        return 1;
464
 
                }
465
 
        }
466
 
        return 0;
467
 
}
468
 
 
469
 
 
470
 
struct rc_list * rc_variable_list_get_writers(
471
 
        struct rc_list * var_list,
472
 
        unsigned int src_type,
473
 
        void * src)
474
 
{
475
 
        struct rc_list * list_ptr;
476
 
        struct rc_list * writer_list = NULL;
477
 
        for (list_ptr = var_list; list_ptr; list_ptr = list_ptr->Next) {
478
 
                struct rc_variable * var = list_ptr->Item;
479
 
                if (variable_writes_src(var, src_type, src)) {
480
 
                        struct rc_variable * friend;
481
 
                        rc_list_add(&writer_list, rc_list(&var->C->Pool, var));
482
 
                        for (friend = var->Friend; friend;
483
 
                                                friend = friend->Friend) {
484
 
                                if (variable_writes_src(friend, src_type, src)) {
485
 
                                        rc_list_add(&writer_list,
486
 
                                                rc_list(&var->C->Pool, friend));
487
 
                                }
488
 
                        }
489
 
                        /* Once we have indentifed the variable and its
490
 
                         * friends that write this source, we can stop
491
 
                         * stop searching, because we know know of the
492
 
                         * other variables in the list will write this source.
493
 
                         * If they did they would be friends of var.
494
 
                         */
495
 
                        break;
496
 
                }
497
 
        }
498
 
        return writer_list;
499
 
}
500
 
 
501
 
void rc_variable_print(struct rc_variable * var)
502
 
{
503
 
        unsigned int i;
504
 
        while (var) {
505
 
                fprintf(stderr, "%u: TEMP[%u].%u: ",
506
 
                        var->Inst->IP, var->Dst.Index, var->Dst.WriteMask);
507
 
                for (i = 0; i < 4; i++) {
508
 
                        fprintf(stderr, "chan %u: start=%u end=%u ", i,
509
 
                                        var->Live[i].Start, var->Live[i].End);
510
 
                }
511
 
                fprintf(stderr, "%u readers\n", var->ReaderCount);
512
 
                if (var->Friend) {
513
 
                        fprintf(stderr, "Friend: \n\t");
514
 
                }
515
 
                var = var->Friend;
516
 
        }
517
 
}