[PATCH] D15679: [FIX] Schedule generation PR25879

Johannes Doerfert via llvm-commits llvm-commits at lists.llvm.org
Mon Dec 21 14:20:08 PST 2015


jdoerfert added a comment.

In http://reviews.llvm.org/D15679#314985, @grosser wrote:

> For reference test/ScopInfo/multiple_exiting_blocks_two_loop.ll is a test case that contains a scop with a loop that does not have a corresponding region.
>
> Johannes, I looked through the code and I have some difficulties to get a picture of what the exiting code does both in detail but also on a high-level. I started to think through it, but if you could add some documentation to the current code that would clearly help.


I can do that.

> Some questions I have:

> 

> What is LSchedulePair.second/NumVisited used for? It seems when the condition NumVisited == L->getNumBlocks() holds you assume all basic blocks of the loop have been processed. Then, you can start to walk up the loop tree and add the other loop dimensions?


Wait. This was in there for months and is core part of the schedule generation. Maybe We should talk about two different things here. The existing code and what I propose to change to fix it. Apparently neither is clear.

The second component of the schedule pair counts how many blocks of a loop have been visited. If this number is equal to the number of blocks in the loop we add this loop to the schedule tree. This is similar to what we did before (in the old schedule generation) but extended to the case that the loop is not perfectely covered by regions.

> I tried to understand the implementation of mapToDomain, which is simple in general but seems to do some additional stuff for certain corner cases that do not occur in our tests. Is the following a equivalent implementation? Under which conditions can Domain become 'NULL' (I checked and it indeed becomes NULL)? I removed the check for isl_union_set_is_empty, as this never happens in any test case and instead assert. Is this correct?




1. Except the first conditional the mapToDimensions was implemented by you.
2. In the current implementation N should always be positive.
3. I am not 100% sure why the empty check was in there... maybe it is not needed anymore, maybe it occures somewhere in lnt. If lnt is green i'm fine with you removing that check.

>   mapToDimension(__isl_take isl_union_set *Domain, int N) {                        

>     assert(N > 0);                                                                 

>                                                                                    

>     if (!Domain)                                                                   

>       return nullptr;                                                              

>                                                                                    

>     assert(!isl_union_set_is_empty(Domain));                                       

>                                                                                    

>     struct MapToDimensionDataTy Data;                                              

>                                                                                    

>     auto *Space = isl_union_set_get_space(Domain);                                 

>     auto *PwAff = isl_union_pw_multi_aff_empty(Space);                             

>                                                                                    

>     Data = {N, PwAff};                                                             

>                                                                                    

>     auto Res = isl_union_set_foreach_set(Domain, &mapToDimension_AddSet, &Data);   

>                                                                                    

>     assert(Res == isl_stat_ok);                                                    

>                                                                                    

>     isl_union_set_free(Domain);                                                    

>     return isl_multi_union_pw_aff_from_union_pw_multi_aff(Data.Res);               

>   }   

>   

> 




> How does the content of LoopSchedules change throught the walk? Can you give some invariant. E.g. when buildSchedule returns, what does LoopSchedules contain?


Initially, it is empty. Nothing is in there and LSchedulePair for every loop will be <nullptr, 0>. Then we will build up isl_schedules and add the number of blocks visited to change both components until all blocks of a loop have been visited and its schedule is integrated into the parent loops schedule. During the recursive construction LoopSchedules is constructed not completely but almost "bottom up". While the schedules for the inner-most loops are constructed the schedule of outer loops can be constructed as well but inner loops should be traversed completely before outer ones and their schedule will then be integrated into the outer loop.

> It seems LSchedule can become nullptr, as the following patch asserts:

> 

>   @@ -3464,6 +3468,7 @@ void Scop::buildSchedule(

>    

>        isl_schedule *LSchedule = LSchedulePair.first;

>        unsigned NumVisited = LSchedulePair.second;

>   +    assert(LSchedule);

>        while (L && NumVisited == L->getNumBlocks()) {

>   

> 

> 

> This is a little surprising. What does it mean if LSchedule is nullptr? When does this happen?


Initially (when a loop is discovered) this is a nullptr as there is no schedule for the loop yet. This nullptr is combined "in sequence" with some real schedule and then stored back in the first component of LSchedule.

> Maybe you can consider these questions when documenting the code. Thank you.


I will add comments to the whole thing as it is apperently not clear how schedules are actually build.


http://reviews.llvm.org/D15679





More information about the llvm-commits mailing list