예제 #1
0
/**
 * Generate abs(a)
 */
LLVMValueRef
lp_build_abs(struct lp_build_context *bld,
             LLVMValueRef a)
{
   const struct lp_type type = bld->type;
   LLVMTypeRef vec_type = lp_build_vec_type(type);

   if(!type.sign)
      return a;

   if(type.floating) {
      /* Mask out the sign bit */
      LLVMTypeRef int_vec_type = lp_build_int_vec_type(type);
      unsigned long long absMask = ~(1ULL << (type.width - 1));
      LLVMValueRef mask = lp_build_int_const_scalar(type, ((unsigned long long) absMask));
      a = LLVMBuildBitCast(bld->builder, a, int_vec_type, "");
      a = LLVMBuildAnd(bld->builder, a, mask, "");
      a = LLVMBuildBitCast(bld->builder, a, vec_type, "");
      return a;
   }

   if(type.width*type.length == 128 && util_cpu_caps.has_ssse3) {
      switch(type.width) {
      case 8:
         return lp_build_intrinsic_unary(bld->builder, "llvm.x86.ssse3.pabs.b.128", vec_type, a);
      case 16:
         return lp_build_intrinsic_unary(bld->builder, "llvm.x86.ssse3.pabs.w.128", vec_type, a);
      case 32:
         return lp_build_intrinsic_unary(bld->builder, "llvm.x86.ssse3.pabs.d.128", vec_type, a);
      }
   }

   return lp_build_max(bld, a, LLVMBuildNeg(bld->builder, a, ""));
}
예제 #2
0
static void emit_ineg(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] = LLVMBuildNeg(builder,
			emit_data->args[0], "");
}
예제 #3
0
파일: TranslateExpr.c 프로젝트: YuKill/ftc
static LLVMValueRef
translateNegOp(SymbolTable *TyTable, SymbolTable *ValTable, ASTNode *Node) {
  ASTNode *Expr = (ASTNode*) ptrVectorGet(&(Node->Child), 0);

  LLVMValueRef ExprPtr  = translateExpr(TyTable, ValTable, Expr);
  LLVMValueRef ExprLoad = LLVMBuildLoad(Builder, ExprPtr, "");
  LLVMBuildNeg (Builder, ExprLoad, "");

  return ExprPtr;
}
예제 #4
0
static void emit_iabs(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] =
		lp_build_emit_llvm_binary(bld_base, TGSI_OPCODE_IMAX,
					  emit_data->args[0],
					  LLVMBuildNeg(builder,
						       emit_data->args[0], ""));
}
예제 #5
0
/**
 * Small vector x scale multiplication optimization.
 */
LLVMValueRef
lp_build_mul_imm(struct lp_build_context *bld,
                 LLVMValueRef a,
                 int b)
{
   LLVMValueRef factor;

   if(b == 0)
      return bld->zero;

   if(b == 1)
      return a;

   if(b == -1)
      return LLVMBuildNeg(bld->builder, a, "");

   if(b == 2 && bld->type.floating)
      return lp_build_add(bld, a, a);

   if(util_is_pot(b)) {
      unsigned shift = ffs(b) - 1;

      if(bld->type.floating) {
#if 0
         /*
          * Power of two multiplication by directly manipulating the mantissa.
          *
          * XXX: This might not be always faster, it will introduce a small error
          * for multiplication by zero, and it will produce wrong results
          * for Inf and NaN.
          */
         unsigned mantissa = lp_mantissa(bld->type);
         factor = lp_build_int_const_scalar(bld->type, (unsigned long long)shift << mantissa);
         a = LLVMBuildBitCast(bld->builder, a, lp_build_int_vec_type(bld->type), "");
         a = LLVMBuildAdd(bld->builder, a, factor, "");
         a = LLVMBuildBitCast(bld->builder, a, lp_build_vec_type(bld->type), "");
         return a;
#endif
      }
      else {
         factor = lp_build_const_scalar(bld->type, shift);
         return LLVMBuildShl(bld->builder, a, factor, "");
      }
   }

   factor = lp_build_const_scalar(bld->type, (double)b);
   return lp_build_mul(bld, a, factor);
}
예제 #6
0
파일: genoperator.c 프로젝트: jonas-l/ponyc
LLVMValueRef gen_neg(compile_t* c, ast_t* ast)
{
  LLVMValueRef value = gen_expr(c, ast);

  if(value == NULL)
    return NULL;

  if(LLVMIsAConstantFP(value))
    return LLVMConstFNeg(value);

  if(LLVMIsAConstantInt(value))
    return LLVMConstNeg(value);

  if(is_fp(value))
    return LLVMBuildFNeg(c->builder, value, "");

  return LLVMBuildNeg(c->builder, value, "");
}
예제 #7
0
/*
 * gen_shift
 *
 * Shifts are a little tricky, since LLVM has explicit left-shift and
 * right-shift instructions, which take non-negative shift values.  BLISS,
 * on the other hand, has a single shift operator and generates right-shifts
 * when the RHS is negative.  If the RHS is a constant, we can do the translation
 * here; otherwise, we have to build a conditional to check at runtime.
 */
