OSDN Git Service

PR rtl-optimization/19464
[pf3gnuchains/gcc-fork.git] / gcc / lambda-code.c
index d564f43..40f3ac3 100644 (file)
@@ -53,7 +53,7 @@
 
  A loop iteration space represents the points traversed by the loop.  A point in the
  iteration space can be represented by a vector of size <loop depth>.  You can
- therefore represent the iteration space as a integral combinations of a set
+ therefore represent the iteration space as an integral combinations of a set
  of basis vectors. 
 
  A loop iteration space is dense if every integer point between the loop
@@ -651,7 +651,19 @@ compute_nest_using_fourier_motzkin (int size,
 }
 
 /* Compute the loop bounds for the auxiliary space NEST.
-   Input system used is Ax <= b.  TRANS is the unimodular transformation.  */
+   Input system used is Ax <= b.  TRANS is the unimodular transformation.  
+   Given the original nest, this function will 
+   1. Convert the nest into matrix form, which consists of a matrix for the
+   coefficients, a matrix for the 
+   invariant coefficients, and a vector for the constants.  
+   2. Use the matrix form to calculate the lattice base for the nest (which is
+   a dense space) 
+   3. Compose the dense space transform with the user specified transform, to 
+   get a transform we can easily calculate transformed bounds for.
+   4. Multiply the composed transformation matrix times the matrix form of the
+   loop.
+   5. Transform the newly created matrix (from step 4) back into a loop nest
+   using fourier motzkin elimination to figure out the bounds.  */
 
 static lambda_loopnest
 lambda_compute_auxillary_space (lambda_loopnest nest,
@@ -786,9 +798,11 @@ lambda_compute_auxillary_space (lambda_loopnest nest,
 }
 
 /* Compute the loop bounds for the target space, using the bounds of
-   the auxiliary nest AUXILLARY_NEST, and the triangular matrix H.  This is
-   done by matrix multiplication and then transformation of the new matrix
-   back into linear expression form.
+   the auxiliary nest AUXILLARY_NEST, and the triangular matrix H.  
+   The target space loop bounds are computed by multiplying the triangular
+   matrix H by the auxillary nest, to get the new loop bounds.  The sign of
+   the loop steps (positive or negative) is then used to swap the bounds if
+   the loop counts downwards.
    Return the target loopnest.  */
 
 static lambda_loopnest
@@ -1853,6 +1867,7 @@ lambda_loopnest_to_gcc_loopnest (struct loop *old_loopnest,
     {
       lambda_loop newloop;
       basic_block bb;
+      edge exit;
       tree ivvar, ivvarinced, exitcond, stmts;
       enum tree_code testtype;
       tree newupperbound, newlowerbound;
@@ -1886,7 +1901,7 @@ lambda_loopnest_to_gcc_loopnest (struct loop *old_loopnest,
                                             new_ivs,
                                             invariants, MAX_EXPR, &stmts);
       bsi_insert_on_edge (loop_preheader_edge (temp), stmts);
-      bsi_commit_edge_inserts (NULL);
+      bsi_commit_edge_inserts ();
       /* Build the new upper bound and insert its statements in the
          basic block of the exit condition */
       newupperbound = lle_to_gcc_expression (LL_UPPER_BOUND (newloop),
@@ -1894,6 +1909,7 @@ lambda_loopnest_to_gcc_loopnest (struct loop *old_loopnest,
                                             type,
                                             new_ivs,
                                             invariants, MIN_EXPR, &stmts);
+      exit = temp->single_exit;
       exitcond = get_loop_exit_condition (temp);
       bb = bb_for_stmt (exitcond);
       bsi = bsi_start (bb);
@@ -1914,14 +1930,13 @@ lambda_loopnest_to_gcc_loopnest (struct loop *old_loopnest,
       
       testtype = LL_STEP (newloop) >= 0 ? LE_EXPR : GE_EXPR;
       
-      /* Since we don't know which cond_expr part currently points to each
-        edge, check which one is invariant and make sure we reverse the
-        comparison if we are trying to replace a <= 50 with 50 >= newiv.
-        This ensures that we still canonicalize to <invariant> <test>
-        <induction variable>.  */
-      if (!expr_invariant_in_loop_p (temp, TREE_OPERAND (exitcond, 0)))
+      /* We want to build a conditional where true means exit the loop, and
+        false means continue the loop.
+        So swap the testtype if this isn't the way things are.*/
+
+      if (exit->flags & EDGE_FALSE_VALUE)
        testtype = swap_tree_comparison (testtype);
-       
+
       COND_EXPR_COND (exitcond) = build (testtype,
                                         boolean_type_node,
                                         newupperbound, ivvarinced);
@@ -2174,9 +2189,10 @@ can_convert_to_perfect_nest (struct loop *loop,
                             VEC (tree) *loopivs)
 {
   basic_block *bbs;
-  tree exit_condition;
+  tree exit_condition, phi;
   size_t i;
   block_stmt_iterator bsi;
+  basic_block exitdest;
 
   /* Can't handle triply nested+ loops yet.  */
   if (!loop->inner || loop->inner->inner)
@@ -2218,6 +2234,16 @@ can_convert_to_perfect_nest (struct loop *loop,
            }
        }
     }  
+
+  /* We also need to make sure the loop exit only has simple copy phis in it,
+     otherwise we don't know how to transform it into a perfect nest right
+     now.  */
+  exitdest = loop->single_exit->dest;
+  
+  for (phi = phi_nodes (exitdest); phi; phi = PHI_CHAIN (phi))
+    if (PHI_NUM_ARGS (phi) != 1)
+      return false;
+
   return true;
 }
 
@@ -2294,9 +2320,6 @@ perfect_nestify (struct loops *loops,
 
   for (phi = phi_nodes (olddest); phi; phi = PHI_CHAIN (phi))
     {
-      /* These should be simple exit phi copies.  */
-      if (PHI_NUM_ARGS (phi) != 1)
-       return false;
       VEC_safe_push (tree, phis, PHI_RESULT (phi));
       VEC_safe_push (tree, phis, PHI_ARG_DEF (phi, 0));
       mark_for_rewrite (PHI_RESULT (phi));
@@ -2315,7 +2338,7 @@ perfect_nestify (struct loops *loops,
       def = VEC_pop (tree, phis);
       phiname = VEC_pop (tree, phis);      
       phi = create_phi_node (phiname, preheaderbb);
-      add_phi_arg (&phi, def, EDGE_PRED (preheaderbb, 0));
+      add_phi_arg (phi, def, EDGE_PRED (preheaderbb, 0));
     }       
   flush_pending_stmts (e);
   unmark_all_for_rewrite ();