linux-sparse.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC PATCH 00/14] rework of cast operations
@ 2017-08-17  4:05 Luc Van Oostenryck
  2017-08-17  4:05 ` [RFC PATCH 01/14] add documentation for IR instructions Luc Van Oostenryck
                   ` (13 more replies)
  0 siblings, 14 replies; 16+ messages in thread
From: Luc Van Oostenryck @ 2017-08-17  4:05 UTC (permalink / raw)
  To: linux-sparse
  Cc: Linus Torvalds, Christopher Li, Dibyendu Majumdar,
	Luc Van Oostenryck

The goal of this series is to specialize the few cast
instuctions into more specialized ones so that the
precise nature of the operations is fully specified
by the instruction and thus no additional need to be
done later.

With this series we have:
- TRUNC, for int to smaller size int
- ZEXT,  for int to bigger int with zero extend
- SEXT,  for int to bigger int with sign extend
- PTRTU, for pointer to same sized [unsigned] int
- UTPTR, for pointer from same sized [unsigned] int
- PTRCAST, for pointer to pointer
- FCVT[US], for float to unsigned/signed integer
- [US]CVTF, for float from unsigned/signed integer
- FCVTF, for float to float

Also:
- for these casts, void pointer are treated as unsigned integers
- casts from int to same sized int are trated as NOP and never
  generated.


There are few points I'm not yet decided about, especially thinking
about what would be needed to to [type based] analysis:
- maybe we should no drop the NOP and have a real NOPCAST ?
- this NOPCAST may then be used for floats and pointers too?
- this NOPCAST could then be simplified away when needed
- PTRTU & UTPTR are in the same situation:
  - are they needed?
  - when can we simplified them away?
- it may be good to split FCVTF into: FTRUNC, NOPCAST & TEXT
- is it still good to treat void pointers the same as some integer?

----------------------------------------------------------------
This series is also available in the git repository at:

  git://github.com/lucvoo/sparse.git cast-rework

----------------------------------------------------------------
Luc Van Oostenryck (14):
      add documentation for IR instructions
      cast: add tests for warnings issued by sparse -v
      cast: prepare finer grained cast instructions
      cast: specialize FPCAST into [USF]CVTF
      cast: handle NO-OP casts
      cast: specialize floats to integer conversion
      cast: specialize casts from unsigned to pointers
      cast: make [u]intptr_ctype alias of [s]size_t_ctype
      cast: make pointer casts always size preserving
      cast: temporary simplify handling cast to/from void*
      cast: specialize cast from pointers
      cast: add support for -Wpointer-to-int-cast
      cast: make casts from pointer always size preserving
      cast: specialize integer casts

 Documentation/IR.md                    | 330 +++++++++++++++++++++++++++++++++
 cse.c                                  |  10 +-
 example.c                              |  22 ++-
 lib.c                                  |   4 +
 lib.h                                  |   2 +
 linearize.c                            | 165 ++++++++++++++---
 linearize.h                            |  11 +-
 liveness.c                             |  10 +-
 simplify.c                             |  54 +++---
 sparse-llvm.c                          |  21 ++-
 sparse.c                               |   5 +-
 symbol.h                               |   3 +
 validation/bitfield-size.c             |   5 +-
 validation/builtin-bswap-variable.c    |   4 +-
 validation/cast-kinds-check.c          |  19 ++
 validation/cast-kinds.c                | 181 ++++++++++--------
 validation/cast-weirds.c               |  51 +++++
 validation/compound-assign-type.c      |   3 +-
 validation/linear/bitfield-init-zero.c |   8 +-
 validation/memops-volatile.c           |   4 +-
 validation/optim/bool-simplify.c       |   4 +-
 21 files changed, 757 insertions(+), 159 deletions(-)
 create mode 100644 Documentation/IR.md
 create mode 100644 validation/cast-kinds-check.c
 create mode 100644 validation/cast-weirds.c

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [RFC PATCH 01/14] add documentation for IR instructions
  2017-08-17  4:05 [RFC PATCH 00/14] rework of cast operations Luc Van Oostenryck
@ 2017-08-17  4:05 ` Luc Van Oostenryck
  2017-08-21 12:18   ` Christopher Li
  2017-08-17  4:05 ` [RFC PATCH 02/14] cast: add tests for warnings issued by sparse -v Luc Van Oostenryck
                   ` (12 subsequent siblings)
  13 siblings, 1 reply; 16+ messages in thread
From: Luc Van Oostenryck @ 2017-08-17  4:05 UTC (permalink / raw)
  To: linux-sparse
  Cc: Linus Torvalds, Christopher Li, Dibyendu Majumdar,
	Luc Van Oostenryck

Until now the 'instructions' used for spare's IR are
not at all documented.

This patch is a fist step toward having these instructions
properly documented.

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
 Documentation/IR.md | 306 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 306 insertions(+)
 create mode 100644 Documentation/IR.md

diff --git a/Documentation/IR.md b/Documentation/IR.md
new file mode 100644
index 000000000..7e13e740d
--- /dev/null
+++ b/Documentation/IR.md
@@ -0,0 +1,306 @@
+# Sparse Instructions (IR)
+
+## General
+Sparse's instructions clearly belong to the family of
+3-addresses code: most instruction taking one or two
+operands and produce one result.
+
+Concretely, things are a bit more complex as a few instructions
+take 3 operands and some take an unbounded number of operands.
+The type of each of these operands can also differs.
+
+Operands, result and some parameters are stored in the members
+of a `struct instruction`.
+Some of these members are used by almost all instructions,
+some others are specific to only one or a few instructions.
+The common ones are:
+- `.src1`, `.src2`, `.src3`: operands of binops or ternary ops, type is `pseudo_t`.
+- `.src`: operand of unary ops (alias for `.src1`), type is `pseudo_t`.
+- `.target`: result of unary, binary & ternary ops, is sometimes used
+	otherwise by some others instructions, type is `pseudo_t`.
+- `.cond`: input operands for condition (alias `.target`!), type is `pseudo_t`.
+- `.type`: usually the type of `.result`, sometimes of the operands, type is `struct symbol *`.
+
+## Terminators
+### OP_RET
+Return from subroutine.
+- `.src` : returned value (NULL if void)
+- `.type`: type of `.src`
+
+### OP_BR
+Unconditional branch
+- `.bb_true`: destination basic block
+
+### OP_CBR
+Conditional branch
+- `.cond`: condition
+- `.type`: type of `.cond`, must be an integral type
+- `.bb_true`, `.bb_false`: destination basic blocks
+
+### OP_SWITCH
+Switch / multi-branch
+- `.cond`: condition
+- `.type`: type of `.cond`, must be an integral type
+- `.multijmp_list`: pairs of case-value - destination basic block
+
+### OP_COMPUTEDGOTO
+Computed goto / branch to register
+- `.target`: target address (type is irrelevant, void*)
+- `.multijmp_list`: list of possible destination basic blocks
+
+## Arithmetic binops
+They all follow the same signature:
+- `.src1`, `.src2`: operands (types must be compatible with `.target`)
+- `.target`: result of the operation
+- `.type`: type of `.target`
+
+### OP_ADD
+Addition.
+
+### OP_SUB
+Subtraction.
+
+### OP_MULU
+Multiplication (unsigned ints & floating-points)
+
+### OP_MULS
+Multiplication (signed ints)
+
+### OP_DIVU
+Division (unsigned ints & floating-points)
+
+### OP_DIVS
+Division (signed ints)
+
+### OP_MODU
+Modulo (unsigned division remainder, integer only)
+
+### OP_MODS
+Modulo (signed division remainder, integer only)
+
+### OP_SHL
+Shift left (integer only)
+
+### OP_LSR
+Logical Shift right (integer only)
+
+### OP_ASR
+Arithmetic Shift right (integer only)
+
+## Logical ops
+They all follow the same signature:
+- `.src1`, `.src2`: operands (types must be compatible with `.target`)
+- `.target`: result of the operation
+- `.type`: type of `.target`, must be an integral type
+
+### OP_AND
+### OP_OR
+### OP_XOR
+
+## Boolean ops
+### OP_AND_BOOL
+### OP_OR_BOOL
+
+## Comparisons
+They all have the following signature:
+- `.src1`, `.src2`: operands (types must be compatible)
+- `.target`: result of the operation (0/1 valued integer)
+- `.type`: type of `.target`, must be an integral type
+
+### OP_SET_EQ
+Compare equal.
+
+### OP_SET_NE
+Compare not-equal.
+
+### OP_SET_LE
+Compare less-than-or-equal (signed).
+
+### OP_SET_GE
+Compare greater-than-or-equal (signed).
+
+### OP_SET_LT
+Compare less-than (signed).
+
+### OP_SET_GT
+Compare greater-than (signed).
+
+### OP_SET_B
+Compare less-than (unsigned).
+
+### OP_SET_A
+Compare greater-than (unsigned).
+
+### OP_SET_BE
+Compare less-than-or-equal (unsigned).
+
+### OP_SET_AE
+Compare greater-than-or-equal (unsigned).
+
+## Unary ops
+### OP_NOT
+Logical not.
+- `.src`: operand (type must be compatible with `.target`)
+- `.target`: result of the operation
+- `.type`: type of `.target`, must be an integral type
+
+### OP_NEG
+Arithmetic negation.
+- `.src`: operand (type must be compatible with `.target`)
+- `.target`: result of the operation
+- `.type`: type of `.target`
+
+## Type conversions
+They all have the following signature:
+- `.src`: source value
+- `.orig_type`: type of `.src`
+- `.target`: result value
+- `.type`: type of `.target`
+
+### OP_CAST
+Cast to unsigned integer (and to void pointer).
+
+### OP_SCAST
+Cast to signed integer.
+
+### OP_FPCAST
+Cast to floating-point.
+
+### OP_PTRCAST
+Cast to pointer.
+
+## Ternary ops
+### OP_SEL
+- `.src1`: condition, must be of integral type
+- `.src2`, `.src3`: operands (types must be compatible with `.target`)
+- `.target`: result of the operation
+- `.type`: type of `.target`
+
+## Memory ops
+### OP_LOAD
+Load.
+- `.src`: base address to load from
+- `.offset`: address offset
+- `.target`: loaded value
+- `.type`: type of `.target`
+
+### OP_STORE
+Store.
+- `.src`: base address to store to
+- `.offset`: address offset
+- `.target`: value to be stored
+- `.type`: type of `.target`
+
+## Others
+### OP_SYMADDR
+Create a pseudo corresponding to the address of a symbol.
+- `.symbol`: input symbol (alias `.src`), type is `pseudo_t`
+- `.target`: symbol's address
+
+### 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)
+- `.val`: (expression) input expression
+- `.target`: the resulting value
+- `.type`: type of `.target`, the value
+
+### OP_PHI
+Phi-node (for SSA form).
+- `.phi_list`: phi-operands (type must be compatible with `.target`)
+- `.target`: "result"
+- `.type`: type of `.target`
+
+### OP_PHISOURCE
+Phi-node source.
+Like OP_COPY but exclusively used to give a defining instructions
+(and thus also a type) to *all* OP_PHI operands.
+- `.phi_src`: operand (type must be compatible with `.target`, alias `.src`)
+- `.target`: the "result" PSEUDO_PHI
+- `.type`: type of `.target`
+- `.phi_users`: list of phi instructions using the target pseudo
+
+### OP_PUSH
+Give an argument to the following OP_CALL.
+- `.arg`: argument (alias `.src`), type is `pseudo_t`
+- `.type`: type of `.src`
+- `.call`: corresponding instruction
+
+### OP_CALL
+Function call.
+- `.func`: the function (can be a symbol or a "register", alias `.src`)), type is `pseudo_t`
+- `.arguments`: list of the associated OP_PUSH instructions
+- `.target`: function return value (if any)
+- `.type`: type of `.target`
+- `.fntype`: the full function type
+
+### OP_INLINED_CALL
+Only used as an annotation to show that the instructions just above
+correspond to a function that have been inlined.
+- `.func`: the function (must be a symbol, alias `.src`)), type is `pseudo_t`
+- `.inlined_args`: list of pseudos that where the function's arguments
+- `.target`: function return value (if any)
+- `.type`: type of `.target`
+- `.fntype`: the full function type
+
+### OP_SLICE
+Extract a "slice" from an aggregate.
+- `.base`: aggregate (alias `.src`), type is `pseudo_t`
+- `.from`, `.len`: offet & size of the "slice" within the aggregate
+- `.target`: result
+- `.type`: type of `.target`
+
+### OP_ASM
+Inlined assembly code.
+- `.string`: asm template
+- `.asm_rules`: asm constraints, rules
+
+## Sparse tagging (line numbers, context, whatever)
+### OP_CONTEXT
+Currently only used for lock/unlock tracking.
+- `.context_expr`: unused
+- `.increment`: (1 for locking, -1 for unlocking)
+- `.check`: (ignore the instruction if 0)
+
+## Misc ops
+### OP_ENTRY
+Function entry point (no associated semantic).
+
+### OP_BADOP
+Invalid operation (should never be generated).
+
+### OP_NOP
+No-op (should never be generated).
+
+### OP_SNOP
+Store no-op (removed store operation).
+
+### OP_LNOP
+Load no-op (removed load operation).
+
+### OP_DEATHNOTE
+Annotation telling the pseudo will be death after the next
+instruction (other than some other annotation, that is).
+
+### OP_COPY
+Copy (only needed after out-of-SSA).
+- `.src`: operand (type must be compatible with `.target`)
+- `.target`: result of the operation
+- `.type`: type of `.target`
+
+### OP_RANGE
+Range/bounds checking (only used for an unused sparse extension).
+- `.src1`: value to be checked
+- `.src2`, src3: bound of the value (must be constants?)
+- `.type`: type of `.src`
+
+## Unused ops
+### OP_VANEXT
+### OP_VAARG
+### OP_MALLOC
+### OP_FREE
+### OP_ALLOCA
+### OP_GET_ELEMENT_PTR
+### OP_INVOKE
+### OP_UNWIND
-- 
2.14.0


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [RFC PATCH 02/14] cast: add tests for warnings issued by sparse -v
  2017-08-17  4:05 [RFC PATCH 00/14] rework of cast operations Luc Van Oostenryck
  2017-08-17  4:05 ` [RFC PATCH 01/14] add documentation for IR instructions Luc Van Oostenryck
@ 2017-08-17  4:05 ` Luc Van Oostenryck
  2017-08-17  4:05 ` [RFC PATCH 03/14] cast: prepare finer grained cast instructions Luc Van Oostenryck
                   ` (11 subsequent siblings)
  13 siblings, 0 replies; 16+ messages in thread
From: Luc Van Oostenryck @ 2017-08-17  4:05 UTC (permalink / raw)
  To: linux-sparse
  Cc: Linus Torvalds, Christopher Li, Dibyendu Majumdar,
	Luc Van Oostenryck

The sparse command (aka the 'checker') do a number of additional
checks when used with the -v flag. I strongly believes that this
option is rarely used let me not disgress about it here.

One of this additional checks are about casts.
Let add soe testcase in thr tessuite in order to avoid any
regression there.

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
 validation/cast-kinds-check.c | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)
 create mode 100644 validation/cast-kinds-check.c

