long_by_long_mulhi() rewritten and commented

Chuck Rasbold rasbold at google.com
Mon Feb 2 08:42:22 PST 2009


Christian -

I think your suggested change with attribution to Hacker's Delight is
a good idea. C2 already references that source elsewhere.

I would change the constants in the comments to match those used in
the building the ideal graph. Then note in a single place that you
adjusted Warren's algorithm to 64 bits.

 -- Chuck

On Mon, Feb 2, 2009 at 3:01 AM, Christian Thalinger
<Christian.Thalinger at sun.com> wrote:
> Hi!
>
> While looking at 6795362, I tried to understand what the code in
> long_by_long_mulhi() does and I rewrote it with a lot more comments
> (plus original code from Hacker's Delight).
>
> I'd like to commit this one but I'm not sure if there might be a
> copyright problem.
>
> Would it be okay to open a new CR and commit it?
>
> -- Christian
>
>
> --- 6795362.3b5ac9e7e6ea/src/share/vm/opto/divnode.cpp  2009-02-02 11:56:15.694744045 +0100
> +++ /export/home/twisti/hotspot-comp/6795362/src/share/vm/opto/divnode.cpp      2009-02-02 11:55:20.837538078 +0100
> @@ -252,34 +252,62 @@ static Node *long_by_long_mulhi( PhaseGV
>     return new (phase->C, 3) MulHiLNode(dividend, v);
>   }
>
> -  const int N = 64;
> -
> -  Node *u_hi = phase->transform(new (phase->C, 3) RShiftLNode(dividend, phase->intcon(N / 2)));
> -  Node *u_lo = phase->transform(new (phase->C, 3) AndLNode(dividend, phase->longcon(0xFFFFFFFF)));
> +  // Taken from Hacker's Delight, Fig. 8-2. Multiply high signed.
> +  // (http://www.hackersdelight.org/HDcode/mulhs.c)
> +  //
> +  // int mulhs(int u, int v) {
> +  //    unsigned u0, v0, w0;
> +  //    int u1, v1, w1, w2, t;
> +  //
> +  //    u0 = u & 0xFFFF;  u1 = u >> 16;
> +  //    v0 = v & 0xFFFF;  v1 = v >> 16;
> +  //    w0 = u0*v0;
> +  //    t  = u1*v0 + (w0 >> 16);
> +  //    w1 = t & 0xFFFF;
> +  //    w2 = t >> 16;
> +  //    w1 = u0*v1 + w1;
> +  //    return u1*v1 + w2 + (w1 >> 16);
> +  // }
>
> -  Node *v_hi = phase->longcon(magic_const >> N/2);
> -  Node *v_lo = phase->longcon(magic_const & 0XFFFFFFFF);
> +  const int N = 64;
>
> -  Node *hihi_product = phase->transform(new (phase->C, 3) MulLNode(u_hi, v_hi));
> -  Node *hilo_product = phase->transform(new (phase->C, 3) MulLNode(u_hi, v_lo));
> -  Node *lohi_product = phase->transform(new (phase->C, 3) MulLNode(u_lo, v_hi));
> -  Node *lolo_product = phase->transform(new (phase->C, 3) MulLNode(u_lo, v_lo));
> -
> -  Node *t1 = phase->transform(new (phase->C, 3) URShiftLNode(lolo_product, phase->intcon(N / 2)));
> -  Node *t2 = phase->transform(new (phase->C, 3) AddLNode(hilo_product, t1));
> -
> -  // Construct both t3 and t4 before transforming so t2 doesn't go dead
> -  // prematurely.
> -  Node *t3 = new (phase->C, 3) RShiftLNode(t2, phase->intcon(N / 2));
> -  Node *t4 = new (phase->C, 3) AndLNode(t2, phase->longcon(0xFFFFFFFF));
> -  t3 = phase->transform(t3);
> -  t4 = phase->transform(t4);
> -
> -  Node *t5 = phase->transform(new (phase->C, 3) AddLNode(t4, lohi_product));
> -  Node *t6 = phase->transform(new (phase->C, 3) RShiftLNode(t5, phase->intcon(N / 2)));
> -  Node *t7 = phase->transform(new (phase->C, 3) AddLNode(t3, hihi_product));
> +  // u0 = u & 0xFFFF;  u1 = u >> 16;
> +  Node *u0 = phase->transform(new (phase->C, 3) AndLNode(dividend, phase->longcon(0xFFFFFFFF)));
> +  Node *u1 = phase->transform(new (phase->C, 3) RShiftLNode(dividend, phase->intcon(N / 2)));
> +
> +  // v0 = v & 0xFFFF;  v1 = v >> 16;
> +  Node *v0 = phase->longcon(magic_const & 0xFFFFFFFF);
> +  Node *v1 = phase->longcon(magic_const >> N / 2);
> +
> +  // w0 = u0*v0;
> +  Node *w0 = phase->transform(new (phase->C, 3) MulLNode(u0, v0));
> +
> +  // t  = u1*v0 + (w0 >> 16);
> +  Node *u1v0 = phase->transform(new (phase->C, 3) MulLNode(u1, v0));
> +  Node *temp = phase->transform(new (phase->C, 3) URShiftLNode(w0, phase->intcon(N / 2)));
> +  Node *t    = phase->transform(new (phase->C, 3) AddLNode(u1v0, temp));
> +
> +  // w1 = t & 0xFFFF;
> +  Node *w1 = new (phase->C, 3) AndLNode(t, phase->longcon(0xFFFFFFFF));
> +
> +  // w2 = t >> 16;
> +  Node *w2 = new (phase->C, 3) RShiftLNode(t, phase->intcon(N / 2));
> +
> +  // 6732154: Construct both w1 and w2 before transforming, so t
> +  // doesn't go dead prematurely.
> +  w1 = phase->transform(w1);
> +  w2 = phase->transform(w2);
> +
> +  // w1 = u0*v1 + w1;
> +  Node *u0v1 = phase->transform(new (phase->C, 3) MulLNode(u0, v1));
> +  w1         = phase->transform(new (phase->C, 3) AddLNode(u0v1, w1));
> +
> +  // return u1*v1 + w2 + (w1 >> 16);
> +  Node *u1v1  = phase->transform(new (phase->C, 3) MulLNode(u1, v1));
> +  Node *temp1 = phase->transform(new (phase->C, 3) AddLNode(u1v1, w2));
> +  Node *temp2 = phase->transform(new (phase->C, 3) RShiftLNode(w1, phase->intcon(N / 2)));
>
> -  return new (phase->C, 3) AddLNode(t7, t6);
> +  return new (phase->C, 3) AddLNode(temp1, temp2);
>  }
>
>
>
>
>



More information about the hotspot-compiler-dev mailing list