[PATCH 10/20] cast: specialize floats to integer conversion

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Currently, casts from floats to integers are processed like
integers (or any other type) to integers. This is simple but
rather unconvenient as it correspond to different operations
that obeys to different rules and which later need extra checks.

Change this by directly using specific instructions:
- FCVTU for floats to unsigned integers
- FCVTS for floats to signed integers

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@xxxxxxxxx>
---
 Documentation/IR.rst           |  6 ++++++
 example.c                      |  3 +++
 linearize.c                    |  5 +++++
 linearize.h                    |  1 +
 liveness.c                     |  1 +
 simplify.c                     |  3 +++
 sparse-llvm.c                  |  8 +++++++-
 validation/cast-kinds-check.c  |  3 ---
 validation/linear/bool-cast.c  |  1 +
 validation/linear/cast-kinds.c | 16 ++++++++--------
 validation/linear/fp2i-cast.c  |  3 ++-
 validation/optim/kill-casts.c  |  1 +
 12 files changed, 38 insertions(+), 13 deletions(-)

diff --git a/Documentation/IR.rst b/Documentation/IR.rst
index 38683a73b..5b9155f76 100644
--- a/Documentation/IR.rst
+++ b/Documentation/IR.rst
@@ -273,6 +273,12 @@ They all have the following signature:
 .. op:: OP_PTRCAST
 	Cast to pointer.
 
+.. op:: OP_FCVTU
+	Conversion from float type to unsigned integer.
+
+.. op:: OP_FCVTS
+	Conversion from float type to signed integer.
+
 .. op:: OP_UCVTF
 	Conversion from unsigned integer to float type.
 
