diff options
author | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2020-11-01 07:09:11 +0100 |
---|---|---|
committer | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2020-11-01 07:09:11 +0100 |
commit | f680124b794b246c8a20f2cb54b2fc7ff989625d (patch) | |
tree | f480814f46fbfc9f462a1221a120ec8e406f41cb | |
parent | 0c7b00977c8826b1cd172f7e90ad14e980190467 (diff) | |
parent | 226b62bc2ee4779447ce788d83aa0b409e384ec8 (diff) | |
download | sparse-f680124b794b246c8a20f2cb54b2fc7ff989625d.tar.gz |
Merge branch 'typed-cmp'
* give an explicit type to compare's operands
-rw-r--r-- | Documentation/IR.rst | 1 | ||||
-rw-r--r-- | linearize.c | 16 | ||||
-rw-r--r-- | linearize.h | 4 | ||||
-rw-r--r-- | simplify.c | 14 | ||||
-rw-r--r-- | validation/optim/cmp-op-type.c | 18 | ||||
-rw-r--r-- | validation/optim/cmp-type0.c | 12 | ||||
-rw-r--r-- | validation/optim/cmp-type1.c | 15 |
7 files changed, 75 insertions, 5 deletions
diff --git a/Documentation/IR.rst b/Documentation/IR.rst index ff5af1c5..6330ee9c 100644 --- a/Documentation/IR.rst +++ b/Documentation/IR.rst @@ -134,6 +134,7 @@ 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 + * .itype: type of the input operands .. op:: OP_SET_EQ Compare equal. diff --git a/linearize.c b/linearize.c index def6cf34..c1e3455a 100644 --- a/linearize.c +++ b/linearize.c @@ -1080,6 +1080,13 @@ static pseudo_t add_binary_op(struct entrypoint *ep, struct symbol *ctype, int o return target; } +static pseudo_t add_cmp_op(struct entrypoint *ep, struct symbol *ctype, int op, struct symbol *itype, pseudo_t left, pseudo_t right) +{ + pseudo_t target = add_binary_op(ep, ctype, op, left, right); + target->def->itype = itype; + return target; +} + static pseudo_t add_setval(struct entrypoint *ep, struct symbol *ctype, struct expression *val) { struct instruction *insn = alloc_typed_instruction(OP_SETVAL, ctype); @@ -1217,7 +1224,7 @@ static pseudo_t linearize_regular_preop(struct entrypoint *ep, struct expression return pre; case '!': { pseudo_t zero = value_pseudo(0); - return add_binary_op(ep, ctype, OP_SET_EQ, pre, zero); + return add_cmp_op(ep, ctype, OP_SET_EQ, expr->unop->ctype, pre, zero); } case '~': return add_unop(ep, ctype, OP_NOT, pre); @@ -1444,7 +1451,7 @@ static inline pseudo_t add_convert_to_bool(struct entrypoint *ep, pseudo_t src, zero = value_pseudo(0); op = OP_SET_NE; } - return add_binary_op(ep, &bool_ctype, op, src, zero); + return add_cmp_op(ep, &bool_ctype, op, type, src, zero); } static pseudo_t linearize_expression_to_bool(struct entrypoint *ep, struct expression *expr) @@ -1773,10 +1780,11 @@ static pseudo_t linearize_compare(struct entrypoint *ep, struct expression *expr [SPECIAL_UNSIGNED_LTE] = OP_SET_BE, [SPECIAL_UNSIGNED_GTE] = OP_SET_AE, }; - int op = opcode_float(cmpop[expr->op], expr->right->ctype); + struct symbol *itype = expr->right->ctype; + int op = opcode_float(cmpop[expr->op], itype); pseudo_t src1 = linearize_expression(ep, expr->left); pseudo_t src2 = linearize_expression(ep, expr->right); - pseudo_t dst = add_binary_op(ep, expr->ctype, op, src1, src2); + pseudo_t dst = add_cmp_op(ep, expr->ctype, op, itype, src1, src2); return dst; } diff --git a/linearize.h b/linearize.h index 57fe2035..77ae7c9a 100644 --- a/linearize.h +++ b/linearize.h @@ -123,6 +123,10 @@ struct instruction { struct /* binops and sel */ { pseudo_t src1, src2, src3; }; + struct /* compare */ { + pseudo_t _src1, _src2; // alias .src[12] + struct symbol *itype; // input operands' type + }; struct /* slice */ { pseudo_t base; unsigned from, len; @@ -635,6 +635,11 @@ static pseudo_t eval_op(int op, unsigned size, pseudo_t src1, pseudo_t src2) default: return NULL; } + + // Warning: this should be done with the output size which may + // be different than the input size used here. But it differs + // only for compares which are not concerned since only returning + // 0 or 1 and for casts which are not handled here. res &= bits; return value_pseudo(res); @@ -767,7 +772,11 @@ static int simplify_mask_shift(struct instruction *sh, unsigned long long mask) static pseudo_t eval_insn(struct instruction *insn) { - return eval_op(insn->opcode, insn->size, insn->src1, insn->src2); + unsigned size = insn->size; + + if (opcode_table[insn->opcode].flags & OPF_COMPARE) + size = insn->itype->bit_size; + return eval_op(insn->opcode, size, insn->src1, insn->src2); } static long long check_shift_count(struct instruction *insn, unsigned long long uval) @@ -1009,6 +1018,7 @@ static int simplify_seteq_setne(struct instruction *insn, long long value) // setcc.m %r <- %a, $b // and similar for setne/eq ... 0/1 insn->opcode = inverse ? opcode_table[opcode].negate : opcode; + insn->itype = def->itype; use_pseudo(insn, def->src1, &insn->src1); use_pseudo(insn, def->src2, &insn->src2); remove_usage(old, &insn->src1); @@ -1025,6 +1035,7 @@ static int simplify_seteq_setne(struct instruction *insn, long long value) // into: // setne.1 %s <- %a, $0 // and same for setne/eq ... 0/1 + insn->itype = def->orig_type; return replace_pseudo(insn, &insn->src1, def->src); case OP_TRUNC: if (!one_use(old)) @@ -1671,6 +1682,7 @@ static int simplify_cast(struct instruction *insn) // setcc.m %r <- %a, %b // and same for s/zext/trunc/ insn->opcode = def->opcode; + insn->itype = def->itype; use_pseudo(insn, def->src2, &insn->src2); return replace_pseudo(insn, &insn->src1, def->src1); } diff --git a/validation/optim/cmp-op-type.c b/validation/optim/cmp-op-type.c new file mode 100644 index 00000000..037272f8 --- /dev/null +++ b/validation/optim/cmp-op-type.c @@ -0,0 +1,18 @@ +extern int get(void); + +static int array[8192]; + +static int foo(void) +{ + int n = -1; + if (n < 0) + n = get(); + return array[n]; +} + +/* + * check-name: cmp-op-type + * check-command: test-linearize -Wno-decl $file + * + * check-output-ignore + */ diff --git a/validation/optim/cmp-type0.c b/validation/optim/cmp-type0.c new file mode 100644 index 00000000..15115b9f --- /dev/null +++ b/validation/optim/cmp-type0.c @@ -0,0 +1,12 @@ +static int foo(long long a) +{ + return 0LL < (0x80000000LL + (a - a)); +} + +/* + * check-name: cmp-type0 + * check-command: test-linearize $file + * + * check-output-ignore + * check-output-returns: 1 + */ diff --git a/validation/optim/cmp-type1.c b/validation/optim/cmp-type1.c new file mode 100644 index 00000000..6df6376b --- /dev/null +++ b/validation/optim/cmp-type1.c @@ -0,0 +1,15 @@ +int foo(void) +{ + int r; + long n; + n = 0; + return n < 2147483648U; +} + +/* + * check-name: cmp-type1 + * check-command: test-linearize -Wno-decl $file + * + * check-output-ignore + * check-output-returns: 1 + */ |