Hi Brad:

This patch looks fine to me.
Putting a small comment in front of proc +() for the cases of  matching 
homogeneous tuples and left-hand and right-hand scalar operands indicating the 
syntax they would bind to would be nice.  Anyone reading the code can refer 
back up to the first case, so adding comments to the implementations for each 
kind of operator would just add noise.

THH

________________________________________
From: Brad Chamberlain [[email protected]]
Sent: Friday, December 20, 2013 7:51 PM
To: Chapel Sourceforge Developers List
Subject: [Chapel-developers] Request for review: simplified homog. tuple        
operations

Hi all --

This is a request for a review to simplify the implementation of standard
operations (+, -, *, etc.) on homogeneous tuple operations.  It's pretty
straightforward.  I thought I was seeing a bit of performance improvement
on my Mac last night, but on linux it seems to be a bit of a wash.
However, looking at the generated code, it seems like a no-brainer -- it
makes it simpler and more straightforward.  Patch attached, proposed log
message below.

-Brad


----

Simplify the implementation of homogeneous tuple operations


Prior to this commit, we have been implementing all tuple operations (+,
-, *, etc.) on singleton tuples, pairs of tuples, and tuple-scalar pairs
using a recursive Lisp-y style of implementation approach.  While this
approach is reasonably elegant to write and very general with respect to
the tuple types, the code it generates is pretty ugly.  For example, a
tuple addition like this:

   var x: 3*real = (1.0, 2.0, 3.0);
   var y: 3*real = (4.0, 5.0, 6.0);

   var z = x + y;

ends up looking like this:

   call_tmp = (1.0 + 4.0);
   ret_to_arg_ref_tmp_ = &wrap_call_tmp;
   chpl__tupleRestHelper2(1.0, 2.0, 3.0, ret_to_arg_ref_tmp_);
   ret_to_arg_ref_tmp_2 = &wrap_call_tmp2;
   chpl__tupleRestHelper2(4.0, 5.0, 6.0, ret_to_arg_ref_tmp_2);
   call_tmp2 = *(wrap_call_tmp + INT64(0));
   call_tmp3 = *(wrap_call_tmp2 + INT64(0));
   call_tmp4 = (call_tmp2 + call_tmp3);
   call_tmp5 = *(wrap_call_tmp + INT64(0));
   call_tmp6 = *(wrap_call_tmp + INT64(1));
   ret_to_arg_ref_tmp_3 = &wrap_call_tmp3;
   chpl__tupleRestHelper(call_tmp5, call_tmp6, ret_to_arg_ref_tmp_3);
   call_tmp7 = *(wrap_call_tmp2 + INT64(0));
   call_tmp8 = *(wrap_call_tmp2 + INT64(1));
   ret_to_arg_ref_tmp_4 = &wrap_call_tmp4;
   chpl__tupleRestHelper(call_tmp7, call_tmp8, ret_to_arg_ref_tmp_4);
   call_tmp9 = *(wrap_call_tmp3 + INT64(0));
   call_tmp10 = *(wrap_call_tmp4 + INT64(0));
   call_tmp11 = (call_tmp9 + call_tmp10);
   *(z + INT64(0)) = call_tmp;
   *(z + INT64(1)) = call_tmp4;
   *(z + INT64(2)) = call_tmp11;

In wrestling through generated code idioms like this for homogeneous
tuples, I realized that there's no need to use the recursive approach
because it's straightforward to anticipate the result type required,
declare a variable for it, and fill the result using a param loop. This
results in much cleaner generated code, like this:

   call_tmp = (1.0 + 4.0);
   call_tmp2 = (2.0 + 5.0);
   call_tmp3 = (3.0 + 6.0);
   *(z + INT64(0)) = call_tmp;
   *(z + INT64(1)) = call_tmp2;
   *(z + INT64(2)) = call_tmp3;

The primary challenge to doing the similar thing for heterogeneous tuples
is that it's difficult to declare the result type using Chapel code today.
For homogeneous operations, we can say things like:

     var result: a.size*(a(1) + b(1)).type;

because we know that the type resulting from adding the 1st component will
apply to all the others as well.  But for a heterogeneous case, we can't
anticipate how many fields the tuple will have and don't have a way for
mapping or expanding type-based computations like this across tuples (at
least that I've been able to come up with so far).

So, in this commit, I provide specialized overloads of the operations for
the (common) cases when the tuple(s) are homogeneous and preserve the
original implementation for the fall-through case when one or both tuples
are heterogeneous.

My next step is to look at eliminating the tuple temps that are used when
assigning tuples, which result from the combination of normalization and
the fact that our assignment operators don't take the LHS by reference.
This should go even further in cleaning up tuple-based code.
------------------------------------------------------------------------------
Rapidly troubleshoot problems before they affect your business. Most IT 
organizations don't have a clear picture of how application performance 
affects their revenue. With AppDynamics, you get 100% visibility into your 
Java,.NET, & PHP application. Start your 15-day FREE TRIAL of AppDynamics Pro!
http://pubads.g.doubleclick.net/gampad/clk?id=84349831&iu=/4140/ostg.clktrk
_______________________________________________
Chapel-developers mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/chapel-developers

Reply via email to