From: Vivek Pandya Date: Sat, 6 Feb 2021 09:22:42 +0000 (+0530) Subject: Added code to process NIR shared load/store intrinsic. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=951926dee3bcb263646018670733bd8b68eb0597;p=mesa.git Added code to process NIR shared load/store intrinsic. Also added code to disassemble and print X86 instructions for egarly compiled function in ORCJIT. --- diff --git a/src/libre-soc/vulkan/libresoc_llvm.c b/src/libre-soc/vulkan/libresoc_llvm.c index 100fc1ea234..06a62424300 100644 --- a/src/libre-soc/vulkan/libresoc_llvm.c +++ b/src/libre-soc/vulkan/libresoc_llvm.c @@ -3,8 +3,13 @@ void InitLLVM(struct libresoc_llvm *llvm_ref) { - LLVMInitializeNativeTarget(); - LLVMInitializeNativeAsmPrinter(); + // LLVMInitializeNativeTarget(); + // LLVMInitializeNativeAsmPrinter(); + LLVMInitializeAllAsmPrinters(); + LLVMInitializeAllTargets(); + LLVMInitializeAllTargetInfos(); + LLVMInitializeAllTargetMCs(); + LLVMInitializeAllDisassemblers(); //LLVMLinkInMCJIT(); char *def_triple = LLVMGetDefaultTargetTriple(); // E.g. "x86_64-linux-gnu" char *error; @@ -121,6 +126,17 @@ void handle_shader_output_decl(struct libresoc_nir_tran_ctx *ctx, } } +LLVMValueRef extract_components(struct libresoc_llvm_context *ctx, LLVMValueRef value, unsigned start, + unsigned channels) +{ + LLVMValueRef chan[channels]; + + for (unsigned i = 0; i < channels; i++) + chan[i] = llvm_extract_elem(ctx, value, i + start); + + return build_gather_values(ctx, chan, channels); +} + static void build_store_values_extended(struct libresoc_llvm_context *lc, LLVMValueRef *values, unsigned value_count, unsigned value_stride, LLVMValueRef vec) @@ -179,6 +195,26 @@ static LLVMValueRef get_src(struct libresoc_nir_tran_ctx *ctx, nir_src src) return ctx->ssa_defs[src.ssa->index]; } +static LLVMTypeRef get_def_type(struct libresoc_nir_tran_ctx *ctx, const nir_ssa_def *def) +{ + LLVMTypeRef type = LLVMIntTypeInContext(ctx->lc.context, def->bit_size); + if (def->num_components > 1) { + type = LLVMVectorType(type, def->num_components); + } + return type; +} + +static LLVMValueRef get_memory_ptr(struct libresoc_nir_tran_ctx *ctx, nir_src src, unsigned bit_size) +{ + LLVMValueRef ptr = get_src(ctx, src); + ptr = LLVMBuildGEP(ctx->lc.builder, ctx->lc.lds, &ptr, 1, ""); + int addr_space = LLVMGetPointerAddressSpace(LLVMTypeOf(ptr)); + + LLVMTypeRef type = LLVMIntTypeInContext(ctx->lc.context, bit_size); + + return LLVMBuildBitCast(ctx->lc.builder, ptr, LLVMPointerType(type, addr_space), ""); +} + static uint32_t widen_mask(uint32_t mask, unsigned multiplier) { uint32_t new_mask = 0; @@ -683,6 +719,146 @@ static LLVMTypeRef glsl_to_llvm_type(struct libresoc_llvm_context *lc, const str return LLVMStructTypeInContext(lc->context, member_types, glsl_get_length(type), false); } +// static LLVMValueRef visit_load(struct libresoc_nir_tran_ctx *ctx, nir_intrinsic_instr *instr, +// bool is_output) +// { +// LLVMValueRef values[8]; +// LLVMTypeRef dest_type = get_def_type(ctx, &instr->dest.ssa); +// LLVMTypeRef component_type; +// unsigned base = nir_intrinsic_base(instr); +// unsigned component = nir_intrinsic_component(instr); +// unsigned count = instr->dest.ssa.num_components * (instr->dest.ssa.bit_size == 64 ? 2 : 1); +// nir_src *vertex_index_src = nir_get_io_vertex_index_src(instr); +// LLVMValueRef vertex_index = vertex_index_src ? get_src(ctx, *vertex_index_src) : NULL; +// nir_src offset = *nir_get_io_offset_src(instr); +// LLVMValueRef indir_index = NULL; + +// if (LLVMGetTypeKind(dest_type) == LLVMVectorTypeKind) +// component_type = LLVMGetElementType(dest_type); +// else +// component_type = dest_type; + +// if (nir_src_is_const(offset)) +// assert(nir_src_as_uint(offset) == 0); +// else +// indir_index = get_src(ctx, offset); + +// if (ctx->stage == MESA_SHADER_TESS_CTRL || (ctx->stage == MESA_SHADER_TESS_EVAL && !is_output)) { +// LLVMValueRef result = ctx->abi->load_tess_varyings( +// ctx->abi, component_type, vertex_index, indir_index, 0, 0, base * 4, component, +// instr->num_components, false, false, !is_output); +// if (instr->dest.ssa.bit_size == 16) { +// result = to_integer(&ctx->lc, result); +// result = LLVMBuildTrunc(ctx->lc.builder, result, dest_type, ""); +// } +// return LLVMBuildBitCast(ctx->lc.builder, result, dest_type, ""); +// } + +// /* No indirect indexing is allowed after this point. */ +// assert(!indir_index); + +// if (ctx->stage == MESA_SHADER_GEOMETRY) { +// LLVMTypeRef type = LLVMIntTypeInContext(ctx->ac.context, instr->dest.ssa.bit_size); +// assert(nir_src_is_const(*vertex_index_src)); + +// return ctx->abi->load_inputs(ctx->abi, 0, base * 4, component, instr->num_components, +// nir_src_as_uint(*vertex_index_src), 0, type); +// } + +// if (ctx->stage == MESA_SHADER_FRAGMENT && is_output && +// nir_intrinsic_io_semantics(instr).fb_fetch_output) +// return ctx->abi->emit_fbfetch(ctx->abi); + +// /* Other non-fragment cases have inputs and outputs in temporaries. */ +// if (ctx->stage != MESA_SHADER_FRAGMENT) { +// for (unsigned chan = component; chan < count + component; chan++) { +// if (is_output) { +// values[chan] = LLVMBuildLoad(ctx->lc.builder, ctx->outputs[base * 4 + chan], ""); +// } else { +// values[chan] = ctx->inputs[base * 4 + chan]; +// if (!values[chan]) +// values[chan] = LLVMGetUndef(ctx->lc.i32); +// } +// } +// LLVMValueRef result = build_varying_gather_values(&ctx->lc, values, count, component); +// return LLVMBuildBitCast(ctx->lc.builder, result, dest_type, ""); +// } + +// /* Fragment shader inputs. */ +// unsigned vertex_id = 2; /* P0 */ + +// if (instr->intrinsic == nir_intrinsic_load_input_vertex) { +// nir_const_value *src0 = nir_src_as_const_value(instr->src[0]); + +// switch (src0[0].i32) { +// case 0: +// vertex_id = 2; +// break; +// case 1: +// vertex_id = 0; +// break; +// case 2: +// vertex_id = 1; +// break; +// default: +// unreachable("Invalid vertex index"); +// } +// } + +// LLVMValueRef attr_number = LLVMConstInt(ctx->lc.i32, base, false); + +// for (unsigned chan = 0; chan < count; chan++) { +// if (component + chan > 4) +// attr_number = LLVMConstInt(ctx->lc.i32, base + 1, false); +// LLVMValueRef llvm_chan = LLVMConstInt(ctx->lc.i32, (component + chan) % 4, false); +// values[chan] = +// build_fs_interp_mov(&ctx->lc, LLVMConstInt(ctx->lc.i32, vertex_id, false), llvm_chan, +// attr_number, get_arg(&ctx->lc, ctx->args->prim_mask)); +// values[chan] = LLVMBuildBitCast(ctx->lc.builder, values[chan], ctx->lc.i32, ""); +// values[chan] = +// LLVMBuildTruncOrBitCast(ctx->lc.builder, values[chan], +// instr->dest.ssa.bit_size == 16 ? ctx->lc.i16 : ctx->lc.i32, ""); +// } + +// LLVMValueRef result = build_gather_values(&ctx->lc, values, count); +// return LLVMBuildBitCast(ctx->lc.builder, result, dest_type, ""); +// } + +static LLVMValueRef visit_load_shared(struct libresoc_nir_tran_ctx *ctx, const nir_intrinsic_instr *instr) +{ + LLVMValueRef values[4], derived_ptr, index, ret; + + LLVMValueRef ptr = get_memory_ptr(ctx, instr->src[0], instr->dest.ssa.bit_size); + + for (int chan = 0; chan < instr->num_components; chan++) { + index = LLVMConstInt(ctx->lc.i32, chan, 0); + derived_ptr = LLVMBuildGEP(ctx->lc.builder, ptr, &index, 1, ""); + values[chan] = LLVMBuildLoad(ctx->lc.builder, derived_ptr, ""); + } + + ret = build_gather_values(&ctx->lc, values, instr->num_components); + return LLVMBuildBitCast(ctx->lc.builder, ret, get_def_type(ctx, &instr->dest.ssa), ""); +} + +static void visit_store_shared(struct libresoc_nir_tran_ctx *ctx, const nir_intrinsic_instr *instr) +{ + LLVMValueRef derived_ptr, data, index; + LLVMBuilderRef builder = ctx->lc.builder; + + LLVMValueRef ptr = get_memory_ptr(ctx, instr->src[1], instr->src[0].ssa->bit_size); + LLVMValueRef src = get_src(ctx, instr->src[0]); + + int writemask = nir_intrinsic_write_mask(instr); + for (int chan = 0; chan < 4; chan++) { + if (!(writemask & (1 << chan))) { + continue; + } + data = llvm_extract_elem(&ctx->lc, src, chan); + index = LLVMConstInt(ctx->lc.i32, chan, 0); + derived_ptr = LLVMBuildGEP(builder, ptr, &index, 1, ""); + LLVMBuildStore(builder, data, derived_ptr); + } +} static void visit_load_const(struct libresoc_nir_tran_ctx *ctx, const nir_load_const_instr *instr) { LLVMValueRef values[4], value = NULL; @@ -876,15 +1052,6 @@ static void visit_deref(struct libresoc_nir_tran_ctx *ctx, nir_deref_instr *inst ctx->ssa_defs[instr->dest.ssa.index] = result; } -static LLVMTypeRef get_def_type(struct libresoc_nir_tran_ctx *ctx, const nir_ssa_def *def) -{ - LLVMTypeRef type = LLVMIntTypeInContext(ctx->lc.context, def->bit_size); - if (def->num_components > 1) { - type = LLVMVectorType(type, def->num_components); - } - return type; -} - static void visit_phi(struct libresoc_nir_tran_ctx *ctx, nir_phi_instr *instr) { LLVMTypeRef type = get_def_type(ctx, &instr->dest.ssa); @@ -2062,10 +2229,10 @@ static void visit_intrinsic(struct libresoc_nir_tran_ctx *ctx, nir_intrinsic_ins visit_store_output(ctx, instr); break; case nir_intrinsic_load_shared: - // result = visit_load_shared(ctx, instr); + result = visit_load_shared(ctx, instr); break; case nir_intrinsic_store_shared: - // visit_store_shared(ctx, instr); + visit_store_shared(ctx, instr); break; case nir_intrinsic_bindless_image_samples: case nir_intrinsic_image_deref_samples: @@ -2335,61 +2502,61 @@ static void visit_intrinsic(struct libresoc_nir_tran_ctx *ctx, nir_intrinsic_ins // result = ac_build_mbcnt(&ctx->ac, get_src(ctx, instr->src[0])); break; case nir_intrinsic_load_scratch: { - // LLVMValueRef offset = get_src(ctx, instr->src[0]); - // LLVMValueRef ptr = ac_build_gep0(&ctx->ac, ctx->scratch, offset); - // LLVMTypeRef comp_type = LLVMIntTypeInContext(ctx->ac.context, instr->dest.ssa.bit_size); - // LLVMTypeRef vec_type = instr->dest.ssa.num_components == 1 - // ? comp_type - // : LLVMVectorType(comp_type, instr->dest.ssa.num_components); - // unsigned addr_space = LLVMGetPointerAddressSpace(LLVMTypeOf(ptr)); - // ptr = LLVMBuildBitCast(ctx->ac.builder, ptr, LLVMPointerType(vec_type, addr_space), ""); - // result = LLVMBuildLoad(ctx->ac.builder, ptr, ""); + LLVMValueRef offset = get_src(ctx, instr->src[0]); + LLVMValueRef ptr = build_gep0(&ctx->lc, ctx->scratch, offset); + LLVMTypeRef comp_type = LLVMIntTypeInContext(ctx->lc.context, instr->dest.ssa.bit_size); + LLVMTypeRef vec_type = instr->dest.ssa.num_components == 1 + ? comp_type + : LLVMVectorType(comp_type, instr->dest.ssa.num_components); + unsigned addr_space = LLVMGetPointerAddressSpace(LLVMTypeOf(ptr)); + ptr = LLVMBuildBitCast(ctx->lc.builder, ptr, LLVMPointerType(vec_type, addr_space), ""); + result = LLVMBuildLoad(ctx->lc.builder, ptr, ""); break; } case nir_intrinsic_store_scratch: { - // LLVMValueRef offset = get_src(ctx, instr->src[1]); - // LLVMValueRef ptr = ac_build_gep0(&ctx->ac, ctx->scratch, offset); - // LLVMTypeRef comp_type = LLVMIntTypeInContext(ctx->ac.context, instr->src[0].ssa->bit_size); - // unsigned addr_space = LLVMGetPointerAddressSpace(LLVMTypeOf(ptr)); - // ptr = LLVMBuildBitCast(ctx->ac.builder, ptr, LLVMPointerType(comp_type, addr_space), ""); - // LLVMValueRef src = get_src(ctx, instr->src[0]); - // unsigned wrmask = nir_intrinsic_write_mask(instr); - // while (wrmask) { - // int start, count; - // u_bit_scan_consecutive_range(&wrmask, &start, &count); - - // LLVMValueRef offset = LLVMConstInt(ctx->ac.i32, start, false); - // LLVMValueRef offset_ptr = LLVMBuildGEP(ctx->ac.builder, ptr, &offset, 1, ""); - // LLVMTypeRef vec_type = count == 1 ? comp_type : LLVMVectorType(comp_type, count); - // offset_ptr = LLVMBuildBitCast(ctx->ac.builder, offset_ptr, - // LLVMPointerType(vec_type, addr_space), ""); - // LLVMValueRef offset_src = ac_extract_components(&ctx->ac, src, start, count); - // LLVMBuildStore(ctx->ac.builder, offset_src, offset_ptr); - // } + LLVMValueRef offset = get_src(ctx, instr->src[1]); + LLVMValueRef ptr = build_gep0(&ctx->lc, ctx->scratch, offset); + LLVMTypeRef comp_type = LLVMIntTypeInContext(ctx->lc.context, instr->src[0].ssa->bit_size); + unsigned addr_space = LLVMGetPointerAddressSpace(LLVMTypeOf(ptr)); + ptr = LLVMBuildBitCast(ctx->lc.builder, ptr, LLVMPointerType(comp_type, addr_space), ""); + LLVMValueRef src = get_src(ctx, instr->src[0]); + unsigned wrmask = nir_intrinsic_write_mask(instr); + while (wrmask) { + int start, count; + u_bit_scan_consecutive_range(&wrmask, &start, &count); + + LLVMValueRef offset = LLVMConstInt(ctx->lc.i32, start, false); + LLVMValueRef offset_ptr = LLVMBuildGEP(ctx->lc.builder, ptr, &offset, 1, ""); + LLVMTypeRef vec_type = count == 1 ? comp_type : LLVMVectorType(comp_type, count); + offset_ptr = LLVMBuildBitCast(ctx->lc.builder, offset_ptr, + LLVMPointerType(vec_type, addr_space), ""); + LLVMValueRef offset_src = extract_components(&ctx->lc, src, start, count); + LLVMBuildStore(ctx->lc.builder, offset_src, offset_ptr); + } break; } case nir_intrinsic_load_constant: { - // unsigned base = nir_intrinsic_base(instr); - // unsigned range = nir_intrinsic_range(instr); + unsigned base = nir_intrinsic_base(instr); + unsigned range = nir_intrinsic_range(instr); - // LLVMValueRef offset = get_src(ctx, instr->src[0]); - // offset = LLVMBuildAdd(ctx->ac.builder, offset, LLVMConstInt(ctx->ac.i32, base, false), ""); + LLVMValueRef offset = get_src(ctx, instr->src[0]); + offset = LLVMBuildAdd(ctx->lc.builder, offset, LLVMConstInt(ctx->lc.i32, base, false), ""); - // /* Clamp the offset to avoid out-of-bound access because global - // * instructions can't handle them. - // */ - // LLVMValueRef size = LLVMConstInt(ctx->ac.i32, base + range, false); - // LLVMValueRef cond = LLVMBuildICmp(ctx->ac.builder, LLVMIntULT, offset, size, ""); - // offset = LLVMBuildSelect(ctx->ac.builder, cond, offset, size, ""); + /* Clamp the offset to avoid out-of-bound access because global + * instructions can't handle them. + */ + LLVMValueRef size = LLVMConstInt(ctx->lc.i32, base + range, false); + LLVMValueRef cond = LLVMBuildICmp(ctx->lc.builder, LLVMIntULT, offset, size, ""); + offset = LLVMBuildSelect(ctx->lc.builder, cond, offset, size, ""); - // LLVMValueRef ptr = ac_build_gep0(&ctx->ac, ctx->constant_data, offset); - // LLVMTypeRef comp_type = LLVMIntTypeInContext(ctx->ac.context, instr->dest.ssa.bit_size); - // LLVMTypeRef vec_type = instr->dest.ssa.num_components == 1 - // ? comp_type - // : LLVMVectorType(comp_type, instr->dest.ssa.num_components); - // unsigned addr_space = LLVMGetPointerAddressSpace(LLVMTypeOf(ptr)); - // ptr = LLVMBuildBitCast(ctx->ac.builder, ptr, LLVMPointerType(vec_type, addr_space), ""); - // result = LLVMBuildLoad(ctx->ac.builder, ptr, ""); + LLVMValueRef ptr = build_gep0(&ctx->lc, ctx->constant_data, offset); + LLVMTypeRef comp_type = LLVMIntTypeInContext(ctx->lc.context, instr->dest.ssa.bit_size); + LLVMTypeRef vec_type = instr->dest.ssa.num_components == 1 + ? comp_type + : LLVMVectorType(comp_type, instr->dest.ssa.num_components); + unsigned addr_space = LLVMGetPointerAddressSpace(LLVMTypeOf(ptr)); + ptr = LLVMBuildBitCast(ctx->lc.builder, ptr, LLVMPointerType(vec_type, addr_space), ""); + result = LLVMBuildLoad(ctx->lc.builder, ptr, ""); break; } default: @@ -2548,10 +2715,70 @@ LLVMModuleRef libresoc_nir_translate(struct libresoc_llvm *llvm_ref, struct nir_ // if (gl_shader_stage_is_compute(nir->info.stage)) // setup_shared(&ctx, nir); visit_cf_list(&ctx, &func->impl->body); + LLVMBuildRetVoid(ctx.lc.builder); char *error = NULL; LLVMVerifyModule(mod, LLVMPrintMessageAction, &error); LLVMDumpModule(mod); LLVMDisposeMessage(error); + LLVMOrcModuleHandle mod_handle; + LLVMErrorRef error_ref = LLVMOrcAddEagerlyCompiledIR(llvm_ref->orc_ref, + &mod_handle, + mod, + orc_sym_resolver, + (void *)(llvm_ref->orc_ref)); + LLVMDumpModule(mod); + char *def_triple = LLVMGetDefaultTargetTriple(); // E.g. "x86_64-linux-gnu" + LLVMDisasmContextRef disasm = LLVMCreateDisasm(def_triple, NULL, + 0, NULL, + NULL); + if (disasm) { +LLVMOrcTargetAddress MainAddr; +LLVMOrcGetSymbolAddress(llvm_ref->orc_ref, &MainAddr ,"main_function"); + const uint8_t *bytes = (const uint8_t *)MainAddr; + char outline[1024]; +uint64_t pc; + pc = 0; +uint64_t extent = 200; + while (pc < extent) { + size_t Size; + + /* + * Print address. We use addresses relative to the start of the function, + * so that between runs. + */ + + + Size = LLVMDisasmInstruction(disasm, (uint8_t *)bytes + pc, extent - pc, 0, outline, + sizeof outline); + + /* + * Print the instruction. + */ + printf("\t%s \n", outline); + + + /* + * Stop disassembling on return statements, if there is no record of a + * jump to a successive address. + * + * XXX: This currently assumes x86 + */ + + if (Size == 1 && bytes[pc] == 0xc3) { + break; + } + + /* + * Advance. + */ + + pc += Size; + + if (pc >= extent) { + break; + } + } + } return mod; // LLVMModuleRef mod = LLVMModuleCreateWithName("libresoc_mod"); // LLVMTypeRef param_types[] = { LLVMInt32Type(), LLVMInt32Type() }; diff --git a/src/libre-soc/vulkan/libresoc_llvm.h b/src/libre-soc/vulkan/libresoc_llvm.h index 4668e47c15b..6aeae357aee 100644 --- a/src/libre-soc/vulkan/libresoc_llvm.h +++ b/src/libre-soc/vulkan/libresoc_llvm.h @@ -6,6 +6,7 @@ #include "libresoc_shader_args.h" #include #include +#include #include #include "nir/nir.h" #include "nir/nir_deref.h" @@ -118,6 +119,8 @@ typedef struct libresoc_llvm_context { struct llvm_flow_state *flow; unsigned float_mode; + + LLVMValueRef lds; } libresoc_llvm_context; struct libresoc_llvm { @@ -158,6 +161,9 @@ struct libresoc_nir_tran_ctx { void InitLLVM(struct libresoc_llvm *llvm_ref); void DestroyLLVM(struct libresoc_llvm *llvm_ref); +LLVMValueRef extract_components(struct libresoc_llvm_context *ctx, LLVMValueRef value, unsigned start, + unsigned channels); + static inline unsigned llvm_reg_index_soa(unsigned index, unsigned chan) { return (index * 4) + chan;