[PATCH 15/20] cast: specialize cast from pointers

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

 



Currently all casts to pointers are processed alike. This is
simple but rather unconvenient in later phases as this
correspond to different operations that obeys to different
rules and which later need extra checks.

Change this by using a specific instructions (OP_UTPTR) for
[unsigned] integer to pointers.

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@xxxxxxxxx>
---
 Documentation/IR.rst               | 10 ++++++++--
 cse.c                              |  4 ++--
 example.c                          |  2 ++
 linearize.c                        |  7 +++++++
 linearize.h                        |  1 +
 liveness.c                         |  1 +
 simplify.c                         |  3 +++
 sparse-llvm.c                      | 25 +++++++++++++++++++------
 sparse.c                           |  1 +
 validation/linear/bool-cast-lp32.c | 19 +++++++++++++++++++
 validation/linear/bool-cast-lp64.c | 18 ++++++++++++++++++
 validation/linear/bool-cast.c      |  1 +
 validation/linear/cast-kinds.c     |  8 ++++----
 validation/optim/kill-casts.c      |  1 +
 14 files changed, 87 insertions(+), 14 deletions(-)
 create mode 100644 validation/linear/bool-cast-lp32.c
 create mode 100644 validation/linear/bool-cast-lp64.c

diff --git a/Documentation/IR.rst b/Documentation/IR.rst
index b7fe98a4a..615753868 100644
--- a/Documentation/IR.rst
+++ b/Documentation/IR.rst
@@ -264,8 +264,11 @@ They all have the following signature:
 	* .target: result value
 	* .type: type of .target
 
+Currently, a cast to a void pointer is treated like a cast to
+an unsigned integer of the same size.
+
 .. op:: OP_CAST
-	Cast to unsigned integer (and to void pointer).
+	Cast to unsigned integer.
 
 .. op:: OP_SCAST
 	Cast to signed integer.
@@ -273,8 +276,11 @@ They all have the following signature:
 .. op:: OP_UTPTR
 	Cast from pointer-sized unsigned integer to pointer type.
 
+.. op:: OP_PTRTU
+	Cast from pointer type to unsigned integer.
+
 .. op:: OP_PTRCAST
-	Cast to pointer.
+	Cast between pointers.
 
 .. op:: OP_FCVTU
 	Conversion from float type to unsigned integer.
diff --git a/cse.c b/cse.c
index 2a0767093..5a55caa7e 100644
--- a/cse.c
+++ b/cse.c
@@ -94,7 +94,7 @@ void cse_collect(struct instruction *insn)
 	case OP_CAST:
 	case OP_SCAST:
 	case OP_PTRCAST:
-	case OP_UTPTR:
+	case OP_UTPTR: case OP_PTRTU:
 		/*
 		 * This is crap! Many "orig_types" are the
 		 * same as far as casts go, we should generate
@@ -242,7 +242,7 @@ static int insn_compare(const void *_i1, const void *_i2)
 	case OP_CAST:
 	case OP_SCAST:
 	case OP_PTRCAST:
-	case OP_UTPTR:
+	case OP_UTPTR: case OP_PTRTU:
 		/*
 		 * This is crap! See the comments on hashing.
 		 */
