diff options
| author | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2017-08-14 15:05:24 +0200 |
|---|---|---|
| committer | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2018-06-23 07:46:40 +0200 |
| commit | 52856c815a191b73530557133bd44ec478f3fece (patch) | |
| tree | 453cf39d9723ab4435b4d7b871317b502d4e8058 | |
| parent | 55cac5336b14524ebc371bcee006e2b497d84c5f (diff) | |
| download | sparse-dev-52856c815a191b73530557133bd44ec478f3fece.tar.gz | |
cast: specialize floats to integer conversion
Currently, casts from floats to integers are processed like
integers (or any other type) to integers. This is simple but
rather unconvenient as it correspond to different operations
that obeys to different rules and which later need extra checks.
Change this by directly using specific instructions:
- FCVTU for floats to unsigned integers
- FCVTS for floats to signed integers
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
| -rw-r--r-- | Documentation/IR.rst | 6 | ||||
| -rw-r--r-- | example.c | 3 | ||||
| -rw-r--r-- | linearize.c | 5 | ||||
| -rw-r--r-- | linearize.h | 1 | ||||
| -rw-r--r-- | simplify.c | 1 | ||||
| -rw-r--r-- | sparse-llvm.c | 8 | ||||
| -rw-r--r-- | validation/cast-kinds-check.c | 3 | ||||
| -rw-r--r-- | validation/linear/bool-cast.c | 1 | ||||
| -rw-r--r-- | validation/linear/cast-kinds.c | 16 | ||||
| -rw-r--r-- | validation/linear/fp2i-cast.c | 3 | ||||
| -rw-r--r-- | validation/optim/kill-casts.c | 1 |
11 files changed, 35 insertions, 13 deletions
diff --git a/Documentation/IR.rst b/Documentation/IR.rst index 38683a73..5b9155f7 100644 --- a/Documentation/IR.rst +++ b/Documentation/IR.rst @@ -273,6 +273,12 @@ They all have the following signature: .. op:: OP_PTRCAST Cast to pointer. +.. op:: OP_FCVTU + Conversion from float type to unsigned integer. + +.. op:: OP_FCVTS + Conversion from float type to signed integer. + .. op:: OP_UCVTF Conversion from unsigned integer to float type. @@ -76,6 +76,8 @@ static const char *opcodes[] = { [OP_COPY] = "copy", [OP_CAST] = "cast", [OP_SCAST] = "scast", + [OP_FCVTU] = "fcvtu", + [OP_FCVTS] = "fcvts", [OP_UCVTF] = "ucvtf", [OP_SCVTF] = "scvtf", [OP_FCVTF] = "fcvtf", @@ -1412,6 +1414,7 @@ static void generate_one_insn(struct instruction *insn, struct bb_state *state) break; case OP_CAST: case OP_SCAST: case OP_PTRCAST: + case OP_FCVTU: case OP_FCVTS: case OP_UCVTF: case OP_SCVTF: case OP_FCVTF: generate_cast(state, insn); diff --git a/linearize.c b/linearize.c index e16d392c..a7d2b068 100644 --- a/linearize.c +++ b/linearize.c @@ -263,6 +263,8 @@ static const char *opcodes[] = { [OP_PHISOURCE] = "phisrc", [OP_CAST] = "cast", [OP_SCAST] = "scast", + [OP_FCVTU] = "fcvtu", + [OP_FCVTS] = "fcvts", [OP_UCVTF] = "ucvtf", [OP_SCVTF] = "scvtf", [OP_FCVTF] = "fcvtf", @@ -447,6 +449,7 @@ const char *show_instruction(struct instruction *insn) } case OP_CAST: case OP_SCAST: + case OP_FCVTU: case OP_FCVTS: case OP_UCVTF: case OP_SCVTF: case OP_FCVTF: case OP_PTRCAST: @@ -1222,6 +1225,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 290600a1..b513d549 100644 --- a/linearize.h +++ b/linearize.h @@ -223,6 +223,7 @@ enum opcode { /* Casts */ OP_CAST, OP_SCAST, + OP_FCVTU, OP_FCVTS, OP_UCVTF, OP_SCVTF, OP_FCVTF, OP_PTRCAST, @@ -1220,6 +1220,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 3e2ac498..75cac8f9 100644 --- a/sparse-llvm.c +++ b/sparse-llvm.c @@ -918,7 +918,7 @@ static void output_op_cast(struct function *fn, struct instruction *insn, LLVMOp if (is_ptr_type(otype)) { op = LLVMPtrToInt; } else if (is_float_type(otype)) { - op = (op == LLVMZExt) ? LLVMFPToUI : LLVMFPToSI; + assert(op == LLVMFPToUI || op == LLVMFPToSI); } else if (is_int_type(otype)) { unsigned int width = otype->bit_size; if (insn->size < width) @@ -1035,6 +1035,12 @@ static void output_insn(struct function *fn, struct instruction *insn) case OP_SCAST: output_op_cast(fn, insn, LLVMSExt); break; + case OP_FCVTU: + output_op_cast(fn, insn, LLVMFPToUI); + break; + case OP_FCVTS: + output_op_cast(fn, insn, LLVMFPToSI); + break; case OP_UCVTF: case OP_SCVTF: case OP_FCVTF: output_op_fpcast(fn, insn); diff --git a/validation/cast-kinds-check.c b/validation/cast-kinds-check.c index b8e94840..1f10e0ec 100644 --- a/validation/cast-kinds-check.c +++ b/validation/cast-kinds-check.c @@ -3,19 +3,16 @@ /* * check-name: cast-kinds check * check-command: sparse -m64 -v $file - * check-known-to-fail * * check-error-start linear/cast-kinds.c:5:45: warning: cast drops bits linear/cast-kinds.c:6:47: warning: cast drops bits linear/cast-kinds.c:7:46: warning: cast drops bits linear/cast-kinds.c:8:45: warning: cast drops bits -linear/cast-kinds.c:10:49: warning: cast drops bits linear/cast-kinds.c:12:48: warning: cast drops bits linear/cast-kinds.c:13:50: warning: cast drops bits linear/cast-kinds.c:14:49: warning: cast drops bits linear/cast-kinds.c:15:48: warning: cast drops bits -linear/cast-kinds.c:17:52: warning: cast drops bits linear/cast-kinds.c:21:49: warning: cast wasn't removed linear/cast-kinds.c:22:48: warning: cast wasn't removed linear/cast-kinds.c:28:52: warning: cast wasn't removed diff --git a/validation/linear/bool-cast.c b/validation/linear/bool-cast.c index 981e9f83..094f4438 100644 --- a/validation/linear/bool-cast.c +++ b/validation/linear/bool-cast.c @@ -27,6 +27,7 @@ static _Bool fdbl_e(dbl a) { return (_Bool)a; } * * check-output-ignore * check-output-excludes: cast\\. + * check-output-excludes: fcvt[us]\\. * check-output-pattern(12): setne\\. * check-output-pattern(2): fcmpune\\. */ diff --git a/validation/linear/cast-kinds.c b/validation/linear/cast-kinds.c index 5944610c..d07a9419 100644 --- a/validation/linear/cast-kinds.c +++ b/validation/linear/cast-kinds.c @@ -95,14 +95,14 @@ iptr_2_int: float_2_int: .L10: <entry-point> - cast.32 %r17 <- (32) %arg1 + fcvts.32 %r17 <- (32) %arg1 ret.32 %r17 double_2_int: .L12: <entry-point> - cast.32 %r20 <- (64) %arg1 + fcvts.32 %r20 <- (64) %arg1 ret.32 %r20 @@ -143,14 +143,14 @@ iptr_2_uint: float_2_uint: .L24: <entry-point> - cast.32 %r38 <- (32) %arg1 + fcvtu.32 %r38 <- (32) %arg1 ret.32 %r38 double_2_uint: .L26: <entry-point> - cast.32 %r41 <- (64) %arg1 + fcvtu.32 %r41 <- (64) %arg1 ret.32 %r41 @@ -191,14 +191,14 @@ iptr_2_long: float_2_long: .L38: <entry-point> - cast.64 %r59 <- (32) %arg1 + fcvts.64 %r59 <- (32) %arg1 ret.64 %r59 double_2_long: .L40: <entry-point> - cast.64 %r62 <- (64) %arg1 + fcvts.64 %r62 <- (64) %arg1 ret.64 %r62 @@ -239,14 +239,14 @@ iptr_2_ulong: float_2_ulong: .L52: <entry-point> - cast.64 %r80 <- (32) %arg1 + fcvtu.64 %r80 <- (32) %arg1 ret.64 %r80 double_2_ulong: .L54: <entry-point> - cast.64 %r83 <- (64) %arg1 + fcvtu.64 %r83 <- (64) %arg1 ret.64 %r83 diff --git a/validation/linear/fp2i-cast.c b/validation/linear/fp2i-cast.c index 98d7453e..c85c4ccd 100644 --- a/validation/linear/fp2i-cast.c +++ b/validation/linear/fp2i-cast.c @@ -26,5 +26,6 @@ ul d2ul(double a) { return a; } * check-command: test-linearize -Wno-decl $file * * check-output-ignore - * check-output-pattern(8): cast\\. + * check-output-pattern(4): fcvts\\. + * check-output-pattern(4): fcvtu\\. */ diff --git a/validation/optim/kill-casts.c b/validation/optim/kill-casts.c index cf52f246..b79335ab 100644 --- a/validation/optim/kill-casts.c +++ b/validation/optim/kill-casts.c @@ -19,4 +19,5 @@ void foo(struct s *x) * * check-output-ignore * check-output-excludes: cast\\. + * check-output-excludes: fcvt[us]\\. */ |