diff --git a/validation/cast-kinds-check.c b/validation/cast-kinds-check.c
new file mode 100644
index 000000000..f3ece313a
--- /dev/null
+++ b/validation/cast-kinds-check.c
@@ -0,0 +1,26 @@
+#include "cast-kinds.c"
+
+/*
+ * check-name: cast-kinds check
+ * check-command: sparse -m64 -v $file
+ *
+ * check-error-start
+cast-kinds.c:5:45: warning: cast drops bits
+cast-kinds.c:6:47: warning: cast drops bits
+cast-kinds.c:7:46: warning: cast drops bits
+cast-kinds.c:8:45: warning: cast drops bits
+cast-kinds.c:10:49: warning: cast drops bits
+cast-kinds.c:12:48: warning: cast drops bits
+cast-kinds.c:13:50: warning: cast drops bits
+cast-kinds.c:14:49: warning: cast drops bits
+cast-kinds.c:15:48: warning: cast drops bits
+cast-kinds.c:17:52: warning: cast drops bits
+cast-kinds.c:21:49: warning: cast wasn't removed
+cast-kinds.c:22:48: warning: cast wasn't removed
+cast-kinds.c:28:52: warning: cast wasn't removed
+cast-kinds.c:29:51: warning: cast wasn't removed
+cast-kinds.c:34:52: warning: cast wasn't removed
+cast-kinds.c:35:54: warning: cast wasn't removed
+cast-kinds.c:36:52: warning: cast wasn't removed
+ * check-error-end
+ */
-- 
2.14.0


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [RFC PATCH 03/14] cast: prepare finer grained cast instructions
  2017-08-17  4:05 [RFC PATCH 00/14] rework of cast operations Luc Van Oostenryck
  2017-08-17  4:05 ` [RFC PATCH 01/14] add documentation for IR instructions Luc Van Oostenryck
  2017-08-17  4:05 ` [RFC PATCH 02/14] cast: add tests for warnings issued by sparse -v Luc Van Oostenryck
@ 2017-08-17  4:05 ` Luc Van Oostenryck
  2017-08-17  4:05 ` [RFC PATCH 04/14] cast: specialize FPCAST into [USF]CVTF Luc Van Oostenryck
                   ` (10 subsequent siblings)
  13 siblings, 0 replies; 16+ messages in thread
From: Luc Van Oostenryck @ 2017-08-17  4:05 UTC (permalink / raw)
  To: linux-sparse
  Cc: Linus Torvalds, Christopher Li, Dibyendu Majumdar,
	Luc Van Oostenryck

As a first step, add a small function classify values into
'machine type:
- signed integer
- unsigned integer
- pointer
- floats
and use this to select the appropriate O_XXXCAST.

Note: this is a preparatory patch and should not introduce
      any changes in the generated IR.

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
 linearize.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++------------
 1 file changed, 63 insertions(+), 15 deletions(-)

diff --git a/linearize.c b/linearize.c
index ba76397ea..c77a3c2df 100644
--- a/linearize.c
+++ b/linearize.c
@@ -1109,28 +1109,75 @@ static pseudo_t linearize_postop(struct entrypoint *ep, struct expression *expr)
  * case, since you can't access through it anyway without another
  * cast.
  */
-static struct instruction *alloc_cast_instruction(struct symbol *src, struct symbol *ctype)
+enum mtype {
+	MTYPE_UINT,
+	MTYPE_SINT,
+	MTYPE_PTR,
+	MTYPE_FLOAT,
+	MTYPE_BAD,
+};
+
+static enum mtype get_mtype(struct symbol *s)
+{
+	int sign = (s->ctype.modifiers & MOD_SIGNED) ? 1 : 0;
+
+retry:	switch (s->type) {
+	case SYM_NODE:
+		s = s->ctype.base_type;
+		goto retry;
+	case SYM_PTR:
+		if (s->ctype.base_type == &void_ctype)
+			// handle void pointer like an uint
+			goto case_int;
+		return MTYPE_PTR;
+	case SYM_BITFIELD:
+	case SYM_RESTRICT:
+	case SYM_FOULED:
+	case SYM_ENUM:
+		s = s->ctype.base_type;
+		/* fall-through */
+	case_int:
+		return sign ? MTYPE_SINT : MTYPE_UINT;
+	case SYM_BASETYPE:
+		if (s->ctype.base_type == &fp_type)
+			return MTYPE_FLOAT;
+		if (s->ctype.base_type == &int_type)
+			goto case_int;
+		/* fall-through */
+	default:
+		return MTYPE_BAD;
+	}
+}
+
+static int get_cast_opcode(struct symbol *dst, struct symbol *src)
 {
-	int opcode = OP_CAST;
-	struct symbol *base = ctype;
+	enum mtype stype = get_mtype(src);
+	enum mtype dtype = get_mtype(dst);
 
-	if (src->ctype.modifiers & MOD_SIGNED)
-		opcode = OP_SCAST;
-	if (base->type == SYM_NODE)
-		base = base->ctype.base_type;
-	if (base->type == SYM_PTR) {
-		base = base->ctype.base_type;
-		if (base != &void_ctype)
-			opcode = OP_PTRCAST;
-	} else if (base->ctype.base_type == &fp_type)
-		opcode = OP_FPCAST;
-	return alloc_typed_instruction(opcode, ctype);
+	switch (dtype) {
+	case MTYPE_FLOAT:
+		return  OP_FPCAST;
+	case MTYPE_PTR:
+		return OP_PTRCAST;
+	case MTYPE_UINT:
+	case MTYPE_SINT:
+		switch (stype) {
+		case MTYPE_SINT:
+			return OP_SCAST;
+		default:
+			break;
+		}
+		/* fall through */
+	default:
+		return OP_CAST;
+	}
 }
 
 static pseudo_t cast_pseudo(struct entrypoint *ep, pseudo_t src, struct symbol *from, struct symbol *to)
 {
 	pseudo_t result;
 	struct instruction *insn;
+	int opcode;
 
 	if (src == VOID)
 		return VOID;
@@ -1138,7 +1185,8 @@ static pseudo_t cast_pseudo(struct entrypoint *ep, pseudo_t src, struct symbol *
 		return VOID;
 	if (from->bit_size < 0 || to->bit_size < 0)
 		return VOID;
-	insn = alloc_cast_instruction(from, to);
+	opcode = get_cast_opcode(to, from);
+	insn = alloc_typed_instruction(opcode, to);
 	result = alloc_pseudo(insn);
 	insn->target = result;
 	insn->orig_type = from;
-- 
2.14.0


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [RFC PATCH 04/14] cast: specialize FPCAST into [USF]CVTF
  2017-08-17  4:05 [RFC PATCH 00/14] rework of cast operations Luc Van Oostenryck
                   ` (2 preceding siblings ...)
  2017-08-17  4:05 ` [RFC PATCH 03/14] cast: prepare finer grained cast instructions Luc Van Oostenryck
@ 2017-08-17  4:05 ` Luc Van Oostenryck
  2017-08-17  4:05 ` [RFC PATCH 05/14] cast: handle NO-OP casts Luc Van Oostenryck
                   ` (9 subsequent siblings)
  13 siblings, 0 replies; 16+ messages in thread
From: Luc Van Oostenryck @ 2017-08-17  4:05 UTC (permalink / raw)
  To: linux-sparse
  Cc: Linus Torvalds, Christopher Li, Dibyendu Majumdar,
	Luc Van Oostenryck

Currently, all cast to a floating point type use OP_FPCAST.
This is aybe simple but rather uncovenient as it correspond
to several quite different operation that later need extra
checks.

Change this by directly using different instructions for the
different case:
- 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>
---
 Documentation/IR.md     | 12 +++++++++---
 example.c               |  8 ++++++--
 linearize.c             | 18 +++++++++++++++---
 linearize.h             |  3 ++-
 liveness.c              |  3 ++-
 simplify.c              | 11 +++++++----
 sparse-llvm.c           |  3 ++-
 validation/cast-kinds.c | 20 ++++++++++----------
 8 files changed, 53 insertions(+), 25 deletions(-)

diff --git a/Documentation/IR.md b/Documentation/IR.md
index 7e13e740d..2d23e65d3 100644
--- a/Documentation/IR.md
+++ b/Documentation/IR.md
@@ -163,12 +163,18 @@ Cast to unsigned integer (and to void pointer).
 ### OP_SCAST
 Cast to signed integer.
 
-### OP_FPCAST
-Cast to floating-point.
-
 ### OP_PTRCAST
 Cast to pointer.
 
+### OP_UCVTF
+Conversion from unsigned integer to a float type.
+
+### OP_SCVTF
+Conversion from signed integer to a float type.
+
+### OP_FCVTF
+Conversion between float types.
+
 ## Ternary ops
 ### OP_SEL
 - `.src1`: condition, must be of integral type
