aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2017-08-16 09:52:54 +0200
committerLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2018-06-23 07:46:40 +0200
commitc6d4716f71de8de9683464b677207304583dc2a0 (patch)
tree9b49d056f48ae59fe666f75fe47aa8492090e0a3
parentd0694a238744b642714e7cd226193dd1365176d0 (diff)
downloadsparse-dev-c6d4716f71de8de9683464b677207304583dc2a0.tar.gz
cast: specialize FPCAST into [USF]CVTF
Currently, all casts to a floating point type use OP_FPCAST. This is maybe simple but rather uncovenient as it correspond to several quite different operations that later need extra checks. Change this by directly using different instructions for the different cases: - FCVTF for float-float conversions - UCVTF for unsigned integer to floats - SCVTF for signed integer to floats and reject attempts to cast a pointer to a float. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
-rw-r--r--Documentation/IR.rst12
-rw-r--r--example.c8
-rw-r--r--linearize.c18
-rw-r--r--linearize.h3
-rw-r--r--simplify.c5
-rw-r--r--sparse-llvm.c16
-rw-r--r--validation/linear/cast-kinds.c20
-rw-r--r--validation/optim/fpcast-constant.c2
8 files changed, 58 insertions, 26 deletions
diff --git a/Documentation/IR.rst b/Documentation/IR.rst
index 67ef06a5..38683a73 100644
--- a/Documentation/IR.rst
+++ b/Documentation/IR.rst
@@ -270,12 +270,18 @@ They all have the following signature:
.. op:: OP_SCAST
Cast to signed integer.
-.. op:: OP_FPCAST
- Cast to floating-point.
-
.. op:: OP_PTRCAST
Cast to pointer.
+.. op:: OP_UCVTF
+ Conversion from unsigned integer to float type.
+
+.. op:: OP_SCVTF
+ Conversion from signed integer to float type.
+
+.. op:: OP_FCVTF
+ Conversion between float types.
+
Ternary ops
-----------
.. op:: OP_SEL
diff --git a/example.c b/example.c
index 00f20eb9..d052014e 100644
--- a/example.c
+++ b/example.c
@@ -76,7 +76,9 @@ static const char *opcodes[] = {
[OP_COPY] = "copy",
[OP_CAST] = "cast",
[OP_SCAST] = "scast",
- [OP_FPCAST] = "fpcast",
+ [OP_UCVTF] = "ucvtf",
+ [OP_SCVTF] = "scvtf",
+ [OP_FCVTF] = "fcvtf",
[OP_PTRCAST] = "ptrcast",
[OP_CALL] = "call",
[OP_SLICE] = "slice",
@@ -1409,7 +1411,9 @@ static void generate_one_insn(struct instruction *insn, struct bb_state *state)
generate_compare(state, insn);
break;
- case OP_CAST: case OP_SCAST: case OP_FPCAST: case OP_PTRCAST:
+ case OP_CAST: case OP_SCAST: case OP_PTRCAST:
+ case OP_UCVTF: case OP_SCVTF:
+ case OP_FCVTF:
generate_cast(state, insn);
break;
diff --git a/linearize.c b/linearize.c
index a69b8f71..582c98e4 100644
--- a/linearize.c
+++ b/linearize.c
@@ -263,7 +263,9 @@ static const char *opcodes[] = {
[OP_PHISOURCE] = "phisrc",
[OP_CAST] = "cast",
[OP_SCAST] = "scast",
- [OP_FPCAST] = "fpcast",
+ [OP_UCVTF] = "ucvtf",
+ [OP_SCVTF] = "scvtf",
+ [OP_FCVTF] = "fcvtf",
[OP_PTRCAST] = "ptrcast",
[OP_INLINED_CALL] = "# call",
[OP_CALL] = "call",
@@ -445,7 +447,8 @@ const char *show_instruction(struct instruction *insn)
}
case OP_CAST:
case OP_SCAST:
- case OP_FPCAST:
+ case OP_UCVTF: case OP_SCVTF:
+ case OP_FCVTF:
case OP_PTRCAST:
buf += sprintf(buf, "%s <- (%d) %s",
show_pseudo(insn->target),
@@ -1202,7 +1205,16 @@ static int get_cast_opcode(struct symbol *dst, struct symbol *src)
switch (dtype) {
case MTYPE_FLOAT:
- return OP_FPCAST;
+ switch (stype) {
+ case MTYPE_FLOAT:
+ return OP_FCVTF;
+ case MTYPE_UINT:
+ return OP_UCVTF;
+ case MTYPE_SINT:
+ return OP_SCVTF;
+ default:
+ return OP_BADOP;
+ }
case MTYPE_PTR:
return OP_PTRCAST;
case MTYPE_UINT:
diff --git a/linearize.h b/linearize.h
index 5e8fb1fa..290600a1 100644
--- a/linearize.h
+++ b/linearize.h
@@ -223,7 +223,8 @@ enum opcode {
/* Casts */
OP_CAST,
OP_SCAST,
- OP_FPCAST,
+ OP_UCVTF, OP_SCVTF,
+ OP_FCVTF,
OP_PTRCAST,
OP_UNOP_END = OP_PTRCAST,
diff --git a/simplify.c b/simplify.c
index 93f86867..062b08c9 100644
--- a/simplify.c
+++ b/simplify.c
@@ -991,7 +991,7 @@ static int simplify_cast(struct instruction *insn)
int op = (orig_type->ctype.modifiers & MOD_SIGNED) ? OP_SCAST : OP_CAST;
if (insn->opcode == op)
goto simplify;
- if (insn->opcode == OP_FPCAST && is_float_type(orig_type))
+ if (insn->opcode == OP_FCVTF)
goto simplify;
}
@@ -1220,7 +1220,8 @@ int simplify_instruction(struct instruction *insn)
return replace_with_pseudo(insn, insn->symbol);
case OP_CAST:
case OP_SCAST:
- case OP_FPCAST:
+ case OP_UCVTF: case OP_SCVTF:
+ case OP_FCVTF:
case OP_PTRCAST:
return simplify_cast(insn);
case OP_PHI:
diff --git a/sparse-llvm.c b/sparse-llvm.c
index eaecb4cd..3e2ac498 100644
--- a/sparse-llvm.c
+++ b/sparse-llvm.c
@@ -944,12 +944,19 @@ static void output_op_fpcast(struct function *fn, struct instruction *insn)
pseudo_name(insn->target, name);
src = get_operand(fn, otype, insn->src);
- if (is_float_type(otype))
+ switch (insn->opcode) {
+ case OP_FCVTF:
target = LLVMBuildFPCast(fn->builder, src, dtype, name);
- else if (is_signed_type(otype))
+ break;
+ case OP_SCVTF:
target = LLVMBuildSIToFP(fn->builder, src, dtype, name);
- else
+ break;
+ case OP_UCVTF:
target = LLVMBuildUIToFP(fn->builder, src, dtype, name);
+ break;
+ default:
+ assert(0);
+ }
insn->target->priv = target;
}
@@ -1028,7 +1035,8 @@ static void output_insn(struct function *fn, struct instruction *insn)
case OP_SCAST:
output_op_cast(fn, insn, LLVMSExt);
break;
- case OP_FPCAST:
+ case OP_UCVTF: case OP_SCVTF:
+ case OP_FCVTF:
output_op_fpcast(fn, insn);
break;
case OP_PTRCAST:
diff --git a/validation/linear/cast-kinds.c b/validation/linear/cast-kinds.c
index e686c01e..d8ac5d34 100644
--- a/validation/linear/cast-kinds.c
+++ b/validation/linear/cast-kinds.c
@@ -320,70 +320,70 @@ vptr_2_iptr:
int_2_float:
.L76:
<entry-point>
- fpcast.32 %r116 <- (32) %arg1
+ scvtf.32 %r116 <- (32) %arg1
ret.32 %r116
uint_2_float:
.L78:
<entry-point>
- fpcast.32 %r119 <- (32) %arg1
+ ucvtf.32 %r119 <- (32) %arg1
ret.32 %r119
long_2_float:
.L80:
<entry-point>
- fpcast.32 %r122 <- (64) %arg1
+ scvtf.32 %r122 <- (64) %arg1
ret.32 %r122
ulong_2_float:
.L82:
<entry-point>
- fpcast.32 %r125 <- (64) %arg1
+ ucvtf.32 %r125 <- (64) %arg1
ret.32 %r125
double_2_float:
.L84:
<entry-point>
- fpcast.32 %r128 <- (64) %arg1
+ fcvtf.32 %r128 <- (64) %arg1
ret.32 %r128
int_2_double:
.L86:
<entry-point>
- fpcast.64 %r131 <- (32) %arg1
+ scvtf.64 %r131 <- (32) %arg1
ret.64 %r131
uint_2_double:
.L88:
<entry-point>
- fpcast.64 %r134 <- (32) %arg1
+ ucvtf.64 %r134 <- (32) %arg1
ret.64 %r134
long_2_double:
.L90:
<entry-point>
- fpcast.64 %r137 <- (64) %arg1
+ scvtf.64 %r137 <- (64) %arg1
ret.64 %r137
ulong_2_double:
.L92:
<entry-point>
- fpcast.64 %r140 <- (64) %arg1
+ ucvtf.64 %r140 <- (64) %arg1
ret.64 %r140
float_2_double:
.L94:
<entry-point>
- fpcast.64 %r143 <- (32) %arg1
+ fcvtf.64 %r143 <- (32) %arg1
ret.64 %r143
diff --git a/validation/optim/fpcast-constant.c b/validation/optim/fpcast-constant.c
index c0f906b3..49355d00 100644
--- a/validation/optim/fpcast-constant.c
+++ b/validation/optim/fpcast-constant.c
@@ -8,6 +8,6 @@ static double foo(double a, int p)
* check-command: test-linearize $file
*
* check-output-ignore
- * check-output-contains: fpcast\\.
+ * check-output-contains: scvtf\\.
* check-output-excludes: fmul\\..*\\$2
*/