aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
authorPekka Enberg <penberg@kernel.org>2011-08-27 14:09:50 +0300
committerPekka Enberg <penberg@kernel.org>2011-08-27 15:23:20 +0300
commit638debc6162ecb79061bbe8095d203d47c1a31d0 (patch)
treefe88768d5e443339c23d5a1db675ca1a7a54a315
parent14a82f46806a584b15d36782419ff66114fac9a7 (diff)
downloadsparse-dev-638debc6162ecb79061bbe8095d203d47c1a31d0.tar.gz
sparse, llvm: Floating point support for binops
Signed-off-by: Pekka Enberg <penberg@kernel.org>
-rw-r--r--sparse-llvm.c94
-rw-r--r--validation/backend/binops.c40
2 files changed, 110 insertions, 24 deletions
diff --git a/sparse-llvm.c b/sparse-llvm.c
index d63a7d37..3091b597 100644
--- a/sparse-llvm.c
+++ b/sparse-llvm.c
@@ -6,6 +6,7 @@
#include <llvm-c/Core.h>
#include <llvm-c/BitWriter.h>
+#include <stdbool.h>
#include <stdio.h>
#include <unistd.h>
#include <assert.h>
@@ -21,30 +22,49 @@ struct function {
LLVMValueRef fn;
};
+static inline bool symbol_is_fp_type(struct symbol *sym)
+{
+ return sym->ctype.base_type == &fp_type;
+}
+
static LLVMTypeRef symbol_type(struct symbol *sym)
{
LLVMTypeRef ret = NULL;
- switch (sym->bit_size) {
- case -1:
- ret = LLVMVoidType();
- break;
- case 8:
- ret = LLVMInt8Type();
- break;
- case 16:
- ret = LLVMInt16Type();
- break;
- case 32:
- ret = LLVMInt32Type();
- break;
- case 64:
- ret = LLVMInt64Type();
- break;
- default:
- die("invalid bit size %d for type %d", sym->bit_size, sym->type);
- break;
- };
+ if (symbol_is_fp_type(sym)) {
+ switch (sym->bit_size) {
+ case 32:
+ ret = LLVMFloatType();
+ break;
+ case 64:
+ ret = LLVMDoubleType();
+ break;
+ default:
+ die("invalid bit size %d for type %d", sym->bit_size, sym->type);
+ break;
+ }
+ } else {
+ switch (sym->bit_size) {
+ case -1:
+ ret = LLVMVoidType();
+ break;
+ case 8:
+ ret = LLVMInt8Type();
+ break;
+ case 16:
+ ret = LLVMInt16Type();
+ break;
+ case 32:
+ ret = LLVMInt32Type();
+ break;
+ case 64:
+ ret = LLVMInt64Type();
+ break;
+ default:
+ die("invalid bit size %d for type %d", sym->bit_size, sym->type);
+ break;
+ }
+ }
return ret;
}
@@ -136,47 +156,69 @@ static void output_op_binary(struct function *fn, struct instruction *insn)
switch (insn->opcode) {
/* Binary */
case OP_ADD:
- target = LLVMBuildAdd(fn->builder, lhs, rhs, target_name);
+ if (symbol_is_fp_type(insn->type))
+ target = LLVMBuildFAdd(fn->builder, lhs, rhs, target_name);
+ else
+ target = LLVMBuildAdd(fn->builder, lhs, rhs, target_name);
break;
case OP_SUB:
- target = LLVMBuildSub(fn->builder, lhs, rhs, target_name);
+ if (symbol_is_fp_type(insn->type))
+ target = LLVMBuildFSub(fn->builder, lhs, rhs, target_name);
+ else
+ target = LLVMBuildSub(fn->builder, lhs, rhs, target_name);
break;
case OP_MULU:
- target = LLVMBuildMul(fn->builder, lhs, rhs, target_name);
+ if (symbol_is_fp_type(insn->type))
+ target = LLVMBuildFMul(fn->builder, lhs, rhs, target_name);
+ else
+ target = LLVMBuildMul(fn->builder, lhs, rhs, target_name);
break;
case OP_MULS:
+ assert(!symbol_is_fp_type(insn->type));
target = LLVMBuildMul(fn->builder, lhs, rhs, target_name);
break;
case OP_DIVU:
- target = LLVMBuildUDiv(fn->builder, lhs, rhs, target_name);
+ if (symbol_is_fp_type(insn->type))
+ target = LLVMBuildFDiv(fn->builder, lhs, rhs, target_name);
+ else
+ target = LLVMBuildUDiv(fn->builder, lhs, rhs, target_name);
break;
case OP_DIVS:
+ assert(!symbol_is_fp_type(insn->type));
target = LLVMBuildSDiv(fn->builder, lhs, rhs, target_name);
break;
case OP_MODU:
+ assert(!symbol_is_fp_type(insn->type));
target = LLVMBuildURem(fn->builder, lhs, rhs, target_name);
break;
case OP_MODS:
+ assert(!symbol_is_fp_type(insn->type));
target = LLVMBuildSRem(fn->builder, lhs, rhs, target_name);
break;
case OP_SHL:
+ assert(!symbol_is_fp_type(insn->type));
target = LLVMBuildShl(fn->builder, lhs, rhs, target_name);
break;
case OP_LSR:
+ assert(!symbol_is_fp_type(insn->type));
target = LLVMBuildLShr(fn->builder, lhs, rhs, target_name);
break;
case OP_ASR:
+ assert(!symbol_is_fp_type(insn->type));
target = LLVMBuildAShr(fn->builder, lhs, rhs, target_name);
break;
/* Logical */
case OP_AND:
+ assert(!symbol_is_fp_type(insn->type));
target = LLVMBuildAnd(fn->builder, lhs, rhs, target_name);
break;
case OP_OR:
+ assert(!symbol_is_fp_type(insn->type));
target = LLVMBuildOr(fn->builder, lhs, rhs, target_name);
break;
case OP_XOR:
+ assert(!symbol_is_fp_type(insn->type));
target = LLVMBuildXor(fn->builder, lhs, rhs, target_name);
break;
case OP_AND_BOOL:
@@ -188,9 +230,11 @@ static void output_op_binary(struct function *fn, struct instruction *insn)
/* Binary comparison */
case OP_SET_EQ:
+ assert(!symbol_is_fp_type(insn->type));
target = LLVMBuildICmp(fn->builder, LLVMIntEQ, lhs, rhs, target_name);
break;
case OP_SET_NE:
+ assert(!symbol_is_fp_type(insn->type));
target = LLVMBuildICmp(fn->builder, LLVMIntNE, lhs, rhs, target_name);
break;
case OP_SET_LE:
@@ -200,9 +244,11 @@ static void output_op_binary(struct function *fn, struct instruction *insn)
assert(0);
break;
case OP_SET_LT:
+ assert(!symbol_is_fp_type(insn->type));
target = LLVMBuildICmp(fn->builder, LLVMIntSLT, lhs, rhs, target_name);
break;
case OP_SET_GT:
+ assert(!symbol_is_fp_type(insn->type));
target = LLVMBuildICmp(fn->builder, LLVMIntSGT, lhs, rhs, target_name);
break;
case OP_SET_B:
diff --git a/validation/backend/binops.c b/validation/backend/binops.c
index 4c941380..1fed9b25 100644
--- a/validation/backend/binops.c
+++ b/validation/backend/binops.c
@@ -8,6 +8,16 @@ static unsigned int uadd(unsigned int x, unsigned int y)
return x + y;
}
+static float fadd(float x, float y)
+{
+ return x + y;
+}
+
+static double dadd(double x, double y)
+{
+ return x + y;
+}
+
static int sub(int x, int y)
{
return x - y;
@@ -18,6 +28,16 @@ static unsigned int usub(unsigned int x, unsigned int y)
return x - y;
}
+static float fsub(float x, float y)
+{
+ return x - y;
+}
+
+static double dsub(double x, double y)
+{
+ return x - y;
+}
+
static int mul(int x, int y)
{
return x * y;
@@ -28,6 +48,16 @@ static unsigned int umul(unsigned int x, unsigned int y)
return x * y;
}
+static float fmul(float x, float y)
+{
+ return x * y;
+}
+
+static double dmul(double x, double y)
+{
+ return x * y;
+}
+
static int div(int x, int y)
{
return x / y;
@@ -38,6 +68,16 @@ static unsigned int udiv(unsigned int x, unsigned int y)
return x / y;
}
+static float fdiv(float x, float y)
+{
+ return x / y;
+}
+
+static double ddiv(double x, double y)
+{
+ return x / y;
+}
+
static int mod(int x, int y)
{
return x % y;