- /* x == c || x >= c + 1 -> x >= c */
- ir_graph *const irg = current_ir_graph;
- ir_node *const block = get_nodes_block(cmp_lo);
- ir_node *const p = new_r_Proj(irg, block, cmp_lo, mode_b, pn_Cmp_Ge);
+ /* x == c || x >= c + 1 ==> x >= c */
+ ir_node *const p = new_r_Proj(cmp_lo, mode_b, pn_Cmp_Ge);
+ return p;
+ }
+ } else if ((pnc_lo == pn_Cmp_Lt || pnc_lo == pn_Cmp_Le) &&
+ (pnc_hi == pn_Cmp_Gt || pnc_lo == pn_Cmp_Ge) &&
+ get_mode_arithmetic(mode) == irma_twos_complement) {
+ /* works for two-complements only */
+ /* x <|<= lo || x >|>= hi ==> (x - lo) >u|>=u (hi-lo) */
+ if (pnc_lo == pn_Cmp_Le) {
+ /* must convert to < */
+ ir_mode *mode = get_tarval_mode(tv_lo);
+ tarval *n = tarval_add(tv_lo, get_mode_one(mode));
+ if (n != tarval_bad && tarval_cmp(n, tv_lo) == pn_Cmp_Gt) {
+ /* no overflow */
+ tv_lo = n;
+ pnc_lo = pn_Cmp_Lt;
+ }
+ }
+ if (pnc_lo == pn_Cmp_Lt) {
+ /* all fine */
+ ir_node *const block = get_nodes_block(cmp_hi);
+ ir_node * x = get_Cmp_left(cmp_hi);
+ ir_mode * mode = get_irn_mode(x);
+ ir_node *sub, *cmp, *c, *subc, *p;
+
+ if (mode_is_signed(mode)) {
+ /* convert to unsigned */
+ mode = find_unsigned_mode(mode);
+ if (mode == NULL)
+ return NULL;
+ x = new_r_Conv(block, x, mode);
+ tv_lo = tarval_convert_to(tv_lo, mode);
+ tv_hi = tarval_convert_to(tv_hi, mode);
+ if (tv_lo == tarval_bad || tv_hi == tarval_bad)
+ return NULL;
+ }
+ c = new_Const(tv_lo);
+ sub = new_r_Sub(block, x, c, mode);
+ subc = new_r_Sub(block, new_Const(tv_hi), c, mode);
+ cmp = new_r_Cmp(block, sub, subc);
+ p = new_r_Proj(cmp, mode_b, pnc_hi);