diff --git a/example.c b/example.c
index 691e0f97c..30e91bbf6 100644
--- a/example.c
+++ b/example.c
@@ -83,7 +83,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_VANEXT] = "va_next",
@@ -1420,7 +1422,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 c77a3c2df..7f8dbc64a 100644
--- a/linearize.c
+++ b/linearize.c
@@ -230,7 +230,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",
@@ -425,7 +427,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),
@@ -1156,7 +1159,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 bac82d7ff..0ec42e588 100644
--- a/linearize.h
+++ b/linearize.h
@@ -198,7 +198,8 @@ enum opcode {
 	OP_PHISOURCE,
 	OP_CAST,
 	OP_SCAST,
-	OP_FPCAST,
+	OP_UCVTF, OP_SCVTF,
+	OP_FCVTF,
 	OP_PTRCAST,
 	OP_INLINED_CALL,
 	OP_CALL,
diff --git a/liveness.c b/liveness.c
index 7461738b4..b3e0a8326 100644
--- a/liveness.c
+++ b/liveness.c
@@ -113,7 +113,8 @@ static void track_instruction_usage(struct basic_block *bb, struct instruction *
 
 	case OP_CAST:
 	case OP_SCAST:
-	case OP_FPCAST:
+	case OP_UCVTF: case OP_SCVTF:
+	case OP_FCVTF:
 	case OP_PTRCAST:
 		USES(src); DEFINES(target);
 		break;
diff --git a/simplify.c b/simplify.c
index 2bc86f53e..e0f31ad45 100644
--- a/simplify.c
+++ b/simplify.c
@@ -238,7 +238,8 @@ void kill_insn(struct instruction *insn, int force)
 
 	case OP_CAST:
 	case OP_SCAST:
-	case OP_FPCAST:
+	case OP_UCVTF: case OP_SCVTF:
+	case OP_FCVTF:
 	case OP_PTRCAST:
 	case OP_SETVAL:
 	case OP_NOT: case OP_NEG:
@@ -340,7 +341,8 @@ static int replace_with_pseudo(struct instruction *insn, pseudo_t pseudo)
 	case OP_SYMADDR:
 	case OP_CAST:
 	case OP_SCAST:
-	case OP_FPCAST:
+	case OP_UCVTF: case OP_SCVTF:
+	case OP_FCVTF:
 	case OP_PTRCAST:
 		kill_use(&insn->src1);
 		break;
@@ -973,7 +975,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;
 	}
 
@@ -1201,7 +1203,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 29fb65f15..c45729ef4 100644
--- a/sparse-llvm.c
+++ b/sparse-llvm.c
@@ -855,7 +855,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:
 		assert(0);
 		break;
 	case OP_PTRCAST:
diff --git a/validation/cast-kinds.c b/validation/cast-kinds.c
index 697f9735e..34bf685d2 100644
--- a/validation/cast-kinds.c
+++ b/validation/cast-kinds.c
@@ -316,70 +316,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
 
 
-- 
2.14.0


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [RFC PATCH 05/14] cast: handle NO-OP casts
  2017-08-17  4:05 [RFC PATCH 00/14] rework of cast operations Luc Van Oostenryck
                   ` (3 preceding siblings ...)
  2017-08-17  4:05 ` [RFC PATCH 04/14] cast: specialize FPCAST into [USF]CVTF Luc Van Oostenryck
@ 2017-08-17  4:05 ` Luc Van Oostenryck
  2017-08-17  4:05 ` [RFC PATCH 06/14] cast: specialize floats to integer conversion Luc Van Oostenryck
                   ` (8 subsequent siblings)
  13 siblings, 0 replies; 16+ messages in thread
From: Luc Van Oostenryck @ 2017-08-17  4:05 UTC (permalink / raw)
  To: linux-sparse
  Cc: Linus Torvalds, Christopher Li, Dibyendu Majumdar,
	Luc Van Oostenryck

Some casts, the ones which deosn't chnage the size or the resulting
'machine type', are no-op.

Directly simplify away such casts.

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
 linearize.c             |  8 ++++++++
 validation/cast-kinds.c | 15 +++++++++++++++
 2 files changed, 23 insertions(+)

diff --git a/linearize.c b/linearize.c
index 7f8dbc64a..3f8d955c5 100644
--- a/linearize.c
+++ b/linearize.c
@@ -1161,6 +1161,8 @@ static int get_cast_opcode(struct symbol *dst, struct symbol *src)
 	case MTYPE_FLOAT:
 		switch (stype) {
 		case MTYPE_FLOAT:
+			if (dst->bit_size == src->bit_size)
+				return OP_NOP;
 			return OP_FCVTF;
 		case MTYPE_UINT:
 			return OP_UCVTF;
@@ -1198,6 +1200,12 @@ static pseudo_t cast_pseudo(struct entrypoint *ep, pseudo_t src, struct symbol *
 	if (from->bit_size < 0 || to->bit_size < 0)
 		return VOID;
 	opcode = get_cast_opcode(to, from);
+	switch (opcode) {
+	case OP_NOP:
+		return src;
+	default:
+		break;
+	}
 	insn = alloc_typed_instruction(opcode, to);
 	result = alloc_pseudo(insn);
 	insn->target = result;
diff --git a/validation/cast-kinds.c b/validation/cast-kinds.c
index 34bf685d2..0312bc92b 100644
--- a/validation/cast-kinds.c
+++ b/validation/cast-kinds.c
@@ -50,6 +50,9 @@ static double long_2_double(long a) { return (double)a; }
 static double ulong_2_double(ulong a) { return (double)a; }
 static double float_2_double(float a) { return (double)a; }
 
+static float float_2_float(float a) { return a; }
+static double double_2_double(double a) { return a; }
+
 /*
  * check-name: cast-kinds
  * check-command: test-linearize -m64 $file
@@ -383,5 +386,17 @@ float_2_double:
 	ret.64      %r143
 
 
+float_2_float:
+.L96:
+	<entry-point>
+	ret.32      %arg1
+
+
+double_2_double:
+.L98:
+	<entry-point>
+	ret.64      %arg1
+
+
  * check-output-end
  */
-- 
2.14.0


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [RFC PATCH 06/14] cast: specialize floats to integer conversion
  2017-08-17  4:05 [RFC PATCH 00/14] rework of cast operations Luc Van Oostenryck
                   ` (4 preceding siblings ...)
  2017-08-17  4:05 ` [RFC PATCH 05/14] cast: handle NO-OP casts Luc Van Oostenryck
@ 2017-08-17  4:05 ` Luc Van Oostenryck
  2017-08-17  4:05 ` [RFC PATCH 07/14] cast: specialize casts from unsigned to pointers Luc Van Oostenryck
                   ` (7 subsequent siblings)
  13 siblings, 0 replies; 16+ messages in thread
From: Luc Van Oostenryck @ 2017-08-17  4:05 UTC (permalink / raw)
  To: linux-sparse
  Cc: Linus Torvalds, Christopher Li, Dibyendu Majumdar,
	Luc Van Oostenryck

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

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

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
 Documentation/IR.md           |  6 ++++++
 example.c                     |  3 +++
 linearize.c                   |  5 +++++
 linearize.h                   |  1 +
 liveness.c                    |  1 +
 simplify.c                    |  3 +++
 sparse-llvm.c                 |  1 +
 validation/cast-kinds-check.c |  2 --
 validation/cast-kinds.c       | 20 ++++++++++++--------
 9 files changed, 32 insertions(+), 10 deletions(-)

diff --git a/Documentation/IR.md b/Documentation/IR.md
index 2d23e65d3..0bfd9765c 100644
--- a/Documentation/IR.md
+++ b/Documentation/IR.md
@@ -166,6 +166,12 @@ Cast to signed integer.
 ### OP_PTRCAST
 Cast to pointer.
 
+### OP_FCVTU
+Conversion from float type to unsigned integer.
+
+### OP_FCVTS
+Conversion from float type to signed integer.
+
 ### OP_UCVTF
 Conversion from unsigned integer to a float type.
 
diff --git a/example.c b/example.c
index 30e91bbf6..0349a7e20 100644
--- a/example.c
+++ b/example.c
@@ -83,6 +83,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",
@@ -1423,6 +1425,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 3f8d955c5..75b200c4b 100644
--- a/linearize.c
+++ b/linearize.c
@@ -230,6 +230,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",
@@ -427,6 +429,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:
@@ -1176,6 +1179,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 0ec42e588..600bae598 100644
--- a/linearize.h
+++ b/linearize.h
@@ -198,6 +198,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 b3e0a8326..3bd95fe5b 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 e0f31ad45..365811b96 100644
--- a/simplify.c
+++ b/simplify.c
@@ -238,6 +238,7 @@ void 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:
@@ -341,6 +342,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:
@@ -1203,6 +1205,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 c45729ef4..04efc6637 100644
--- a/sparse-llvm.c
+++ b/sparse-llvm.c
@@ -855,6 +855,7 @@ static void output_insn(struct function *fn, struct instruction *insn)
 	case OP_SCAST:
 		output_op_cast(fn, insn, LLVMSExt);
 		break;
+	case OP_FCVTU: case OP_FCVTS:
 	case OP_UCVTF: case OP_SCVTF:
 	case OP_FCVTF:
 		assert(0);
diff --git a/validation/cast-kinds-check.c b/validation/cast-kinds-check.c
index f3ece313a..be6b684b4 100644
--- a/validation/cast-kinds-check.c
+++ b/validation/cast-kinds-check.c
@@ -9,12 +9,10 @@ cast-kinds.c:5:45: warning: cast drops bits
 cast-kinds.c:6:47: warning: cast drops bits
 cast-kinds.c:7:46: warning: cast drops bits
 cast-kinds.c:8:45: warning: cast drops bits
-cast-kinds.c:10:49: warning: cast drops bits
 cast-kinds.c:12:48: warning: cast drops bits
 cast-kinds.c:13:50: warning: cast drops bits
 cast-kinds.c:14:49: warning: cast drops bits
 cast-kinds.c:15:48: warning: cast drops bits
-cast-kinds.c:17:52: warning: cast drops bits
 cast-kinds.c:21:49: warning: cast wasn't removed
 cast-kinds.c:22:48: warning: cast wasn't removed
 cast-kinds.c:28:52: warning: cast wasn't removed
diff --git a/validation/cast-kinds.c b/validation/cast-kinds.c
index 0312bc92b..d07a94190 100644
--- a/validation/cast-kinds.c
+++ b/validation/cast-kinds.c
@@ -95,13 +95,14 @@ iptr_2_int:
 float_2_int:
 .L10:
 	<entry-point>
-	ret.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
 
 
@@ -142,13 +143,14 @@ iptr_2_uint:
 float_2_uint:
 .L24:
 	<entry-point>
-	ret.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
 
 
@@ -189,14 +191,15 @@ 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>
-	ret.64      %arg1
+	fcvts.64    %r62 <- (64) %arg1
+	ret.64      %r62
 
 
 int_2_ulong:
@@ -236,14 +239,15 @@ 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>
-	ret.64      %arg1
+	fcvtu.64    %r83 <- (64) %arg1
+	ret.64      %r83
 
 
 int_2_vptr:
-- 
2.14.0


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [RFC PATCH 07/14] cast: specialize casts from unsigned to pointers
  2017-08-17  4:05 [RFC PATCH 00/14] rework of cast operations Luc Van Oostenryck
                   ` (5 preceding siblings ...)
  2017-08-17  4:05 ` [RFC PATCH 06/14] cast: specialize floats to integer conversion Luc Van Oostenryck
@ 2017-08-17  4:05 ` Luc Van Oostenryck
  2017-08-17  4:05 ` [RFC PATCH 08/14] cast: make [u]intptr_ctype alias of [s]size_t_ctype Luc Van Oostenryck
                   ` (6 subsequent siblings)
  13 siblings, 0 replies; 16+ messages in thread
From: Luc Van Oostenryck @ 2017-08-17  4:05 UTC (permalink / raw)
  To: linux-sparse
  Cc: Linus Torvalds, Christopher Li, Dibyendu Majumdar,
	Luc Van Oostenryck

Currently all casts to pointers are processed alike. This is
but rather uncovenient as it correspond to different operations
that may obey 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@gmail.com>
---
 Documentation/IR.md           |  3 +++
 cse.c                         |  2 ++
 example.c                     |  2 ++
 lib.c                         |  2 ++
 lib.h                         |  1 +
 linearize.c                   | 20 +++++++++++++++++-
 linearize.h                   |  1 +
 liveness.c                    |  1 +
 simplify.c                    |  3 +++
 sparse-llvm.c                 |  1 +
 validation/cast-kinds-check.c |  2 ++
 validation/cast-kinds.c       | 13 ++++++++----
 validation/cast-weirds.c      | 49 +++++++++++++++++++++++++++++++++++++++++++
 13 files changed, 95 insertions(+), 5 deletions(-)
 create mode 100644 validation/cast-weirds.c

diff --git a/Documentation/IR.md b/Documentation/IR.md
index 0bfd9765c..039bdb097 100644
--- a/Documentation/IR.md
+++ b/Documentation/IR.md
@@ -163,6 +163,9 @@ Cast to unsigned integer (and to void pointer).
 ### OP_SCAST
 Cast to signed integer.
 
+### OP_UTPTR
+Cast from unsigned integer to pointer type.
+
 ### OP_PTRCAST
 Cast to pointer.
 
diff --git a/cse.c b/cse.c
index 17b3da01a..3e5d493d1 100644
--- a/cse.c
+++ b/cse.c
@@ -89,6 +89,7 @@ static void clean_up_one_instruction(struct basic_block *bb, struct instruction
 	case OP_CAST:
 	case OP_SCAST:
 	case OP_PTRCAST:
+	case OP_UTPTR:
 		/*
 		 * This is crap! Many "orig_types" are the
 		 * same as far as casts go, we should generate
@@ -233,6 +234,7 @@ static int insn_compare(const void *_i1, const void *_i2)
 	case OP_CAST:
 	case OP_SCAST:
 	case OP_PTRCAST:
+	case OP_UTPTR:
 		/*
 		 * This is crap! See the comments on hashing.
 		 */
diff --git a/example.c b/example.c
index 0349a7e20..18eef6627 100644
--- a/example.c
+++ b/example.c
@@ -88,6 +88,7 @@ static const char *opcodes[] = {
 	[OP_UCVTF] = "ucvtf",
 	[OP_SCVTF] = "scvtf",
 	[OP_FCVTF] = "fcvtf",
+	[OP_UTPTR] = "utptr",
 	[OP_PTRCAST] = "ptrcast",
 	[OP_CALL] = "call",
 	[OP_VANEXT] = "va_next",
@@ -1425,6 +1426,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_UTPTR:
 	case OP_FCVTU: case OP_FCVTS:
 	case OP_UCVTF: case OP_SCVTF:
 	case OP_FCVTF:
diff --git a/lib.c b/lib.c
index 73e9a2fe6..1c67e1912 100644
--- a/lib.c
+++ b/lib.c
@@ -230,6 +230,7 @@ int Wdefault_bitfield_sign = 0;
 int Wdesignated_init = 1;
 int Wdo_while = 0;
 int Winit_cstring = 0;
+int Wint_to_pointer_cast = 1;
 int Wenum_mismatch = 1;
 int Wsparse_error = 0;
 int Wmemcpy_max_count = 1;
@@ -523,6 +524,7 @@ static const struct warning {
 	{ "do-while", &Wdo_while },
 	{ "enum-mismatch", &Wenum_mismatch },
 	{ "init-cstring", &Winit_cstring },
+	{ "int-to-pointer-cast", &Wint_to_pointer_cast },
 	{ "memcpy-max-count", &Wmemcpy_max_count },
 	{ "non-pointer-null", &Wnon_pointer_null },
 	{ "old-initializer", &Wold_initializer },
diff --git a/lib.h b/lib.h
index 307ccaeb2..010317970 100644
--- a/lib.h
+++ b/lib.h
@@ -125,6 +125,7 @@ extern int Wdo_while;
 extern int Wenum_mismatch;
 extern int Wsparse_error;
 extern int Winit_cstring;
+extern int Wint_to_pointer_cast;
 extern int Wmemcpy_max_count;
 extern int Wnon_pointer_null;
 extern int Wold_initializer;
diff --git a/linearize.c b/linearize.c
index 75b200c4b..85d472ca6 100644
--- a/linearize.c
+++ b/linearize.c
@@ -235,6 +235,7 @@ static const char *opcodes[] = {
 	[OP_UCVTF] = "ucvtf",
 	[OP_SCVTF] = "scvtf",
 	[OP_FCVTF] = "fcvtf",
+	[OP_UTPTR] = "utptr",
 	[OP_PTRCAST] = "ptrcast",
 	[OP_INLINED_CALL] = "# call",
 	[OP_CALL] = "call",
@@ -432,6 +433,7 @@ const char *show_instruction(struct instruction *insn)
 	case OP_FCVTU: case OP_FCVTS:
 	case OP_UCVTF: case OP_SCVTF:
 	case OP_FCVTF:
+	case OP_UTPTR:
 	case OP_PTRCAST:
 		buf += sprintf(buf, "%s <- (%d) %s",
 			show_pseudo(insn->target),
@@ -1175,7 +1177,17 @@ static int get_cast_opcode(struct symbol *dst, struct symbol *src)
 			return OP_BADOP;
 		}
 	case MTYPE_PTR:
-		return OP_PTRCAST;
+		switch (stype) {
+		case MTYPE_UINT:
+		case MTYPE_SINT:
+			if (is_ptr_type(src))	// must be a void pointer
+				return OP_PTRCAST;// FIXME: to be removed?
+			return OP_UTPTR;
+		case MTYPE_PTR:
+			return OP_PTRCAST;
+		default:
+			return OP_BADOP;
+		}
 	case MTYPE_UINT:
 	case MTYPE_SINT:
 		switch (stype) {
@@ -1208,6 +1220,12 @@ static pseudo_t cast_pseudo(struct entrypoint *ep, pseudo_t src, struct symbol *
 	switch (opcode) {
 	case OP_NOP:
 		return src;
+	case OP_UTPTR:
+		if (from->bit_size == to->bit_size)
+			break;
+		if (Wint_to_pointer_cast)
+			warning(to->pos, "non size-preserving integer to pointer cast");
+		break;
 	default:
 		break;
 	}
diff --git a/linearize.h b/linearize.h
index 600bae598..3570f1507 100644
--- a/linearize.h
+++ b/linearize.h
@@ -201,6 +201,7 @@ enum opcode {
 	OP_FCVTU, OP_FCVTS,
 	OP_UCVTF, OP_SCVTF,
 	OP_FCVTF,
+	OP_UTPTR,
 	OP_PTRCAST,
 	OP_INLINED_CALL,
 	OP_CALL,
diff --git a/liveness.c b/liveness.c
index 3bd95fe5b..b9c6e4017 100644
--- a/liveness.c
+++ b/liveness.c
@@ -116,6 +116,7 @@ static void track_instruction_usage(struct basic_block *bb, struct instruction *
 	case OP_FCVTU: case OP_FCVTS:
 	case OP_UCVTF: case OP_SCVTF:
 	case OP_FCVTF:
+	case OP_UTPTR:
 	case OP_PTRCAST:
 		USES(src); DEFINES(target);
 		break;
diff --git a/simplify.c b/simplify.c
index 365811b96..f8222d31b 100644
--- a/simplify.c
+++ b/simplify.c
@@ -241,6 +241,7 @@ void kill_insn(struct instruction *insn, int force)
 	case OP_FCVTU: case OP_FCVTS:
 	case OP_UCVTF: case OP_SCVTF:
 	case OP_FCVTF:
+	case OP_UTPTR:
 	case OP_PTRCAST:
 	case OP_SETVAL:
 	case OP_NOT: case OP_NEG:
@@ -345,6 +346,7 @@ static int replace_with_pseudo(struct instruction *insn, pseudo_t pseudo)
 	case OP_FCVTU: case OP_FCVTS:
 	case OP_UCVTF: case OP_SCVTF:
 	case OP_FCVTF:
+	case OP_UTPTR:
 	case OP_PTRCAST:
 		kill_use(&insn->src1);
 		break;
@@ -1208,6 +1210,7 @@ int simplify_instruction(struct instruction *insn)
 	case OP_FCVTU: case OP_FCVTS:
 	case OP_UCVTF: case OP_SCVTF:
 	case OP_FCVTF:
+	case OP_UTPTR:
 	case OP_PTRCAST:
 		return simplify_cast(insn);
 	case OP_PHI:
diff --git a/sparse-llvm.c b/sparse-llvm.c
index 04efc6637..f4567a5f7 100644
--- a/sparse-llvm.c
+++ b/sparse-llvm.c
@@ -860,6 +860,7 @@ static void output_insn(struct function *fn, struct instruction *insn)
 	case OP_FCVTF:
 		assert(0);
 		break;
+	case OP_UTPTR:
 	case OP_PTRCAST:
 		output_op_ptrcast(fn, insn);
 		break;
diff --git a/validation/cast-kinds-check.c b/validation/cast-kinds-check.c
index be6b684b4..365fe6e40 100644
--- a/validation/cast-kinds-check.c
+++ b/validation/cast-kinds-check.c
@@ -20,5 +20,7 @@ cast-kinds.c:29:51: warning: cast wasn't removed
 cast-kinds.c:34:52: warning: cast wasn't removed
 cast-kinds.c:35:54: warning: cast wasn't removed
 cast-kinds.c:36:52: warning: cast wasn't removed
+cast-kinds.c:37:42: warning: non size-preserving integer to pointer cast
+cast-kinds.c:38:44: warning: non size-preserving integer to pointer cast
  * check-error-end
  */
diff --git a/validation/cast-kinds.c b/validation/cast-kinds.c
index d07a94190..e5b64b768 100644
--- a/validation/cast-kinds.c
+++ b/validation/cast-kinds.c
@@ -57,6 +57,11 @@ static double double_2_double(double a) { return a; }
  * check-name: cast-kinds
  * check-command: test-linearize -m64 $file
  *
+ * check-error-start
+cast-kinds.c:37:42: warning: non size-preserving integer to pointer cast
+cast-kinds.c:38:44: warning: non size-preserving integer to pointer cast
+ * check-error-end
+ *
  * check-output-start
 uint_2_int:
 .L0:
@@ -288,28 +293,28 @@ iptr_2_vptr:
 int_2_iptr:
 .L66:
 	<entry-point>
-	ptrcast.64  %r101 <- (32) %arg1
+	utptr.64    %r101 <- (32) %arg1
 	ret.64      %r101
 
 
 uint_2_iptr:
 .L68:
 	<entry-point>
-	ptrcast.64  %r104 <- (32) %arg1
+	utptr.64    %r104 <- (32) %arg1
 	ret.64      %r104
 
 
 long_2_iptr:
 .L70:
 	<entry-point>
-	ptrcast.64  %r107 <- (64) %arg1
+	utptr.64    %r107 <- (64) %arg1
 	ret.64      %r107
 
 
 ulong_2_iptr:
 .L72:
 	<entry-point>
-	ptrcast.64  %r110 <- (64) %arg1
+	utptr.64    %r110 <- (64) %arg1
 	ret.64      %r110
 
 
diff --git a/validation/cast-weirds.c b/validation/cast-weirds.c
new file mode 100644
index 000000000..136137b4c
--- /dev/null
+++ b/validation/cast-weirds.c
@@ -0,0 +1,49 @@
+typedef unsigned int uint;
+typedef unsigned long ulong;
+
+static int * int_2_iptr(int a) { return (int *)a; }
+static int * uint_2_iptr(uint a) { return (int *)a; }
+
+static void * int_2_vptr(int a) { return (void *)a; }
+static void * uint_2_vptr(uint a) { return (void *)a; }
+
+/*
+ * check-name: cast-weirds
+ * check-command: test-linearize -m64 $file
+ *
+ * check-error-start
+cast-weirds.c:4:42: warning: non size-preserving integer to pointer cast
+cast-weirds.c:5:44: warning: non size-preserving integer to pointer cast
+ * check-error-end
+ *
+ * check-output-start
+int_2_iptr:
+.L0:
+	<entry-point>
+	utptr.64    %r2 <- (32) %arg1
+	ret.64      %r2
+
+
+uint_2_iptr:
+.L2:
+	<entry-point>
+	utptr.64    %r5 <- (32) %arg1
+	ret.64      %r5
+
+
+int_2_vptr:
+.L4:
+	<entry-point>
+	scast.64    %r8 <- (32) %arg1
+	ret.64      %r8
+
+
+uint_2_vptr:
+.L6:
+	<entry-point>
+	cast.64     %r11 <- (32) %arg1
+	ret.64      %r11
+
+
+ * check-output-end
+ */
-- 
2.14.0


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [RFC PATCH 08/14] cast: make [u]intptr_ctype alias of [s]size_t_ctype
  2017-08-17  4:05 [RFC PATCH 00/14] rework of cast operations Luc Van Oostenryck
                   ` (6 preceding siblings ...)
  2017-08-17  4:05 ` [RFC PATCH 07/14] cast: specialize casts from unsigned to pointers Luc Van Oostenryck
@ 2017-08-17  4:05 ` Luc Van Oostenryck
  2017-08-17  4:05 ` [RFC PATCH 09/14] cast: make pointer casts always size preserving Luc Van Oostenryck
                   ` (5 subsequent siblings)
  13 siblings, 0 replies; 16+ messages in thread
From: Luc Van Oostenryck @ 2017-08-17  4:05 UTC (permalink / raw)
  To: linux-sparse
  Cc: Linus Torvalds, Christopher Li, Dibyendu Majumdar,
	Luc Van Oostenryck

When processing integer to/from pointers, we would like to have
an integer type which has the same size as a pointer.

Currently, it's always th case for [s]size_t but it's preferable
to have a specific type which will always offer this guarantee,
like [u]intptr_t.

Fix this lazily by defining [u]intptr_ctype to [s]size_t_ctype.

Note: this intptr_t is just internal to sparse and can be different
      from the type choosen by the libc/platform.

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
 symbol.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/symbol.h b/symbol.h
index 327449611..3e343e41e 100644
--- a/symbol.h
+++ b/symbol.h
@@ -270,6 +270,9 @@ extern struct symbol	bool_ctype, void_ctype, type_ctype,
 			incomplete_ctype, label_ctype, bad_ctype,
 			null_ctype;
 
+#define	uintptr_ctype	 size_t_ctype
+#define	 intptr_ctype	ssize_t_ctype
+
 /* Special internal symbols */
 extern struct symbol	zero_int;
 
-- 
2.14.0


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [RFC PATCH 09/14] cast: make pointer casts always size preserving
  2017-08-17  4:05 [RFC PATCH 00/14] rework of cast operations Luc Van Oostenryck
                   ` (7 preceding siblings ...)
  2017-08-17  4:05 ` [RFC PATCH 08/14] cast: make [u]intptr_ctype alias of [s]size_t_ctype Luc Van Oostenryck
@ 2017-08-17  4:05 ` Luc Van Oostenryck
  2017-08-17  4:05 ` [RFC PATCH 10/14] cast: temporary simplify handling cast to/from void* Luc Van Oostenryck
                   ` (4 subsequent siblings)
  13 siblings, 0 replies; 16+ messages in thread
From: Luc Van Oostenryck @ 2017-08-17  4:05 UTC (permalink / raw)
  To: linux-sparse
  Cc: Linus Torvalds, Christopher Li, Dibyendu Majumdar,
	Luc Van Oostenryck

Currently casts to pointers can be done from any integer type.
However, casts to (or from) pointers are only meaningful if value
preserving and thus between object of the same size.

To avoid to have to worry about sign/zero extension while doing
casts to pointers it's good to not have to deal with such casts.

Do this by doing first, if needed, a cast an integer of the same
size as a pointer before doing the cast to a pointer.

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
 Documentation/IR.md      |  2 +-
 linearize.c              |  2 ++
 validation/cast-kinds.c  | 62 +++++++++++++++++++++++++-----------------------
 validation/cast-weirds.c | 18 +++++++-------
 4 files changed, 45 insertions(+), 39 deletions(-)

diff --git a/Documentation/IR.md b/Documentation/IR.md
index 039bdb097..a1a32c562 100644
--- a/Documentation/IR.md
+++ b/Documentation/IR.md
@@ -164,7 +164,7 @@ Cast to unsigned integer (and to void pointer).
 Cast to signed integer.
 
 ### OP_UTPTR
-Cast from unsigned integer to pointer type.
+Cast from pointer-sized unsigned integer to pointer type.
 
 ### OP_PTRCAST
 Cast to pointer.
diff --git a/linearize.c b/linearize.c
index 85d472ca6..8be26db58 100644
--- a/linearize.c
+++ b/linearize.c
@@ -1225,6 +1225,8 @@ static pseudo_t cast_pseudo(struct entrypoint *ep, pseudo_t src, struct symbol *
 			break;
 		if (Wint_to_pointer_cast)
 			warning(to->pos, "non size-preserving integer to pointer cast");
+		src = cast_pseudo(ep, src, from, size_t_ctype);
+		from = size_t_ctype;
 		break;
 	default:
 		break;
diff --git a/validation/cast-kinds.c b/validation/cast-kinds.c
index e5b64b768..aa9f9bb29 100644
--- a/validation/cast-kinds.c
+++ b/validation/cast-kinds.c
@@ -293,106 +293,108 @@ iptr_2_vptr:
 int_2_iptr:
 .L66:
 	<entry-point>
-	utptr.64    %r101 <- (32) %arg1
-	ret.64      %r101
+	scast.64    %r101 <- (32) %arg1
+	utptr.64    %r102 <- (64) %r101
+	ret.64      %r102
 
 
 uint_2_iptr:
 .L68:
 	<entry-point>
-	utptr.64    %r104 <- (32) %arg1
-	ret.64      %r104
+	cast.64     %r105 <- (32) %arg1
+	utptr.64    %r106 <- (64) %r105
+	ret.64      %r106
 
 
 long_2_iptr:
 .L70:
 	<entry-point>
-	utptr.64    %r107 <- (64) %arg1
-	ret.64      %r107
+	utptr.64    %r109 <- (64) %arg1
+	ret.64      %r109
 
 
 ulong_2_iptr:
 .L72:
 	<entry-point>
-	utptr.64    %r110 <- (64) %arg1
-	ret.64      %r110
+	utptr.64    %r112 <- (64) %arg1
+	ret.64      %r112
 
 
 vptr_2_iptr:
 .L74:
 	<entry-point>
-	ptrcast.64  %r113 <- (64) %arg1
-	ret.64      %r113
+	ptrcast.64  %r115 <- (64) %arg1
+	ret.64      %r115
 
 
 int_2_float:
 .L76:
 	<entry-point>
-	scvtf.32    %r116 <- (32) %arg1
-	ret.32      %r116
+	scvtf.32    %r118 <- (32) %arg1
+	ret.32      %r118
 
 
 uint_2_float:
 .L78:
 	<entry-point>
-	ucvtf.32    %r119 <- (32) %arg1
-	ret.32      %r119
+	ucvtf.32    %r121 <- (32) %arg1
+	ret.32      %r121
 
 
 long_2_float:
 .L80:
 	<entry-point>
-	scvtf.32    %r122 <- (64) %arg1
-	ret.32      %r122
+	scvtf.32    %r124 <- (64) %arg1
+	ret.32      %r124
 
 
 ulong_2_float:
 .L82:
 	<entry-point>
-	ucvtf.32    %r125 <- (64) %arg1
-	ret.32      %r125
+	ucvtf.32    %r127 <- (64) %arg1
+	ret.32      %r127
 
 
 double_2_float:
 .L84:
 	<entry-point>
-	fcvtf.32    %r128 <- (64) %arg1
-	ret.32      %r128
+	fcvtf.32    %r130 <- (64) %arg1
+	ret.32      %r130
 
 
 int_2_double:
 .L86:
 	<entry-point>
-	scvtf.64    %r131 <- (32) %arg1
-	ret.64      %r131
+	scvtf.64    %r133 <- (32) %arg1
+	ret.64      %r133
 
 
 uint_2_double:
 .L88:
 	<entry-point>
-	ucvtf.64    %r134 <- (32) %arg1
-	ret.64      %r134
+	ucvtf.64    %r136 <- (32) %arg1
+	ret.64      %r136
 
 
 long_2_double:
 .L90:
 	<entry-point>
-	scvtf.64    %r137 <- (64) %arg1
-	ret.64      %r137
+	scvtf.64    %r139 <- (64) %arg1
+	ret.64      %r139
 
 
 ulong_2_double:
 .L92:
 	<entry-point>
-	ucvtf.64    %r140 <- (64) %arg1
-	ret.64      %r140
+	ucvtf.64    %r142 <- (64) %arg1
+	ret.64      %r142
 
 
 float_2_double:
 .L94:
 	<entry-point>
-	fcvtf.64    %r143 <- (32) %arg1
-	ret.64      %r143
+	fcvtf.64    %r145 <- (32) %arg1
+	ret.64      %r145
 
 
 float_2_float:
diff --git a/validation/cast-weirds.c b/validation/cast-weirds.c
index 136137b4c..71e52ff57 100644
--- a/validation/cast-weirds.c
+++ b/validation/cast-weirds.c
@@ -20,29 +20,31 @@ cast-weirds.c:5:44: warning: non size-preserving integer to pointer cast
 int_2_iptr:
 .L0:
 	<entry-point>
-	utptr.64    %r2 <- (32) %arg1
-	ret.64      %r2
+	scast.64    %r2 <- (32) %arg1
+	utptr.64    %r3 <- (64) %r2
+	ret.64      %r3
 
 
 uint_2_iptr:
 .L2:
 	<entry-point>
-	utptr.64    %r5 <- (32) %arg1
-	ret.64      %r5
+	cast.64     %r6 <- (32) %arg1
+	utptr.64    %r7 <- (64) %r6
+	ret.64      %r7
 
 
 int_2_vptr:
 .L4:
 	<entry-point>
-	scast.64    %r8 <- (32) %arg1
-	ret.64      %r8
+	scast.64    %r10 <- (32) %arg1
+	ret.64      %r10
 
 
 uint_2_vptr:
 .L6:
 	<entry-point>
-	cast.64     %r11 <- (32) %arg1
-	ret.64      %r11
+	cast.64     %r13 <- (32) %arg1
+	ret.64      %r13
 
 
  * check-output-end
-- 
2.14.0


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [RFC PATCH 10/14] cast: temporary simplify handling cast to/from void*
  2017-08-17  4:05 [RFC PATCH 00/14] rework of cast operations Luc Van Oostenryck
                   ` (8 preceding siblings ...)
  2017-08-17  4:05 ` [RFC PATCH 09/14] cast: make pointer casts always size preserving Luc Van Oostenryck
@ 2017-08-17  4:05 ` Luc Van Oostenryck
  2017-08-17  4:05 ` [RFC PATCH 11/14] cast: specialize cast from pointers Luc Van Oostenryck
                   ` (3 subsequent siblings)
  13 siblings, 0 replies; 16+ messages in thread
From: Luc Van Oostenryck @ 2017-08-17  4:05 UTC (permalink / raw)
  To: linux-sparse
  Cc: Linus Torvalds, Christopher Li, Dibyendu Majumdar,
	Luc Van Oostenryck

Currently pointer cast from/to void are treated as casts
to/from integer. The rationale being that a void pointer can't
anyway be dereferenced.

Allow to contnue to do by using a new 'machine type' for void
pointer which then allow to select the right type of cast:
OP_PTRCAST or OP_[S]CAST.

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
 linearize.c | 19 +++++++++++++++----
 1 file changed, 15 insertions(+), 4 deletions(-)

diff --git a/linearize.c b/linearize.c
index 8be26db58..01e6abde8 100644
--- a/linearize.c
+++ b/linearize.c
@@ -1121,6 +1121,7 @@ enum mtype {
 	MTYPE_UINT,
 	MTYPE_SINT,
 	MTYPE_PTR,
+	MTYPE_VPTR,	// TODO: must be removed ?
 	MTYPE_FLOAT,
 	MTYPE_BAD,
 };
@@ -1135,8 +1136,7 @@ retry:	switch (s->type) {
 		goto retry;
 	case SYM_PTR:
 		if (s->ctype.base_type == &void_ctype)
-			// handle void pointer like an uint
-			goto case_int;
+			return MTYPE_VPTR;
 		return MTYPE_PTR;
 	case SYM_BITFIELD:
 	case SYM_RESTRICT:
@@ -1180,14 +1180,25 @@ static int get_cast_opcode(struct symbol *dst, struct symbol *src)
 		switch (stype) {
 		case MTYPE_UINT:
 		case MTYPE_SINT:
-			if (is_ptr_type(src))	// must be a void pointer
-				return OP_PTRCAST;// FIXME: to be removed?
 			return OP_UTPTR;
 		case MTYPE_PTR:
+		case MTYPE_VPTR:
 			return OP_PTRCAST;
 		default:
 			return OP_BADOP;
 		}
+	case MTYPE_VPTR:
+		switch (stype) {
+		case MTYPE_PTR:
+		case MTYPE_VPTR:
+		case MTYPE_UINT:
+			return OP_CAST;
+		case MTYPE_SINT:
+			return OP_SCAST;
+		default:
+			return OP_BADOP;
+			break;
+		}
 	case MTYPE_UINT:
 	case MTYPE_SINT:
 		switch (stype) {
-- 
2.14.0


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [RFC PATCH 11/14] cast: specialize cast from pointers
  2017-08-17  4:05 [RFC PATCH 00/14] rework of cast operations Luc Van Oostenryck
                   ` (9 preceding siblings ...)
  2017-08-17  4:05 ` [RFC PATCH 10/14] cast: temporary simplify handling cast to/from void* Luc Van Oostenryck
@ 2017-08-17  4:05 ` Luc Van Oostenryck
  2017-08-17  4:05 ` [RFC PATCH 12/14] cast: add support for -Wpointer-to-int-cast Luc Van Oostenryck
                   ` (2 subsequent siblings)
  13 siblings, 0 replies; 16+ messages in thread
From: Luc Van Oostenryck @ 2017-08-17  4:05 UTC (permalink / raw)
  To: linux-sparse
  Cc: Linus Torvalds, Christopher Li, Dibyendu Majumdar,
	Luc Van Oostenryck

Currently all casts to pointers are processed alike. This is
simple creating the cast but rather uncovenient in later phases
as this correspond to different operations that may obey 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@gmail.com>
---
 Documentation/IR.md     | 10 ++++++++--
 cse.c                   |  4 ++--
 example.c               |  2 ++
 linearize.c             |  7 +++++++
 linearize.h             |  1 +
 liveness.c              |  1 +
 simplify.c              |  3 +++
 sparse-llvm.c           |  1 +
 sparse.c                |  1 +
 validation/cast-kinds.c |  8 ++++----
 10 files changed, 30 insertions(+), 8 deletions(-)

diff --git a/Documentation/IR.md b/Documentation/IR.md
index a1a32c562..8f7083ea4 100644
--- a/Documentation/IR.md
+++ b/Documentation/IR.md
@@ -157,8 +157,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_CAST
-Cast to unsigned integer (and to void pointer).
+Cast to unsigned integer.
 
 ### OP_SCAST
 Cast to signed integer.
@@ -166,8 +169,11 @@ Cast to signed integer.
 ### OP_UTPTR
 Cast from pointer-sized unsigned integer to pointer type.
 
+### OP_PTRTU
+Cast from pointer type to unsigned integer.
+
 ### OP_PTRCAST
-Cast to pointer.
+Cast between pointer.
 
 ### OP_FCVTU
 Conversion from float type to unsigned integer.
diff --git a/cse.c b/cse.c
index 3e5d493d1..166b7cda6 100644
--- a/cse.c
+++ b/cse.c
@@ -89,7 +89,7 @@ static void clean_up_one_instruction(struct basic_block *bb, struct instruction
 	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
@@ -234,7 +234,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 18eef6627..3a0ec0747 100644
--- a/example.c
+++ b/example.c
@@ -89,6 +89,7 @@ static const char *opcodes[] = {
 	[OP_SCVTF] = "scvtf",
 	[OP_FCVTF] = "fcvtf",
 	[OP_UTPTR] = "utptr",
+	[OP_PTRTU] = "utptr",
 	[OP_PTRCAST] = "ptrcast",
 	[OP_CALL] = "call",
 	[OP_VANEXT] = "va_next",
@@ -1427,6 +1428,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 01e6abde8..a1b647864 100644
--- a/linearize.c
+++ b/linearize.c
@@ -236,6 +236,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",
@@ -434,6 +435,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),
@@ -1204,6 +1206,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 3570f1507..165d2b579 100644
--- a/linearize.h
+++ b/linearize.h
@@ -202,6 +202,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 b9c6e4017..ef2030f3e 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 f8222d31b..86512cc84 100644
--- a/simplify.c
+++ b/simplify.c
@@ -242,6 +242,7 @@ void 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:
@@ -347,6 +348,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;
@@ -1211,6 +1213,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 f4567a5f7..8dd6a5185 100644
--- a/sparse-llvm.c
+++ b/sparse-llvm.c
@@ -861,6 +861,7 @@ static void output_insn(struct function *fn, struct instruction *insn)
 		assert(0);
 		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 bceacd94e..9f9611e25 100644
--- a/sparse.c
+++ b/sparse.c
@@ -215,6 +215,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/cast-kinds.c b/validation/cast-kinds.c
index aa9f9bb29..f60013e68 100644
--- a/validation/cast-kinds.c
+++ b/validation/cast-kinds.c
@@ -93,7 +93,7 @@ vptr_2_int:
 iptr_2_int:
 .L8:
 	<entry-point>
-	cast.32     %r14 <- (64) %arg1
+	ptrtu.32    %r14 <- (64) %arg1
 	ret.32      %r14
 
 
@@ -141,7 +141,7 @@ vptr_2_uint:
 iptr_2_uint:
 .L22:
 	<entry-point>
-	cast.32     %r35 <- (64) %arg1
+	ptrtu.32    %r35 <- (64) %arg1
 	ret.32      %r35
 
 
@@ -189,7 +189,7 @@ vptr_2_long:
 iptr_2_long:
 .L36:
 	<entry-point>
-	cast.64     %r56 <- (64) %arg1
+	ptrtu.64    %r56 <- (64) %arg1
 	ret.64      %r56
 
 
@@ -237,7 +237,7 @@ vptr_2_ulong:
 iptr_2_ulong:
 .L50:
 	<entry-point>
-	cast.64     %r77 <- (64) %arg1
+	ptrtu.64    %r77 <- (64) %arg1
 	ret.64      %r77
 
 
-- 
2.14.0


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [RFC PATCH 12/14] cast: add support for -Wpointer-to-int-cast
  2017-08-17  4:05 [RFC PATCH 00/14] rework of cast operations Luc Van Oostenryck
                   ` (10 preceding siblings ...)
  2017-08-17  4:05 ` [RFC PATCH 11/14] cast: specialize cast from pointers Luc Van Oostenryck
@ 2017-08-17  4:05 ` Luc Van Oostenryck
  2017-08-17  4:05 ` [RFC PATCH 13/14] cast: make casts from pointer always size preserving Luc Van Oostenryck
  2017-08-17  4:05 ` [RFC PATCH 14/14] cast: specialize integer casts Luc Van Oostenryck
  13 siblings, 0 replies; 16+ messages in thread
From: Luc Van Oostenryck @ 2017-08-17  4:05 UTC (permalink / raw)
  To: linux-sparse
  Cc: Linus Torvalds, Christopher Li, Dibyendu Majumdar,
	Luc Van Oostenryck

It's relatively common to cast a pointer to an unsigned long,
for example to make some bit operations.
It's much less sensicla to cast a pointer to an integer smaller
(or bigger) than a pointer is.

So allow to emit a diagnostic for this, under the control of a
new warning flag: -Wpointer-to-cast.

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
 lib.c                         | 2 ++
 lib.h                         | 1 +
 linearize.c                   | 5 +++++
 validation/cast-kinds-check.c | 2 +-
 validation/cast-kinds.c       | 2 ++
 5 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/lib.c b/lib.c
index 1c67e1912..7bfe9eb4e 100644
--- a/lib.c
+++ b/lib.c
@@ -241,6 +241,7 @@ int Woverride_init = 1;
 int Woverride_init_all = 0;
 int Woverride_init_whole_range = 0;
 int Wparen_string = 0;
+int Wpointer_to_int_cast = 1;
 int Wptr_subtraction_blows = 0;
 int Wreturn_void = 0;
 int Wshadow = 0;
@@ -532,6 +533,7 @@ static const struct warning {
 	{ "override-init", &Woverride_init },
 	{ "override-init-all", &Woverride_init_all },
 	{ "paren-string", &Wparen_string },
+	{ "pointer-to-int-cast", &Wpointer_to_int_cast },
 	{ "ptr-subtraction-blows", &Wptr_subtraction_blows },
 	{ "return-void", &Wreturn_void },
 	{ "shadow", &Wshadow },
diff --git a/lib.h b/lib.h
index 010317970..e588bb8c5 100644
--- a/lib.h
+++ b/lib.h
@@ -134,6 +134,7 @@ extern int Woverride_init;
 extern int Woverride_init_all;
 extern int Woverride_init_whole_range;
 extern int Wparen_string;
+extern int Wpointer_to_int_cast;
 extern int Wptr_subtraction_blows;
 extern int Wreturn_void;
 extern int Wshadow;
diff --git a/linearize.c b/linearize.c
index a1b647864..cae402ad3 100644
--- a/linearize.c
+++ b/linearize.c
@@ -1246,6 +1246,11 @@ static pseudo_t cast_pseudo(struct entrypoint *ep, pseudo_t src, struct symbol *
 		src = cast_pseudo(ep, src, from, size_t_ctype);
 		from = size_t_ctype;
 		break;
+	case OP_PTRTU:
+		if (from->bit_size == to->bit_size)
+			break;
+		if (Wpointer_to_int_cast)
+			warning(to->pos, "non size-preserving pointer to integer cast");
 	default:
 		break;
 	}
diff --git a/validation/cast-kinds-check.c b/validation/cast-kinds-check.c
index 365fe6e40..0eb94d047 100644
--- a/validation/cast-kinds-check.c
+++ b/validation/cast-kinds-check.c
@@ -2,7 +2,7 @@
 
 /*
  * check-name: cast-kinds check
- * check-command: sparse -m64 -v $file
+ * check-command: sparse -m64 -v -Wno-pointer-to-int-cast $file
  *
  * check-error-start
 cast-kinds.c:5:45: warning: cast drops bits
diff --git a/validation/cast-kinds.c b/validation/cast-kinds.c
index f60013e68..747a181ce 100644
--- a/validation/cast-kinds.c
+++ b/validation/cast-kinds.c
@@ -58,6 +58,8 @@ static double double_2_double(double a) { return a; }
  * check-command: test-linearize -m64 $file
  *
  * check-error-start
+cast-kinds.c:8:41: warning: non size-preserving pointer to integer cast
+cast-kinds.c:15:43: warning: non size-preserving pointer to integer cast
 cast-kinds.c:37:42: warning: non size-preserving integer to pointer cast
 cast-kinds.c:38:44: warning: non size-preserving integer to pointer cast
  * check-error-end
-- 
2.14.0


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [RFC PATCH 13/14] cast: make casts from pointer always size preserving
  2017-08-17  4:05 [RFC PATCH 00/14] rework of cast operations Luc Van Oostenryck
                   ` (11 preceding siblings ...)
  2017-08-17  4:05 ` [RFC PATCH 12/14] cast: add support for -Wpointer-to-int-cast Luc Van Oostenryck
@ 2017-08-17  4:05 ` Luc Van Oostenryck
  2017-08-17  4:05 ` [RFC PATCH 14/14] cast: specialize integer casts Luc Van Oostenryck
  13 siblings, 0 replies; 16+ messages in thread
From: Luc Van Oostenryck @ 2017-08-17  4:05 UTC (permalink / raw)
  To: linux-sparse
  Cc: Linus Torvalds, Christopher Li, Dibyendu Majumdar,
	Luc Van Oostenryck

Currently casts from pointers can be done to any integer type.
However, casts to (or from) pointers are only meaningful if
it preserves the value and thus dince between same-sized objects.

To avoid to have to worry about sign/zero extension while doing
casts to pointers it's good to not have to deal with such casts.

Do this by doing first a cast to an unsigned integer of the same size
as a pointer and then, if needed, doing to cast to the final type.
As such we have only to support pointer cast to unsigned char of the
same size and on the other we have the generic integer-to-interger
casts we to support anyway.

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
 Documentation/IR.md           |   2 +-
 linearize.c                   |   2 +
 sparse.c                      |   1 -
 validation/cast-kinds-check.c |   2 -
 validation/cast-kinds.c       | 170 +++++++++++++++++++++---------------------
 5 files changed, 89 insertions(+), 88 deletions(-)

diff --git a/Documentation/IR.md b/Documentation/IR.md
index 8f7083ea4..dcfd89bb6 100644
--- a/Documentation/IR.md
+++ b/Documentation/IR.md
@@ -170,7 +170,7 @@ Cast to signed integer.
 Cast from pointer-sized unsigned integer to pointer type.
 
 ### OP_PTRTU
-Cast from pointer type to unsigned integer.
+Cast from pointer type to pointer sized unsigned integer.
 
 ### OP_PTRCAST
 Cast between pointer.
diff --git a/linearize.c b/linearize.c
index cae402ad3..5d6cf7385 100644
--- a/linearize.c
+++ b/linearize.c
@@ -1251,6 +1251,8 @@ static pseudo_t cast_pseudo(struct entrypoint *ep, pseudo_t src, struct symbol *
 			break;
 		if (Wpointer_to_int_cast)
 			warning(to->pos, "non size-preserving pointer to integer cast");
+		src = cast_pseudo(ep, src, from, size_t_ctype);
+		return cast_pseudo(ep, src, size_t_ctype, to);
 	default:
 		break;
 	}
diff --git a/sparse.c b/sparse.c
index 9f9611e25..bceacd94e 100644
--- a/sparse.c
+++ b/sparse.c
@@ -215,7 +215,6 @@ 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/cast-kinds-check.c b/validation/cast-kinds-check.c
index 0eb94d047..fe0f83e24 100644
--- a/validation/cast-kinds-check.c
+++ b/validation/cast-kinds-check.c
@@ -14,9 +14,7 @@ cast-kinds.c:13:50: warning: cast drops bits
 cast-kinds.c:14:49: warning: cast drops bits
 cast-kinds.c:15:48: warning: cast drops bits
 cast-kinds.c:21:49: warning: cast wasn't removed
-cast-kinds.c:22:48: warning: cast wasn't removed
 cast-kinds.c:28:52: warning: cast wasn't removed
-cast-kinds.c:29:51: warning: cast wasn't removed
 cast-kinds.c:34:52: warning: cast wasn't removed
 cast-kinds.c:35:54: warning: cast wasn't removed
 cast-kinds.c:36:52: warning: cast wasn't removed
diff --git a/validation/cast-kinds.c b/validation/cast-kinds.c
index 747a181ce..3ac95c3dc 100644
--- a/validation/cast-kinds.c
+++ b/validation/cast-kinds.c
@@ -95,22 +95,23 @@ vptr_2_int:
 iptr_2_int:
 .L8:
 	<entry-point>
-	ptrtu.32    %r14 <- (64) %arg1
-	ret.32      %r14
+	ptrtu.64    %r14 <- (64) %arg1
+	cast.32     %r15 <- (64) %r14
+	ret.32      %r15
 
 
 float_2_int:
 .L10:
 	<entry-point>
-	fcvts.32    %r17 <- (32) %arg1
-	ret.32      %r17
+	fcvts.32    %r18 <- (32) %arg1
+	ret.32      %r18
 
 
 double_2_int:
 .L12:
 	<entry-point>
-	fcvts.32    %r20 <- (64) %arg1
-	ret.32      %r20
+	fcvts.32    %r21 <- (64) %arg1
+	ret.32      %r21
 
 
 int_2_uint:
@@ -122,57 +123,58 @@ int_2_uint:
 long_2_uint:
 .L16:
 	<entry-point>
-	scast.32    %r26 <- (64) %arg1
-	ret.32      %r26
+	scast.32    %r27 <- (64) %arg1
+	ret.32      %r27
 
 
 ulong_2_uint:
 .L18:
 	<entry-point>
-	cast.32     %r29 <- (64) %arg1
-	ret.32      %r29
+	cast.32     %r30 <- (64) %arg1
+	ret.32      %r30
 
 
 vptr_2_uint:
 .L20:
 	<entry-point>
-	cast.32     %r32 <- (64) %arg1
-	ret.32      %r32
+	cast.32     %r33 <- (64) %arg1
+	ret.32      %r33
 
 
 iptr_2_uint:
 .L22:
 	<entry-point>
-	ptrtu.32    %r35 <- (64) %arg1
-	ret.32      %r35
+	ptrtu.64    %r36 <- (64) %arg1
+	cast.32     %r37 <- (64) %r36
+	ret.32      %r37
 
 
 float_2_uint:
 .L24:
 	<entry-point>
-	fcvtu.32    %r38 <- (32) %arg1
-	ret.32      %r38
+	fcvtu.32    %r40 <- (32) %arg1
+	ret.32      %r40
 
 
 double_2_uint:
 .L26:
 	<entry-point>
-	fcvtu.32    %r41 <- (64) %arg1
-	ret.32      %r41
+	fcvtu.32    %r43 <- (64) %arg1
+	ret.32      %r43
 
 
 int_2_long:
 .L28:
 	<entry-point>
-	scast.64    %r44 <- (32) %arg1
-	ret.64      %r44
+	scast.64    %r46 <- (32) %arg1
+	ret.64      %r46
 
 
 uint_2_long:
 .L30:
 	<entry-point>
-	cast.64     %r47 <- (32) %arg1
-	ret.64      %r47
+	cast.64     %r49 <- (32) %arg1
+	ret.64      %r49
 
 
 ulong_2_long:
@@ -184,43 +186,43 @@ ulong_2_long:
 vptr_2_long:
 .L34:
 	<entry-point>
-	cast.64     %r53 <- (64) %arg1
-	ret.64      %r53
+	cast.64     %r55 <- (64) %arg1
+	ret.64      %r55
 
 
 iptr_2_long:
 .L36:
 	<entry-point>
-	ptrtu.64    %r56 <- (64) %arg1
-	ret.64      %r56
+	ptrtu.64    %r58 <- (64) %arg1
+	ret.64      %r58
 
 
 float_2_long:
 .L38:
 	<entry-point>
-	fcvts.64    %r59 <- (32) %arg1
-	ret.64      %r59
+	fcvts.64    %r61 <- (32) %arg1
+	ret.64      %r61
 
 
 double_2_long:
 .L40:
 	<entry-point>
-	fcvts.64    %r62 <- (64) %arg1
-	ret.64      %r62
+	fcvts.64    %r64 <- (64) %arg1
+	ret.64      %r64
 
 
 int_2_ulong:
 .L42:
 	<entry-point>
-	scast.64    %r65 <- (32) %arg1
-	ret.64      %r65
+	scast.64    %r67 <- (32) %arg1
+	ret.64      %r67
 
 
 uint_2_ulong:
 .L44:
 	<entry-point>
-	cast.64     %r68 <- (32) %arg1
-	ret.64      %r68
+	cast.64     %r70 <- (32) %arg1
+	ret.64      %r70
 
 
 long_2_ulong:
@@ -232,171 +234,171 @@ long_2_ulong:
 vptr_2_ulong:
 .L48:
 	<entry-point>
-	cast.64     %r74 <- (64) %arg1
-	ret.64      %r74
+	cast.64     %r76 <- (64) %arg1
+	ret.64      %r76
 
 
 iptr_2_ulong:
 .L50:
 	<entry-point>
-	ptrtu.64    %r77 <- (64) %arg1
-	ret.64      %r77
+	ptrtu.64    %r79 <- (64) %arg1
+	ret.64      %r79
 
 
 float_2_ulong:
 .L52:
 	<entry-point>
-	fcvtu.64    %r80 <- (32) %arg1
-	ret.64      %r80
+	fcvtu.64    %r82 <- (32) %arg1
+	ret.64      %r82
 
 
 double_2_ulong:
 .L54:
 	<entry-point>
-	fcvtu.64    %r83 <- (64) %arg1
-	ret.64      %r83
+	fcvtu.64    %r85 <- (64) %arg1
+	ret.64      %r85
 
 
 int_2_vptr:
 .L56:
 	<entry-point>
-	scast.64    %r86 <- (32) %arg1
-	ret.64      %r86
+	scast.64    %r88 <- (32) %arg1
+	ret.64      %r88
 
 
 uint_2_vptr:
 .L58:
 	<entry-point>
-	cast.64     %r89 <- (32) %arg1
-	ret.64      %r89
+	cast.64     %r91 <- (32) %arg1
+	ret.64      %r91
 
 
 long_2_vptr:
 .L60:
 	<entry-point>
-	scast.64    %r92 <- (64) %arg1
-	ret.64      %r92
+	scast.64    %r94 <- (64) %arg1
+	ret.64      %r94
 
 
 ulong_2_vptr:
 .L62:
 	<entry-point>
-	cast.64     %r95 <- (64) %arg1
-	ret.64      %r95
+	cast.64     %r97 <- (64) %arg1
+	ret.64      %r97
 
 
 iptr_2_vptr:
 .L64:
 	<entry-point>
-	cast.64     %r98 <- (64) %arg1
-	ret.64      %r98
+	cast.64     %r100 <- (64) %arg1
+	ret.64      %r100
 
 
 int_2_iptr:
 .L66:
 	<entry-point>
-	scast.64    %r101 <- (32) %arg1
-	utptr.64    %r102 <- (64) %r101
-	ret.64      %r102
+	scast.64    %r103 <- (32) %arg1
+	utptr.64    %r104 <- (64) %r103
+	ret.64      %r104
 
 
 uint_2_iptr:
 .L68:
 	<entry-point>
-	cast.64     %r105 <- (32) %arg1
-	utptr.64    %r106 <- (64) %r105
-	ret.64      %r106
+	cast.64     %r107 <- (32) %arg1
+	utptr.64    %r108 <- (64) %r107
+	ret.64      %r108
 
 
 long_2_iptr:
 .L70:
 	<entry-point>
-	utptr.64    %r109 <- (64) %arg1
-	ret.64      %r109
+	utptr.64    %r111 <- (64) %arg1
+	ret.64      %r111
 
 
 ulong_2_iptr:
 .L72:
 	<entry-point>
-	utptr.64    %r112 <- (64) %arg1
-	ret.64      %r112
+	utptr.64    %r114 <- (64) %arg1
+	ret.64      %r114
 
 
 vptr_2_iptr:
 .L74:
 	<entry-point>
-	ptrcast.64  %r115 <- (64) %arg1
-	ret.64      %r115
+	ptrcast.64  %r117 <- (64) %arg1
+	ret.64      %r117
 
 
 int_2_float:
 .L76:
 	<entry-point>
-	scvtf.32    %r118 <- (32) %arg1
-	ret.32      %r118
+	scvtf.32    %r120 <- (32) %arg1
+	ret.32      %r120
 
 
 uint_2_float:
 .L78:
 	<entry-point>
-	ucvtf.32    %r121 <- (32) %arg1
-	ret.32      %r121
+	ucvtf.32    %r123 <- (32) %arg1
+	ret.32      %r123
 
 
 long_2_float:
 .L80:
 	<entry-point>
-	scvtf.32    %r124 <- (64) %arg1
-	ret.32      %r124
+	scvtf.32    %r126 <- (64) %arg1
+	ret.32      %r126
 
 
 ulong_2_float:
 .L82:
 	<entry-point>
-	ucvtf.32    %r127 <- (64) %arg1
-	ret.32      %r127
+	ucvtf.32    %r129 <- (64) %arg1
+	ret.32      %r129
 
 
 double_2_float:
 .L84:
 	<entry-point>
-	fcvtf.32    %r130 <- (64) %arg1
-	ret.32      %r130
+	fcvtf.32    %r132 <- (64) %arg1
+	ret.32      %r132
 
 
 int_2_double:
 .L86:
 	<entry-point>
-	scvtf.64    %r133 <- (32) %arg1
-	ret.64      %r133
+	scvtf.64    %r135 <- (32) %arg1
+	ret.64      %r135
 
 
 uint_2_double:
 .L88:
 	<entry-point>
-	ucvtf.64    %r136 <- (32) %arg1
-	ret.64      %r136
+	ucvtf.64    %r138 <- (32) %arg1
+	ret.64      %r138
 
 
 long_2_double:
 .L90:
 	<entry-point>
-	scvtf.64    %r139 <- (64) %arg1
-	ret.64      %r139
+	scvtf.64    %r141 <- (64) %arg1
+	ret.64      %r141
 
 
 ulong_2_double:
 .L92:
 	<entry-point>
-	ucvtf.64    %r142 <- (64) %arg1
-	ret.64      %r142
+	ucvtf.64    %r144 <- (64) %arg1
+	ret.64      %r144
 
 
 float_2_double:
 .L94:
 	<entry-point>
-	fcvtf.64    %r145 <- (32) %arg1
-	ret.64      %r145
+	fcvtf.64    %r147 <- (32) %arg1
+	ret.64      %r147
 
 
 float_2_float:
-- 
2.14.0


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [RFC PATCH 14/14] cast: specialize integer casts
  2017-08-17  4:05 [RFC PATCH 00/14] rework of cast operations Luc Van Oostenryck
                   ` (12 preceding siblings ...)
  2017-08-17  4:05 ` [RFC PATCH 13/14] cast: make casts from pointer always size preserving Luc Van Oostenryck
@ 2017-08-17  4:05 ` Luc Van Oostenryck
  13 siblings, 0 replies; 16+ messages in thread
From: Luc Van Oostenryck @ 2017-08-17  4:05 UTC (permalink / raw)
  To: linux-sparse
  Cc: Linus Torvalds, Christopher Li, Dibyendu Majumdar,
	Luc Van Oostenryck

Aoo cast to unsigned integer and signed integer used to be
done with 2 instructions: OP_CAST & OP_SCAST.

Those are not very convenient as they don't reflect the real
operation that need to be done.
This patch specialize thises instruction in 4:
- OP_TRUNC, for casts to a smaller type
- OP_ZEXT,  for cast that need a zero extension
- OP_SEXT,  for cast that need a sign extension
Integer-to-integer casts of the same size are treated
as a NOP and in fact are never emitted.

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
 Documentation/IR.md                    |  11 +-
 cse.c                                  |   8 +-
 example.c                              |   9 +-
 linearize.c                            |  27 +++--
 linearize.h                            |   5 +-
 liveness.c                             |   4 +-
 simplify.c                             |  36 +++----
 sparse-llvm.c                          |  15 ++-
 sparse.c                               |   5 +-
 validation/bitfield-size.c             |   5 +-
 validation/builtin-bswap-variable.c    |   4 +-
 validation/cast-kinds-check.c          |   5 -
 validation/cast-kinds.c                | 179 ++++++++++++++++-----------------
 validation/cast-weirds.c               |   8 +-
 validation/compound-assign-type.c      |   3 +-
 validation/linear/bitfield-init-zero.c |   8 +-
 validation/memops-volatile.c           |   4 +-
 validation/optim/bool-simplify.c       |   4 +-
 18 files changed, 171 insertions(+), 169 deletions(-)

diff --git a/Documentation/IR.md b/Documentation/IR.md
index dcfd89bb6..e0299aba0 100644
--- a/Documentation/IR.md
+++ b/Documentation/IR.md
@@ -160,11 +160,14 @@ They all have the following signature:
 Currently, a cast to a void pointer is treated like a
 cast to an unsigned integer of the same size.
 
-### OP_CAST
-Cast to unsigned integer.
+### OP_TRUNC
+Cast from integer to an integer of a smaller size.
 
-### OP_SCAST
-Cast to signed integer.
+### OP_SEXT
+Cast from integer to an integer of a bigger size with sign extension.
+
+### OP_ZEXT
+Cast from integer to an integer of a bigger size with zero extension.
 
 ### OP_UTPTR
 Cast from pointer-sized unsigned integer to pointer type.
diff --git a/cse.c b/cse.c
index 166b7cda6..790e7b663 100644
--- a/cse.c
+++ b/cse.c
@@ -86,8 +86,8 @@ static void clean_up_one_instruction(struct basic_block *bb, struct instruction
 		hash += hashval(insn->symbol);
 		break;
 
-	case OP_CAST:
-	case OP_SCAST:
+	case OP_SEXT: case OP_ZEXT:
+	case OP_TRUNC:
 	case OP_PTRCAST:
 	case OP_UTPTR: case OP_PTRTU:
 		/*
@@ -231,8 +231,8 @@ static int insn_compare(const void *_i1, const void *_i2)
 	case OP_PHI:
 		return phi_list_compare(i1->phi_list, i2->phi_list);
 
-	case OP_CAST:
-	case OP_SCAST:
+	case OP_SEXT: case OP_ZEXT:
+	case OP_TRUNC:
 	case OP_PTRCAST:
 	case OP_UTPTR: case OP_PTRTU:
 		/*
diff --git a/example.c b/example.c
index 3a0ec0747..7192fc462 100644
--- a/example.c
+++ b/example.c
@@ -81,8 +81,9 @@ static const char *opcodes[] = {
 	[OP_PHI] = "phi",
 	[OP_PHISOURCE] = "phisrc",
 	[OP_COPY] = "copy",
-	[OP_CAST] = "cast",
-	[OP_SCAST] = "scast",
+	[OP_SEXT] = "sext",
+	[OP_ZEXT] = "zext",
+	[OP_TRUNC] = "trunc",
 	[OP_FCVTU] = "fcvtu",
 	[OP_FCVTS] = "fcvts",
 	[OP_UCVTF] = "ucvtf",
@@ -1426,7 +1427,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_PTRCAST:
+	case OP_SEXT: case OP_ZEXT:
+	case OP_TRUNC:
+	case OP_PTRCAST:
 	case OP_UTPTR:
 	case OP_PTRTU:
 	case OP_FCVTU: case OP_FCVTS:
diff --git a/linearize.c b/linearize.c
index 5d6cf7385..da33fe09b 100644
--- a/linearize.c
+++ b/linearize.c
@@ -228,8 +228,9 @@ static const char *opcodes[] = {
 	/* Other */
 	[OP_PHI] = "phi",
 	[OP_PHISOURCE] = "phisrc",
-	[OP_CAST] = "cast",
-	[OP_SCAST] = "scast",
+	[OP_SEXT] = "sext",
+	[OP_ZEXT] = "zext",
+	[OP_TRUNC] = "trunc",
 	[OP_FCVTU] = "fcvtu",
 	[OP_FCVTS] = "fcvts",
 	[OP_UCVTF] = "ucvtf",
@@ -429,8 +430,8 @@ const char *show_instruction(struct instruction *insn)
 		} END_FOR_EACH_PTR(arg);
 		break;
 	}
-	case OP_CAST:
-	case OP_SCAST:
+	case OP_SEXT: case OP_ZEXT:
+	case OP_TRUNC:
 	case OP_FCVTU: case OP_FCVTS:
 	case OP_UCVTF: case OP_SCVTF:
 	case OP_FCVTF:
@@ -1194,13 +1195,14 @@ static int get_cast_opcode(struct symbol *dst, struct symbol *src)
 		case MTYPE_PTR:
 		case MTYPE_VPTR:
 		case MTYPE_UINT:
-			return OP_CAST;
+			stype = MTYPE_UINT;
+			/* fall through */
 		case MTYPE_SINT:
-			return OP_SCAST;
+			break;
 		default:
 			return OP_BADOP;
-			break;
 		}
+		/* fall through */
 	case MTYPE_UINT:
 	case MTYPE_SINT:
 		switch (stype) {
@@ -1210,15 +1212,18 @@ static int get_cast_opcode(struct symbol *dst, struct symbol *src)
 			return OP_PTRTU;
 		case MTYPE_VPTR:
 		case MTYPE_UINT:
-			return OP_CAST;
 		case MTYPE_SINT:
-			return OP_SCAST;
+			if (dst->bit_size ==src->bit_size)
+				return OP_NOP;
+			if (dst->bit_size  < src->bit_size)
+				return OP_TRUNC;
+			return stype == MTYPE_SINT ? OP_SEXT : OP_ZEXT;
 		default:
-			break;
+			return OP_BADOP;
 		}
 		/* fall through */
 	default:
-		return OP_CAST;
+		return OP_BADOP;
 	}
 }
 