diff --git a/example.c b/example.c
index 20c950483..b2553cdd3 100644
--- a/example.c
+++ b/example.c
@@ -82,6 +82,7 @@ static const char *opcodes[] = {
 	[OP_SCVTF] = "scvtf",
 	[OP_FCVTF] = "fcvtf",
 	[OP_UTPTR] = "utptr",
+	[OP_PTRTU] = "utptr",
 	[OP_PTRCAST] = "ptrcast",
 	[OP_CALL] = "call",
 	[OP_SLICE] = "slice",
@@ -1416,6 +1417,7 @@ static void generate_one_insn(struct instruction *insn, struct bb_state *state)
 
 	case OP_CAST: case OP_SCAST: case OP_PTRCAST:
 	case OP_UTPTR:
+	case OP_PTRTU:
 	case OP_FCVTU: case OP_FCVTS:
 	case OP_UCVTF: case OP_SCVTF:
 	case OP_FCVTF:
diff --git a/linearize.c b/linearize.c
index 9e46c3a16..45f8d05ee 100644
--- a/linearize.c
+++ b/linearize.c
@@ -269,6 +269,7 @@ static const char *opcodes[] = {
 	[OP_SCVTF] = "scvtf",
 	[OP_FCVTF] = "fcvtf",
 	[OP_UTPTR] = "utptr",
+	[OP_PTRTU] = "ptrtu",
 	[OP_PTRCAST] = "ptrcast",
 	[OP_INLINED_CALL] = "# call",
 	[OP_CALL] = "call",
@@ -454,6 +455,7 @@ const char *show_instruction(struct instruction *insn)
 	case OP_UCVTF: case OP_SCVTF:
 	case OP_FCVTF:
 	case OP_UTPTR:
+	case OP_PTRTU:
 	case OP_PTRCAST:
 		buf += sprintf(buf, "%s <- (%d) %s",
 			show_pseudo(insn->target),
@@ -1249,6 +1251,11 @@ static int get_cast_opcode(struct symbol *dst, struct symbol *src)
 		switch (stype) {
 		case MTYPE_FLOAT:
 			return dtype == MTYPE_UINT ? OP_FCVTU : OP_FCVTS;
+		case MTYPE_PTR:
+			return OP_PTRTU;
+		case MTYPE_VPTR:
+		case MTYPE_UINT:
+			return OP_CAST;
 		case MTYPE_SINT:
 			return OP_SCAST;
 		default:
diff --git a/linearize.h b/linearize.h
index 20ede605c..51eb13164 100644
--- a/linearize.h
+++ b/linearize.h
@@ -238,6 +238,7 @@ enum opcode {
 	OP_UCVTF, OP_SCVTF,
 	OP_FCVTF,
 	OP_UTPTR,
+	OP_PTRTU,
 	OP_PTRCAST,
 	OP_INLINED_CALL,
 	OP_CALL,
diff --git a/liveness.c b/liveness.c
index af71f146b..28b0bbb22 100644
--- a/liveness.c
+++ b/liveness.c
@@ -117,6 +117,7 @@ static void track_instruction_usage(struct basic_block *bb, struct instruction *
 	case OP_UCVTF: case OP_SCVTF:
 	case OP_FCVTF:
 	case OP_UTPTR:
+	case OP_PTRTU:
 	case OP_PTRCAST:
 		USES(src); DEFINES(target);
 		break;
diff --git a/simplify.c b/simplify.c
index 03b9d244a..75c926001 100644
--- a/simplify.c
+++ b/simplify.c
@@ -257,6 +257,7 @@ int kill_insn(struct instruction *insn, int force)
 	case OP_UCVTF: case OP_SCVTF:
 	case OP_FCVTF:
 	case OP_UTPTR:
+	case OP_PTRTU:
 	case OP_PTRCAST:
 	case OP_SETVAL:
 	case OP_NOT: case OP_NEG:
@@ -361,6 +362,7 @@ static int replace_with_pseudo(struct instruction *insn, pseudo_t pseudo)
 	case OP_UCVTF: case OP_SCVTF:
 	case OP_FCVTF:
 	case OP_UTPTR:
+	case OP_PTRTU:
 	case OP_PTRCAST:
 		kill_use(&insn->src1);
 		break;
@@ -1233,6 +1235,7 @@ int simplify_instruction(struct instruction *insn)
 	case OP_UCVTF: case OP_SCVTF:
 	case OP_FCVTF:
 	case OP_UTPTR:
+	case OP_PTRTU:
 	case OP_PTRCAST:
 		return simplify_cast(insn);
 	case OP_PHI:
diff --git a/sparse-llvm.c b/sparse-llvm.c
index cddabba0d..12771cf91 100644
--- a/sparse-llvm.c
+++ b/sparse-llvm.c
@@ -881,17 +881,29 @@ static void output_op_ptrcast(struct function *fn, struct instruction *insn)
 	LLVMOpcode op;
 	char target_name[64];
 
-	assert(is_ptr_type(insn->type));
-
 	src = get_operand(fn, otype, insn->src);
 	pseudo_name(insn->target, target_name);
 
 	dtype = symbol_type(insn->type);
-	if (is_ptr_type(otype)) {
-		op = LLVMBitCast;
-	} else if (is_int_type(otype)) {
+	switch (insn->opcode) {
+	case OP_UTPTR:
+	case OP_SCAST:			// FIXME
+		assert(is_int_type(otype));
+		assert(is_ptr_type(insn->type));
 		op = LLVMIntToPtr;
-	} else {
+		break;
+	case OP_PTRTU:
+		assert(is_ptr_type(otype));
+		assert(is_int_type(insn->type));
+		op = LLVMPtrToInt;
+		break;
+	case OP_PTRCAST:
+	case OP_CAST:			// FIXME
+		assert(is_ptr_type(otype));
+		assert(is_ptr_type(insn->type));
+		op = LLVMBitCast;
+		break;
+	default:
 		assert(0);
 	}
 
@@ -1046,6 +1058,7 @@ static void output_insn(struct function *fn, struct instruction *insn)
 		output_op_fpcast(fn, insn);
 		break;
 	case OP_UTPTR:
+	case OP_PTRTU:
 	case OP_PTRCAST:
 		output_op_ptrcast(fn, insn);
 		break;
diff --git a/sparse.c b/sparse.c
index 056d14ff6..ab3841ad4 100644
--- a/sparse.c
+++ b/sparse.c
@@ -217,6 +217,7 @@ static void check_one_instruction(struct instruction *insn)
 {
 	switch (insn->opcode) {
 	case OP_CAST: case OP_SCAST:
+	case OP_PTRTU:
 		if (verbose)
 			check_cast_instruction(insn);
 		break;
diff --git a/validation/linear/bool-cast-lp32.c b/validation/linear/bool-cast-lp32.c
new file mode 100644
index 000000000..44a650f41
--- /dev/null
+++ b/validation/linear/bool-cast-lp32.c
@@ -0,0 +1,19 @@
+extern int ffun(void);
+typedef void *vdp;
+typedef int  *sip;
+
+static _Bool fvdp_i(vdp a) { return a; }
+static _Bool fvdp_e(vdp a) { return (_Bool)a; }
+static _Bool fsip_i(sip a) { return a; }
+static _Bool fsip_e(sip a) { return (_Bool)a; }
+static _Bool ffun_i(void)  { return ffun; }
+static _Bool ffun_e(void)  { return (_Bool)ffun; }
+
+/*
+ * check-name: bool-cast-pointer
+ * check-command: test-linearize -m32 -fdump-ir $file
+ * check-known-to-fail
+ *
+ * check-output-ignore
+ * check-output-excludes: ptrtu\\.
+ */
diff --git a/validation/linear/bool-cast-lp64.c b/validation/linear/bool-cast-lp64.c
new file mode 100644
index 000000000..9b2a020ae
--- /dev/null
+++ b/validation/linear/bool-cast-lp64.c
@@ -0,0 +1,18 @@
+extern int ffun(void);
+typedef void *vdp;
+typedef int  *sip;
+
+static _Bool fvdp_i(vdp a) { return a; }
+static _Bool fvdp_e(vdp a) { return (_Bool)a; }
+static _Bool fsip_i(sip a) { return a; }
+static _Bool fsip_e(sip a) { return (_Bool)a; }
+static _Bool ffun_i(void)  { return ffun; }
+static _Bool ffun_e(void)  { return (_Bool)ffun; }
+
+/*
+ * check-name: bool-cast-pointer
+ * check-command: test-linearize -m64 -fdump-ir $file
+ *
+ * check-output-ignore
+ * check-output-excludes: ptrtu\\.
+ */
diff --git a/validation/linear/bool-cast.c b/validation/linear/bool-cast.c
index 65d7b447a..7212a3aa8 100644
--- a/validation/linear/bool-cast.c
+++ b/validation/linear/bool-cast.c
@@ -28,6 +28,7 @@ static _Bool fdbl_e(dbl a) { return (_Bool)a; }
  * check-output-ignore
  * check-output-excludes: cast\\.
  * check-output-excludes: fcvt[us]\\.
+ * check-output-excludes: ptrtu\\.
  * 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 1742cd1e5..6683ea931 100644
--- a/validation/linear/cast-kinds.c
+++ b/validation/linear/cast-kinds.c
@@ -88,7 +88,7 @@ vptr_2_int:
 iptr_2_int:
 .L8:
 	<entry-point>
-	cast.32     %r14 <- (64) %arg1
+	ptrtu.32    %r14 <- (64) %arg1
 	ret.32      %r14
 
 
@@ -136,7 +136,7 @@ vptr_2_uint:
 iptr_2_uint:
 .L22:
 	<entry-point>
-	cast.32     %r35 <- (64) %arg1
+	ptrtu.32    %r35 <- (64) %arg1
 	ret.32      %r35
 
 
@@ -184,7 +184,7 @@ vptr_2_long:
 iptr_2_long:
 .L36:
 	<entry-point>
-	cast.64     %r56 <- (64) %arg1
+	ptrtu.64    %r56 <- (64) %arg1
 	ret.64      %r56
 
 
@@ -232,7 +232,7 @@ vptr_2_ulong:
 iptr_2_ulong:
 .L50:
 	<entry-point>
-	cast.64     %r77 <- (64) %arg1
+	ptrtu.64    %r77 <- (64) %arg1
 	ret.64      %r77
 
 
diff --git a/validation/optim/kill-casts.c b/validation/optim/kill-casts.c
index c375f5fbc..140b8d20b 100644
--- a/validation/optim/kill-casts.c
+++ b/validation/optim/kill-casts.c
@@ -21,4 +21,5 @@ void foo(struct s *x)
  * check-output-excludes: cast\\.
  * check-output-excludes: fcvt[us]\\.
  * check-output-excludes: utptr\\.
+ * check-output-excludes: ptrtu\\.
  */
-- 
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