/* create new unsigned integer type with `n_bits` number of bits */ struct type *type_new_uint_n(size_t n_bits) { struct type *r = malloc(sizeof *r); r->val = TYPE_UINT; r->u.n_bits = n_bits; r->llvm_type = LLVMIntType(n_bits); return r; }
/** * Gather elements from scatter positions in memory into a single vector. * * @param src_width src element width * @param dst_width result element width (source will be expanded to fit) * @param length length of the offsets, * @param base_ptr base pointer, should be a i8 pointer type. * @param offsets vector with offsets */ LLVMValueRef lp_build_gather(LLVMBuilderRef builder, unsigned length, unsigned src_width, unsigned dst_width, LLVMValueRef base_ptr, LLVMValueRef offsets) { LLVMTypeRef src_type = LLVMIntType(src_width); LLVMTypeRef src_ptr_type = LLVMPointerType(src_type, 0); LLVMTypeRef dst_elem_type = LLVMIntType(dst_width); LLVMTypeRef dst_vec_type = LLVMVectorType(dst_elem_type, length); LLVMValueRef res; unsigned i; res = LLVMGetUndef(dst_vec_type); for(i = 0; i < length; ++i) { LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0); LLVMValueRef elem_offset; LLVMValueRef elem_ptr; LLVMValueRef elem; elem_offset = LLVMBuildExtractElement(builder, offsets, index, ""); elem_ptr = LLVMBuildGEP(builder, base_ptr, &elem_offset, 1, ""); elem_ptr = LLVMBuildBitCast(builder, elem_ptr, src_ptr_type, ""); elem = LLVMBuildLoad(builder, elem_ptr, ""); assert(src_width <= dst_width); if(src_width > dst_width) elem = LLVMBuildTrunc(builder, elem, dst_elem_type, ""); if(src_width < dst_width) elem = LLVMBuildZExt(builder, elem, dst_elem_type, ""); res = LLVMBuildInsertElement(builder, res, elem, index, ""); } return res; }
LLVMValueRef lp_build_zero(struct lp_type type) { if (type.length == 1) { if (type.floating) return LLVMConstReal(LLVMFloatType(), 0.0); else return LLVMConstInt(LLVMIntType(type.width), 0, 0); } else { LLVMTypeRef vec_type = lp_build_vec_type(type); return LLVMConstNull(vec_type); } }
/** * @param mask TGSI_WRITEMASK_xxx */ LLVMValueRef lp_build_const_mask_aos(struct lp_type type, unsigned mask) { LLVMTypeRef elem_type = LLVMIntType(type.width); LLVMValueRef masks[LP_MAX_VECTOR_LENGTH]; unsigned i, j; assert(type.length <= LP_MAX_VECTOR_LENGTH); for (j = 0; j < type.length; j += 4) { for( i = 0; i < 4; ++i) { masks[j + i] = LLVMConstInt(elem_type, mask & (1 << i) ? ~0ULL : 0, 1); } } return LLVMConstVector(masks, type.length); }
/** * Generate the code to do inside/outside triangle testing for the * four pixels in a 2x2 quad. This will set the four elements of the * quad mask vector to 0 or ~0. * \param i which quad of the quad group to test, in [0,3] */ static void generate_tri_edge_mask(LLVMBuilderRef builder, unsigned i, LLVMValueRef *mask, /* ivec4, out */ LLVMValueRef c0, /* int32 */ LLVMValueRef c1, /* int32 */ LLVMValueRef c2, /* int32 */ LLVMValueRef step0_ptr, /* ivec4 */ LLVMValueRef step1_ptr, /* ivec4 */ LLVMValueRef step2_ptr) /* ivec4 */ { #define OPTIMIZE_IN_OUT_TEST 0 #if OPTIMIZE_IN_OUT_TEST struct lp_build_if_state ifctx; LLVMValueRef not_draw_all; #endif struct lp_build_flow_context *flow; struct lp_type i32_type; LLVMTypeRef i32vec4_type, mask_type; LLVMValueRef c0_vec, c1_vec, c2_vec; LLVMValueRef in_out_mask; assert(i < 4); /* int32 vector type */ memset(&i32_type, 0, sizeof i32_type); i32_type.floating = FALSE; /* values are integers */ i32_type.sign = TRUE; /* values are signed */ i32_type.norm = FALSE; /* values are not normalized */ i32_type.width = 32; /* 32-bit int values */ i32_type.length = 4; /* 4 elements per vector */ i32vec4_type = lp_build_int32_vec4_type(); mask_type = LLVMIntType(32 * 4); /* * Use a conditional here to do detailed pixel in/out testing. * We only have to do this if c0 != INT_MIN. */ flow = lp_build_flow_create(builder); lp_build_flow_scope_begin(flow); { #if OPTIMIZE_IN_OUT_TEST /* not_draw_all = (c0 != INT_MIN) */ not_draw_all = LLVMBuildICmp(builder, LLVMIntNE, c0, LLVMConstInt(LLVMInt32Type(), INT_MIN, 0), ""); in_out_mask = lp_build_int_const_scalar(i32_type, ~0); lp_build_flow_scope_declare(flow, &in_out_mask); /* if (not_draw_all) {... */ lp_build_if(&ifctx, flow, builder, not_draw_all); #endif { LLVMValueRef step0_vec, step1_vec, step2_vec; LLVMValueRef m0_vec, m1_vec, m2_vec; LLVMValueRef index, m; /* c0_vec = {c0, c0, c0, c0} * Note that we emit this code four times but LLVM optimizes away * three instances of it. */ c0_vec = lp_build_broadcast(builder, i32vec4_type, c0); c1_vec = lp_build_broadcast(builder, i32vec4_type, c1); c2_vec = lp_build_broadcast(builder, i32vec4_type, c2); lp_build_name(c0_vec, "edgeconst0vec"); lp_build_name(c1_vec, "edgeconst1vec"); lp_build_name(c2_vec, "edgeconst2vec"); /* load step0vec, step1, step2 vec from memory */ index = LLVMConstInt(LLVMInt32Type(), i, 0); step0_vec = LLVMBuildLoad(builder, LLVMBuildGEP(builder, step0_ptr, &index, 1, ""), ""); step1_vec = LLVMBuildLoad(builder, LLVMBuildGEP(builder, step1_ptr, &index, 1, ""), ""); step2_vec = LLVMBuildLoad(builder, LLVMBuildGEP(builder, step2_ptr, &index, 1, ""), ""); lp_build_name(step0_vec, "step0vec"); lp_build_name(step1_vec, "step1vec"); lp_build_name(step2_vec, "step2vec"); /* m0_vec = step0_ptr[i] > c0_vec */ m0_vec = lp_build_compare(builder, i32_type, PIPE_FUNC_GREATER, step0_vec, c0_vec); m1_vec = lp_build_compare(builder, i32_type, PIPE_FUNC_GREATER, step1_vec, c1_vec); m2_vec = lp_build_compare(builder, i32_type, PIPE_FUNC_GREATER, step2_vec, c2_vec); /* in_out_mask = m0_vec & m1_vec & m2_vec */ m = LLVMBuildAnd(builder, m0_vec, m1_vec, ""); in_out_mask = LLVMBuildAnd(builder, m, m2_vec, ""); lp_build_name(in_out_mask, "inoutmaskvec"); } #if OPTIMIZE_IN_OUT_TEST lp_build_endif(&ifctx); #endif } lp_build_flow_scope_end(flow); lp_build_flow_destroy(flow); /* This is the initial alive/dead pixel mask for a quad of four pixels. * It's an int[4] vector with each word set to 0 or ~0. * Words will get cleared when pixels faile the Z test, etc. */ *mask = in_out_mask; }