static LLVMValueRef
gen_shift (gencodectx_t gctx, expr_node_t *lhs, expr_node_t *rhs, LLVMTypeRef neededtype)
{
    LLVMBuilderRef builder = gctx->curfn->builder;
    LLVMTypeRef inttype = gctx->fullwordtype;
    LLVMValueRef lval, rval, result, test;

    lval = (lhs == 0 ? 0 : llvmgen_expression(gctx, lhs, inttype));

    if (expr_type(rhs) == EXPTYPE_PRIM_LIT) {
        long count = expr_litval(rhs);
        if (count < 0) {
            rval = LLVMConstInt(inttype, -count, 0);
            result = LLVMBuildLShr(builder, lval, rval, llvmgen_temp(gctx));
        } else {
            rval = LLVMConstInt(inttype, count, 0);
            result = LLVMBuildShl(builder, lval, rval, llvmgen_temp(gctx));
        }
    } else {
        LLVMBasicBlockRef exitblock = llvmgen_exitblock_create(gctx, 0);
        LLVMBasicBlockRef lshiftblk, rshiftblk;
        llvm_btrack_t *bt = llvmgen_btrack_create(gctx, exitblock);

        lshiftblk = LLVMInsertBasicBlockInContext(gctx->llvmctx, exitblock, llvmgen_label(gctx));
        rshiftblk = LLVMInsertBasicBlockInContext(gctx->llvmctx, exitblock, llvmgen_label(gctx));

        rval = llvmgen_expression(gctx, rhs, inttype);
        test = LLVMBuildICmp(builder, LLVMIntSLT, rval, LLVMConstNull(inttype), llvmgen_temp(gctx));
        LLVMBuildCondBr(builder, test, rshiftblk, lshiftblk);
        LLVMPositionBuilderAtEnd(builder, lshiftblk);
        result = LLVMBuildShl(builder, lval, rval, llvmgen_temp(gctx));
        llvmgen_btrack_update(gctx, bt, result);
        LLVMPositionBuilderAtEnd(builder, rshiftblk);
        rval = LLVMBuildNeg(builder, rval, llvmgen_temp(gctx));
        result = LLVMBuildLShr(builder, lval, rval, llvmgen_temp(gctx));
        llvmgen_btrack_update(gctx, bt, result);
        result = llvmgen_btrack_finalize(gctx, bt, inttype);
    }

    return llvmgen_adjustval(gctx, result, neededtype, 0);

} /* gen_shift */
예제 #8
0
/*
 * gen_operator_expression
 *
 * Code generation for operator expressions.  Most of them have straightforward
 * translations into LLVM instructions and are handled directly here.
 */
