LLVMValueRef gen_div(struct node *ast) { return LLVMBuildSDiv(builder, codegen(ast->one), codegen(ast->two), ""); }
static void emit_idiv(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; emit_data->output[emit_data->chan] = LLVMBuildSDiv(builder, emit_data->args[0], emit_data->args[1], ""); }
static LLVMValueRef translateIntBinOp(NodeKind Op, LLVMValueRef ValueE1, LLVMValueRef ValueE2) { switch (Op) { case OrOp: return LLVMBuildOr (Builder, ValueE1, ValueE2, ""); case AndOp: return LLVMBuildAnd(Builder, ValueE1, ValueE2, ""); case SumOp: return LLVMBuildAdd(Builder, ValueE1, ValueE2, ""); case SubOp: return LLVMBuildSub(Builder, ValueE1, ValueE2, ""); case MultOp: return LLVMBuildMul(Builder, ValueE1, ValueE2, ""); case DivOp: return LLVMBuildSDiv(Builder, ValueE1, ValueE2, ""); case LtOp: return LLVMBuildICmp(Builder, LLVMIntSLT, ValueE1, ValueE2, ""); case LeOp: return LLVMBuildICmp(Builder, LLVMIntSLE, ValueE1, ValueE2, ""); case GtOp: return LLVMBuildICmp(Builder, LLVMIntSGT, ValueE1, ValueE2, ""); case GeOp: return LLVMBuildICmp(Builder, LLVMIntSGE, ValueE1, ValueE2, ""); case EqOp: return LLVMBuildICmp(Builder, LLVMIntEQ, ValueE1, ValueE2, ""); case DiffOp: return LLVMBuildICmp(Builder, LLVMIntNE, ValueE1, ValueE2, ""); default: return NULL; } }
static inline LLVMValueRef LLVM_visit(ASTNode *node, LLVMBuilderRef builder) { switch(node->type) { case AST_BINARY_OP: { ASTBinaryOp *binary_op = (ASTBinaryOp*)node; LLVMValueRef a = LLVM_visit(binary_op->lhs, builder); LLVMValueRef b = LLVM_visit(binary_op->rhs, builder); switch(binary_op->op) { case '+': return LLVMBuildAdd(builder, a, b, "a + b"); case '-': return LLVMBuildSub(builder, a, b, "a - b"); case '*': return LLVMBuildMul(builder, a, b, "a * b"); case '/': return LLVMBuildSDiv(builder, a, b, "a / b"); } } case AST_INT: { return LLVMConstInt(LLVMInt32Type(), ((ASTInt*)node)->value, 0); } } }
static LLVMValueRef lp_build_gather_avx2(struct gallivm_state *gallivm, unsigned length, unsigned src_width, struct lp_type dst_type, LLVMValueRef base_ptr, LLVMValueRef offsets) { LLVMBuilderRef builder = gallivm->builder; LLVMTypeRef src_type, src_vec_type; LLVMValueRef res; struct lp_type res_type = dst_type; res_type.length *= length; if (dst_type.floating) { src_type = src_width == 64 ? LLVMDoubleTypeInContext(gallivm->context) : LLVMFloatTypeInContext(gallivm->context); } else { src_type = LLVMIntTypeInContext(gallivm->context, src_width); } src_vec_type = LLVMVectorType(src_type, length); /* XXX should allow hw scaling (can handle i8, i16, i32, i64 for x86) */ assert(LLVMTypeOf(base_ptr) == LLVMPointerType(LLVMInt8TypeInContext(gallivm->context), 0)); if (0) { /* * XXX: This will cause LLVM pre 3.7 to hang; it works on LLVM 3.8 but * will not use the AVX2 gather instrinsics (even with llvm 4.0), at * least with Haswell. See * http://lists.llvm.org/pipermail/llvm-dev/2016-January/094448.html * And the generated code doing the emulation is quite a bit worse * than what we get by doing it ourselves too. */ LLVMTypeRef i32_type = LLVMIntTypeInContext(gallivm->context, 32); LLVMTypeRef i32_vec_type = LLVMVectorType(i32_type, length); LLVMTypeRef i1_type = LLVMIntTypeInContext(gallivm->context, 1); LLVMTypeRef i1_vec_type = LLVMVectorType(i1_type, length); LLVMTypeRef src_ptr_type = LLVMPointerType(src_type, 0); LLVMValueRef src_ptr; base_ptr = LLVMBuildBitCast(builder, base_ptr, src_ptr_type, ""); /* Rescale offsets from bytes to elements */ LLVMValueRef scale = LLVMConstInt(i32_type, src_width/8, 0); scale = lp_build_broadcast(gallivm, i32_vec_type, scale); assert(LLVMTypeOf(offsets) == i32_vec_type); offsets = LLVMBuildSDiv(builder, offsets, scale, ""); src_ptr = LLVMBuildGEP(builder, base_ptr, &offsets, 1, "vector-gep"); char intrinsic[64]; util_snprintf(intrinsic, sizeof intrinsic, "llvm.masked.gather.v%u%s%u", length, dst_type.floating ? "f" : "i", src_width); LLVMValueRef alignment = LLVMConstInt(i32_type, src_width/8, 0); LLVMValueRef mask = LLVMConstAllOnes(i1_vec_type); LLVMValueRef passthru = LLVMGetUndef(src_vec_type); LLVMValueRef args[] = { src_ptr, alignment, mask, passthru }; res = lp_build_intrinsic(builder, intrinsic, src_vec_type, args, 4, 0); } else { LLVMTypeRef i8_type = LLVMIntTypeInContext(gallivm->context, 8); const char *intrinsic = NULL; unsigned l_idx = 0; assert(src_width == 32 || src_width == 64); if (src_width == 32) { assert(length == 4 || length == 8); } else { assert(length == 2 || length == 4); } static const char *intrinsics[2][2][2] = { {{"llvm.x86.avx2.gather.d.d", "llvm.x86.avx2.gather.d.d.256"}, {"llvm.x86.avx2.gather.d.q", "llvm.x86.avx2.gather.d.q.256"}}, {{"llvm.x86.avx2.gather.d.ps", "llvm.x86.avx2.gather.d.ps.256"}, {"llvm.x86.avx2.gather.d.pd", "llvm.x86.avx2.gather.d.pd.256"}}, }; if ((src_width == 32 && length == 8) || (src_width == 64 && length == 4)) { l_idx = 1; } intrinsic = intrinsics[dst_type.floating][src_width == 64][l_idx]; LLVMValueRef passthru = LLVMGetUndef(src_vec_type); LLVMValueRef mask = LLVMConstAllOnes(src_vec_type); mask = LLVMConstBitCast(mask, src_vec_type); LLVMValueRef scale = LLVMConstInt(i8_type, 1, 0); LLVMValueRef args[] = { passthru, base_ptr, offsets, mask, scale }; res = lp_build_intrinsic(builder, intrinsic, src_vec_type, args, 5, 0); } res = LLVMBuildBitCast(builder, res, lp_build_vec_type(gallivm, res_type), ""); return res; }