+ }
+ }
+ if (num == 1)
+ return k;
+ return -1;
+}
+
+
+/* for shorter lines */
+#define ABS(a) tarval_abs(a)
+#define NEG(a) tarval_neg(a)
+#define NOT(a) tarval_not(a)
+#define SHL(a, b) tarval_shl(a, b)
+#define SHR(a, b) tarval_shr(a, b)
+#define ADD(a, b) tarval_add(a, b)
+#define SUB(a, b) tarval_sub(a, b, NULL)
+#define MUL(a, b) tarval_mul(a, b)
+#define DIV(a, b) tarval_div(a, b)
+#define MOD(a, b) tarval_mod(a, b)
+#define CMP(a, b) tarval_cmp(a, b)
+#define CNV(a, m) tarval_convert_to(a, m)
+#define ONE(m) get_mode_one(m)
+#define ZERO(m) get_mode_null(m)
+
+/** The result of a the magic() function. */
+struct ms {
+ ir_tarval *M; /**< magic number */
+ int s; /**< shift amount */
+ int need_add; /**< an additional add is needed */
+ int need_sub; /**< an additional sub is needed */
+};
+
+/**
+ * Signed division by constant d: calculate the Magic multiplier M and the shift amount s
+ *
+ * see Hacker's Delight: 10-6 Integer Division by Constants: Incorporation into a Compiler
+ */
+static struct ms magic(ir_tarval *d)
+{
+ ir_mode *mode = get_tarval_mode(d);
+ ir_mode *u_mode = find_unsigned_mode(mode);
+ int bits = get_mode_size_bits(u_mode);
+ int p;
+ ir_tarval *ad, *anc, *delta, *q1, *r1, *q2, *r2, *t; /* unsigned */
+ ir_relation d_cmp, M_cmp;
+
+ ir_tarval *bits_minus_1, *two_bits_1;
+
+ struct ms mag;
+
+ tarval_int_overflow_mode_t rem = tarval_get_integer_overflow_mode();
+
+ /* we need overflow mode to work correctly */
+ tarval_set_integer_overflow_mode(TV_OVERFLOW_WRAP);
+
+ /* 2^(bits-1) */
+ bits_minus_1 = new_tarval_from_long(bits - 1, u_mode);
+ two_bits_1 = SHL(get_mode_one(u_mode), bits_minus_1);
+
+ ad = CNV(ABS(d), u_mode);
+ t = ADD(two_bits_1, SHR(CNV(d, u_mode), bits_minus_1));
+ anc = SUB(SUB(t, ONE(u_mode)), MOD(t, ad)); /* Absolute value of nc */
+ p = bits - 1; /* Init: p */
+ q1 = DIV(two_bits_1, anc); /* Init: q1 = 2^p/|nc| */
+ r1 = SUB(two_bits_1, MUL(q1, anc)); /* Init: r1 = rem(2^p, |nc|) */
+ q2 = DIV(two_bits_1, ad); /* Init: q2 = 2^p/|d| */
+ r2 = SUB(two_bits_1, MUL(q2, ad)); /* Init: r2 = rem(2^p, |d|) */
+
+ do {
+ ++p;
+ q1 = ADD(q1, q1); /* Update q1 = 2^p/|nc| */
+ r1 = ADD(r1, r1); /* Update r1 = rem(2^p, |nc|) */
+
+ if (CMP(r1, anc) & ir_relation_greater_equal) {
+ q1 = ADD(q1, ONE(u_mode));
+ r1 = SUB(r1, anc);
+ }
+
+ q2 = ADD(q2, q2); /* Update q2 = 2^p/|d| */
+ r2 = ADD(r2, r2); /* Update r2 = rem(2^p, |d|) */
+
+ if (CMP(r2, ad) & ir_relation_greater_equal) {
+ q2 = ADD(q2, ONE(u_mode));
+ r2 = SUB(r2, ad);
+ }
+
+ delta = SUB(ad, r2);
+ } while (CMP(q1, delta) & ir_relation_less || (CMP(q1, delta) & ir_relation_equal && CMP(r1, ZERO(u_mode)) & ir_relation_equal));
+
+ d_cmp = CMP(d, ZERO(mode));
+
+ if (d_cmp & ir_relation_greater_equal)
+ mag.M = ADD(CNV(q2, mode), ONE(mode));
+ else
+ mag.M = SUB(ZERO(mode), ADD(CNV(q2, mode), ONE(mode)));
+
+ M_cmp = CMP(mag.M, ZERO(mode));
+
+ mag.s = p - bits;
+
+ /* need an add if d > 0 && M < 0 */
+ mag.need_add = d_cmp & ir_relation_greater && M_cmp & ir_relation_less;
+
+ /* need a sub if d < 0 && M > 0 */
+ mag.need_sub = d_cmp & ir_relation_less && M_cmp & ir_relation_greater;
+
+ tarval_set_integer_overflow_mode(rem);
+
+ return mag;
+}
+
+/** The result of the magicu() function. */
+struct mu {
+ ir_tarval *M; /**< magic add constant */
+ int s; /**< shift amount */
+ int need_add; /**< add indicator */
+};
+
+/**
+ * Unsigned division by constant d: calculate the Magic multiplier M and the shift amount s
+ *
+ * see Hacker's Delight: 10-10 Integer Division by Constants: Incorporation into a Compiler (Unsigned)
+ */
+static struct mu magicu(ir_tarval *d)
+{
+ ir_mode *mode = get_tarval_mode(d);
+ int bits = get_mode_size_bits(mode);
+ int p;
+ ir_tarval *nc, *delta, *q1, *r1, *q2, *r2;
+ ir_tarval *bits_minus_1, *two_bits_1, *seven_ff;
+
+ struct mu magu;
+
+ tarval_int_overflow_mode_t rem = tarval_get_integer_overflow_mode();
+
+ /* we need overflow mode to work correctly */
+ tarval_set_integer_overflow_mode(TV_OVERFLOW_WRAP);
+
+ bits_minus_1 = new_tarval_from_long(bits - 1, mode);
+ two_bits_1 = SHL(get_mode_one(mode), bits_minus_1);
+ seven_ff = SUB(two_bits_1, ONE(mode));
+
+ magu.need_add = 0; /* initialize the add indicator */
+ nc = SUB(NEG(ONE(mode)), MOD(NEG(d), d));
+ p = bits - 1; /* Init: p */
+ q1 = DIV(two_bits_1, nc); /* Init: q1 = 2^p/nc */
+ r1 = SUB(two_bits_1, MUL(q1, nc)); /* Init: r1 = rem(2^p, nc) */
+ q2 = DIV(seven_ff, d); /* Init: q2 = (2^p - 1)/d */
+ r2 = SUB(seven_ff, MUL(q2, d)); /* Init: r2 = rem(2^p - 1, d) */
+
+ do {
+ ++p;
+ if (CMP(r1, SUB(nc, r1)) & ir_relation_greater_equal) {
+ q1 = ADD(ADD(q1, q1), ONE(mode));
+ r1 = SUB(ADD(r1, r1), nc);
+ }
+ else {
+ q1 = ADD(q1, q1);
+ r1 = ADD(r1, r1);
+ }
+
+ if (CMP(ADD(r2, ONE(mode)), SUB(d, r2)) & ir_relation_greater_equal) {
+ if (CMP(q2, seven_ff) & ir_relation_greater_equal)
+ magu.need_add = 1;
+
+ q2 = ADD(ADD(q2, q2), ONE(mode));
+ r2 = SUB(ADD(ADD(r2, r2), ONE(mode)), d);
+ }
+ else {
+ if (CMP(q2, two_bits_1) & ir_relation_greater_equal)
+ magu.need_add = 1;
+
+ q2 = ADD(q2, q2);
+ r2 = ADD(ADD(r2, r2), ONE(mode));
+ }
+ delta = SUB(SUB(d, ONE(mode)), r2);
+ } while (p < 2*bits &&
+ (CMP(q1, delta) & ir_relation_less || (CMP(q1, delta) & ir_relation_equal && CMP(r1, ZERO(mode)) & ir_relation_equal)));
+
+ magu.M = ADD(q2, ONE(mode)); /* Magic number */
+ magu.s = p - bits; /* and shift amount */
+
+ tarval_set_integer_overflow_mode(rem);
+
+ return magu;
+}
+
+/**
+ * Build the Mulh replacement code for n / tv.
+ *
+ * Note that 'div' might be a Mod operation as well
+ */
+static ir_node *replace_div_by_mulh(ir_node *div, ir_tarval *tv)
+{
+ dbg_info *dbg = get_irn_dbg_info(div);
+ ir_node *n = get_binop_left(div);
+ ir_node *block = get_nodes_block(div);
+ ir_mode *mode = get_irn_mode(n);
+ int bits = get_mode_size_bits(mode);
+ ir_node *q;
+
+ /* Beware: do not transform bad code */
+ if (is_Bad(n) || is_Bad(block))
+ return div;
+
+ if (mode_is_signed(mode)) {
+ ir_graph *irg = get_irn_irg(div);
+ struct ms mag = magic(tv);
+
+ /* generate the Mulh instruction */
+ ir_node *c = new_r_Const(irg, mag.M);
+ ir_node *t;
+ q = new_rd_Mulh(dbg, block, n, c, mode);
+
+ /* do we need an Add or Sub */
+ if (mag.need_add)
+ q = new_rd_Add(dbg, block, q, n, mode);
+ else if (mag.need_sub)
+ q = new_rd_Sub(dbg, block, q, n, mode);
+
+ /* Do we need the shift */
+ if (mag.s > 0) {
+ c = new_r_Const_long(irg, mode_Iu, mag.s);
+ q = new_rd_Shrs(dbg, block, q, c, mode);
+ }
+
+ /* final */
+ c = new_r_Const_long(irg, mode_Iu, bits - 1);
+ t = new_rd_Shr(dbg, block, q, c, mode);
+
+ q = new_rd_Add(dbg, block, q, t, mode);
+ } else {
+ struct mu mag = magicu(tv);
+ ir_graph *irg = get_irn_irg(div);
+
+ /* generate the Mulh instruction */
+ ir_node *c = new_r_Const(irg, mag.M);
+ q = new_rd_Mulh(dbg, block, n, c, mode);