+static bool is_local_variable(expression_t *expression)
+{
+ if (expression->kind != EXPR_REFERENCE)
+ return false;
+ reference_expression_t *ref_expr = &expression->reference;
+ declaration_t *declaration = ref_expr->declaration;
+ return declaration->declaration_kind == DECLARATION_KIND_LOCAL_VARIABLE;
+}
+
+static pn_Cmp get_pnc(const expression_kind_t kind, type_t *const type)
+{
+ switch(kind) {
+ case EXPR_BINARY_EQUAL: return pn_Cmp_Eq;
+ case EXPR_BINARY_ISLESSGREATER: return pn_Cmp_Lg;
+ case EXPR_BINARY_NOTEQUAL:
+ return is_type_float(skip_typeref(type)) ? pn_Cmp_Ne : pn_Cmp_Lg;
+ 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;
+ declaration_t *var2, *var = NULL;
+ ir_node *res = NULL;
+ pn_Cmp cmp_val;
+
+ cmp_val = get_pnc(expression->base.kind, op1->base.type);
+
+ if (is_local_variable(op1) && is_local_variable(op2)) {
+ var = op1->reference.declaration;
+ var2 = op2->reference.declaration;
+
+ type_t *const type = skip_typeref(var->type);
+ ir_mode *const mode = get_ir_mode(type);
+
+ ir_node *const irn1 = get_value(var->v.value_number, mode);
+ ir_node *const 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;
+ }
+
+ expression_t *con;
+ 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 *const 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->kind) {
+ 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 *bitfield_extract_to_firm(const unary_expression_t *expression)
+{
+ expression_t *select = expression->value;
+ assert(select->kind == EXPR_SELECT);
+
+ type_t *type = select->base.type;
+ assert(type->kind == TYPE_BITFIELD);
+ ir_mode *mode = get_ir_mode(type->bitfield.base_type);
+ dbg_info *dbgi = get_dbg_info(&expression->base.source_position);
+ ir_node *addr = expression_to_addr(select);
+ ir_node *mem = get_store();
+ ir_node *load = new_d_Load(dbgi, mem, addr, mode);
+ ir_node *load_mem = new_d_Proj(dbgi, load, mode_M, pn_Load_M);
+ ir_node *load_res = new_d_Proj(dbgi, load, mode, pn_Load_res);
+
+ load_res = create_conv(dbgi, load_res, mode_int);
+
+ set_store(load_mem);
+
+ /* kill upper bits */
+ ir_entity *entity = select->select.compound_entry->v.entity;
+ int bitoffset = get_entity_offset_bits_remainder(entity);
+ ir_type *entity_type = get_entity_type(entity);
+ int bitsize = get_mode_size_bits(get_type_mode(entity_type));
+ long shift_bitsl = machine_size - bitoffset - bitsize;
+ assert(shift_bitsl >= 0);
+ tarval *tvl = new_tarval_from_long(shift_bitsl, mode_uint);
+ ir_node *countl = new_d_Const(dbgi, mode_uint, tvl);
+ ir_node *shiftl = new_d_Shl(dbgi, load_res, countl, mode_int);
+
+ long shift_bitsr = bitoffset + shift_bitsl;
+ assert(shift_bitsr <= (long) machine_size);
+ tarval *tvr = new_tarval_from_long(shift_bitsr, mode_uint);
+ ir_node *countr = new_d_Const(dbgi, mode_uint, tvr);
+ ir_node *shiftr;
+ if(mode_is_signed(mode)) {
+ shiftr = new_d_Shrs(dbgi, shiftl, countr, mode_int);
+ } else {
+ shiftr = new_d_Shr(dbgi, shiftl, countr, mode_int);
+ }
+
+ return create_conv(dbgi, shiftr, mode);
+}
+