From 18d0f77a30506e71e804751d4e987749c9bcb068 Mon Sep 17 00:00:00 2001 From: Michael Beck Date: Thu, 6 Dec 2007 17:05:18 +0000 Subject: [PATCH] Fully implemented __assume() [r18627] --- ast2firm.c | 148 ++++++++++++++++++++++++++++++++++++++++++++--------- ast_t.h | 11 ++-- parser.c | 16 ++++++ 3 files changed, 145 insertions(+), 30 deletions(-) diff --git a/ast2firm.c b/ast2firm.c index 2ef79c6..7686794 100644 --- a/ast2firm.c +++ b/ast2firm.c @@ -1287,6 +1287,119 @@ static ir_node *create_incdec(const unary_expression_t *expression) } } +static bool is_local_variable(expression_t *expression) +{ + if (expression->type != EXPR_REFERENCE) + return false; + reference_expression_t *ref_expr = &expression->reference; + declaration_t *declaration = ref_expr->declaration; + return declaration->declaration_type == DECLARATION_TYPE_LOCAL_VARIABLE; +} + +static long get_pnc(const expression_type_t type) +{ + switch(type) { + case EXPR_BINARY_EQUAL: return pn_Cmp_Eq; + case EXPR_BINARY_ISLESSGREATER: return pn_Cmp_Lg; + case EXPR_BINARY_NOTEQUAL: return pn_Cmp_Ne; + case EXPR_BINARY_ISLESS: + case EXPR_BINARY_LESS: return pn_Cmp_Lt; + case EXPR_BINARY_ISLESSEQUAL: + case EXPR_BINARY_LESSEQUAL: return pn_Cmp_Le; + case EXPR_BINARY_ISGREATER: + case EXPR_BINARY_GREATER: return pn_Cmp_Gt; + case EXPR_BINARY_ISGREATEREQUAL: + case EXPR_BINARY_GREATEREQUAL: return pn_Cmp_Ge; + case EXPR_BINARY_ISUNORDERED: return pn_Cmp_Uo; + + default: + break; + } + panic("trying to get pn_Cmp from non-comparison binexpr type"); +} + +/** + * Handle the assume optimizer hint: check if a Confirm + * node can be created. + * + * @param dbi debug info + * @param expr the IL assume expression + * + * we support here only some simple cases: + * - var rel const + * - const rel val + * - var rel var + */ +static ir_node *handle_assume_compare(dbg_info *dbi, const binary_expression_t *expression) +{ + expression_t *op1 = expression->left; + expression_t *op2 = expression->right; + expression_t *con; + declaration_t *var2, *var = NULL; + ir_node *res = NULL; + pn_Cmp cmp_val; + + cmp_val = get_pnc(expression->expression.type); + + if (is_local_variable(op1) && is_local_variable(op2)) { + var = op1->reference.declaration; + var2 = op2->reference.declaration; + + type_t *type = skip_typeref(var->type); + ir_mode *const mode = get_ir_mode(type); + + ir_node *irn1 = get_value(var->v.value_number, mode); + ir_node *irn2 = get_value(var2->v.value_number, mode); + + res = new_d_Confirm(dbi, irn2, irn1, get_inversed_pnc(cmp_val)); + set_value(var2->v.value_number, res); + + res = new_d_Confirm(dbi, irn1, irn2, cmp_val); + set_value(var->v.value_number, res); + + return res; + } + + if (is_local_variable(op1) && is_constant_expression(op2)) { + var = op1->reference.declaration; + con = op2; + } else if (is_constant_expression(op1) && is_local_variable(op2)) { + cmp_val = get_inversed_pnc(cmp_val); + var = op2->reference.declaration; + con = op1; + } + + if (var != NULL) { + type_t *type = skip_typeref(var->type); + ir_mode *const mode = get_ir_mode(type); + + res = get_value(var->v.value_number, mode); + res = new_d_Confirm(dbi, res, expression_to_firm(con), cmp_val); + set_value(var->v.value_number, res); + } + return res; +} + +/** + * Handle the assume optimizer hint. + * + * @param dbi debug info + * @param expr the IL assume expression + */ +static ir_node *handle_assume(dbg_info *dbi, const expression_t *expression) { + switch(expression->type) { + case EXPR_BINARY_EQUAL: + case EXPR_BINARY_NOTEQUAL: + case EXPR_BINARY_LESS: + case EXPR_BINARY_LESSEQUAL: + case EXPR_BINARY_GREATER: + case EXPR_BINARY_GREATEREQUAL: + return handle_assume_compare(dbi, &expression->binary); + default: + return NULL; + } +} + static ir_node *unary_expression_to_firm(const unary_expression_t *expression) { dbg_info *dbgi = get_dbg_info(&expression->expression.source_position); @@ -1295,21 +1408,23 @@ static ir_node *unary_expression_to_firm(const unary_expression_t *expression) if(expression->expression.type == EXPR_UNARY_TAKE_ADDRESS) return expression_to_addr(expression->value); - const expression_t *value = expression->value; - ir_node *value_node = expression_to_firm(value); + const expression_t *value = expression->value; switch(expression->expression.type) { case EXPR_UNARY_NEGATE: { + ir_node *value_node = expression_to_firm(value); ir_mode *mode = get_ir_mode(type); return new_d_Minus(dbgi, value_node, mode); } case EXPR_UNARY_PLUS: - return value_node; + return expression_to_firm(value); case EXPR_UNARY_BITWISE_NEGATE: { + ir_node *value_node = expression_to_firm(value); ir_mode *mode = get_ir_mode(type); return new_d_Not(dbgi, value_node, mode); } case EXPR_UNARY_NOT: { + ir_node *value_node = expression_to_firm(value); ir_mode *mode = get_ir_mode(type); if(get_irn_mode(value_node) != mode_b) { value_node = create_conv(dbgi, value_node, mode_b); @@ -1321,6 +1436,7 @@ static ir_node *unary_expression_to_firm(const unary_expression_t *expression) return value_node; } case EXPR_UNARY_DEREFERENCE: { + ir_node *value_node = expression_to_firm(value); type_t *value_type = skip_typeref(value->base.datatype); ir_type *irtype = get_ir_type(value_type); assert(is_Pointer_type(irtype)); @@ -1333,15 +1449,19 @@ static ir_node *unary_expression_to_firm(const unary_expression_t *expression) case EXPR_UNARY_PREFIX_DECREMENT: return create_incdec(expression); case EXPR_UNARY_CAST: { + ir_node *value_node = expression_to_firm(value); ir_mode *mode = get_ir_mode(type); ir_node *node = create_conv(dbgi, value_node, mode); node = do_strict_conv(dbgi, node); return node; } case EXPR_UNARY_CAST_IMPLICIT: { + ir_node *value_node = expression_to_firm(value); ir_mode *mode = get_ir_mode(type); return create_conv(dbgi, value_node, mode); } + case EXPR_UNARY_ASSUME: + return handle_assume(dbgi, value); default: break; @@ -1349,28 +1469,6 @@ static ir_node *unary_expression_to_firm(const unary_expression_t *expression) panic("invalid UNEXPR type found"); } -static long get_pnc(const expression_type_t type) -{ - switch(type) { - case EXPR_BINARY_EQUAL: return pn_Cmp_Eq; - case EXPR_BINARY_ISLESSGREATER: return pn_Cmp_Lg; - case EXPR_BINARY_NOTEQUAL: return pn_Cmp_Ne; - case EXPR_BINARY_ISLESS: - case EXPR_BINARY_LESS: return pn_Cmp_Lt; - case EXPR_BINARY_ISLESSEQUAL: - case EXPR_BINARY_LESSEQUAL: return pn_Cmp_Le; - case EXPR_BINARY_ISGREATER: - case EXPR_BINARY_GREATER: return pn_Cmp_Gt; - case EXPR_BINARY_ISGREATEREQUAL: - case EXPR_BINARY_GREATEREQUAL: return pn_Cmp_Ge; - case EXPR_BINARY_ISUNORDERED: return pn_Cmp_Uo; - - default: - break; - } - panic("trying to get pn_Cmp from non-comparison binexpr type"); -} - static ir_node *create_lazy_op(const binary_expression_t *expression) { dbg_info *dbgi = get_dbg_info(&expression->expression.source_position); diff --git a/ast_t.h b/ast_t.h index 0f5f420..bd7d3e9 100644 --- a/ast_t.h +++ b/ast_t.h @@ -389,12 +389,13 @@ struct declaration_t { /** next declaration with same symbol */ declaration_t *symbol_next; - unsigned char declaration_type; /* used in ast2firm module */ + /* the following fields are used in ast2firm module */ + unsigned char declaration_type; union { - unsigned int value_number; /* used in ast2firm module */ - ir_entity *entity; /* used in ast2firm module */ - ir_node *block; /* used in ast2firm module */ - tarval *enum_val; /* used in ast2firm module */ + unsigned int value_number; + ir_entity *entity; + ir_node *block; + tarval *enum_val; } v; }; diff --git a/parser.c b/parser.c index e7be7bc..8e2df70 100644 --- a/parser.c +++ b/parser.c @@ -3399,6 +3399,20 @@ static expression_t *parse_builtin_expect(void) return expression; } +static expression_t *parse_assume(void) { + eat(T_assume); + + expression_t *expression + = allocate_expression_zero(EXPR_UNARY_ASSUME); + + expect('('); + expression->unary.value = parse_expression(); + expect(')'); + + expression->base.datatype = type_void; + return expression; +} + static expression_t *parse_primary_expression(void) { switch(token.type) { @@ -3436,6 +3450,8 @@ static expression_t *parse_primary_expression(void) case T___builtin_islessgreater: case T___builtin_isunordered: return parse_compare_builtin(); + case T_assume: + return parse_assume(); case '(': return parse_brace_expression(); -- 2.20.1