diff --git a/example.c b/example.c
index 23b941e7a..89ef7b834 100644
--- a/example.c
+++ b/example.c
@@ -76,6 +76,8 @@ static const char *opcodes[] = {
 	[OP_COPY] = "copy",
 	[OP_CAST] = "cast",
 	[OP_SCAST] = "scast",
+	[OP_FCVTU] = "fcvtu",
+	[OP_FCVTS] = "fcvts",
 	[OP_UCVTF] = "ucvtf",
 	[OP_SCVTF] = "scvtf",
 	[OP_FCVTF] = "fcvtf",
@@ -1412,6 +1414,7 @@ static void generate_one_insn(struct instruction *insn, struct bb_state *state)
 		break;
 
 	case OP_CAST: case OP_SCAST: case OP_PTRCAST:
+	case OP_FCVTU: case OP_FCVTS:
 	case OP_UCVTF: case OP_SCVTF:
 	case OP_FCVTF:
 		generate_cast(state, insn);
diff --git a/linearize.c b/linearize.c
index 0258a82a5..a05589367 100644
--- a/linearize.c
+++ b/linearize.c
@@ -263,6 +263,8 @@ static const char *opcodes[] = {
 	[OP_PHISOURCE] = "phisrc",
 	[OP_CAST] = "cast",
 	[OP_SCAST] = "scast",
+	[OP_FCVTU] = "fcvtu",
+	[OP_FCVTS] = "fcvts",
 	[OP_UCVTF] = "ucvtf",
 	[OP_SCVTF] = "scvtf",
 	[OP_FCVTF] = "fcvtf",
@@ -447,6 +449,7 @@ const char *show_instruction(struct instruction *insn)
 	}
 	case OP_CAST:
 	case OP_SCAST:
+	case OP_FCVTU: case OP_FCVTS:
 	case OP_UCVTF: case OP_SCVTF:
 	case OP_FCVTF:
 	case OP_PTRCAST:
@@ -1221,6 +1224,8 @@ static int get_cast_opcode(struct symbol *dst, struct symbol *src)
 	case MTYPE_UINT:
 	case MTYPE_SINT:
 		switch (stype) {
+		case MTYPE_FLOAT:
+			return dtype == MTYPE_UINT ? OP_FCVTU : OP_FCVTS;
 		case MTYPE_SINT:
 			return OP_SCAST;
 		default:
diff --git a/linearize.h b/linearize.h
index 2900b5cae..8b1cb7950 100644
--- a/linearize.h
+++ b/linearize.h
@@ -234,6 +234,7 @@ enum opcode {
 	OP_PHISOURCE,
 	OP_CAST,
 	OP_SCAST,
+	OP_FCVTU, OP_FCVTS,
 	OP_UCVTF, OP_SCVTF,
 	OP_FCVTF,
 	OP_PTRCAST,
diff --git a/liveness.c b/liveness.c
index 362b8a413..bf5c9a692 100644
--- a/liveness.c
+++ b/liveness.c
@@ -113,6 +113,7 @@ static void track_instruction_usage(struct basic_block *bb, struct instruction *
 
 	case OP_CAST:
 	case OP_SCAST:
+	case OP_FCVTU: case OP_FCVTS:
 	case OP_UCVTF: case OP_SCVTF:
 	case OP_FCVTF:
 	case OP_PTRCAST:
diff --git a/simplify.c b/simplify.c
index fe23741fb..642198ab1 100644
--- a/simplify.c
+++ b/simplify.c
@@ -253,6 +253,7 @@ int kill_insn(struct instruction *insn, int force)
 
 	case OP_CAST:
 	case OP_SCAST:
+	case OP_FCVTU: case OP_FCVTS:
 	case OP_UCVTF: case OP_SCVTF:
 	case OP_FCVTF:
 	case OP_PTRCAST:
@@ -355,6 +356,7 @@ static int replace_with_pseudo(struct instruction *insn, pseudo_t pseudo)
 	case OP_SYMADDR:
 	case OP_CAST:
 	case OP_SCAST:
+	case OP_FCVTU: case OP_FCVTS:
 	case OP_UCVTF: case OP_SCVTF:
 	case OP_FCVTF:
 	case OP_PTRCAST:
@@ -1225,6 +1227,7 @@ int simplify_instruction(struct instruction *insn)
 		return replace_with_pseudo(insn, insn->symbol);
 	case OP_CAST:
 	case OP_SCAST:
+	case OP_FCVTU: case OP_FCVTS:
 	case OP_UCVTF: case OP_SCVTF:
 	case OP_FCVTF:
 	case OP_PTRCAST:
diff --git a/sparse-llvm.c b/sparse-llvm.c
index 4919305b5..29362f892 100644
--- a/sparse-llvm.c
+++ b/sparse-llvm.c
@@ -918,7 +918,7 @@ static void output_op_cast(struct function *fn, struct instruction *insn, LLVMOp
 	if (is_ptr_type(otype)) {
 		op = LLVMPtrToInt;
 	} else if (is_float_type(otype)) {
-		op = (op == LLVMZExt) ? LLVMFPToUI : LLVMFPToSI;
+		assert(op == LLVMFPToUI || op == LLVMFPToSI);
 	} else if (is_int_type(otype)) {
 		unsigned int width = otype->bit_size;
 		if (insn->size < width)
@@ -1035,6 +1035,12 @@ static void output_insn(struct function *fn, struct instruction *insn)
 	case OP_SCAST:
 		output_op_cast(fn, insn, LLVMSExt);
 		break;
+	case OP_FCVTU:
+		output_op_cast(fn, insn, LLVMFPToUI);
+		break;
+	case OP_FCVTS:
+		output_op_cast(fn, insn, LLVMFPToSI);
+		break;
 	case OP_UCVTF: case OP_SCVTF:
 	case OP_FCVTF:
 		output_op_fpcast(fn, insn);
diff --git a/validation/cast-kinds-check.c b/validation/cast-kinds-check.c
index b8e948407..1f10e0ecf 100644
--- a/validation/cast-kinds-check.c
+++ b/validation/cast-kinds-check.c
@@ -3,19 +3,16 @@
 /*
  * check-name: cast-kinds check
  * check-command: sparse -m64 -v $file
- * check-known-to-fail
  *
  * check-error-start
 linear/cast-kinds.c:5:45: warning: cast drops bits
 linear/cast-kinds.c:6:47: warning: cast drops bits
 linear/cast-kinds.c:7:46: warning: cast drops bits
 linear/cast-kinds.c:8:45: warning: cast drops bits
-linear/cast-kinds.c:10:49: warning: cast drops bits
 linear/cast-kinds.c:12:48: warning: cast drops bits
 linear/cast-kinds.c:13:50: warning: cast drops bits
 linear/cast-kinds.c:14:49: warning: cast drops bits
 linear/cast-kinds.c:15:48: warning: cast drops bits
-linear/cast-kinds.c:17:52: warning: cast drops bits
 linear/cast-kinds.c:21:49: warning: cast wasn't removed
 linear/cast-kinds.c:22:48: warning: cast wasn't removed
 linear/cast-kinds.c:28:52: warning: cast wasn't removed
diff --git a/validation/linear/bool-cast.c b/validation/linear/bool-cast.c
index 50d7a14ad..65d7b447a 100644
--- a/validation/linear/bool-cast.c
+++ b/validation/linear/bool-cast.c
@@ -27,6 +27,7 @@ static _Bool fdbl_e(dbl a) { return (_Bool)a; }
  *
  * check-output-ignore
  * check-output-excludes: cast\\.
+ * check-output-excludes: fcvt[us]\\.
  * check-output-pattern(12): setne\\.
  * check-output-pattern(2): fcmpune\\.
  */
diff --git a/validation/linear/cast-kinds.c b/validation/linear/cast-kinds.c
index 5944610c6..d07a94190 100644
--- a/validation/linear/cast-kinds.c
+++ b/validation/linear/cast-kinds.c
@@ -95,14 +95,14 @@ iptr_2_int:
 float_2_int:
 .L10:
 	<entry-point>
-	cast.32     %r17 <- (32) %arg1
+	fcvts.32    %r17 <- (32) %arg1
 	ret.32      %r17
 
 
 double_2_int:
 .L12:
 	<entry-point>
-	cast.32     %r20 <- (64) %arg1
+	fcvts.32    %r20 <- (64) %arg1
 	ret.32      %r20
 
 
@@ -143,14 +143,14 @@ iptr_2_uint:
 float_2_uint:
 .L24:
 	<entry-point>
-	cast.32     %r38 <- (32) %arg1
+	fcvtu.32    %r38 <- (32) %arg1
 	ret.32      %r38
 
 
 double_2_uint:
 .L26:
 	<entry-point>
-	cast.32     %r41 <- (64) %arg1
+	fcvtu.32    %r41 <- (64) %arg1
 	ret.32      %r41
 
 
@@ -191,14 +191,14 @@ iptr_2_long:
 float_2_long:
 .L38:
 	<entry-point>
-	cast.64     %r59 <- (32) %arg1
+	fcvts.64    %r59 <- (32) %arg1
 	ret.64      %r59
 
 
 double_2_long:
 .L40:
 	<entry-point>
-	cast.64     %r62 <- (64) %arg1
+	fcvts.64    %r62 <- (64) %arg1
 	ret.64      %r62
 
 
@@ -239,14 +239,14 @@ iptr_2_ulong:
 float_2_ulong:
 .L52:
 	<entry-point>
-	cast.64     %r80 <- (32) %arg1
+	fcvtu.64    %r80 <- (32) %arg1
 	ret.64      %r80
 
 
 double_2_ulong:
 .L54:
 	<entry-point>
-	cast.64     %r83 <- (64) %arg1
+	fcvtu.64    %r83 <- (64) %arg1
 	ret.64      %r83
 
 
diff --git a/validation/linear/fp2i-cast.c b/validation/linear/fp2i-cast.c
index 98d7453e5..c85c4ccd7 100644
--- a/validation/linear/fp2i-cast.c
+++ b/validation/linear/fp2i-cast.c
@@ -26,5 +26,6 @@ ul d2ul(double a) { return a; }
  * check-command: test-linearize -Wno-decl $file
  *
  * check-output-ignore
- * check-output-pattern(8): cast\\.
+ * check-output-pattern(4): fcvts\\.
+ * check-output-pattern(4): fcvtu\\.
  */
diff --git a/validation/optim/kill-casts.c b/validation/optim/kill-casts.c
index cf52f2460..b79335abb 100644
--- a/validation/optim/kill-casts.c
+++ b/validation/optim/kill-casts.c
@@ -19,4 +19,5 @@ void foo(struct s *x)
  *
  * check-output-ignore
  * check-output-excludes: cast\\.
+ * check-output-excludes: fcvt[us]\\.
  */
-- 
2.17.1

--
To unsubscribe from this list: send the line "unsubscribe linux-sparse" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Newbies FAQ]     [LKML]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Trinity Fuzzer Tool]

  Powered by Linux