aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2020-09-07 00:54:31 +0200
committerLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2020-09-07 00:58:33 +0200
commit24bdaac6682c36f5f7878321e8f9eb02c0993572 (patch)
tree3a42a487bf2c06da52b270d6e6784d16f806828e
parent7524a9a874a75a477e9ddf2268ebccc2d3ee87ea (diff)
parent814cda15f647c14e0892deef3c57d73417e87b34 (diff)
downloadsparse-24bdaac6682c36f5f7878321e8f9eb02c0993572.tar.gz
Merge branch 'linear-fma' into next
* add support for a new instruction: OP_FMA * teach sparse to linearize __builtin_fma()
-rw-r--r--Documentation/IR.rst7
-rw-r--r--builtin.c3
-rw-r--r--linearize.c29
-rw-r--r--opcode.def1
-rw-r--r--validation/linear/builtin-fma.c19
5 files changed, 57 insertions, 2 deletions
diff --git a/Documentation/IR.rst b/Documentation/IR.rst
index 97d4b2b2..ff5af1c5 100644
--- a/Documentation/IR.rst
+++ b/Documentation/IR.rst
@@ -309,6 +309,13 @@ Ternary ops
* .target: result of the operation
* .type: type of .target
+.. op:: OP_FMADD
+ Fused multiply-add.
+
+ * .src1, .src2, .src3: operands (types must be compatible with .target)
+ * .target: result of the operation (must be a floating-point type)
+ * .type: type of .target
+
.. op:: OP_RANGE
Range/bounds checking (only used for an unused sparse extension).
diff --git a/builtin.c b/builtin.c
index 2e9be8be..26b612dc 100644
--- a/builtin.c
+++ b/builtin.c
@@ -490,6 +490,9 @@ static const struct builtin_fn builtins_common[] = {
{ "__builtin_ffs", &int_ctype, 0, { &int_ctype }, .op = &ffs_op },
{ "__builtin_ffsl", &int_ctype, 0, { &long_ctype }, .op = &ffs_op },
{ "__builtin_ffsll", &int_ctype, 0, { &llong_ctype }, .op = &ffs_op },
+ { "__builtin_fma", &double_ctype, 0, { &double_ctype, &double_ctype, &double_ctype }},
+ { "__builtin_fmaf", &float_ctype, 0, { &float_ctype, &float_ctype, &float_ctype }},
+ { "__builtin_fmal", &ldouble_ctype, 0, { &ldouble_ctype, &ldouble_ctype, &ldouble_ctype }},
{ "__builtin_frame_address", &ptr_ctype, 0, { &uint_ctype }},
{ "__builtin_free", &void_ctype, 0, { &ptr_ctype }},
{ "__builtin_huge_val", &double_ctype, 0 },
diff --git a/linearize.c b/linearize.c
index 5a8e7497..1081bda8 100644
--- a/linearize.c
+++ b/linearize.c
@@ -244,6 +244,7 @@ static const char *opcodes[] = {
/* Special three-input */
[OP_SEL] = "select",
+ [OP_FMADD] = "fmadd",
/* Memory */
[OP_LOAD] = "load",
@@ -461,6 +462,7 @@ const char *show_instruction(struct instruction *insn)
break;
case OP_SEL:
+ case OP_FMADD:
buf += sprintf(buf, "%s <- %s, %s, %s", show_pseudo(insn->target),
show_pseudo(insn->src1), show_pseudo(insn->src2), show_pseudo(insn->src3));
break;
@@ -1511,8 +1513,11 @@ static pseudo_t linearize_call_expression(struct entrypoint *ep, struct expressi
fntype = fn->ctype;
// handle builtins
- if (fntype->op && fntype->op->linearize)
- return fntype->op->linearize(ep, expr);
+ if (fntype->op && fntype->op->linearize) {
+ retval = fntype->op->linearize(ep, expr);
+ if (retval)
+ return retval;
+ }
ctype = &fntype->ctype;
if (fntype->type == SYM_NODE)
@@ -2580,6 +2585,23 @@ struct entrypoint *linearize_symbol(struct symbol *sym)
* Builtin functions
*/
+static pseudo_t linearize_fma(struct entrypoint *ep, struct expression *expr)
+{
+ struct instruction *insn = alloc_typed_instruction(OP_FMADD, expr->ctype);
+ struct expression *arg;
+
+ PREPARE_PTR_LIST(expr->args, arg);
+ insn->src1 = linearize_expression(ep, arg);
+ NEXT_PTR_LIST(arg)
+ insn->src2 = linearize_expression(ep, arg);
+ NEXT_PTR_LIST(arg)
+ insn->src3 = linearize_expression(ep, arg);
+ FINISH_PTR_LIST(arg);
+
+ add_one_insn(ep, insn);
+ return insn->target = alloc_pseudo(insn);
+}
+
static pseudo_t linearize_unreachable(struct entrypoint *ep, struct expression *exp)
{
add_unreachable(ep);
@@ -2592,6 +2614,9 @@ static struct sym_init {
struct symbol_op op;
} builtins_table[] = {
// must be declared in builtin.c:declare_builtins[]
+ { "__builtin_fma", linearize_fma },
+ { "__builtin_fmaf", linearize_fma },
+ { "__builtin_fmal", linearize_fma },
{ "__builtin_unreachable", linearize_unreachable },
{ }
};
diff --git a/opcode.def b/opcode.def
index 2583e2f4..7959efaf 100644
--- a/opcode.def
+++ b/opcode.def
@@ -91,6 +91,7 @@ OPCODE(SLICE, BADOP, BADOP, BADOP, 1, OPF_TARGET)
/* Select - three input values */
OPCODE(SEL, BADOP, BADOP, BADOP, 3, OPF_TARGET)
+OPCODE(FMADD, BADOP, BADOP, BADOP, 3, OPF_TARGET)
/* Memory */
OPCODE(LOAD, BADOP, BADOP, BADOP, 1, OPF_TARGET)
diff --git a/validation/linear/builtin-fma.c b/validation/linear/builtin-fma.c
new file mode 100644
index 00000000..b1024f39
--- /dev/null
+++ b/validation/linear/builtin-fma.c
@@ -0,0 +1,19 @@
+double fma(double a, double x, double y)
+{
+ return __builtin_fma(a, x, y);
+}
+
+/*
+ * check-name: builtin-fma
+ * check-command: test-linearize -Wno-decl $file
+ *
+ * check-output-start
+fma:
+.L0:
+ <entry-point>
+ fmadd.64 %r4 <- %r1, %r2, %r3
+ ret.64 %r4
+
+
+ * check-output-end
+ */