1 /**************************************************************************
2 *
3 * Copyright 2011-2012 Advanced Micro Devices, Inc.
4 * Copyright 2010 VMware, Inc.
5 * Copyright 2009 VMware, Inc.
6 * Copyright 2007-2008 VMware, Inc.
7 * All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the
11 * "Software"), to deal in the Software without restriction, including
12 * without limitation the rights to use, copy, modify, merge, publish,
13 * distribute, sub license, and/or sell copies of the Software, and to
14 * permit persons to whom the Software is furnished to do so, subject to
15 * the following conditions:
16 *
17 * The above copyright notice and this permission notice (including the
18 * next paragraph) shall be included in all copies or substantial portions
19 * of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
24 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
25 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
26 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
27 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 *
29 **************************************************************************/
30
31 #include "gallivm/lp_bld_tgsi.h"
32
33 #include "gallivm/lp_bld_arit.h"
34 #include "gallivm/lp_bld_gather.h"
35 #include "gallivm/lp_bld_init.h"
36 #include "gallivm/lp_bld_intr.h"
37 #include "tgsi/tgsi_info.h"
38 #include "tgsi/tgsi_parse.h"
39 #include "tgsi/tgsi_util.h"
40 #include "util/u_memory.h"
41
42
43 // grow the instruction buffer by this number of instructions
44 #define LP_NUM_INSTRUCTIONS 256
45
46
47 /* The user is responsible for freeing list->instructions */
48 unsigned
lp_bld_tgsi_list_init(struct lp_build_tgsi_context * bld_base)49 lp_bld_tgsi_list_init(struct lp_build_tgsi_context *bld_base)
50 {
51 bld_base->instructions = (struct tgsi_full_instruction *)
52 MALLOC(LP_NUM_INSTRUCTIONS * sizeof(struct tgsi_full_instruction));
53 if (!bld_base->instructions) {
54 return 0;
55 }
56 bld_base->max_instructions = LP_NUM_INSTRUCTIONS;
57 return 1;
58 }
59
60
61 unsigned
lp_bld_tgsi_add_instruction(struct lp_build_tgsi_context * bld_base,const struct tgsi_full_instruction * inst_to_add)62 lp_bld_tgsi_add_instruction(struct lp_build_tgsi_context *bld_base,
63 const struct tgsi_full_instruction *inst_to_add)
64 {
65 if (bld_base->num_instructions == bld_base->max_instructions) {
66 struct tgsi_full_instruction *instructions =
67 REALLOC(bld_base->instructions, bld_base->max_instructions
68 * sizeof(struct tgsi_full_instruction),
69 (bld_base->max_instructions + LP_NUM_INSTRUCTIONS)
70 * sizeof(struct tgsi_full_instruction));
71 if (!instructions) {
72 return 0;
73 }
74 bld_base->instructions = instructions;
75 bld_base->max_instructions += LP_NUM_INSTRUCTIONS;
76 }
77 memcpy(bld_base->instructions + bld_base->num_instructions, inst_to_add,
78 sizeof(bld_base->instructions[0]));
79
80 bld_base->num_instructions++;
81
82 return 1;
83 }
84
85
86 /**
87 * This function assumes that all the args in emit_data have been set.
88 */
89 static void
lp_build_action_set_dst_type(struct lp_build_emit_data * emit_data,struct lp_build_tgsi_context * bld_base,unsigned tgsi_opcode)90 lp_build_action_set_dst_type(struct lp_build_emit_data *emit_data,
91 struct lp_build_tgsi_context *bld_base,
92 unsigned tgsi_opcode)
93 {
94 if (emit_data->arg_count == 0) {
95 emit_data->dst_type =
96 LLVMVoidTypeInContext(bld_base->base.gallivm->context);
97 } else {
98 /* XXX: Not all opcodes have the same src and dst types. */
99 emit_data->dst_type = LLVMTypeOf(emit_data->args[0]);
100 }
101 }
102
103
104 void
lp_build_tgsi_intrinsic(const struct lp_build_tgsi_action * action,struct lp_build_tgsi_context * bld_base,struct lp_build_emit_data * emit_data)105 lp_build_tgsi_intrinsic(const struct lp_build_tgsi_action *action,
106 struct lp_build_tgsi_context *bld_base,
107 struct lp_build_emit_data *emit_data)
108 {
109 struct lp_build_context * base = &bld_base->base;
110 emit_data->output[emit_data->chan] = lp_build_intrinsic(
111 base->gallivm->builder, action->intr_name,
112 emit_data->dst_type, emit_data->args, emit_data->arg_count, 0);
113 }
114
115
116 LLVMValueRef
lp_build_emit_llvm(struct lp_build_tgsi_context * bld_base,unsigned tgsi_opcode,struct lp_build_emit_data * emit_data)117 lp_build_emit_llvm(struct lp_build_tgsi_context *bld_base,
118 unsigned tgsi_opcode,
119 struct lp_build_emit_data *emit_data)
120 {
121 struct lp_build_tgsi_action * action = &bld_base->op_actions[tgsi_opcode];
122 /* XXX: Assert that this is a componentwise or replicate instruction */
123
124 lp_build_action_set_dst_type(emit_data, bld_base, tgsi_opcode);
125 emit_data->chan = 0;
126 assert(action->emit);
127 action->emit(action, bld_base, emit_data);
128 return emit_data->output[0];
129 }
130
131
132 LLVMValueRef
lp_build_emit_llvm_unary(struct lp_build_tgsi_context * bld_base,unsigned tgsi_opcode,LLVMValueRef arg0)133 lp_build_emit_llvm_unary(struct lp_build_tgsi_context *bld_base,
134 unsigned tgsi_opcode,
135 LLVMValueRef arg0)
136 {
137 struct lp_build_emit_data emit_data = {{0}};
138 emit_data.info = tgsi_get_opcode_info(tgsi_opcode);
139 emit_data.arg_count = 1;
140 emit_data.args[0] = arg0;
141 return lp_build_emit_llvm(bld_base, tgsi_opcode, &emit_data);
142 }
143
144
145 LLVMValueRef
lp_build_emit_llvm_binary(struct lp_build_tgsi_context * bld_base,unsigned tgsi_opcode,LLVMValueRef arg0,LLVMValueRef arg1)146 lp_build_emit_llvm_binary(struct lp_build_tgsi_context *bld_base,
147 unsigned tgsi_opcode,
148 LLVMValueRef arg0,
149 LLVMValueRef arg1)
150 {
151 struct lp_build_emit_data emit_data = {{0}};
152 emit_data.info = tgsi_get_opcode_info(tgsi_opcode);
153 emit_data.arg_count = 2;
154 emit_data.args[0] = arg0;
155 emit_data.args[1] = arg1;
156 return lp_build_emit_llvm(bld_base, tgsi_opcode, &emit_data);
157 }
158
159
160 LLVMValueRef
lp_build_emit_llvm_ternary(struct lp_build_tgsi_context * bld_base,unsigned tgsi_opcode,LLVMValueRef arg0,LLVMValueRef arg1,LLVMValueRef arg2)161 lp_build_emit_llvm_ternary(struct lp_build_tgsi_context *bld_base,
162 unsigned tgsi_opcode,
163 LLVMValueRef arg0,
164 LLVMValueRef arg1,
165 LLVMValueRef arg2)
166 {
167 struct lp_build_emit_data emit_data = {{0}};
168 emit_data.info = tgsi_get_opcode_info(tgsi_opcode);
169 emit_data.arg_count = 3;
170 emit_data.args[0] = arg0;
171 emit_data.args[1] = arg1;
172 emit_data.args[2] = arg2;
173 return lp_build_emit_llvm(bld_base, tgsi_opcode, &emit_data);
174 }
175
176
177 /**
178 * The default fetch implementation.
179 */
180 void
lp_build_fetch_args(struct lp_build_tgsi_context * bld_base,struct lp_build_emit_data * emit_data)181 lp_build_fetch_args(struct lp_build_tgsi_context *bld_base,
182 struct lp_build_emit_data *emit_data)
183 {
184 for (unsigned src = 0; src < emit_data->info->num_src; src++) {
185 emit_data->args[src] = lp_build_emit_fetch(bld_base, emit_data->inst,
186 src, emit_data->src_chan);
187 }
188 emit_data->arg_count = emit_data->info->num_src;
189 lp_build_action_set_dst_type(emit_data, bld_base,
190 emit_data->inst->Instruction.Opcode);
191 }
192
193
194 /**
195 * with 64-bit src and dst channels aren't 1:1.
196 * check the src/dst types for the opcode,
197 * 1. if neither is 64-bit then src == dst;
198 * 2. if dest is 64-bit
199 * - don't store to y or w
200 * - if src is 64-bit then src == dst.
201 * - else for f2d, d.xy = s.x
202 * - else for f2d, d.zw = s.y
203 * 3. if dst is single, src is 64-bit
204 * - map dst x,z to src xy;
205 * - map dst y,w to src zw;
206 */
207 static int
get_src_chan_idx(enum tgsi_opcode opcode,int dst_chan_index)208 get_src_chan_idx(enum tgsi_opcode opcode,
209 int dst_chan_index)
210 {
211 enum tgsi_opcode_type dtype = tgsi_opcode_infer_dst_type(opcode, 0);
212 enum tgsi_opcode_type stype = tgsi_opcode_infer_src_type(opcode, 0);
213
214 if (!tgsi_type_is_64bit(dtype) && !tgsi_type_is_64bit(stype))
215 return dst_chan_index;
216 if (tgsi_type_is_64bit(dtype)) {
217 if (dst_chan_index == 1 || dst_chan_index == 3)
218 return -1;
219 if (tgsi_type_is_64bit(stype))
220 return dst_chan_index;
221 if (dst_chan_index == 0)
222 return 0;
223 if (dst_chan_index == 2)
224 return 1;
225 } else {
226 if (dst_chan_index == 0 || dst_chan_index == 2)
227 return 0;
228 if (dst_chan_index == 1 || dst_chan_index == 3)
229 return 2;
230 }
231 return -1;
232 }
233
234
235 /* XXX: COMMENT
236 * It should be assumed that this function ignores writemasks
237 */
238 boolean
lp_build_tgsi_inst_llvm(struct lp_build_tgsi_context * bld_base,const struct tgsi_full_instruction * inst)239 lp_build_tgsi_inst_llvm(struct lp_build_tgsi_context *bld_base,
240 const struct tgsi_full_instruction *inst)
241 {
242 enum tgsi_opcode opcode = inst->Instruction.Opcode;
243 const struct tgsi_opcode_info *info = tgsi_get_opcode_info(opcode);
244 const struct lp_build_tgsi_action *action = &bld_base->op_actions[opcode];
245 struct lp_build_emit_data emit_data;
246 unsigned chan_index;
247 LLVMValueRef val;
248 bld_base->pc++;
249
250 if (bld_base->emit_debug) {
251 bld_base->emit_debug(bld_base, inst, info);
252 }
253
254 /* Ignore deprecated instructions */
255 switch (inst->Instruction.Opcode) {
256 case TGSI_OPCODE_UP2US:
257 case TGSI_OPCODE_UP4B:
258 case TGSI_OPCODE_UP4UB:
259 /* deprecated? */
260 assert(0);
261 return FALSE;
262 break;
263 }
264
265 /* Check if the opcode has been implemented */
266 if (!action->emit) {
267 return FALSE;
268 }
269
270 memset(&emit_data, 0, sizeof(emit_data));
271
272 assert(info->num_dst <= 2);
273 if (info->num_dst) {
274 TGSI_FOR_EACH_DST0_ENABLED_CHANNEL(inst, chan_index) {
275 emit_data.output[chan_index] = bld_base->base.undef;
276 }
277
278 if (info->num_dst >= 2) {
279 TGSI_FOR_EACH_DST1_ENABLED_CHANNEL(inst, chan_index) {
280 emit_data.output1[chan_index] = bld_base->base.undef;
281 }
282 }
283 }
284
285 emit_data.inst = inst;
286 emit_data.info = info;
287
288 /* Emit the instructions */
289 if (info->output_mode == TGSI_OUTPUT_COMPONENTWISE && bld_base->soa) {
290 TGSI_FOR_EACH_DST0_ENABLED_CHANNEL(inst, chan_index) {
291 int src_index = get_src_chan_idx(inst->Instruction.Opcode, chan_index);
292 /* ignore channels 1/3 in double dst */
293 if (src_index == -1)
294 continue;
295 emit_data.chan = chan_index;
296 emit_data.src_chan = src_index;
297 if (!action->fetch_args) {
298 lp_build_fetch_args(bld_base, &emit_data);
299 } else {
300 action->fetch_args(bld_base, &emit_data);
301 }
302 action->emit(action, bld_base, &emit_data);
303 }
304 } else {
305 emit_data.chan = LP_CHAN_ALL;
306 if (action->fetch_args) {
307 action->fetch_args(bld_base, &emit_data);
308 }
309 /* Make sure the output value is stored in emit_data.output[0], unless
310 * the opcode is channel dependent */
311 if (info->output_mode != TGSI_OUTPUT_CHAN_DEPENDENT) {
312 emit_data.chan = 0;
313 }
314 action->emit(action, bld_base, &emit_data);
315
316 /* Replicate the output values */
317 if (info->output_mode == TGSI_OUTPUT_REPLICATE && bld_base->soa) {
318 val = emit_data.output[0];
319 memset(emit_data.output, 0, sizeof(emit_data.output));
320 TGSI_FOR_EACH_DST0_ENABLED_CHANNEL(inst, chan_index) {
321 emit_data.output[chan_index] = val;
322 }
323
324 if (info->num_dst >= 2) {
325 val = emit_data.output1[0];
326 memset(emit_data.output1, 0, sizeof(emit_data.output1));
327 TGSI_FOR_EACH_DST1_ENABLED_CHANNEL(inst, chan_index) {
328 emit_data.output1[chan_index] = val;
329 }
330 }
331 }
332 }
333
334 if (info->num_dst > 0 && info->opcode != TGSI_OPCODE_STORE) {
335 bld_base->emit_store(bld_base, inst, info, 0, emit_data.output);
336 if (info->num_dst >= 2)
337 bld_base->emit_store(bld_base, inst, info, 1, emit_data.output1);
338 }
339 return TRUE;
340 }
341
342
343 LLVMValueRef
lp_build_emit_fetch_src(struct lp_build_tgsi_context * bld_base,const struct tgsi_full_src_register * reg,enum tgsi_opcode_type stype,const unsigned chan_index)344 lp_build_emit_fetch_src(struct lp_build_tgsi_context *bld_base,
345 const struct tgsi_full_src_register *reg,
346 enum tgsi_opcode_type stype,
347 const unsigned chan_index)
348 {
349 unsigned swizzle;
350 LLVMValueRef res;
351
352 if (chan_index == LP_CHAN_ALL) {
353 swizzle = ~0u;
354 } else {
355 swizzle = tgsi_util_get_full_src_register_swizzle(reg, chan_index);
356 if (swizzle > 3) {
357 assert(0 && "invalid swizzle in emit_fetch()");
358 return bld_base->base.undef;
359 }
360 if (tgsi_type_is_64bit(stype)) {
361 unsigned swizzle2;
362 swizzle2 = tgsi_util_get_full_src_register_swizzle(reg, chan_index + 1);
363 if (swizzle2 > 3) {
364 assert(0 && "invalid swizzle in emit_fetch()");
365 return bld_base->base.undef;
366 }
367 swizzle |= (swizzle2 << 16);
368 }
369 }
370
371 assert(reg->Register.Index <= bld_base->info->file_max[reg->Register.File]);
372
373 if (bld_base->emit_fetch_funcs[reg->Register.File]) {
374 res = bld_base->emit_fetch_funcs[reg->Register.File](bld_base, reg, stype,
375 swizzle);
376 } else {
377 assert(0 && "invalid src register in emit_fetch()");
378 return bld_base->base.undef;
379 }
380
381 if (reg->Register.Absolute) {
382 switch (stype) {
383 case TGSI_TYPE_FLOAT:
384 case TGSI_TYPE_UNTYPED:
385 /* modifiers on movs assume data is float */
386 res = lp_build_abs(&bld_base->base, res);
387 break;
388 case TGSI_TYPE_DOUBLE:
389 case TGSI_TYPE_UNSIGNED:
390 case TGSI_TYPE_SIGNED:
391 case TGSI_TYPE_UNSIGNED64:
392 case TGSI_TYPE_SIGNED64:
393 case TGSI_TYPE_VOID:
394 default:
395 /* abs modifier is only legal on floating point types */
396 assert(0);
397 break;
398 }
399 }
400
401 if (reg->Register.Negate) {
402 switch (stype) {
403 case TGSI_TYPE_FLOAT:
404 case TGSI_TYPE_UNTYPED:
405 /* modifiers on movs assume data is float */
406 res = lp_build_negate(&bld_base->base, res);
407 break;
408 case TGSI_TYPE_DOUBLE:
409 /* no double build context */
410 assert(0);
411 break;
412 case TGSI_TYPE_SIGNED:
413 case TGSI_TYPE_UNSIGNED:
414 res = lp_build_negate(&bld_base->int_bld, res);
415 break;
416 case TGSI_TYPE_SIGNED64:
417 case TGSI_TYPE_UNSIGNED64:
418 res = lp_build_negate(&bld_base->int64_bld, res);
419 break;
420 case TGSI_TYPE_VOID:
421 default:
422 assert(0);
423 break;
424 }
425 }
426
427 /*
428 * Swizzle the argument
429 */
430
431 if (swizzle == ~0u) {
432 res = bld_base->emit_swizzle(bld_base, res,
433 reg->Register.SwizzleX,
434 reg->Register.SwizzleY,
435 reg->Register.SwizzleZ,
436 reg->Register.SwizzleW);
437 }
438
439 return res;
440 }
441
442
443 LLVMValueRef
lp_build_emit_fetch(struct lp_build_tgsi_context * bld_base,const struct tgsi_full_instruction * inst,unsigned src_op,const unsigned chan_index)444 lp_build_emit_fetch(struct lp_build_tgsi_context *bld_base,
445 const struct tgsi_full_instruction *inst,
446 unsigned src_op,
447 const unsigned chan_index)
448 {
449 const struct tgsi_full_src_register *reg = &inst->Src[src_op];
450 enum tgsi_opcode_type stype =
451 tgsi_opcode_infer_src_type(inst->Instruction.Opcode, src_op);
452
453 return lp_build_emit_fetch_src(bld_base, reg, stype, chan_index);
454 }
455
456
457 LLVMValueRef
lp_build_emit_fetch_texoffset(struct lp_build_tgsi_context * bld_base,const struct tgsi_full_instruction * inst,unsigned tex_off_op,const unsigned chan_index)458 lp_build_emit_fetch_texoffset(struct lp_build_tgsi_context *bld_base,
459 const struct tgsi_full_instruction *inst,
460 unsigned tex_off_op,
461 const unsigned chan_index)
462 {
463 const struct tgsi_texture_offset *off = &inst->TexOffsets[tex_off_op];
464 struct tgsi_full_src_register reg;
465 unsigned swizzle;
466 LLVMValueRef res;
467 enum tgsi_opcode_type stype = TGSI_TYPE_SIGNED;
468
469 /* convert offset "register" to ordinary register so can use normal emit funcs */
470 memset(®, 0, sizeof(reg));
471 reg.Register.File = off->File;
472 reg.Register.Index = off->Index;
473 reg.Register.SwizzleX = off->SwizzleX;
474 reg.Register.SwizzleY = off->SwizzleY;
475 reg.Register.SwizzleZ = off->SwizzleZ;
476
477 if (chan_index == LP_CHAN_ALL) {
478 swizzle = ~0;
479 } else {
480 assert(chan_index < TGSI_SWIZZLE_W);
481 swizzle = tgsi_util_get_src_register_swizzle(®.Register, chan_index);
482 }
483
484 assert(off->Index <= bld_base->info->file_max[off->File]);
485
486 if (bld_base->emit_fetch_funcs[off->File]) {
487 res = bld_base->emit_fetch_funcs[off->File](bld_base, ®, stype,
488 swizzle);
489 } else {
490 assert(0 && "invalid src register in emit_fetch_texoffset()");
491 return bld_base->base.undef;
492 }
493
494 /*
495 * Swizzle the argument
496 */
497
498 if (swizzle == ~0u) {
499 res = bld_base->emit_swizzle(bld_base, res,
500 off->SwizzleX,
501 off->SwizzleY,
502 off->SwizzleZ,
503 /* there's no 4th channel */
504 off->SwizzleX);
505 }
506
507 return res;
508 }
509
510
511 boolean
lp_build_tgsi_llvm(struct lp_build_tgsi_context * bld_base,const struct tgsi_token * tokens)512 lp_build_tgsi_llvm(struct lp_build_tgsi_context *bld_base,
513 const struct tgsi_token *tokens)
514 {
515 if (bld_base->emit_prologue) {
516 bld_base->emit_prologue(bld_base);
517 }
518
519 if (!lp_bld_tgsi_list_init(bld_base)) {
520 return FALSE;
521 }
522
523 struct tgsi_parse_context parse;
524 tgsi_parse_init(&parse, tokens);
525
526 while(!tgsi_parse_end_of_tokens(&parse)) {
527 tgsi_parse_token(&parse);
528
529 switch(parse.FullToken.Token.Type) {
530 case TGSI_TOKEN_TYPE_DECLARATION:
531 /* Inputs already interpolated */
532 bld_base->emit_declaration(bld_base, &parse.FullToken.FullDeclaration);
533 break;
534 case TGSI_TOKEN_TYPE_INSTRUCTION:
535 lp_bld_tgsi_add_instruction(bld_base, &parse.FullToken.FullInstruction);
536 break;
537 case TGSI_TOKEN_TYPE_IMMEDIATE:
538 bld_base->emit_immediate(bld_base, &parse.FullToken.FullImmediate);
539 break;
540 case TGSI_TOKEN_TYPE_PROPERTY:
541 break;
542 default:
543 assert(0);
544 }
545 }
546
547 if (bld_base->emit_prologue_post_decl) {
548 bld_base->emit_prologue_post_decl(bld_base);
549 }
550
551 while (bld_base->pc != -1) {
552 const struct tgsi_full_instruction *instr =
553 bld_base->instructions + bld_base->pc;
554 if (!lp_build_tgsi_inst_llvm(bld_base, instr)) {
555 _debug_printf("warning: failed to translate tgsi opcode %s to LLVM\n",
556 tgsi_get_opcode_name(instr->Instruction.Opcode));
557 return FALSE;
558 }
559 }
560
561 tgsi_parse_free(&parse);
562
563 FREE(bld_base->instructions);
564
565 if (bld_base->emit_epilogue) {
566 bld_base->emit_epilogue(bld_base);
567 }
568
569 return TRUE;
570 }
571