static LLVMValueRef
gen_operator_expression (gencodectx_t gctx, expr_node_t *exp, LLVMTypeRef neededtype)
{
    expr_node_t *lhs = expr_op_lhs(exp);
    expr_node_t *rhs = expr_op_rhs(exp);
    optype_t op = expr_op_type(exp);
    LLVMBuilderRef builder = gctx->curfn->builder;
    LLVMTypeRef inttype;
    LLVMValueRef lval, rval, result;

    if (op == OPER_FETCH) {
        return gen_fetch(gctx, rhs, neededtype);
    }

    if (op == OPER_ASSIGN) {
        LLVMValueRef val = llvmgen_assignment(gctx, lhs, rhs);
        return llvmgen_adjustval(gctx, val, neededtype, 0);
    }

    if (op == OPER_SHIFT) {
        return gen_shift(gctx, lhs, rhs, neededtype);
    }

    inttype = LLVMIntTypeInContext(gctx->llvmctx, machine_scalar_bits(gctx->mach));

    lval = (lhs == 0 ? 0 : llvmgen_expression(gctx, lhs, inttype));
    rval = llvmgen_expression(gctx, rhs, inttype);
    switch (op) {
        case OPER_UNARY_PLUS:
            result = rval;
            break;
        case OPER_UNARY_MINUS:
            result = LLVMBuildNeg(builder, rval, llvmgen_temp(gctx));
            break;
        case OPER_ADD:
            result = LLVMBuildAdd(builder, lval, rval, llvmgen_temp(gctx));
            break;
        case OPER_SUBTRACT:
            result = LLVMBuildSub(builder, lval, rval, llvmgen_temp(gctx));
            break;
        case OPER_MULT:
            result = LLVMBuildMul(builder, lval, rval, llvmgen_temp(gctx));
            break;
        case OPER_DIV:
            result = LLVMBuildUDiv(builder, lval, rval, llvmgen_temp(gctx));
            break;
        case OPER_MODULO:
            result = LLVMBuildURem(builder, lval, rval, llvmgen_temp(gctx));
            break;
        case OPER_AND:
            result = LLVMBuildAnd(builder, lval, rval, llvmgen_temp(gctx));
            break;
        case OPER_OR:
            result = LLVMBuildOr(builder, lval, rval, llvmgen_temp(gctx));
            break;
        case OPER_NOT:
            result = LLVMBuildNot(builder, rval, llvmgen_temp(gctx));
            break;
        case OPER_XOR:
            result = LLVMBuildXor(builder, lval, rval, llvmgen_temp(gctx));
            break;
        case OPER_EQV:
            result = LLVMBuildXor(builder, lval, rval, llvmgen_temp(gctx));
            result = LLVMBuildNot(builder, result, llvmgen_temp(gctx));
            break;
        default:
            if (op >= OPER_CMP_EQL && op <= OPER_CMP_GEQA) {
                result = LLVMBuildICmp(builder,
                                       llvmgen_predfromop(op, machine_addr_signed(gctx->mach)),
                                       lval, rval, llvmgen_temp(gctx));
            } else {
                // Everything should be covered
                expr_signal(gctx->ectx, STC__INTCMPERR, "gen_operator_expression");
                result = LLVMConstNull(inttype);
            }
            break;
    }

    return llvmgen_adjustval(gctx, result, neededtype, 0);

} /* gen_operator_expression */
예제 #9
0
/*
 * gen_fetch
 *
 * Generates a load operation for a fetch expression.
 */
static LLVMValueRef
gen_fetch (gencodectx_t gctx, expr_node_t *rhs, LLVMTypeRef neededtype)
{
    LLVMBuilderRef builder = gctx->curfn->builder;
    llvm_accinfo_t accinfo;
    LLVMValueRef addr, val;
    LLVMTypeRef type;
    int shifts_required = 0;
    int signext;

    // For field references with non-zero bit position, or with
    // non-CTCE size, we'll have to do bit shifting to extract
    // the field.
    addr = llvmgen_addr_expression(gctx, rhs, &accinfo);
    if (accinfo.posval != 0 || accinfo.sizeval != 0) {
        type = gctx->fullwordtype;
        if ((accinfo.flags & LLVMGEN_M_ACC_CONSTSIZ)) {
            accinfo.sizeval = LLVMConstInt(gctx->fullwordtype, accinfo.size, 0);
        }
        shifts_required = 1;
    } else if ((accinfo.flags & LLVMGEN_M_ACC_CONSTSIZ)) {
        if (accinfo.size == 0) {
            // XXX signal invalid size
            type = gctx->int1type;
        } else {
            type = LLVMIntTypeInContext(gctx->llvmctx, accinfo.size);
        }
    } else {
        type = gctx->fullwordtype;
    }
    signext = ((accinfo.flags & LLVMGEN_M_SEG_SIGNEXT) != 0);

    // If we're fetching from a register, there's no load intruction
    // required - EXCEPT if this was a scalar BIND, where the BIND

    if ((accinfo.segclass == LLVM_REG &&
        (accinfo.flags & LLVMGEN_M_SEG_DEREFED) == 0) &&
        (accinfo.flags & LLVMGEN_M_SEG_BINDPTR) == 0) {
        val = llvmgen_adjustval(gctx, addr, type, signext);
    } else {
        addr = llvmgen_adjustval(gctx, addr, LLVMPointerType(type, 0), 0);
        val = LLVMBuildLoad(builder, addr, llvmgen_temp(gctx));
        if ((accinfo.flags & LLVMGEN_M_SEG_VOLATILE) != 0) LLVMSetVolatile(val, 1);
    }
    if (shifts_required) {
        val = llvmgen_adjustval(gctx, val, gctx->fullwordtype, signext);
        if (signext) {
            val = LLVMBuildAShr(builder, val, accinfo.posval, llvmgen_temp(gctx));
        } else {
            val = LLVMBuildLShr(builder, val, accinfo.posval, llvmgen_temp(gctx));
        }

        if ((accinfo.flags & LLVMGEN_M_ACC_CONSTSIZ) != 0) {
            LLVMTypeRef trunctype = LLVMIntTypeInContext(gctx->llvmctx, accinfo.size);
            val = llvmgen_adjustval(gctx, val, trunctype, signext);
        } else {
            LLVMValueRef neg1 = LLVMConstAllOnes(gctx->fullwordtype);
            LLVMValueRef mask;

            mask = LLVMBuildShl(builder, neg1, accinfo.sizeval, llvmgen_temp(gctx));
            mask = LLVMBuildNeg(builder, mask, llvmgen_temp(gctx));
            val = LLVMBuildAnd(builder, val, mask, llvmgen_temp(gctx));
            if (signext) {
                val = LLVMBuildSExt(builder, val, gctx->fullwordtype, llvmgen_temp(gctx));
            }
        }
    }

    return llvmgen_adjustval(gctx, val, neededtype, signext);

} /* gen_fetch */
예제 #10
0
파일: codegen.c 프로젝트: dobyrch/dbc
LLVMValueRef gen_neg(struct node *ast)
{
	return LLVMBuildNeg(builder,
			codegen(ast->one),
			"");
}
예제 #11
0
LLVMValueRef
lp_build_negate(struct lp_build_context *bld,
                LLVMValueRef a)
{
   return LLVMBuildNeg(bld->builder, a, "");
}
예제 #12
0
/* This function will take a bool and sign extend it to a specified bitwidth.
   It will also perform i1 to floating point conversions if necessary. All vector
   components that are equal to 1 will be converted to -1 in accordance with the 
   OpenCL standard. */