diff --git a/linearize.h b/linearize.h
index 165d2b579..5f2c94e86 100644
--- a/linearize.h
+++ b/linearize.h
@@ -196,8 +196,9 @@ enum opcode {
 	/* Other */
 	OP_PHI,
 	OP_PHISOURCE,
-	OP_CAST,
-	OP_SCAST,
+	OP_SEXT,
+	OP_ZEXT,
+	OP_TRUNC,
 	OP_FCVTU, OP_FCVTS,
 	OP_UCVTF, OP_SCVTF,
 	OP_FCVTF,
diff --git a/liveness.c b/liveness.c
index ef2030f3e..bf98bcca0 100644
--- a/liveness.c
+++ b/liveness.c
@@ -111,8 +111,8 @@ static void track_instruction_usage(struct basic_block *bb, struct instruction *
 		USES(phi_src);
 		break;
 
-	case OP_CAST:
-	case OP_SCAST:
+	case OP_SEXT: case OP_ZEXT:
+	case OP_TRUNC:
 	case OP_FCVTU: case OP_FCVTS:
 	case OP_UCVTF: case OP_SCVTF:
 	case OP_FCVTF:
diff --git a/simplify.c b/simplify.c
index 86512cc84..dcd29f427 100644
--- a/simplify.c
+++ b/simplify.c
@@ -236,8 +236,8 @@ void kill_insn(struct instruction *insn, int force)
 		kill_use(&insn->src2);
 		/* fall through */
 
-	case OP_CAST:
-	case OP_SCAST:
+	case OP_SEXT: case OP_ZEXT:
+	case OP_TRUNC:
 	case OP_FCVTU: case OP_FCVTS:
 	case OP_UCVTF: case OP_SCVTF:
 	case OP_FCVTF:
@@ -342,8 +342,8 @@ static int replace_with_pseudo(struct instruction *insn, pseudo_t pseudo)
 	case OP_NOT:
 	case OP_NEG:
 	case OP_SYMADDR:
-	case OP_CAST:
-	case OP_SCAST:
+	case OP_SEXT: case OP_ZEXT:
+	case OP_TRUNC:
 	case OP_FCVTU: case OP_FCVTS:
 	case OP_UCVTF: case OP_SCVTF:
 	case OP_FCVTF:
@@ -386,7 +386,7 @@ static unsigned int operand_size(struct instruction *insn, pseudo_t pseudo)
 
 	if (pseudo->type == PSEUDO_REG) {
 		struct instruction *src = pseudo->def;
-		if (src && src->opcode == OP_CAST && src->orig_type) {
+		if (src && src->opcode == OP_ZEXT && src->orig_type) {
 			unsigned int orig_size = src->orig_type->bit_size;
 			if (orig_size < size)
 				size = orig_size;
@@ -978,11 +978,14 @@ static int simplify_cast(struct instruction *insn)
 	}
 
 	if (size == orig_size) {
-		int op = (orig_type->ctype.modifiers & MOD_SIGNED) ? OP_SCAST : OP_CAST;
-		if (insn->opcode == op)
-			goto simplify;
-		if (insn->opcode == OP_FCVTF)
+		switch (insn->opcode) {
+		//case OP_NOPCAST:	// FIXME: what to do?
+		//case OP_PTRCAST:	// FIXME: what to do?
+		case OP_FCVTF:
 			goto simplify;
+		default:
+			break;
+		}
 	}
 
 	return 0;
@@ -1131,13 +1134,10 @@ static int simplify_branch(struct instruction *insn)
 				return REPEAT_CSE;
 			}
 		}
-		if (def->opcode == OP_CAST || def->opcode == OP_SCAST) {
-			int orig_size = def->orig_type ? def->orig_type->bit_size : 0;
-			if (def->size > orig_size) {
-				use_pseudo(insn, def->src, &insn->cond);
-				remove_usage(cond, &insn->cond);
-				return REPEAT_CSE;
-			}
+		if (def->opcode == OP_SEXT || def->opcode == OP_ZEXT) {
+			use_pseudo(insn, def->src, &insn->cond);
+			remove_usage(cond, &insn->cond);
+			return REPEAT_CSE;
 		}
 	}
 	return 0;
@@ -1207,8 +1207,8 @@ int simplify_instruction(struct instruction *insn)
 		if (dead_insn(insn, NULL, NULL, NULL))
 			return REPEAT_CSE | REPEAT_SYMBOL_CLEANUP;
 		return replace_with_pseudo(insn, insn->symbol);
-	case OP_CAST:
-	case OP_SCAST:
+	case OP_SEXT: case OP_ZEXT:
+	case OP_TRUNC:
 	case OP_FCVTU: case OP_FCVTS:
 	case OP_UCVTF: case OP_SCVTF:
 	case OP_FCVTF:
diff --git a/sparse-llvm.c b/sparse-llvm.c
index 8dd6a5185..debf0cb7a 100644
--- a/sparse-llvm.c
+++ b/sparse-llvm.c
@@ -790,13 +790,7 @@ static void output_op_cast(struct function *fn, struct instruction *insn, LLVMOp
 		src = pseudo_to_value(fn, insn, insn->src);
 
 	pseudo_name(insn->target, target_name);
-
-	assert(!symbol_is_fp_type(insn->type));
-
-	if (insn->size < LLVMGetIntTypeWidth(LLVMTypeOf(src)))
-		target = LLVMBuildTrunc(fn->builder, src, insn_symbol_type(fn->module, insn), target_name);
-	else
-		target = LLVMBuildCast(fn->builder, op, src, insn_symbol_type(fn->module, insn), target_name);
+	target = LLVMBuildCast(fn->builder, op, src, insn_symbol_type(fn->module, insn), target_name);
 
 	insn->target->priv = target;
 }
@@ -849,12 +843,15 @@ static void output_insn(struct function *fn, struct instruction *insn)
 	case OP_CALL:
 		output_op_call(fn, insn);
 		break;
-	case OP_CAST:
+	case OP_ZEXT:
 		output_op_cast(fn, insn, LLVMZExt);
 		break;
-	case OP_SCAST:
+	case OP_SEXT:
 		output_op_cast(fn, insn, LLVMSExt);
 		break;
+	case OP_TRUNC:
+		output_op_cast(fn, insn, LLVMTrunc);
+		break;
 	case OP_FCVTU: case OP_FCVTS:
 	case OP_UCVTF: case OP_SCVTF:
 	case OP_FCVTF:
diff --git a/sparse.c b/sparse.c
index bceacd94e..b4d14aeec 100644
--- a/sparse.c
+++ b/sparse.c
@@ -120,7 +120,7 @@ static void check_cast_instruction(struct instruction *insn)
 		int old = orig_type->bit_size;
 		int new = insn->size;
 		int oldsigned = (orig_type->ctype.modifiers & MOD_SIGNED) != 0;
-		int newsigned = insn->opcode == OP_SCAST;
+		int newsigned = insn->opcode == OP_SEXT;
 
 		if (new > old) {
 			if (oldsigned == newsigned)
@@ -214,7 +214,8 @@ static void check_call_instruction(struct instruction *insn)
 static void check_one_instruction(struct instruction *insn)
 {
 	switch (insn->opcode) {
-	case OP_CAST: case OP_SCAST:
+	case OP_SEXT: case OP_ZEXT:
+	case OP_TRUNC:
 		if (verbose)
 			check_cast_instruction(insn);
 		break;
diff --git a/validation/bitfield-size.c b/validation/bitfield-size.c
index ce78ecf21..c708a52db 100644
--- a/validation/bitfield-size.c
+++ b/validation/bitfield-size.c
@@ -35,7 +35,8 @@ unsigned int get_pbfi_b(struct bfi *bf) { return bf->b; }
  * check-command: test-linearize -Wno-decl $file
  * check-output-ignore
  *
- * check-output-pattern-24-times: cast\\.
- * check-output-pattern-12-times: cast\\.4
+ * check-output-pattern-8-times: zext\\.
+ * check-output-pattern-4-times: sext\\.
+ * check-output-pattern-12-times: trunc\\.4
  * check-output-pattern-6-times: lsr\\..*\\$6
  */
diff --git a/validation/builtin-bswap-variable.c b/validation/builtin-bswap-variable.c
index 738ba2a45..40ad64134 100644
--- a/validation/builtin-bswap-variable.c
+++ b/validation/builtin-bswap-variable.c
@@ -25,8 +25,8 @@ static u64 swap64v(u32 a)
  *
  * check-output-ignore
  * check-output-contains:call.16 .* __builtin_bswap16
- * check-output-contains:cast.32 .* (64) %arg1
+ * check-output-contains:trunc.32 .* (64) %arg1
  * check-output-contains:call.32 .* __builtin_bswap32
- * check-output-contains:cast.64 .* (32) %arg1
+ * check-output-contains:zext.64 .* (32) %arg1
  * check-output-contains:call.64 .* __builtin_bswap64
  */
diff --git a/validation/cast-kinds-check.c b/validation/cast-kinds-check.c
index fe0f83e24..4654dbda2 100644
--- a/validation/cast-kinds-check.c
+++ b/validation/cast-kinds-check.c
@@ -13,11 +13,6 @@ cast-kinds.c:12:48: warning: cast drops bits
 cast-kinds.c:13:50: warning: cast drops bits
 cast-kinds.c:14:49: warning: cast drops bits
 cast-kinds.c:15:48: warning: cast drops bits
-cast-kinds.c:21:49: warning: cast wasn't removed
-cast-kinds.c:28:52: warning: cast wasn't removed
-cast-kinds.c:34:52: warning: cast wasn't removed
-cast-kinds.c:35:54: warning: cast wasn't removed
-cast-kinds.c:36:52: warning: cast wasn't removed
 cast-kinds.c:37:42: warning: non size-preserving integer to pointer cast
 cast-kinds.c:38:44: warning: non size-preserving integer to pointer cast
  * check-error-end
diff --git a/validation/cast-kinds.c b/validation/cast-kinds.c
index 3ac95c3dc..7d977f91b 100644
--- a/validation/cast-kinds.c
+++ b/validation/cast-kinds.c
@@ -74,44 +74,44 @@ uint_2_int:
 long_2_int:
 .L2:
 	<entry-point>
-	scast.32    %r5 <- (64) %arg1
-	ret.32      %r5
+	trunc.32    %r4 <- (64) %arg1
+	ret.32      %r4
 
 
 ulong_2_int:
 .L4:
 	<entry-point>
-	cast.32     %r8 <- (64) %arg1
-	ret.32      %r8
+	trunc.32    %r7 <- (64) %arg1
+	ret.32      %r7
 
 
 vptr_2_int:
 .L6:
 	<entry-point>
-	cast.32     %r11 <- (64) %arg1
-	ret.32      %r11
+	trunc.32    %r10 <- (64) %arg1
+	ret.32      %r10
 
 
 iptr_2_int:
 .L8:
 	<entry-point>
-	ptrtu.64    %r14 <- (64) %arg1
-	cast.32     %r15 <- (64) %r14
-	ret.32      %r15
+	ptrtu.64    %r13 <- (64) %arg1
+	trunc.32    %r14 <- (64) %r13
+	ret.32      %r14
 
 
 float_2_int:
 .L10:
 	<entry-point>
-	fcvts.32    %r18 <- (32) %arg1
-	ret.32      %r18
+	fcvts.32    %r17 <- (32) %arg1
+	ret.32      %r17
 
 
 double_2_int:
 .L12:
 	<entry-point>
-	fcvts.32    %r21 <- (64) %arg1
-	ret.32      %r21
+	fcvts.32    %r20 <- (64) %arg1
+	ret.32      %r20
 
 
 int_2_uint:
@@ -123,58 +123,58 @@ int_2_uint:
 long_2_uint:
 .L16:
 	<entry-point>
-	scast.32    %r27 <- (64) %arg1
-	ret.32      %r27
+	trunc.32    %r25 <- (64) %arg1
+	ret.32      %r25
 
 
 ulong_2_uint:
 .L18:
 	<entry-point>
-	cast.32     %r30 <- (64) %arg1
-	ret.32      %r30
+	trunc.32    %r28 <- (64) %arg1
+	ret.32      %r28
 
 
 vptr_2_uint:
 .L20:
 	<entry-point>
-	cast.32     %r33 <- (64) %arg1
-	ret.32      %r33
+	trunc.32    %r31 <- (64) %arg1
+	ret.32      %r31
 
 
 iptr_2_uint:
 .L22:
 	<entry-point>
-	ptrtu.64    %r36 <- (64) %arg1
-	cast.32     %r37 <- (64) %r36
-	ret.32      %r37
+	ptrtu.64    %r34 <- (64) %arg1
+	trunc.32    %r35 <- (64) %r34
+	ret.32      %r35
 
 
 float_2_uint:
 .L24:
 	<entry-point>
-	fcvtu.32    %r40 <- (32) %arg1
-	ret.32      %r40
+	fcvtu.32    %r38 <- (32) %arg1
+	ret.32      %r38
 
 
 double_2_uint:
 .L26:
 	<entry-point>
-	fcvtu.32    %r43 <- (64) %arg1
-	ret.32      %r43
+	fcvtu.32    %r41 <- (64) %arg1
+	ret.32      %r41
 
 
 int_2_long:
 .L28:
 	<entry-point>
-	scast.64    %r46 <- (32) %arg1
-	ret.64      %r46
+	sext.64     %r44 <- (32) %arg1
+	ret.64      %r44
 
 
 uint_2_long:
 .L30:
 	<entry-point>
-	cast.64     %r49 <- (32) %arg1
-	ret.64      %r49
+	zext.64     %r47 <- (32) %arg1
+	ret.64      %r47
 
 
 ulong_2_long:
@@ -186,43 +186,42 @@ ulong_2_long:
 vptr_2_long:
 .L34:
 	<entry-point>
-	cast.64     %r55 <- (64) %arg1
-	ret.64      %r55
+	ret.64      %arg1
 
 
 iptr_2_long:
 .L36:
 	<entry-point>
-	ptrtu.64    %r58 <- (64) %arg1
-	ret.64      %r58
+	ptrtu.64    %r54 <- (64) %arg1
+	ret.64      %r54
 
 
 float_2_long:
 .L38:
 	<entry-point>
-	fcvts.64    %r61 <- (32) %arg1
-	ret.64      %r61
+	fcvts.64    %r57 <- (32) %arg1
+	ret.64      %r57
 
 
 double_2_long:
 .L40:
 	<entry-point>
-	fcvts.64    %r64 <- (64) %arg1
-	ret.64      %r64
+	fcvts.64    %r60 <- (64) %arg1
+	ret.64      %r60
 
 
 int_2_ulong:
 .L42:
 	<entry-point>
-	scast.64    %r67 <- (32) %arg1
-	ret.64      %r67
+	sext.64     %r63 <- (32) %arg1
+	ret.64      %r63
 
 
 uint_2_ulong:
 .L44:
 	<entry-point>
-	cast.64     %r70 <- (32) %arg1
-	ret.64      %r70
+	zext.64     %r66 <- (32) %arg1
+	ret.64      %r66
 
 
 long_2_ulong:
@@ -234,171 +233,167 @@ long_2_ulong:
 vptr_2_ulong:
 .L48:
 	<entry-point>
-	cast.64     %r76 <- (64) %arg1
-	ret.64      %r76
+	ret.64      %arg1
 
 
 iptr_2_ulong:
 .L50:
 	<entry-point>
-	ptrtu.64    %r79 <- (64) %arg1
-	ret.64      %r79
+	ptrtu.64    %r73 <- (64) %arg1
+	ret.64      %r73
 
 
 float_2_ulong:
 .L52:
 	<entry-point>
-	fcvtu.64    %r82 <- (32) %arg1
-	ret.64      %r82
+	fcvtu.64    %r76 <- (32) %arg1
+	ret.64      %r76
 
 
 double_2_ulong:
 .L54:
 	<entry-point>
-	fcvtu.64    %r85 <- (64) %arg1
-	ret.64      %r85
+	fcvtu.64    %r79 <- (64) %arg1
+	ret.64      %r79
 
 
 int_2_vptr:
 .L56:
 	<entry-point>
-	scast.64    %r88 <- (32) %arg1
-	ret.64      %r88
+	sext.64     %r82 <- (32) %arg1
+	ret.64      %r82
 
 
 uint_2_vptr:
 .L58:
 	<entry-point>
-	cast.64     %r91 <- (32) %arg1
-	ret.64      %r91
+	zext.64     %r85 <- (32) %arg1
+	ret.64      %r85
 
 
 long_2_vptr:
 .L60:
 	<entry-point>
-	scast.64    %r94 <- (64) %arg1
-	ret.64      %r94
+	ret.64      %arg1
 
 
 ulong_2_vptr:
 .L62:
 	<entry-point>
-	cast.64     %r97 <- (64) %arg1
-	ret.64      %r97
+	ret.64      %arg1
 
 
 iptr_2_vptr:
 .L64:
 	<entry-point>
-	cast.64     %r100 <- (64) %arg1
-	ret.64      %r100
+	ret.64      %arg1
 
 
 int_2_iptr:
 .L66:
 	<entry-point>
-	scast.64    %r103 <- (32) %arg1
-	utptr.64    %r104 <- (64) %r103
-	ret.64      %r104
+	sext.64     %r94 <- (32) %arg1
+	utptr.64    %r95 <- (64) %r94
+	ret.64      %r95
 
 
 uint_2_iptr:
 .L68:
 	<entry-point>
-	cast.64     %r107 <- (32) %arg1
-	utptr.64    %r108 <- (64) %r107
-	ret.64      %r108
+	zext.64     %r98 <- (32) %arg1
+	utptr.64    %r99 <- (64) %r98
+	ret.64      %r99
 
 
 long_2_iptr:
 .L70:
 	<entry-point>
-	utptr.64    %r111 <- (64) %arg1
-	ret.64      %r111
+	utptr.64    %r102 <- (64) %arg1
+	ret.64      %r102
 
 
 ulong_2_iptr:
 .L72:
 	<entry-point>
-	utptr.64    %r114 <- (64) %arg1
-	ret.64      %r114
+	utptr.64    %r105 <- (64) %arg1
+	ret.64      %r105
 
 
 vptr_2_iptr:
 .L74:
 	<entry-point>
-	ptrcast.64  %r117 <- (64) %arg1
-	ret.64      %r117
+	ptrcast.64  %r108 <- (64) %arg1
+	ret.64      %r108
 
 
 int_2_float:
 .L76:
 	<entry-point>
-	scvtf.32    %r120 <- (32) %arg1
-	ret.32      %r120
+	scvtf.32    %r111 <- (32) %arg1
+	ret.32      %r111
 
 
 uint_2_float:
 .L78:
 	<entry-point>
-	ucvtf.32    %r123 <- (32) %arg1
-	ret.32      %r123
+	ucvtf.32    %r114 <- (32) %arg1
+	ret.32      %r114
 
 
 long_2_float:
 .L80:
 	<entry-point>
-	scvtf.32    %r126 <- (64) %arg1
-	ret.32      %r126
+	scvtf.32    %r117 <- (64) %arg1
+	ret.32      %r117
 
 
 ulong_2_float:
 .L82:
 	<entry-point>
-	ucvtf.32    %r129 <- (64) %arg1
-	ret.32      %r129
+	ucvtf.32    %r120 <- (64) %arg1
+	ret.32      %r120
 
 
 double_2_float:
 .L84:
 	<entry-point>
-	fcvtf.32    %r132 <- (64) %arg1
-	ret.32      %r132
+	fcvtf.32    %r123 <- (64) %arg1
+	ret.32      %r123
 
 
 int_2_double:
 .L86:
 	<entry-point>
-	scvtf.64    %r135 <- (32) %arg1
-	ret.64      %r135
+	scvtf.64    %r126 <- (32) %arg1
+	ret.64      %r126
 
 
 uint_2_double:
 .L88:
 	<entry-point>
-	ucvtf.64    %r138 <- (32) %arg1
-	ret.64      %r138
+	ucvtf.64    %r129 <- (32) %arg1
+	ret.64      %r129
 
 
 long_2_double:
 .L90:
 	<entry-point>
-	scvtf.64    %r141 <- (64) %arg1
-	ret.64      %r141
+	scvtf.64    %r132 <- (64) %arg1
+	ret.64      %r132
 
 
 ulong_2_double:
 .L92:
 	<entry-point>
-	ucvtf.64    %r144 <- (64) %arg1
-	ret.64      %r144
+	ucvtf.64    %r135 <- (64) %arg1
+	ret.64      %r135
 
 
 float_2_double:
 .L94:
 	<entry-point>
-	fcvtf.64    %r147 <- (32) %arg1
-	ret.64      %r147
+	fcvtf.64    %r138 <- (32) %arg1
+	ret.64      %r138
 
 
 float_2_float:
diff --git a/validation/cast-weirds.c b/validation/cast-weirds.c
index 71e52ff57..a99c65d25 100644
--- a/validation/cast-weirds.c
+++ b/validation/cast-weirds.c
@@ -20,7 +20,7 @@ cast-weirds.c:5:44: warning: non size-preserving integer to pointer cast
 int_2_iptr:
 .L0:
 	<entry-point>
-	scast.64    %r2 <- (32) %arg1
+	sext.64     %r2 <- (32) %arg1
 	utptr.64    %r3 <- (64) %r2
 	ret.64      %r3
 
@@ -28,7 +28,7 @@ int_2_iptr:
 uint_2_iptr:
 .L2:
 	<entry-point>
-	cast.64     %r6 <- (32) %arg1
+	zext.64     %r6 <- (32) %arg1
 	utptr.64    %r7 <- (64) %r6
 	ret.64      %r7
 
@@ -36,14 +36,14 @@ uint_2_iptr:
 int_2_vptr:
 .L4:
 	<entry-point>
-	scast.64    %r10 <- (32) %arg1
+	sext.64     %r10 <- (32) %arg1
 	ret.64      %r10
 
 
 uint_2_vptr:
 .L6:
 	<entry-point>
-	cast.64     %r13 <- (32) %arg1
+	zext.64     %r13 <- (32) %arg1
 	ret.64      %r13
 
 
diff --git a/validation/compound-assign-type.c b/validation/compound-assign-type.c
index 450fa26d9..e13dcfcd2 100644
--- a/validation/compound-assign-type.c
+++ b/validation/compound-assign-type.c
@@ -11,5 +11,6 @@ static unsigned int foo(unsigned int x, long a)
  *
  * check-output-excludes: divu\\.32
  * check-output-contains: divs\\.64
- * check-output-contains: scast\\.32
+ * check-output-contains: zext.64 .* (32) %arg1
+ * check-output-contains: trunc.32 .* (64)
  */
diff --git a/validation/linear/bitfield-init-zero.c b/validation/linear/bitfield-init-zero.c
index 39a64345e..7a410a7c4 100644
--- a/validation/linear/bitfield-init-zero.c
+++ b/validation/linear/bitfield-init-zero.c
@@ -57,7 +57,7 @@ int bfs_get0(void)
 bfuu_init:
 .L0:
 	<entry-point>
-	cast.9      %r2 <- (32) %arg1
+	trunc.9     %r2 <- (32) %arg1
 	shl.32      %r4 <- %r2, $11
 	ret.32      %r4
 
@@ -65,7 +65,7 @@ bfuu_init:
 bfus_init:
 .L2:
 	<entry-point>
-	scast.9     %r10 <- (32) %arg1
+	trunc.9     %r10 <- (32) %arg1
 	shl.32      %r12 <- %r10, $11
 	ret.32      %r12
 
@@ -79,7 +79,7 @@ bfu_get0:
 bfsu_init:
 .L6:
 	<entry-point>
-	cast.9      %r23 <- (32) %arg1
+	trunc.9     %r23 <- (32) %arg1
 	shl.32      %r25 <- %r23, $11
 	ret.32      %r25
 
@@ -87,7 +87,7 @@ bfsu_init:
 bfss_init:
 .L8:
 	<entry-point>
-	scast.9     %r31 <- (32) %arg1
+	trunc.9     %r31 <- (32) %arg1
 	shl.32      %r33 <- %r31, $11
 	ret.32      %r33
 
diff --git a/validation/memops-volatile.c b/validation/memops-volatile.c
index 0f3e12ad2..3b8662f1e 100644
--- a/validation/memops-volatile.c
+++ b/validation/memops-volatile.c
@@ -13,8 +13,8 @@ foo:
 .L0:
 	<entry-point>
 	store.32    %arg2 -> 0[%arg1]
-	load.32     %r5 <- 0[%arg1]
-	ret.32      %r5
+	load.32     %r4 <- 0[%arg1]
+	ret.32      %r4
 
 
  * check-output-end
diff --git a/validation/optim/bool-simplify.c b/validation/optim/bool-simplify.c
index 05be11497..5b3cf449e 100644
--- a/validation/optim/bool-simplify.c
+++ b/validation/optim/bool-simplify.c
@@ -33,7 +33,7 @@ and_1:
 .L2:
 	<entry-point>
 	setne.1     %r8 <- %arg1, $0
-	cast.32     %r11 <- (1) %r8
+	zext.32     %r11 <- (1) %r8
 	ret.32      %r11
 
 
@@ -41,7 +41,7 @@ or_0:
 .L4:
 	<entry-point>
 	setne.1     %r14 <- %arg1, $0
-	cast.32     %r17 <- (1) %r14
+	zext.32     %r17 <- (1) %r14
 	ret.32      %r17
 
 
-- 
2.14.0


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: [RFC PATCH 01/14] add documentation for IR instructions
  2017-08-17  4:05 ` [RFC PATCH 01/14] add documentation for IR instructions Luc Van Oostenryck
@ 2017-08-21 12:18   ` Christopher Li
  0 siblings, 0 replies; 16+ messages in thread
From: Christopher Li @ 2017-08-21 12:18 UTC (permalink / raw)
  To: Luc Van Oostenryck; +Cc: Linux-Sparse, Linus Torvalds, Dibyendu Majumdar

On Thu, Aug 17, 2017 at 12:05 AM, Luc Van Oostenryck
<luc.vanoostenryck@gmail.com> wrote:
> Until now the 'instructions' used for spare's IR are
> not at all documented.
>
> This patch is a fist step toward having these instructions
> properly documented.

Yes, the sparse doucment is lacking.

This is great.

Thanks you.

Chris

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2017-08-21 12:18 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-08-17  4:05 [RFC PATCH 00/14] rework of cast operations Luc Van Oostenryck
2017-08-17  4:05 ` [RFC PATCH 01/14] add documentation for IR instructions Luc Van Oostenryck
2017-08-21 12:18   ` Christopher Li
2017-08-17  4:05 ` [RFC PATCH 02/14] cast: add tests for warnings issued by sparse -v Luc Van Oostenryck
2017-08-17  4:05 ` [RFC PATCH 03/14] cast: prepare finer grained cast instructions Luc Van Oostenryck
2017-08-17  4:05 ` [RFC PATCH 04/14] cast: specialize FPCAST into [USF]CVTF Luc Van Oostenryck
2017-08-17  4:05 ` [RFC PATCH 05/14] cast: handle NO-OP casts Luc Van Oostenryck
2017-08-17  4:05 ` [RFC PATCH 06/14] cast: specialize floats to integer conversion Luc Van Oostenryck
2017-08-17  4:05 ` [RFC PATCH 07/14] cast: specialize casts from unsigned to pointers Luc Van Oostenryck
2017-08-17  4:05 ` [RFC PATCH 08/14] cast: make [u]intptr_ctype alias of [s]size_t_ctype Luc Van Oostenryck
2017-08-17  4:05 ` [RFC PATCH 09/14] cast: make pointer casts always size preserving Luc Van Oostenryck
2017-08-17  4:05 ` [RFC PATCH 10/14] cast: temporary simplify handling cast to/from void* Luc Van Oostenryck
2017-08-17  4:05 ` [RFC PATCH 11/14] cast: specialize cast from pointers Luc Van Oostenryck
2017-08-17  4:05 ` [RFC PATCH 12/14] cast: add support for -Wpointer-to-int-cast Luc Van Oostenryck
2017-08-17  4:05 ` [RFC PATCH 13/14] cast: make casts from pointer always size preserving Luc Van Oostenryck
2017-08-17  4:05 ` [RFC PATCH 14/14] cast: specialize integer casts Luc Van Oostenryck

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).