* [PATCH 1/2] add OP_SETFVAL
2017-04-12 9:29 [PATCH 0/2] floating-point literals Luc Van Oostenryck
@ 2017-04-12 9:29 ` Luc Van Oostenryck
2017-04-12 9:29 ` [PATCH 2/2] CSE: support CSE of floating-point literal Luc Van Oostenryck
1 sibling, 0 replies; 3+ messages in thread
From: Luc Van Oostenryck @ 2017-04-12 9:29 UTC (permalink / raw)
To: linux-sparse; +Cc: Christopher Li, Luc Van Oostenryck
OP_SETVAL is used to create floating-point and string
as well as labels-as-values. This multi-purpose aspect
sometimes make things a bit more complicated.
Change this by using a new instruction for the direct
creation of floating-point literals without needing
to have an intermediate EXPR_FVALUE.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
Documentation/instructions.txt | 12 ++++++----
linearize.c | 18 ++++++++++----
linearize.h | 4 ++++
liveness.c | 1 +
simplify.c | 1 +
sparse-llvm.c | 16 +++++++++----
validation/cast-constant-to-float.c | 6 ++---
validation/cast-constants.c | 20 ++++++++--------
validation/fp-ops.c | 2 +-
validation/optim/bool-context-fp.c | 47 +++++++++++++++++++++++++++++++++++++
10 files changed, 100 insertions(+), 27 deletions(-)
create mode 100644 validation/optim/bool-context-fp.c
diff --git a/Documentation/instructions.txt b/Documentation/instructions.txt
index b8d3d6bbc..236811daf 100644
--- a/Documentation/instructions.txt
+++ b/Documentation/instructions.txt
@@ -199,11 +199,15 @@ Create a pseudo corresponding to the address of a symbol.
- .symbol: (pseudo_t) input symbol (alias .src)
- .target: symbol's address
+=== OP_SETFVAL ===
+Create a pseudo corresponding to a floating-point literal.
+- .fvalue: the literal's value (long double)
+- .target: the corresponding pseudo
+- .type: type of the literal & .target
+
=== OP_SETVAL ===
-Create a pseudo corresponding to a value.
-The value is given as an expression EXPR_STRING, EXPR_FVALUE or
-EXPR_LABEL (pseudos for integral constants are directly created
-at linearization and doesn't need this instruction)
+Create a pseudo corresponding to a string literal or a label-as-value.
+The value is given as an expression EXPR_STRING or EXPR_LABEL.
- .val: (expression) input expression
- .target: the resulting value
- .type: type of .target, the value
diff --git a/linearize.c b/linearize.c
index 902d45087..9fda0a1ad 100644
--- a/linearize.c
+++ b/linearize.c
@@ -245,6 +245,7 @@ static const char *opcodes[] = {
[OP_LOAD] = "load",
[OP_STORE] = "store",
[OP_SETVAL] = "set",
+ [OP_SETFVAL] = "setfval",
[OP_SYMADDR] = "symaddr",
[OP_GET_ELEMENT_PTR] = "getelem",
@@ -386,6 +387,11 @@ const char *show_instruction(struct instruction *insn)
}
break;
}
+ case OP_SETFVAL:
+ buf += sprintf(buf, "%s <- ", show_pseudo(insn->target));
+ buf += sprintf(buf, "%Lf", insn->fvalue);
+ break;
+
case OP_SWITCH: {
struct multijmp *jmp;
buf += sprintf(buf, "%s", show_pseudo(insn->cond));
@@ -1018,12 +1024,10 @@ static pseudo_t add_setval(struct entrypoint *ep, struct symbol *ctype, struct e
static pseudo_t add_setfval(struct entrypoint *ep, struct symbol *ctype, long double fval)
{
- struct instruction *insn = alloc_typed_instruction(OP_SETVAL, ctype);
- struct expression *expr = alloc_expression(insn->pos, EXPR_FVALUE);
+ struct instruction *insn = alloc_typed_instruction(OP_SETFVAL, ctype);
pseudo_t target = alloc_pseudo(insn);
insn->target = target;
- insn->val = expr;
- expr->fvalue = fval;
+ insn->fvalue = fval;
add_one_insn(ep, insn);
return target;
}
@@ -1629,9 +1633,13 @@ pseudo_t linearize_expression(struct entrypoint *ep, struct expression *expr)
case EXPR_VALUE:
return value_pseudo(expr->value);
- case EXPR_STRING: case EXPR_FVALUE: case EXPR_LABEL:
+ case EXPR_STRING:
+ case EXPR_LABEL:
return add_setval(ep, expr->ctype, expr);
+ case EXPR_FVALUE:
+ return add_setfval(ep, expr->ctype, expr->fvalue);
+
case EXPR_STATEMENT:
return linearize_statement(ep, expr->statement);
diff --git a/linearize.h b/linearize.h
index 7e8c0eb2c..6f4298f33 100644
--- a/linearize.h
+++ b/linearize.h
@@ -111,6 +111,9 @@ struct instruction {
pseudo_t symbol; /* Subtle: same offset as "src" !! */
struct expression *val;
};
+ struct /* setfval */ {
+ long double fvalue;
+ };
struct /* call */ {
pseudo_t func;
union {
@@ -223,6 +226,7 @@ enum opcode {
OP_LOAD,
OP_STORE,
OP_SETVAL,
+ OP_SETFVAL,
OP_SYMADDR,
OP_GET_ELEMENT_PTR,
diff --git a/liveness.c b/liveness.c
index f7c0414b5..9a95851f8 100644
--- a/liveness.c
+++ b/liveness.c
@@ -90,6 +90,7 @@ static void track_instruction_usage(struct basic_block *bb, struct instruction *
break;
case OP_SETVAL:
+ case OP_SETFVAL:
DEFINES(target);
break;
diff --git a/simplify.c b/simplify.c
index 256a68b22..5e3d57470 100644
--- a/simplify.c
+++ b/simplify.c
@@ -272,6 +272,7 @@ void kill_insn(struct instruction *insn, int force)
return;
case OP_BR:
+ case OP_SETFVAL:
default:
break;
}
diff --git a/sparse-llvm.c b/sparse-llvm.c
index 415f29607..da9f2ce25 100644
--- a/sparse-llvm.c
+++ b/sparse-llvm.c
@@ -955,13 +955,9 @@ static void output_op_fpcast(struct function *fn, struct instruction *insn)
static void output_op_setval(struct function *fn, struct instruction *insn)
{
struct expression *val = insn->val;
- LLVMTypeRef dtype = symbol_type(insn->type);
LLVMValueRef target;
switch (val->type) {
- case EXPR_FVALUE:
- target = LLVMConstReal(dtype, val->fvalue);
- break;
case EXPR_LABEL:
target = LLVMBlockAddress(fn->fn, val->symbol->bb_target->priv);
break;
@@ -972,6 +968,15 @@ static void output_op_setval(struct function *fn, struct instruction *insn)
insn->target->priv = target;
}
+static void output_op_setfval(struct function *fn, struct instruction *insn)
+{
+ LLVMTypeRef dtype = symbol_type(insn->type);
+ LLVMValueRef target;
+
+ target = LLVMConstReal(dtype, insn->fvalue);
+ insn->target->priv = target;
+}
+
static void output_insn(struct function *fn, struct instruction *insn)
{
switch (insn->opcode) {
@@ -990,6 +995,9 @@ static void output_insn(struct function *fn, struct instruction *insn)
case OP_SETVAL:
output_op_setval(fn, insn);
break;
+ case OP_SETFVAL:
+ output_op_setfval(fn, insn);
+ break;
case OP_SWITCH:
output_op_switch(fn, insn);
break;
diff --git a/validation/cast-constant-to-float.c b/validation/cast-constant-to-float.c
index 86b7ac0f7..ef7892f17 100644
--- a/validation/cast-constant-to-float.c
+++ b/validation/cast-constant-to-float.c
@@ -13,21 +13,21 @@ double f3(void) { return -1.0; }
f1:
.L0:
<entry-point>
- set.64 %r1 <- -1.000000
+ setfval.64 %r1 <- -1.000000
ret.64 %r1
f2:
.L2:
<entry-point>
- set.64 %r3 <- -1.000000
+ setfval.64 %r3 <- -1.000000
ret.64 %r3
f3:
.L4:
<entry-point>
- set.64 %r5 <- -1.000000
+ setfval.64 %r5 <- -1.000000
ret.64 %r5
diff --git a/validation/cast-constants.c b/validation/cast-constants.c
index f47d6fd34..9e2006724 100644
--- a/validation/cast-constants.c
+++ b/validation/cast-constants.c
@@ -286,70 +286,70 @@ vptr_2_iptr:
int_2_float:
.L76:
<entry-point>
- set.32 %r39 <- 123.000000
+ setfval.32 %r39 <- 123.000000
ret.32 %r39
uint_2_float:
.L78:
<entry-point>
- set.32 %r41 <- 123.000000
+ setfval.32 %r41 <- 123.000000
ret.32 %r41
long_2_float:
.L80:
<entry-point>
- set.32 %r43 <- 123.000000
+ setfval.32 %r43 <- 123.000000
ret.32 %r43
ulong_2_float:
.L82:
<entry-point>
- set.32 %r45 <- 123.000000
+ setfval.32 %r45 <- 123.000000
ret.32 %r45
double_2_float:
.L84:
<entry-point>
- set.32 %r47 <- 1.123000
+ setfval.32 %r47 <- 1.123000
ret.32 %r47
int_2_double:
.L86:
<entry-point>
- set.64 %r49 <- 123.000000
+ setfval.64 %r49 <- 123.000000
ret.64 %r49
uint_2_double:
.L88:
<entry-point>
- set.64 %r51 <- 123.000000
+ setfval.64 %r51 <- 123.000000
ret.64 %r51
long_2_double:
.L90:
<entry-point>
- set.64 %r53 <- 123.000000
+ setfval.64 %r53 <- 123.000000
ret.64 %r53
ulong_2_double:
.L92:
<entry-point>
- set.64 %r55 <- 123.000000
+ setfval.64 %r55 <- 123.000000
ret.64 %r55
float_2_double:
.L94:
<entry-point>
- set.64 %r57 <- 1.123000
+ setfval.64 %r57 <- 1.123000
ret.64 %r57
diff --git a/validation/fp-ops.c b/validation/fp-ops.c
index 7f58a72fc..14bb12462 100644
--- a/validation/fp-ops.c
+++ b/validation/fp-ops.c
@@ -48,7 +48,7 @@ fneg:
ftst:
.L10:
<entry-point>
- set.64 %r21 <- 0.000000
+ setfval.64 %r21 <- 0.000000
fcmpoeq.1 %r23 <- %arg1, %r21
ret.1 %r23
diff --git a/validation/optim/bool-context-fp.c b/validation/optim/bool-context-fp.c
new file mode 100644
index 000000000..ad075c56e
--- /dev/null
+++ b/validation/optim/bool-context-fp.c
@@ -0,0 +1,47 @@
+#define bool _Bool
+
+bool bfimp(float a) { return a; }
+bool bfexp(float a) { return (bool)a; }
+
+bool bfnot(float a) { return !a; }
+int ifnot(float a) { return !a; }
+
+/*
+ * check-name: bool context fp
+ * check-command: test-linearize -Wno-decl $file
+ *
+ * check-output-start
+bfimp:
+.L0:
+ <entry-point>
+ setfval.32 %r2 <- 0.000000
+ fcmpune.1 %r3 <- %arg1, %r2
+ ret.1 %r3
+
+
+bfexp:
+.L2:
+ <entry-point>
+ setfval.32 %r6 <- 0.000000
+ fcmpune.1 %r7 <- %arg1, %r6
+ ret.1 %r7
+
+
+bfnot:
+.L4:
+ <entry-point>
+ setfval.32 %r10 <- 0.000000
+ fcmpoeq.1 %r12 <- %arg1, %r10
+ ret.1 %r12
+
+
+ifnot:
+.L6:
+ <entry-point>
+ setfval.32 %r15 <- 0.000000
+ fcmpoeq.32 %r16 <- %arg1, %r15
+ ret.32 %r16
+
+
+ * check-output-end
+ */
--
2.12.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH 2/2] CSE: support CSE of floating-point literal
2017-04-12 9:29 [PATCH 0/2] floating-point literals Luc Van Oostenryck
2017-04-12 9:29 ` [PATCH 1/2] add OP_SETFVAL Luc Van Oostenryck
@ 2017-04-12 9:29 ` Luc Van Oostenryck
1 sibling, 0 replies; 3+ messages in thread
From: Luc Van Oostenryck @ 2017-04-12 9:29 UTC (permalink / raw)
To: linux-sparse; +Cc: Christopher Li, Luc Van Oostenryck
Before the introduction of OP_SETFVAL, floating-point were
created via OP_SETVAL whose CSE is done by comparing the
pointer of the corresponding expression without any
interpretation of this pointer.
As consequence, even if two OP_SETVAL have two identical
expressions (value), in most cases the corresponding pointers
are not identical, completly inhibiting the CSE of OP_SETVALs.
Fix the CSE of floating-point literals by directly using
the value given by the new OP_SETFVAL.
Note: to respect some of the subtilities of floating-point,
the equality comparison of two literals is not done on
the floating-point value itself but bit-by-bit on its
binary representation (as such we can continue to make the
distinction between +0.0 & -0.0, handle NaNs, ...).
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
cse.c | 11 +++++++++++
validation/optim/cse-setfval.c | 12 ++++++++++++
2 files changed, 23 insertions(+)
create mode 100644 validation/optim/cse-setfval.c
diff --git a/cse.c b/cse.c
index f535636b4..cd1e8942c 100644
--- a/cse.c
+++ b/cse.c
@@ -89,6 +89,10 @@ static void clean_up_one_instruction(struct basic_block *bb, struct instruction
hash += hashval(insn->val);
break;
+ case OP_SETFVAL:
+ hash += hashval(insn->fvalue);
+ break;
+
case OP_SYMADDR:
hash += hashval(insn->symbol);
break;
@@ -178,6 +182,7 @@ static int insn_compare(const void *_i1, const void *_i2)
{
const struct instruction *i1 = _i1;
const struct instruction *i2 = _i2;
+ int diff;
if (i1->opcode != i2->opcode)
return i1->opcode < i2->opcode ? -1 : 1;
@@ -240,6 +245,12 @@ static int insn_compare(const void *_i1, const void *_i2)
return i1->val < i2->val ? -1 : 1;
break;
+ case OP_SETFVAL:
+ diff = memcmp(&i1->fvalue, &i2->fvalue, sizeof(i1->fvalue));
+ if (diff)
+ return diff;
+ break;
+
/* Other */
case OP_PHI:
return phi_list_compare(i1->phi_list, i2->phi_list);
diff --git a/validation/optim/cse-setfval.c b/validation/optim/cse-setfval.c
new file mode 100644
index 000000000..59c00a407
--- /dev/null
+++ b/validation/optim/cse-setfval.c
@@ -0,0 +1,12 @@
+int ftest(double a, double b)
+{
+ return a == 0.125 || b == 0.125;
+}
+
+/*
+ * check-name: CSE OP_SETFVAL
+ * check-command: test-linearize -Wno-decl $file
+ *
+ * check-output-ignore
+ * check-output-pattern-1-times: setfval\\.
+ */
--
2.12.0
^ permalink raw reply related [flat|nested] 3+ messages in thread