struct cl2llvm_val_t *cl2llvm_bool_ext(struct cl2llvm_val_t *bool_val,
	struct cl2llvmTypeWrap *type)
{
	struct cl2llvm_val_t *value;
	struct cl2llvmTypeWrap *switch_type;
	LLVMTypeRef totype;
	int vec_length;

	switch_type = cl2llvmTypeWrapCreate(cl2llvmTypeWrapGetLlvmType(type), cl2llvmTypeWrapGetSign(type));

	if (LLVMGetTypeKind(cl2llvmTypeWrapGetLlvmType(type)) == LLVMVectorTypeKind)		
		cl2llvmTypeWrapSetLlvmType(switch_type, LLVMGetElementType(cl2llvmTypeWrapGetLlvmType(type)));
		

	if (LLVMGetTypeKind(cl2llvmTypeWrapGetLlvmType(type)) == LLVMVectorTypeKind)
	{
		vec_length = LLVMGetVectorSize(cl2llvmTypeWrapGetLlvmType(type));
		switch (LLVMGetTypeKind(cl2llvmTypeWrapGetLlvmType(switch_type)))
		{
		case LLVMIntegerTypeKind:
			totype = cl2llvmTypeWrapGetLlvmType(type);
			break;
		case LLVMFloatTypeKind:
			totype = LLVMVectorType(LLVMInt32Type(), vec_length);
			break;
		case LLVMDoubleTypeKind:
			totype = LLVMVectorType(LLVMInt64Type(), vec_length);
			break;
		case LLVMHalfTypeKind:
			totype = LLVMVectorType(LLVMInt16Type(), vec_length);
			break;
		default:
			cl2llvm_yyerror("unreachable code reached");
			break;
		}
	}
	else
		totype = LLVMInt32Type();
	
	value = cl2llvm_val_create();

	snprintf(temp_var_name, sizeof temp_var_name,
		"tmp_%d", temp_var_count++);

	/* Build sign extension */
	value->val = LLVMBuildSExt(cl2llvm_builder, 
		bool_val->val, totype, temp_var_name);	
	cl2llvmTypeWrapSetLlvmType(value->type, totype);
	cl2llvmTypeWrapSetSign(value->type, 1);

	/* if value is a vector, change 1's to -1's */
	if (LLVMGetTypeKind(cl2llvmTypeWrapGetLlvmType(type)) == LLVMVectorTypeKind)
	{
		snprintf(temp_var_name, sizeof temp_var_name,
			"tmp_%d", temp_var_count++);

		value->val = LLVMBuildNeg(cl2llvm_builder, 
			value->val, temp_var_name);
	}

	cl2llvmTypeWrapFree(switch_type);

	return value;
}