1*e4b17023SJohn Marino /* Loop flattening for Graphite. 2*e4b17023SJohn Marino Copyright (C) 2010 Free Software Foundation, Inc. 3*e4b17023SJohn Marino Contributed by Sebastian Pop <sebastian.pop@amd.com>. 4*e4b17023SJohn Marino 5*e4b17023SJohn Marino This file is part of GCC. 6*e4b17023SJohn Marino 7*e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify 8*e4b17023SJohn Marino it under the terms of the GNU General Public License as published by 9*e4b17023SJohn Marino the Free Software Foundation; either version 3, or (at your option) 10*e4b17023SJohn Marino any later version. 11*e4b17023SJohn Marino 12*e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, 13*e4b17023SJohn Marino but WITHOUT ANY WARRANTY; without even the implied warranty of 14*e4b17023SJohn Marino MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15*e4b17023SJohn Marino GNU General Public License for more details. 16*e4b17023SJohn Marino 17*e4b17023SJohn Marino You should have received a copy of the GNU General Public License 18*e4b17023SJohn Marino along with GCC; see the file COPYING3. If not see 19*e4b17023SJohn Marino <http://www.gnu.org/licenses/>. */ 20*e4b17023SJohn Marino 21*e4b17023SJohn Marino #include "config.h" 22*e4b17023SJohn Marino #include "system.h" 23*e4b17023SJohn Marino #include "coretypes.h" 24*e4b17023SJohn Marino #include "tree-flow.h" 25*e4b17023SJohn Marino #include "tree-dump.h" 26*e4b17023SJohn Marino #include "cfgloop.h" 27*e4b17023SJohn Marino #include "tree-chrec.h" 28*e4b17023SJohn Marino #include "tree-data-ref.h" 29*e4b17023SJohn Marino #include "tree-scalar-evolution.h" 30*e4b17023SJohn Marino #include "sese.h" 31*e4b17023SJohn Marino 32*e4b17023SJohn Marino #ifdef HAVE_cloog 33*e4b17023SJohn Marino #include "ppl_c.h" 34*e4b17023SJohn Marino #include "graphite-ppl.h" 35*e4b17023SJohn Marino #include "graphite-poly.h" 36*e4b17023SJohn Marino 37*e4b17023SJohn Marino /* The loop flattening pass transforms loop nests into a single loop, 38*e4b17023SJohn Marino removing the loop nesting structure. The auto-vectorization can 39*e4b17023SJohn Marino then apply on the full loop body, without needing the outer-loop 40*e4b17023SJohn Marino vectorization. 41*e4b17023SJohn Marino 42*e4b17023SJohn Marino The loop flattening pass that has been described in a very Fortran 43*e4b17023SJohn Marino specific way in the 1992 paper by Reinhard von Hanxleden and Ken 44*e4b17023SJohn Marino Kennedy: "Relaxing SIMD Control Flow Constraints using Loop 45*e4b17023SJohn Marino Transformations" available from 46*e4b17023SJohn Marino http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.54.5033 47*e4b17023SJohn Marino 48*e4b17023SJohn Marino The canonical example is as follows: suppose that we have a loop 49*e4b17023SJohn Marino nest with known iteration counts 50*e4b17023SJohn Marino 51*e4b17023SJohn Marino | for (i = 1; i <= 6; i++) 52*e4b17023SJohn Marino | for (j = 1; j <= 6; j++) 53*e4b17023SJohn Marino | S1(i,j); 54*e4b17023SJohn Marino 55*e4b17023SJohn Marino The loop flattening is performed by linearizing the iteration space 56*e4b17023SJohn Marino using the function "f (x) = 6 * i + j". In this case, CLooG would 57*e4b17023SJohn Marino produce this code: 58*e4b17023SJohn Marino 59*e4b17023SJohn Marino | for (c1=7;c1<=42;c1++) { 60*e4b17023SJohn Marino | i = floord(c1-1,6); 61*e4b17023SJohn Marino | S1(i,c1-6*i); 62*e4b17023SJohn Marino | } 63*e4b17023SJohn Marino 64*e4b17023SJohn Marino There are several limitations for loop flattening that are linked 65*e4b17023SJohn Marino to the expressivity of the polyhedral model. One has to take an 66*e4b17023SJohn Marino upper bound approximation to deal with the parametric case of loop 67*e4b17023SJohn Marino flattening. For example, in the loop nest: 68*e4b17023SJohn Marino 69*e4b17023SJohn Marino | for (i = 1; i <= N; i++) 70*e4b17023SJohn Marino | for (j = 1; j <= M; j++) 71*e4b17023SJohn Marino | S1(i,j); 72*e4b17023SJohn Marino 73*e4b17023SJohn Marino One would like to flatten this loop using a linearization function 74*e4b17023SJohn Marino like this "f (x) = M * i + j". However CLooG's schedules are not 75*e4b17023SJohn Marino expressive enough to deal with this case, and so the parameter M 76*e4b17023SJohn Marino has to be replaced by an integer upper bound approximation. If we 77*e4b17023SJohn Marino further know in the context of the scop that "M <= 6", then it is 78*e4b17023SJohn Marino possible to linearize the loop with "f (x) = 6 * i + j". In this 79*e4b17023SJohn Marino case, CLooG would produce this code: 80*e4b17023SJohn Marino 81*e4b17023SJohn Marino | for (c1=7;c1<=6*M+N;c1++) { 82*e4b17023SJohn Marino | i = ceild(c1-N,6); 83*e4b17023SJohn Marino | if (i <= floord(c1-1,6)) { 84*e4b17023SJohn Marino | S1(i,c1-6*i); 85*e4b17023SJohn Marino | } 86*e4b17023SJohn Marino | } 87*e4b17023SJohn Marino 88*e4b17023SJohn Marino For an arbitrarily complex loop nest the algorithm proceeds in two 89*e4b17023SJohn Marino steps. First, the LST is flattened by removing the loops structure 90*e4b17023SJohn Marino and by inserting the statements in the order they appear in 91*e4b17023SJohn Marino depth-first order. Then, the scattering of each statement is 92*e4b17023SJohn Marino transformed accordingly. 93*e4b17023SJohn Marino 94*e4b17023SJohn Marino Supposing that the original program is represented by the following 95*e4b17023SJohn Marino LST: 96*e4b17023SJohn Marino 97*e4b17023SJohn Marino | (loop_1 98*e4b17023SJohn Marino | stmt_1 99*e4b17023SJohn Marino | (loop_2 stmt_3 100*e4b17023SJohn Marino | (loop_3 stmt_4) 101*e4b17023SJohn Marino | (loop_4 stmt_5 stmt_6) 102*e4b17023SJohn Marino | stmt_7 103*e4b17023SJohn Marino | ) 104*e4b17023SJohn Marino | stmt_2 105*e4b17023SJohn Marino | ) 106*e4b17023SJohn Marino 107*e4b17023SJohn Marino Loop flattening traverses the LST in depth-first order, and 108*e4b17023SJohn Marino flattens pairs of loops successively by projecting the inner loops 109*e4b17023SJohn Marino in the iteration domain of the outer loops: 110*e4b17023SJohn Marino 111*e4b17023SJohn Marino lst_project_loop (loop_2, loop_3, stride) 112*e4b17023SJohn Marino 113*e4b17023SJohn Marino | (loop_1 114*e4b17023SJohn Marino | stmt_1 115*e4b17023SJohn Marino | (loop_2 stmt_3 stmt_4 116*e4b17023SJohn Marino | (loop_4 stmt_5 stmt_6) 117*e4b17023SJohn Marino | stmt_7 118*e4b17023SJohn Marino | ) 119*e4b17023SJohn Marino | stmt_2 120*e4b17023SJohn Marino | ) 121*e4b17023SJohn Marino 122*e4b17023SJohn Marino lst_project_loop (loop_2, loop_4, stride) 123*e4b17023SJohn Marino 124*e4b17023SJohn Marino | (loop_1 125*e4b17023SJohn Marino | stmt_1 126*e4b17023SJohn Marino | (loop_2 stmt_3 stmt_4 stmt_5 stmt_6 stmt_7) 127*e4b17023SJohn Marino | stmt_2 128*e4b17023SJohn Marino | ) 129*e4b17023SJohn Marino 130*e4b17023SJohn Marino lst_project_loop (loop_1, loop_2, stride) 131*e4b17023SJohn Marino 132*e4b17023SJohn Marino | (loop_1 133*e4b17023SJohn Marino | stmt_1 stmt_3 stmt_4 stmt_5 stmt_6 stmt_7 stmt_2 134*e4b17023SJohn Marino | ) 135*e4b17023SJohn Marino 136*e4b17023SJohn Marino At each step, the iteration domain of the outer loop is enlarged to 137*e4b17023SJohn Marino contain enough points to iterate over the inner loop domain. */ 138*e4b17023SJohn Marino 139*e4b17023SJohn Marino /* Initializes RES to the number of iterations of the linearized loop 140*e4b17023SJohn Marino LST. RES is the cardinal of the iteration domain of LST. */ 141*e4b17023SJohn Marino 142*e4b17023SJohn Marino static void 143*e4b17023SJohn Marino lst_linearized_niter (lst_p lst, mpz_t res) 144*e4b17023SJohn Marino { 145*e4b17023SJohn Marino int i; 146*e4b17023SJohn Marino lst_p l; 147*e4b17023SJohn Marino mpz_t n; 148*e4b17023SJohn Marino 149*e4b17023SJohn Marino mpz_init (n); 150*e4b17023SJohn Marino mpz_set_si (res, 0); 151*e4b17023SJohn Marino 152*e4b17023SJohn Marino FOR_EACH_VEC_ELT (lst_p, LST_SEQ (lst), i, l) 153*e4b17023SJohn Marino if (LST_LOOP_P (l)) 154*e4b17023SJohn Marino { 155*e4b17023SJohn Marino lst_linearized_niter (l, n); 156*e4b17023SJohn Marino mpz_add (res, res, n); 157*e4b17023SJohn Marino } 158*e4b17023SJohn Marino 159*e4b17023SJohn Marino if (LST_LOOP_P (lst)) 160*e4b17023SJohn Marino { 161*e4b17023SJohn Marino lst_niter_for_loop (lst, n); 162*e4b17023SJohn Marino 163*e4b17023SJohn Marino if (mpz_cmp_si (res, 0) != 0) 164*e4b17023SJohn Marino mpz_mul (res, res, n); 165*e4b17023SJohn Marino else 166*e4b17023SJohn Marino mpz_set (res, n); 167*e4b17023SJohn Marino } 168*e4b17023SJohn Marino 169*e4b17023SJohn Marino mpz_clear (n); 170*e4b17023SJohn Marino } 171*e4b17023SJohn Marino 172*e4b17023SJohn Marino /* Applies the translation "f (x) = x + OFFSET" to the loop containing 173*e4b17023SJohn Marino STMT. */ 174*e4b17023SJohn Marino 175*e4b17023SJohn Marino static void 176*e4b17023SJohn Marino lst_offset (lst_p stmt, mpz_t offset) 177*e4b17023SJohn Marino { 178*e4b17023SJohn Marino lst_p inner = LST_LOOP_FATHER (stmt); 179*e4b17023SJohn Marino poly_bb_p pbb = LST_PBB (stmt); 180*e4b17023SJohn Marino ppl_Polyhedron_t poly = PBB_TRANSFORMED_SCATTERING (pbb); 181*e4b17023SJohn Marino int inner_depth = lst_depth (inner); 182*e4b17023SJohn Marino ppl_dimension_type inner_dim = psct_dynamic_dim (pbb, inner_depth); 183*e4b17023SJohn Marino ppl_Linear_Expression_t expr; 184*e4b17023SJohn Marino ppl_dimension_type dim; 185*e4b17023SJohn Marino ppl_Coefficient_t one; 186*e4b17023SJohn Marino mpz_t x; 187*e4b17023SJohn Marino 188*e4b17023SJohn Marino mpz_init (x); 189*e4b17023SJohn Marino mpz_set_si (x, 1); 190*e4b17023SJohn Marino ppl_new_Coefficient (&one); 191*e4b17023SJohn Marino ppl_assign_Coefficient_from_mpz_t (one, x); 192*e4b17023SJohn Marino 193*e4b17023SJohn Marino ppl_Polyhedron_space_dimension (poly, &dim); 194*e4b17023SJohn Marino ppl_new_Linear_Expression_with_dimension (&expr, dim); 195*e4b17023SJohn Marino 196*e4b17023SJohn Marino ppl_set_coef (expr, inner_dim, 1); 197*e4b17023SJohn Marino ppl_set_inhomogeneous_gmp (expr, offset); 198*e4b17023SJohn Marino ppl_Polyhedron_affine_image (poly, inner_dim, expr, one); 199*e4b17023SJohn Marino ppl_delete_Linear_Expression (expr); 200*e4b17023SJohn Marino ppl_delete_Coefficient (one); 201*e4b17023SJohn Marino } 202*e4b17023SJohn Marino 203*e4b17023SJohn Marino /* Scale by FACTOR the loop LST containing STMT. */ 204*e4b17023SJohn Marino 205*e4b17023SJohn Marino static void 206*e4b17023SJohn Marino lst_scale (lst_p lst, lst_p stmt, mpz_t factor) 207*e4b17023SJohn Marino { 208*e4b17023SJohn Marino mpz_t x; 209*e4b17023SJohn Marino ppl_Coefficient_t one; 210*e4b17023SJohn Marino int outer_depth = lst_depth (lst); 211*e4b17023SJohn Marino poly_bb_p pbb = LST_PBB (stmt); 212*e4b17023SJohn Marino ppl_Polyhedron_t poly = PBB_TRANSFORMED_SCATTERING (pbb); 213*e4b17023SJohn Marino ppl_dimension_type outer_dim = psct_dynamic_dim (pbb, outer_depth); 214*e4b17023SJohn Marino ppl_Linear_Expression_t expr; 215*e4b17023SJohn Marino ppl_dimension_type dim; 216*e4b17023SJohn Marino 217*e4b17023SJohn Marino mpz_init (x); 218*e4b17023SJohn Marino mpz_set_si (x, 1); 219*e4b17023SJohn Marino ppl_new_Coefficient (&one); 220*e4b17023SJohn Marino ppl_assign_Coefficient_from_mpz_t (one, x); 221*e4b17023SJohn Marino 222*e4b17023SJohn Marino ppl_Polyhedron_space_dimension (poly, &dim); 223*e4b17023SJohn Marino ppl_new_Linear_Expression_with_dimension (&expr, dim); 224*e4b17023SJohn Marino 225*e4b17023SJohn Marino /* outer_dim = factor * outer_dim. */ 226*e4b17023SJohn Marino ppl_set_coef_gmp (expr, outer_dim, factor); 227*e4b17023SJohn Marino ppl_Polyhedron_affine_image (poly, outer_dim, expr, one); 228*e4b17023SJohn Marino ppl_delete_Linear_Expression (expr); 229*e4b17023SJohn Marino 230*e4b17023SJohn Marino mpz_clear (x); 231*e4b17023SJohn Marino ppl_delete_Coefficient (one); 232*e4b17023SJohn Marino } 233*e4b17023SJohn Marino 234*e4b17023SJohn Marino /* Project the INNER loop into the iteration domain of the OUTER loop. 235*e4b17023SJohn Marino STRIDE is the number of iterations between two iterations of the 236*e4b17023SJohn Marino outer loop. */ 237*e4b17023SJohn Marino 238*e4b17023SJohn Marino static void 239*e4b17023SJohn Marino lst_project_loop (lst_p outer, lst_p inner, mpz_t stride) 240*e4b17023SJohn Marino { 241*e4b17023SJohn Marino int i; 242*e4b17023SJohn Marino lst_p stmt; 243*e4b17023SJohn Marino mpz_t x; 244*e4b17023SJohn Marino ppl_Coefficient_t one; 245*e4b17023SJohn Marino int outer_depth = lst_depth (outer); 246*e4b17023SJohn Marino int inner_depth = lst_depth (inner); 247*e4b17023SJohn Marino 248*e4b17023SJohn Marino mpz_init (x); 249*e4b17023SJohn Marino mpz_set_si (x, 1); 250*e4b17023SJohn Marino ppl_new_Coefficient (&one); 251*e4b17023SJohn Marino ppl_assign_Coefficient_from_mpz_t (one, x); 252*e4b17023SJohn Marino 253*e4b17023SJohn Marino FOR_EACH_VEC_ELT (lst_p, LST_SEQ (inner), i, stmt) 254*e4b17023SJohn Marino { 255*e4b17023SJohn Marino poly_bb_p pbb = LST_PBB (stmt); 256*e4b17023SJohn Marino ppl_Polyhedron_t poly = PBB_TRANSFORMED_SCATTERING (pbb); 257*e4b17023SJohn Marino ppl_dimension_type outer_dim = psct_dynamic_dim (pbb, outer_depth); 258*e4b17023SJohn Marino ppl_dimension_type inner_dim = psct_dynamic_dim (pbb, inner_depth); 259*e4b17023SJohn Marino ppl_Linear_Expression_t expr; 260*e4b17023SJohn Marino ppl_dimension_type dim; 261*e4b17023SJohn Marino ppl_dimension_type *ds; 262*e4b17023SJohn Marino 263*e4b17023SJohn Marino /* There should be no loops under INNER. */ 264*e4b17023SJohn Marino gcc_assert (!LST_LOOP_P (stmt)); 265*e4b17023SJohn Marino ppl_Polyhedron_space_dimension (poly, &dim); 266*e4b17023SJohn Marino ppl_new_Linear_Expression_with_dimension (&expr, dim); 267*e4b17023SJohn Marino 268*e4b17023SJohn Marino /* outer_dim = outer_dim * stride + inner_dim. */ 269*e4b17023SJohn Marino ppl_set_coef (expr, inner_dim, 1); 270*e4b17023SJohn Marino ppl_set_coef_gmp (expr, outer_dim, stride); 271*e4b17023SJohn Marino ppl_Polyhedron_affine_image (poly, outer_dim, expr, one); 272*e4b17023SJohn Marino ppl_delete_Linear_Expression (expr); 273*e4b17023SJohn Marino 274*e4b17023SJohn Marino /* Project on inner_dim. */ 275*e4b17023SJohn Marino ppl_new_Linear_Expression_with_dimension (&expr, dim - 1); 276*e4b17023SJohn Marino ppl_Polyhedron_affine_image (poly, inner_dim, expr, one); 277*e4b17023SJohn Marino ppl_delete_Linear_Expression (expr); 278*e4b17023SJohn Marino 279*e4b17023SJohn Marino /* Remove inner loop and the static schedule of its body. */ 280*e4b17023SJohn Marino /* FIXME: As long as we use PPL we are not able to remove the old 281*e4b17023SJohn Marino scattering dimensions. The reason is that these dimensions are not 282*e4b17023SJohn Marino entirely unused. They are not necessary as part of the scheduling 283*e4b17023SJohn Marino vector, as the earlier dimensions already unambiguously define the 284*e4b17023SJohn Marino execution time, however they may still be needed to carry modulo 285*e4b17023SJohn Marino constraints as introduced e.g. by strip mining. The correct solution 286*e4b17023SJohn Marino would be to project these dimensions out of the scattering polyhedra. 287*e4b17023SJohn Marino In case they are still required to carry modulo constraints they should be kept 288*e4b17023SJohn Marino internally as existentially quantified dimensions. PPL does only support 289*e4b17023SJohn Marino projection of rational polyhedra, however in this case we need an integer 290*e4b17023SJohn Marino projection. With isl this will be trivial to implement. For now we just 291*e4b17023SJohn Marino leave the dimensions. This is a little ugly, but should be correct. */ 292*e4b17023SJohn Marino if (0) { 293*e4b17023SJohn Marino ds = XNEWVEC (ppl_dimension_type, 2); 294*e4b17023SJohn Marino ds[0] = inner_dim; 295*e4b17023SJohn Marino ds[1] = inner_dim + 1; 296*e4b17023SJohn Marino ppl_Polyhedron_remove_space_dimensions (poly, ds, 2); 297*e4b17023SJohn Marino PBB_NB_SCATTERING_TRANSFORM (pbb) -= 2; 298*e4b17023SJohn Marino free (ds); 299*e4b17023SJohn Marino } 300*e4b17023SJohn Marino } 301*e4b17023SJohn Marino 302*e4b17023SJohn Marino mpz_clear (x); 303*e4b17023SJohn Marino ppl_delete_Coefficient (one); 304*e4b17023SJohn Marino } 305*e4b17023SJohn Marino 306*e4b17023SJohn Marino /* Flattens the loop nest LST. Return true when something changed. 307*e4b17023SJohn Marino OFFSET is used to compute the number of iterations of the outermost 308*e4b17023SJohn Marino loop before the current LST is executed. */ 309*e4b17023SJohn Marino 310*e4b17023SJohn Marino static bool 311*e4b17023SJohn Marino lst_flatten_loop (lst_p lst, mpz_t init_offset) 312*e4b17023SJohn Marino { 313*e4b17023SJohn Marino int i; 314*e4b17023SJohn Marino lst_p l; 315*e4b17023SJohn Marino bool res = false; 316*e4b17023SJohn Marino mpz_t n, one, offset, stride; 317*e4b17023SJohn Marino 318*e4b17023SJohn Marino mpz_init (n); 319*e4b17023SJohn Marino mpz_init (one); 320*e4b17023SJohn Marino mpz_init (offset); 321*e4b17023SJohn Marino mpz_init (stride); 322*e4b17023SJohn Marino mpz_set (offset, init_offset); 323*e4b17023SJohn Marino mpz_set_si (one, 1); 324*e4b17023SJohn Marino 325*e4b17023SJohn Marino lst_linearized_niter (lst, stride); 326*e4b17023SJohn Marino lst_niter_for_loop (lst, n); 327*e4b17023SJohn Marino mpz_tdiv_q (stride, stride, n); 328*e4b17023SJohn Marino 329*e4b17023SJohn Marino FOR_EACH_VEC_ELT (lst_p, LST_SEQ (lst), i, l) 330*e4b17023SJohn Marino if (LST_LOOP_P (l)) 331*e4b17023SJohn Marino { 332*e4b17023SJohn Marino res = true; 333*e4b17023SJohn Marino 334*e4b17023SJohn Marino lst_flatten_loop (l, offset); 335*e4b17023SJohn Marino lst_niter_for_loop (l, n); 336*e4b17023SJohn Marino 337*e4b17023SJohn Marino lst_project_loop (lst, l, stride); 338*e4b17023SJohn Marino 339*e4b17023SJohn Marino /* The offset is the number of iterations minus 1, as we want 340*e4b17023SJohn Marino to execute the next statements at the same iteration as the 341*e4b17023SJohn Marino last iteration of the loop. */ 342*e4b17023SJohn Marino mpz_sub (n, n, one); 343*e4b17023SJohn Marino mpz_add (offset, offset, n); 344*e4b17023SJohn Marino } 345*e4b17023SJohn Marino else 346*e4b17023SJohn Marino { 347*e4b17023SJohn Marino lst_scale (lst, l, stride); 348*e4b17023SJohn Marino if (mpz_cmp_si (offset, 0) != 0) 349*e4b17023SJohn Marino lst_offset (l, offset); 350*e4b17023SJohn Marino } 351*e4b17023SJohn Marino 352*e4b17023SJohn Marino FOR_EACH_VEC_ELT (lst_p, LST_SEQ (lst), i, l) 353*e4b17023SJohn Marino if (LST_LOOP_P (l)) 354*e4b17023SJohn Marino lst_remove_loop_and_inline_stmts_in_loop_father (l); 355*e4b17023SJohn Marino 356*e4b17023SJohn Marino mpz_clear (n); 357*e4b17023SJohn Marino mpz_clear (one); 358*e4b17023SJohn Marino mpz_clear (offset); 359*e4b17023SJohn Marino mpz_clear (stride); 360*e4b17023SJohn Marino return res; 361*e4b17023SJohn Marino } 362*e4b17023SJohn Marino 363*e4b17023SJohn Marino /* Remove all but the first 3 dimensions of the scattering: 364*e4b17023SJohn Marino - dim0: the static schedule for the loop 365*e4b17023SJohn Marino - dim1: the dynamic schedule of the loop 366*e4b17023SJohn Marino - dim2: the static schedule for the loop body. */ 367*e4b17023SJohn Marino 368*e4b17023SJohn Marino static void 369*e4b17023SJohn Marino remove_unused_scattering_dimensions (lst_p lst) 370*e4b17023SJohn Marino { 371*e4b17023SJohn Marino int i; 372*e4b17023SJohn Marino lst_p stmt; 373*e4b17023SJohn Marino mpz_t x; 374*e4b17023SJohn Marino ppl_Coefficient_t one; 375*e4b17023SJohn Marino 376*e4b17023SJohn Marino mpz_init (x); 377*e4b17023SJohn Marino mpz_set_si (x, 1); 378*e4b17023SJohn Marino ppl_new_Coefficient (&one); 379*e4b17023SJohn Marino ppl_assign_Coefficient_from_mpz_t (one, x); 380*e4b17023SJohn Marino 381*e4b17023SJohn Marino FOR_EACH_VEC_ELT (lst_p, LST_SEQ (lst), i, stmt) 382*e4b17023SJohn Marino { 383*e4b17023SJohn Marino poly_bb_p pbb = LST_PBB (stmt); 384*e4b17023SJohn Marino ppl_Polyhedron_t poly = PBB_TRANSFORMED_SCATTERING (pbb); 385*e4b17023SJohn Marino int j, nb_dims_to_remove = PBB_NB_SCATTERING_TRANSFORM (pbb) - 3; 386*e4b17023SJohn Marino ppl_dimension_type *ds; 387*e4b17023SJohn Marino 388*e4b17023SJohn Marino /* There should be no loops inside LST after flattening. */ 389*e4b17023SJohn Marino gcc_assert (!LST_LOOP_P (stmt)); 390*e4b17023SJohn Marino 391*e4b17023SJohn Marino if (!nb_dims_to_remove) 392*e4b17023SJohn Marino continue; 393*e4b17023SJohn Marino 394*e4b17023SJohn Marino ds = XNEWVEC (ppl_dimension_type, nb_dims_to_remove); 395*e4b17023SJohn Marino for (j = 0; j < nb_dims_to_remove; j++) 396*e4b17023SJohn Marino ds[j] = j + 3; 397*e4b17023SJohn Marino 398*e4b17023SJohn Marino ppl_Polyhedron_remove_space_dimensions (poly, ds, nb_dims_to_remove); 399*e4b17023SJohn Marino PBB_NB_SCATTERING_TRANSFORM (pbb) -= nb_dims_to_remove; 400*e4b17023SJohn Marino free (ds); 401*e4b17023SJohn Marino } 402*e4b17023SJohn Marino 403*e4b17023SJohn Marino mpz_clear (x); 404*e4b17023SJohn Marino ppl_delete_Coefficient (one); 405*e4b17023SJohn Marino } 406*e4b17023SJohn Marino 407*e4b17023SJohn Marino /* Flattens all the loop nests of LST. Return true when something 408*e4b17023SJohn Marino changed. */ 409*e4b17023SJohn Marino 410*e4b17023SJohn Marino static bool 411*e4b17023SJohn Marino lst_do_flatten (lst_p lst) 412*e4b17023SJohn Marino { 413*e4b17023SJohn Marino int i; 414*e4b17023SJohn Marino lst_p l; 415*e4b17023SJohn Marino bool res = false; 416*e4b17023SJohn Marino mpz_t zero; 417*e4b17023SJohn Marino 418*e4b17023SJohn Marino if (!lst 419*e4b17023SJohn Marino || !LST_LOOP_P (lst)) 420*e4b17023SJohn Marino return false; 421*e4b17023SJohn Marino 422*e4b17023SJohn Marino mpz_init (zero); 423*e4b17023SJohn Marino mpz_set_si (zero, 0); 424*e4b17023SJohn Marino 425*e4b17023SJohn Marino FOR_EACH_VEC_ELT (lst_p, LST_SEQ (lst), i, l) 426*e4b17023SJohn Marino if (LST_LOOP_P (l)) 427*e4b17023SJohn Marino { 428*e4b17023SJohn Marino res |= lst_flatten_loop (l, zero); 429*e4b17023SJohn Marino 430*e4b17023SJohn Marino /* FIXME: As long as we use PPL we are not able to remove the old 431*e4b17023SJohn Marino scattering dimensions. The reason is that these dimensions are not 432*e4b17023SJohn Marino entirely unused. They are not necessary as part of the scheduling 433*e4b17023SJohn Marino vector, as the earlier dimensions already unambiguously define the 434*e4b17023SJohn Marino execution time, however they may still be needed to carry modulo 435*e4b17023SJohn Marino constraints as introduced e.g. by strip mining. The correct solution 436*e4b17023SJohn Marino would be to project these dimensions out of the scattering polyhedra. 437*e4b17023SJohn Marino In case they are still required to carry modulo constraints they should be kept 438*e4b17023SJohn Marino internally as existentially quantified dimensions. PPL does only support 439*e4b17023SJohn Marino projection of rational polyhedra, however in this case we need an integer 440*e4b17023SJohn Marino projection. With isl this will be trivial to implement. For now we just 441*e4b17023SJohn Marino leave the dimensions. This is a little ugly, but should be correct. */ 442*e4b17023SJohn Marino if (0) 443*e4b17023SJohn Marino remove_unused_scattering_dimensions (l); 444*e4b17023SJohn Marino } 445*e4b17023SJohn Marino 446*e4b17023SJohn Marino lst_update_scattering (lst); 447*e4b17023SJohn Marino mpz_clear (zero); 448*e4b17023SJohn Marino return res; 449*e4b17023SJohn Marino } 450*e4b17023SJohn Marino 451*e4b17023SJohn Marino /* Flatten all the loop nests in SCOP. Returns true when something 452*e4b17023SJohn Marino changed. */ 453*e4b17023SJohn Marino 454*e4b17023SJohn Marino bool 455*e4b17023SJohn Marino flatten_all_loops (scop_p scop) 456*e4b17023SJohn Marino { 457*e4b17023SJohn Marino return lst_do_flatten (SCOP_TRANSFORMED_SCHEDULE (scop)); 458*e4b17023SJohn Marino } 459*e4b17023SJohn Marino 460*e4b17023SJohn Marino #endif 461