LLVMConstVector(swizzles, 4), "");
}
+static struct tgsi_declaration_range
+get_array_range(struct lp_build_tgsi_context *bld_base,
+ unsigned File, const struct tgsi_ind_register *reg)
+{
+ struct radeon_llvm_context * ctx = radeon_llvm_context(bld_base);
+ if (File != TGSI_FILE_TEMPORARY || reg->ArrayID == 0 ||
+ reg->ArrayID > RADEON_LLVM_MAX_ARRAYS) {
+ struct tgsi_declaration_range range;
+ range.First = 0;
+ range.Last = bld_base->info->file_max[File];
+ return range;
+ }
+
+ return ctx->arrays[reg->ArrayID - 1];
+}
+
static LLVMValueRef
emit_array_index(
struct lp_build_tgsi_soa_context *bld,
- const struct tgsi_full_src_register *reg,
- unsigned swizzle)
+ const struct tgsi_ind_register *reg,
+ unsigned offset)
{
struct gallivm_state * gallivm = bld->bld_base.base.gallivm;
- LLVMValueRef addr = LLVMBuildLoad(gallivm->builder,
- bld->addr[reg->Indirect.Index][swizzle], "");
- LLVMValueRef offset = lp_build_const_int32(gallivm, reg->Register.Index);
- LLVMValueRef hw_index = LLVMBuildAdd(gallivm->builder, addr, offset, "");
- LLVMValueRef soa_index = LLVMBuildMul(gallivm->builder, hw_index,
- lp_build_const_int32(gallivm, 4), "");
- LLVMValueRef array_index = LLVMBuildAdd(gallivm->builder, soa_index,
- lp_build_const_int32(gallivm, swizzle), "");
-
- return array_index;
+ LLVMValueRef addr = LLVMBuildLoad(gallivm->builder, bld->addr[reg->Index][reg->Swizzle], "");
+ return LLVMBuildAdd(gallivm->builder, addr, lp_build_const_int32(gallivm, offset), "");
}
static LLVMValueRef
-emit_fetch_immediate(
+emit_fetch(
struct lp_build_tgsi_context *bld_base,
const struct tgsi_full_src_register *reg,
enum tgsi_opcode_type type,
+ unsigned swizzle);
+
+static LLVMValueRef
+emit_array_fetch(
+ struct lp_build_tgsi_context *bld_base,
+ unsigned File, enum tgsi_opcode_type type,
+ struct tgsi_declaration_range range,
unsigned swizzle)
{
- LLVMTypeRef ctype;
- LLVMContextRef ctx = bld_base->base.gallivm->context;
+ struct lp_build_tgsi_soa_context *bld = lp_soa_context(bld_base);
+ struct gallivm_state * gallivm = bld->bld_base.base.gallivm;
+ LLVMBuilderRef builder = bld_base->base.gallivm->builder;
- switch (type) {
- case TGSI_TYPE_UNSIGNED:
- case TGSI_TYPE_SIGNED:
- ctype = LLVMInt32TypeInContext(ctx);
- break;
- case TGSI_TYPE_UNTYPED:
- case TGSI_TYPE_FLOAT:
- ctype = LLVMFloatTypeInContext(ctx);
- break;
- default:
- ctype = 0;
- break;
- }
+ unsigned i, size = range.Last - range.First + 1;
+ LLVMTypeRef vec = LLVMVectorType(tgsi2llvmtype(bld_base, type), size);
+ LLVMValueRef result = LLVMGetUndef(vec);
- struct lp_build_tgsi_soa_context *bld = lp_soa_context(bld_base);
- return LLVMConstBitCast(bld->immediates[reg->Register.Index][swizzle], ctype);
+ struct tgsi_full_src_register tmp_reg = {};
+ tmp_reg.Register.File = File;
+
+ for (i = 0; i < size; ++i) {
+ tmp_reg.Register.Index = i + range.First;
+ LLVMValueRef temp = emit_fetch(bld_base, &tmp_reg, type, swizzle);
+ result = LLVMBuildInsertElement(builder, result, temp,
+ lp_build_const_int32(gallivm, i), "");
+ }
+ return result;
}
-static LLVMValueRef
-emit_fetch_input(
- struct lp_build_tgsi_context *bld_base,
- const struct tgsi_full_src_register *reg,
- enum tgsi_opcode_type type,
- unsigned swizzle)
+static bool uses_temp_indirect_addressing(
+ struct lp_build_tgsi_context *bld_base)
{
- struct radeon_llvm_context * ctx = radeon_llvm_context(bld_base);
- if (swizzle == ~0) {
- LLVMValueRef values[TGSI_NUM_CHANNELS] = {};
- unsigned chan;
- for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
- values[chan] = ctx->inputs[radeon_llvm_reg_index_soa(
- reg->Register.Index, chan)];
- }
- return lp_build_gather_values(bld_base->base.gallivm, values,
- TGSI_NUM_CHANNELS);
- } else {
- return bitcast(bld_base, type, ctx->inputs[radeon_llvm_reg_index_soa(reg->Register.Index, swizzle)]);
- }
+ struct lp_build_tgsi_soa_context *bld = lp_soa_context(bld_base);
+ return (bld->indirect_files & (1 << TGSI_FILE_TEMPORARY));
}
static LLVMValueRef
-emit_fetch_temporary(
+emit_fetch(
struct lp_build_tgsi_context *bld_base,
const struct tgsi_full_src_register *reg,
enum tgsi_opcode_type type,
unsigned swizzle)
{
+ struct radeon_llvm_context * ctx = radeon_llvm_context(bld_base);
struct lp_build_tgsi_soa_context *bld = lp_soa_context(bld_base);
LLVMBuilderRef builder = bld_base->base.gallivm->builder;
+ LLVMValueRef result, ptr;
+
if (swizzle == ~0) {
- LLVMValueRef values[TGSI_NUM_CHANNELS] = {};
+ LLVMValueRef values[TGSI_NUM_CHANNELS];
unsigned chan;
for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
- values[chan] = emit_fetch_temporary(bld_base, reg, type, chan);
+ values[chan] = emit_fetch(bld_base, reg, type, chan);
}
return lp_build_gather_values(bld_base->base.gallivm, values,
- TGSI_NUM_CHANNELS);
+ TGSI_NUM_CHANNELS);
}
if (reg->Register.Indirect) {
- LLVMValueRef array_index = emit_array_index(bld, reg, swizzle);
- LLVMValueRef ptr = LLVMBuildGEP(builder, bld->temps_array, &array_index,
- 1, "");
- return LLVMBuildLoad(builder, ptr, "");
- } else {
- LLVMValueRef temp_ptr;
- temp_ptr = lp_get_temp_ptr_soa(bld, reg->Register.Index, swizzle);
- return bitcast(bld_base,type,LLVMBuildLoad(builder, temp_ptr, ""));
+ struct tgsi_declaration_range range = get_array_range(bld_base,
+ reg->Register.File, ®->Indirect);
+ return LLVMBuildExtractElement(builder,
+ emit_array_fetch(bld_base, reg->Register.File, type, range, swizzle),
+ emit_array_index(bld, ®->Indirect, reg->Register.Index - range.First),
+ "");
+ }
+
+ switch(reg->Register.File) {
+ case TGSI_FILE_IMMEDIATE: {
+ LLVMTypeRef ctype = tgsi2llvmtype(bld_base, type);
+ return LLVMConstBitCast(bld->immediates[reg->Register.Index][swizzle], ctype);
}
+
+ case TGSI_FILE_INPUT:
+ result = ctx->inputs[radeon_llvm_reg_index_soa(reg->Register.Index, swizzle)];
+ break;
+
+ case TGSI_FILE_TEMPORARY:
+ if (uses_temp_indirect_addressing(bld_base)) {
+ ptr = lp_get_temp_ptr_soa(bld, reg->Register.Index, swizzle);
+ break;
+ }
+ ptr = ctx->temps[reg->Register.Index * TGSI_NUM_CHANNELS + swizzle];
+ result = LLVMBuildLoad(builder, ptr, "");
+ break;
+
+ case TGSI_FILE_OUTPUT:
+ ptr = lp_get_output_ptr(bld, reg->Register.Index, swizzle);
+ result = LLVMBuildLoad(builder, ptr, "");
+ break;
+
+ default:
+ return LLVMGetUndef(tgsi2llvmtype(bld_base, type));
+ }
+
+ return bitcast(bld_base, type, result);
}
-static LLVMValueRef
-emit_fetch_output(
- struct lp_build_tgsi_context *bld_base,
+static LLVMValueRef fetch_system_value(
+ struct lp_build_tgsi_context * bld_base,
const struct tgsi_full_src_register *reg,
enum tgsi_opcode_type type,
unsigned swizzle)
{
- struct lp_build_tgsi_soa_context *bld = lp_soa_context(bld_base);
- LLVMBuilderRef builder = bld_base->base.gallivm->builder;
- if (reg->Register.Indirect) {
- LLVMValueRef array_index = emit_array_index(bld, reg, swizzle);
- LLVMValueRef ptr = LLVMBuildGEP(builder, bld->outputs_array, &array_index,
- 1, "");
- return LLVMBuildLoad(builder, ptr, "");
- } else {
- LLVMValueRef temp_ptr;
- temp_ptr = lp_get_output_ptr(bld, reg->Register.Index, swizzle);
- return LLVMBuildLoad(builder, temp_ptr, "");
- }
+ struct radeon_llvm_context * ctx = radeon_llvm_context(bld_base);
+ LLVMValueRef cval = ctx->system_values[reg->Register.Index];
+ return bitcast(bld_base, type, cval);
}
static void emit_declaration(
const struct tgsi_full_declaration *decl)
{
struct radeon_llvm_context * ctx = radeon_llvm_context(bld_base);
+ unsigned first, last, i, idx;
switch(decl->Declaration.File) {
case TGSI_FILE_ADDRESS:
{
}
case TGSI_FILE_TEMPORARY:
- lp_emit_declaration_soa(bld_base, decl);
+ if (decl->Declaration.Array && decl->Array.ArrayID <= RADEON_LLVM_MAX_ARRAYS)
+ ctx->arrays[decl->Array.ArrayID - 1] = decl->Range;
+ if (uses_temp_indirect_addressing(bld_base)) {
+ lp_emit_declaration_soa(bld_base, decl);
+ break;
+ }
+ first = decl->Range.First;
+ last = decl->Range.Last;
+ if (!ctx->temps_count) {
+ ctx->temps_count = bld_base->info->file_max[TGSI_FILE_TEMPORARY] + 1;
+ ctx->temps = MALLOC(TGSI_NUM_CHANNELS * ctx->temps_count * sizeof(LLVMValueRef));
+ }
+ for (idx = first; idx <= last; idx++) {
+ for (i = 0; i < TGSI_NUM_CHANNELS; i++) {
+ ctx->temps[idx * TGSI_NUM_CHANNELS + i] =
+ lp_build_alloca(bld_base->base.gallivm, bld_base->base.vec_type,
+ "temp");
+ }
+ }
break;
case TGSI_FILE_INPUT:
const struct tgsi_opcode_info * info,
LLVMValueRef dst[4])
{
+ struct radeon_llvm_context * ctx = radeon_llvm_context(bld_base);
struct lp_build_tgsi_soa_context *bld = lp_soa_context(bld_base);
struct gallivm_state *gallivm = bld->bld_base.base.gallivm;
struct lp_build_context base = bld->bld_base.base;
LLVMValueRef temp_ptr;
unsigned chan, chan_index;
boolean is_vec_store = FALSE;
+
if (dst[0]) {
LLVMTypeKind k = LLVMGetTypeKind(LLVMTypeOf(dst[0]));
is_vec_store = (k == LLVMVectorTypeKind);
&clamp_emit_data);
}
- switch(reg->Register.File) {
- case TGSI_FILE_OUTPUT:
- temp_ptr = bld->outputs[reg->Register.Index][chan_index];
- break;
+ if (reg->Register.File == TGSI_FILE_ADDRESS) {
+ temp_ptr = bld->addr[reg->Register.Index][chan_index];
+ LLVMBuildStore(builder, value, temp_ptr);
+ continue;
+ }
+
+ value = bitcast(bld_base, TGSI_TYPE_FLOAT, value);
- case TGSI_FILE_TEMPORARY:
- temp_ptr = lp_get_temp_ptr_soa(bld, reg->Register.Index, chan_index);
- break;
+ if (reg->Register.Indirect) {
+ struct tgsi_declaration_range range = get_array_range(bld_base,
+ reg->Register.File, ®->Indirect);
+
+ unsigned i, size = range.Last - range.First + 1;
+ LLVMValueRef array = LLVMBuildInsertElement(builder,
+ emit_array_fetch(bld_base, reg->Register.File, TGSI_TYPE_FLOAT, range, chan_index),
+ value, emit_array_index(bld, ®->Indirect, reg->Register.Index - range.First), "");
+
+ for (i = 0; i < size; ++i) {
+ switch(reg->Register.File) {
+ case TGSI_FILE_OUTPUT:
+ temp_ptr = bld->outputs[i + range.First][chan_index];
+ break;
+
+ case TGSI_FILE_TEMPORARY:
+ if (uses_temp_indirect_addressing(bld_base))
+ temp_ptr = lp_get_temp_ptr_soa(bld, i + range.First, chan_index);
+ else
+ temp_ptr = ctx->temps[(i + range.First) * TGSI_NUM_CHANNELS + chan_index];
+ break;
+
+ default:
+ return;
+ }
+ value = LLVMBuildExtractElement(builder, array,
+ lp_build_const_int32(gallivm, i), "");
+ LLVMBuildStore(builder, value, temp_ptr);
+ }
- default:
- return;
- }
+ } else {
+ switch(reg->Register.File) {
+ case TGSI_FILE_OUTPUT:
+ temp_ptr = bld->outputs[reg->Register.Index][chan_index];
+ break;
- value = bitcast(bld_base, TGSI_TYPE_FLOAT, value);
+ case TGSI_FILE_TEMPORARY:
+ if (uses_temp_indirect_addressing(bld_base))
+ break;
+ temp_ptr = ctx->temps[ TGSI_NUM_CHANNELS * reg->Register.Index + chan_index];
+ break;
- LLVMBuildStore(builder, value, temp_ptr);
+ default:
+ return;
+ }
+ LLVMBuildStore(builder, value, temp_ptr);
+ }
}
}
ctx->loop_depth--;
}
-static void if_emit(
+static void if_cond_emit(
const struct lp_build_tgsi_action * action,
struct lp_build_tgsi_context * bld_base,
- struct lp_build_emit_data * emit_data)
+ struct lp_build_emit_data * emit_data,
+ LLVMValueRef cond)
{
struct radeon_llvm_context * ctx = radeon_llvm_context(bld_base);
struct gallivm_state * gallivm = bld_base->base.gallivm;
- LLVMValueRef cond;
LLVMBasicBlockRef if_block, else_block, endif_block;
- cond = LLVMBuildICmp(gallivm->builder, LLVMIntNE,
- bitcast(bld_base, TGSI_TYPE_UNSIGNED, emit_data->args[0]),
- bld_base->int_bld.zero, "");
-
endif_block = LLVMAppendBasicBlockInContext(gallivm->context,
ctx->main_fn, "ENDIF");
if_block = LLVMInsertBasicBlockInContext(gallivm->context,
ctx->branch[ctx->branch_depth - 1].has_else = 0;
}
+static void if_emit(
+ const struct lp_build_tgsi_action * action,
+ struct lp_build_tgsi_context * bld_base,
+ struct lp_build_emit_data * emit_data)
+{
+ struct gallivm_state * gallivm = bld_base->base.gallivm;
+ LLVMValueRef cond;
+
+ cond = LLVMBuildFCmp(gallivm->builder, LLVMRealUNE,
+ emit_data->args[0],
+ bld_base->base.zero, "");
+
+ if_cond_emit(action, bld_base, emit_data, cond);
+}
+
+static void uif_emit(
+ const struct lp_build_tgsi_action * action,
+ struct lp_build_tgsi_context * bld_base,
+ struct lp_build_emit_data * emit_data)
+{
+ struct gallivm_state * gallivm = bld_base->base.gallivm;
+ LLVMValueRef cond;
+
+ cond = LLVMBuildICmp(gallivm->builder, LLVMIntNE,
+ bitcast(bld_base, TGSI_TYPE_UNSIGNED, emit_data->args[0]),
+ bld_base->int_bld.zero, "");
+
+ if_cond_emit(action, bld_base, emit_data, cond);
+}
+
static void kil_emit(
const struct lp_build_tgsi_action * action,
struct lp_build_tgsi_context * bld_base,
}
}
-
void radeon_llvm_emit_prepare_cube_coords(
struct lp_build_tgsi_context * bld_base,
- LLVMValueRef *arg,
- unsigned target)
+ struct lp_build_emit_data * emit_data,
+ LLVMValueRef *coords_arg)
{
- boolean shadowcube = (target == TGSI_TEXTURE_SHADOWCUBE);
+
+ unsigned target = emit_data->inst->Texture.Texture;
+ unsigned opcode = emit_data->inst->Instruction.Opcode;
struct gallivm_state * gallivm = bld_base->base.gallivm;
LLVMBuilderRef builder = gallivm->builder;
LLVMTypeRef type = bld_base->base.elem_type;
LLVMValueRef coords[4];
LLVMValueRef mad_args[3];
- unsigned i, cnt;
-
- LLVMValueRef v = build_intrinsic(builder, "llvm.AMDGPU.cube",
- LLVMVectorType(type, 4),
- arg, 1, LLVMReadNoneAttribute);
+ LLVMValueRef idx;
+ struct LLVMOpaqueValue *cube_vec;
+ LLVMValueRef v;
+ unsigned i;
- /* save src.w for shadow cube */
- cnt = shadowcube ? 3 : 4;
+ cube_vec = lp_build_gather_values(bld_base->base.gallivm, coords_arg, 4);
+ v = build_intrinsic(builder, "llvm.AMDGPU.cube", LLVMVectorType(type, 4),
+ &cube_vec, 1, LLVMReadNoneAttribute);
- for (i = 0; i < cnt; ++i) {
- LLVMValueRef idx = lp_build_const_int32(gallivm, i);
+ for (i = 0; i < 4; ++i) {
+ idx = lp_build_const_int32(gallivm, i);
coords[i] = LLVMBuildExtractElement(builder, v, idx, "");
}
coords[1] = lp_build_emit_llvm_ternary(bld_base, TGSI_OPCODE_MAD,
mad_args[0], mad_args[1], mad_args[2]);
- /* apply yxwy swizzle to cooords */
+ /* apply xyz = yxw swizzle to cooords */
coords[2] = coords[3];
coords[3] = coords[1];
coords[1] = coords[0];
coords[0] = coords[3];
- *arg = lp_build_gather_values(bld_base->base.gallivm, coords, 4);
+ if (target == TGSI_TEXTURE_CUBE_ARRAY ||
+ target == TGSI_TEXTURE_SHADOWCUBE_ARRAY) {
+ /* for cube arrays coord.z = coord.w(array_index) * 8 + face */
+ /* coords_arg.w component - array_index for cube arrays */
+ coords[2] = lp_build_emit_llvm_ternary(bld_base, TGSI_OPCODE_MAD,
+ coords_arg[3], lp_build_const_float(gallivm, 8.0), coords[2]);
+ }
+
+ /* Preserve compare/lod/bias. Put it in coords.w. */
+ if (opcode == TGSI_OPCODE_TEX2 ||
+ opcode == TGSI_OPCODE_TXB2 ||
+ opcode == TGSI_OPCODE_TXL2) {
+ coords[3] = coords_arg[4];
+ } else if (opcode == TGSI_OPCODE_TXB ||
+ opcode == TGSI_OPCODE_TXL ||
+ target == TGSI_TEXTURE_SHADOWCUBE) {
+ coords[3] = coords_arg[3];
+ }
+
+ memcpy(coords_arg, coords, sizeof(coords));
}
static void txd_fetch_args(
TGSI_OPCODE_DIV, arg, src_w);
}
coords[3] = bld_base->base.one;
- emit_data->args[0] = lp_build_gather_values(bld_base->base.gallivm,
- coords, 4);
- emit_data->arg_count = 1;
if ((inst->Texture.Texture == TGSI_TEXTURE_CUBE ||
- inst->Texture.Texture == TGSI_TEXTURE_SHADOWCUBE) &&
+ inst->Texture.Texture == TGSI_TEXTURE_CUBE_ARRAY ||
+ inst->Texture.Texture == TGSI_TEXTURE_SHADOWCUBE ||
+ inst->Texture.Texture == TGSI_TEXTURE_SHADOWCUBE_ARRAY) &&
inst->Instruction.Opcode != TGSI_OPCODE_TXQ &&
inst->Instruction.Opcode != TGSI_OPCODE_TXQ_LZ) {
- radeon_llvm_emit_prepare_cube_coords(bld_base, &emit_data->args[0],
- inst->Texture.Texture);
+ radeon_llvm_emit_prepare_cube_coords(bld_base, emit_data, coords);
}
+
+ emit_data->args[0] = lp_build_gather_values(bld_base->base.gallivm,
+ coords, 4);
+ emit_data->arg_count = 1;
}
static void tex_fetch_args(
const struct tgsi_full_instruction * inst = emit_data->inst;
- LLVMValueRef coords[4];
+ LLVMValueRef coords[5];
unsigned chan;
for (chan = 0; chan < 4; chan++) {
coords[chan] = lp_build_emit_fetch(bld_base, inst, 0, chan);
}
- emit_data->arg_count = 1;
- emit_data->args[0] = lp_build_gather_values(bld_base->base.gallivm,
- coords, 4);
- emit_data->dst_type = LLVMVectorType(bld_base->base.elem_type, 4);
+ if (inst->Instruction.Opcode == TGSI_OPCODE_TEX2 ||
+ inst->Instruction.Opcode == TGSI_OPCODE_TXB2 ||
+ inst->Instruction.Opcode == TGSI_OPCODE_TXL2) {
+ /* These instructions have additional operand that should be packed
+ * into the cube coord vector by radeon_llvm_emit_prepare_cube_coords.
+ * That operand should be passed as a float value in the args array
+ * right after the coord vector. After packing it's not used anymore,
+ * that's why arg_count is not increased */
+ coords[4] = lp_build_emit_fetch(bld_base, inst, 1, 0);
+ }
if ((inst->Texture.Texture == TGSI_TEXTURE_CUBE ||
- inst->Texture.Texture == TGSI_TEXTURE_SHADOWCUBE) &&
+ inst->Texture.Texture == TGSI_TEXTURE_CUBE_ARRAY ||
+ inst->Texture.Texture == TGSI_TEXTURE_SHADOWCUBE ||
+ inst->Texture.Texture == TGSI_TEXTURE_SHADOWCUBE_ARRAY) &&
inst->Instruction.Opcode != TGSI_OPCODE_TXQ &&
inst->Instruction.Opcode != TGSI_OPCODE_TXQ_LZ) {
- radeon_llvm_emit_prepare_cube_coords(bld_base, &emit_data->args[0],
- inst->Texture.Texture);
+ radeon_llvm_emit_prepare_cube_coords(bld_base, emit_data, coords);
}
+
+ emit_data->arg_count = 1;
+ emit_data->args[0] = lp_build_gather_values(bld_base->base.gallivm,
+ coords, 4);
+ emit_data->dst_type = LLVMVectorType(bld_base->base.elem_type, 4);
}
static void txf_fetch_args(
case TGSI_OPCODE_ISLT: pred = LLVMIntSLT; break;
default:
assert(!"unknown instruction");
+ pred = 0;
+ break;
}
LLVMValueRef v = LLVMBuildICmp(builder, pred,
emit_data->output[emit_data->chan] = v;
}
+static void emit_ucmp(
+ const struct lp_build_tgsi_action * action,
+ struct lp_build_tgsi_context * bld_base,
+ struct lp_build_emit_data * emit_data)
+{
+ LLVMBuilderRef builder = bld_base->base.gallivm->builder;
+
+ LLVMValueRef arg0 = LLVMBuildBitCast(builder, emit_data->args[0],
+ bld_base->uint_bld.elem_type, "");
+
+ LLVMValueRef v = LLVMBuildICmp(builder, LLVMIntNE, arg0,
+ bld_base->uint_bld.zero, "");
+
+ emit_data->output[emit_data->chan] =
+ LLVMBuildSelect(builder, v, emit_data->args[1], emit_data->args[2], "");
+}
+
static void emit_cmp(
const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context * bld_base,
LLVMRealPredicate pred;
LLVMValueRef cond;
- /* XXX I'm not sure whether to do unordered or ordered comparisons,
- * but llvmpipe uses unordered comparisons, so for consistency we use
- * unordered. (The authors of llvmpipe aren't sure about using
- * unordered vs ordered comparisons either.
+ /* Use ordered for everything but NE (which is usual for
+ * float comparisons)
*/
switch (emit_data->inst->Instruction.Opcode) {
- case TGSI_OPCODE_SGE: pred = LLVMRealUGE; break;
- case TGSI_OPCODE_SEQ: pred = LLVMRealUEQ; break;
- case TGSI_OPCODE_SLE: pred = LLVMRealULE; break;
- case TGSI_OPCODE_SLT: pred = LLVMRealULT; break;
+ case TGSI_OPCODE_SGE: pred = LLVMRealOGE; break;
+ case TGSI_OPCODE_SEQ: pred = LLVMRealOEQ; break;
+ case TGSI_OPCODE_SLE: pred = LLVMRealOLE; break;
+ case TGSI_OPCODE_SLT: pred = LLVMRealOLT; break;
case TGSI_OPCODE_SNE: pred = LLVMRealUNE; break;
- case TGSI_OPCODE_SGT: pred = LLVMRealUGT; break;
- default: assert(!"unknown instruction");
+ case TGSI_OPCODE_SGT: pred = LLVMRealOGT; break;
+ default: assert(!"unknown instruction"); pred = 0; break;
}
cond = LLVMBuildFCmp(builder,
cond, bld_base->base.one, bld_base->base.zero, "");
}
+static void emit_fcmp(
+ const struct lp_build_tgsi_action *action,
+ struct lp_build_tgsi_context * bld_base,
+ struct lp_build_emit_data * emit_data)
+{
+ LLVMBuilderRef builder = bld_base->base.gallivm->builder;
+ LLVMContextRef context = bld_base->base.gallivm->context;
+ LLVMRealPredicate pred;
+
+ /* Use ordered for everything but NE (which is usual for
+ * float comparisons)
+ */
+ switch (emit_data->inst->Instruction.Opcode) {
+ case TGSI_OPCODE_FSEQ: pred = LLVMRealOEQ; break;
+ case TGSI_OPCODE_FSGE: pred = LLVMRealOGE; break;
+ case TGSI_OPCODE_FSLT: pred = LLVMRealOLT; break;
+ case TGSI_OPCODE_FSNE: pred = LLVMRealUNE; break;
+ default: assert(!"unknown instruction"); pred = 0; break;
+ }
+
+ LLVMValueRef v = LLVMBuildFCmp(builder, pred,
+ emit_data->args[0], emit_data->args[1],"");
+
+ v = LLVMBuildSExtOrBitCast(builder, v,
+ LLVMInt32TypeInContext(context), "");
+
+ emit_data->output[emit_data->chan] = v;
+}
+
static void emit_not(
const struct lp_build_tgsi_action * action,
struct lp_build_tgsi_context * bld_base,
emit_data->output[emit_data->chan] = LLVMBuildNot(builder, v, "");
}
+static void emit_arl(
+ const struct lp_build_tgsi_action * action,
+ struct lp_build_tgsi_context * bld_base,
+ struct lp_build_emit_data * emit_data)
+{
+ LLVMBuilderRef builder = bld_base->base.gallivm->builder;
+ LLVMValueRef floor_index = lp_build_emit_llvm_unary(bld_base, TGSI_OPCODE_FLR, emit_data->args[0]);
+ emit_data->output[emit_data->chan] = LLVMBuildFPToSI(builder,
+ floor_index, bld_base->base.int_elem_type , "");
+}
+
static void emit_and(
const struct lp_build_tgsi_action * action,
struct lp_build_tgsi_context * bld_base,
void radeon_llvm_context_init(struct radeon_llvm_context * ctx)
{
struct lp_type type;
- LLVMTypeRef main_fn_type;
- LLVMBasicBlockRef main_fn_body;
/* Initialize the gallivm object:
* We are only using the module, context, and builder fields of this struct.
ctx->gallivm.context);
ctx->gallivm.builder = LLVMCreateBuilderInContext(ctx->gallivm.context);
- /* Setup the module */
- main_fn_type = LLVMFunctionType(LLVMVoidTypeInContext(ctx->gallivm.context),
- NULL, 0, 0);
- ctx->main_fn = LLVMAddFunction(ctx->gallivm.module, "main", main_fn_type);
- main_fn_body = LLVMAppendBasicBlockInContext(ctx->gallivm.context,
- ctx->main_fn, "main_body");
- LLVMPositionBuilderAtEnd(ctx->gallivm.builder, main_fn_body);
-
ctx->store_output_intr = "llvm.AMDGPU.store.output.";
ctx->swizzle_intr = "llvm.AMDGPU.swizzle";
struct lp_build_tgsi_context * bld_base = &ctx->soa.bld_base;
/* XXX: We need to revisit this.I think the correct way to do this is
* to use length = 4 here and use the elem_bld for everything. */
type.floating = TRUE;
+ type.fixed = FALSE;
type.sign = TRUE;
+ type.norm = FALSE;
type.width = 32;
type.length = 1;
bld_base->emit_declaration = emit_declaration;
bld_base->emit_immediate = emit_immediate;
- bld_base->emit_fetch_funcs[TGSI_FILE_IMMEDIATE] = emit_fetch_immediate;
- bld_base->emit_fetch_funcs[TGSI_FILE_INPUT] = emit_fetch_input;
- bld_base->emit_fetch_funcs[TGSI_FILE_TEMPORARY] = emit_fetch_temporary;
- bld_base->emit_fetch_funcs[TGSI_FILE_OUTPUT] = emit_fetch_output;
+ bld_base->emit_fetch_funcs[TGSI_FILE_IMMEDIATE] = emit_fetch;
+ bld_base->emit_fetch_funcs[TGSI_FILE_INPUT] = emit_fetch;
+ bld_base->emit_fetch_funcs[TGSI_FILE_TEMPORARY] = emit_fetch;
+ bld_base->emit_fetch_funcs[TGSI_FILE_OUTPUT] = emit_fetch;
+ bld_base->emit_fetch_funcs[TGSI_FILE_SYSTEM_VALUE] = fetch_system_value;
/* Allocate outputs */
ctx->soa.outputs = ctx->outputs;
+ ctx->num_arrays = 0;
+
/* XXX: Is there a better way to initialize all this ? */
lp_set_default_actions(bld_base);
bld_base->op_actions[TGSI_OPCODE_ABS].emit = build_tgsi_intrinsic_readonly;
bld_base->op_actions[TGSI_OPCODE_ABS].intr_name = "fabs";
- bld_base->op_actions[TGSI_OPCODE_ARL].emit = build_tgsi_intrinsic_nomem;
- bld_base->op_actions[TGSI_OPCODE_ARL].intr_name = "llvm.AMDGPU.arl";
+ bld_base->op_actions[TGSI_OPCODE_ARL].emit = emit_arl;
bld_base->op_actions[TGSI_OPCODE_AND].emit = emit_and;
bld_base->op_actions[TGSI_OPCODE_BGNLOOP].emit = bgnloop_emit;
bld_base->op_actions[TGSI_OPCODE_BRK].emit = brk_emit;
bld_base->op_actions[TGSI_OPCODE_FRC].intr_name = "llvm.AMDIL.fraction.";
bld_base->op_actions[TGSI_OPCODE_F2I].emit = emit_f2i;
bld_base->op_actions[TGSI_OPCODE_F2U].emit = emit_f2u;
+ bld_base->op_actions[TGSI_OPCODE_FSEQ].emit = emit_fcmp;
+ bld_base->op_actions[TGSI_OPCODE_FSGE].emit = emit_fcmp;
+ bld_base->op_actions[TGSI_OPCODE_FSLT].emit = emit_fcmp;
+ bld_base->op_actions[TGSI_OPCODE_FSNE].emit = emit_fcmp;
bld_base->op_actions[TGSI_OPCODE_IABS].emit = build_tgsi_intrinsic_nomem;
bld_base->op_actions[TGSI_OPCODE_IABS].intr_name = "llvm.AMDIL.abs.";
bld_base->op_actions[TGSI_OPCODE_IDIV].emit = emit_idiv;
bld_base->op_actions[TGSI_OPCODE_IF].emit = if_emit;
+ bld_base->op_actions[TGSI_OPCODE_UIF].emit = uif_emit;
bld_base->op_actions[TGSI_OPCODE_IMAX].emit = build_tgsi_intrinsic_nomem;
bld_base->op_actions[TGSI_OPCODE_IMAX].intr_name = "llvm.AMDGPU.imax";
bld_base->op_actions[TGSI_OPCODE_IMIN].emit = build_tgsi_intrinsic_nomem;
bld_base->op_actions[TGSI_OPCODE_ISLT].emit = emit_icmp;
bld_base->op_actions[TGSI_OPCODE_ISSG].emit = emit_ssg;
bld_base->op_actions[TGSI_OPCODE_I2F].emit = emit_i2f;
- bld_base->op_actions[TGSI_OPCODE_KIL].emit = kil_emit;
- bld_base->op_actions[TGSI_OPCODE_KIL].intr_name = "llvm.AMDGPU.kill";
- bld_base->op_actions[TGSI_OPCODE_KILP].emit = lp_build_tgsi_intrinsic;
- bld_base->op_actions[TGSI_OPCODE_KILP].intr_name = "llvm.AMDGPU.kilp";
+ bld_base->op_actions[TGSI_OPCODE_KILL_IF].emit = kil_emit;
+ bld_base->op_actions[TGSI_OPCODE_KILL_IF].intr_name = "llvm.AMDGPU.kill";
+ bld_base->op_actions[TGSI_OPCODE_KILL].emit = lp_build_tgsi_intrinsic;
+ bld_base->op_actions[TGSI_OPCODE_KILL].intr_name = "llvm.AMDGPU.kilp";
bld_base->op_actions[TGSI_OPCODE_LG2].emit = build_tgsi_intrinsic_readonly;
bld_base->op_actions[TGSI_OPCODE_LG2].intr_name = "llvm.log2.f32";
bld_base->op_actions[TGSI_OPCODE_LRP].emit = build_tgsi_intrinsic_nomem;
bld_base->op_actions[TGSI_OPCODE_SSG].emit = emit_ssg;
bld_base->op_actions[TGSI_OPCODE_TEX].fetch_args = tex_fetch_args;
bld_base->op_actions[TGSI_OPCODE_TEX].intr_name = "llvm.AMDGPU.tex";
+ bld_base->op_actions[TGSI_OPCODE_TEX2].fetch_args = tex_fetch_args;
+ bld_base->op_actions[TGSI_OPCODE_TEX2].intr_name = "llvm.AMDGPU.tex";
bld_base->op_actions[TGSI_OPCODE_TXB].fetch_args = tex_fetch_args;
bld_base->op_actions[TGSI_OPCODE_TXB].intr_name = "llvm.AMDGPU.txb";
+ bld_base->op_actions[TGSI_OPCODE_TXB2].fetch_args = tex_fetch_args;
+ bld_base->op_actions[TGSI_OPCODE_TXB2].intr_name = "llvm.AMDGPU.txb";
bld_base->op_actions[TGSI_OPCODE_TXD].fetch_args = txd_fetch_args;
bld_base->op_actions[TGSI_OPCODE_TXD].intr_name = "llvm.AMDGPU.txd";
bld_base->op_actions[TGSI_OPCODE_TXF].fetch_args = txf_fetch_args;
bld_base->op_actions[TGSI_OPCODE_TXF].intr_name = "llvm.AMDGPU.txf";
bld_base->op_actions[TGSI_OPCODE_TXL].fetch_args = tex_fetch_args;
bld_base->op_actions[TGSI_OPCODE_TXL].intr_name = "llvm.AMDGPU.txl";
+ bld_base->op_actions[TGSI_OPCODE_TXL2].fetch_args = tex_fetch_args;
+ bld_base->op_actions[TGSI_OPCODE_TXL2].intr_name = "llvm.AMDGPU.txl";
bld_base->op_actions[TGSI_OPCODE_TXP].fetch_args = txp_fetch_args;
bld_base->op_actions[TGSI_OPCODE_TXP].intr_name = "llvm.AMDGPU.tex";
bld_base->op_actions[TGSI_OPCODE_TXQ].fetch_args = tex_fetch_args;
bld_base->op_actions[TGSI_OPCODE_USNE].emit = emit_icmp;
bld_base->op_actions[TGSI_OPCODE_U2F].emit = emit_u2f;
bld_base->op_actions[TGSI_OPCODE_XOR].emit = emit_xor;
+ bld_base->op_actions[TGSI_OPCODE_UCMP].emit = emit_ucmp;
bld_base->rsq_action.emit = build_tgsi_intrinsic_nomem;
bld_base->rsq_action.intr_name = "llvm.AMDGPU.rsq";
}
+void radeon_llvm_create_func(struct radeon_llvm_context * ctx,
+ LLVMTypeRef *ParamTypes, unsigned ParamCount)
+{
+ LLVMTypeRef main_fn_type;
+ LLVMBasicBlockRef main_fn_body;
+
+ /* Setup the function */
+ main_fn_type = LLVMFunctionType(LLVMVoidTypeInContext(ctx->gallivm.context),
+ ParamTypes, ParamCount, 0);
+ ctx->main_fn = LLVMAddFunction(ctx->gallivm.module, "main", main_fn_type);
+ main_fn_body = LLVMAppendBasicBlockInContext(ctx->gallivm.context,
+ ctx->main_fn, "main_body");
+ LLVMPositionBuilderAtEnd(ctx->gallivm.builder, main_fn_body);
+}
+
void radeon_llvm_finalize_module(struct radeon_llvm_context * ctx)
{
struct gallivm_state * gallivm = ctx->soa.bld_base.base.gallivm;
/* Add some optimization passes */
LLVMAddScalarReplAggregatesPass(gallivm->passmgr);
+ LLVMAddLICMPass(gallivm->passmgr);
+ LLVMAddAggressiveDCEPass(gallivm->passmgr);
LLVMAddCFGSimplificationPass(gallivm->passmgr);
- /* Run the passs */
+ /* Run the pass */
LLVMRunFunctionPassManager(gallivm->passmgr, ctx->main_fn);
LLVMDisposeBuilder(gallivm->builder);
{
LLVMDisposeModule(ctx->soa.bld_base.base.gallivm->module);
LLVMContextDispose(ctx->soa.bld_base.base.gallivm->context);
+ FREE(ctx->temps);
}