optimisation: changed some for() loops to do-while() to give the compiler
authorJean-Marc Valin <jean-marc.valin@usherbrooke.ca>
Wed, 26 Mar 2008 10:31:56 +0000 (21:31 +1100)
committerJean-Marc Valin <jean-marc.valin@usherbrooke.ca>
Wed, 26 Mar 2008 10:31:56 +0000 (21:31 +1100)
a hint that there has to be at least one iteration.

libcelt/rate.c
libcelt/rate.h
libcelt/vq.c

index 1a90034..fe0bad4 100644 (file)
@@ -1,4 +1,4 @@
-/* (C) 2007 Jean-Marc Valin, CSIRO
+/* (C) 2007-2008 Jean-Marc Valin, CSIRO
 */
 /*
    Redistribution and use in source and binary forms, with or without
 */
 /*
    Redistribution and use in source and binary forms, with or without
@@ -165,6 +165,7 @@ static int bits2pulses(const CELTMode *m, int band, int bits)
    for (i=0;i<LOG_MAX_PULSES;i++)
    {
       int mid = (lo+hi)>>1;
    for (i=0;i<LOG_MAX_PULSES;i++)
    {
       int mid = (lo+hi)>>1;
+      /* OPT: Make sure this is implemented with a conditional move */
       if (m->bits[band][mid] >= bits)
          hi = mid;
       else
       if (m->bits[band][mid] >= bits)
          hi = mid;
       else
index 968b8fd..0d69368 100644 (file)
@@ -1,4 +1,4 @@
-/* (C) 2007 Jean-Marc Valin, CSIRO
+/* (C) 2007-2008 Jean-Marc Valin, CSIRO
 */
 /*
    Redistribution and use in source and binary forms, with or without
 */
 /*
    Redistribution and use in source and binary forms, with or without
index cdba91e..3eb3390 100644 (file)
@@ -157,8 +157,9 @@ void alg_quant(celt_norm_t *X, celt_mask_t *W, int N, int K, const celt_norm_t *
       /* Choose between fast and accurate strategy depending on where we are in the search */
       if (pulsesLeft>1)
       {
       /* Choose between fast and accurate strategy depending on where we are in the search */
       if (pulsesLeft>1)
       {
-         for (j=0;j<N;j++)
-         {
+         /* OPT: This loop is very CPU-intensive */
+         j=0;
+         do {
             celt_word32_t num;
             celt_word16_t den;
             /* Select sign based on X[j] alone */
             celt_word32_t num;
             celt_word16_t den;
             /* Select sign based on X[j] alone */
@@ -173,13 +174,14 @@ void alg_quant(celt_norm_t *X, celt_mask_t *W, int N, int K, const celt_norm_t *
             den = ROUND16(Ryy,14);
             /* The idea is to check for num/den >= best_num/best_den, but that way
                we can do it without any division */
             den = ROUND16(Ryy,14);
             /* The idea is to check for num/den >= best_num/best_den, but that way
                we can do it without any division */
+            /* OPT: Make sure to use a conditional move here */
             if (MULT16_32_Q15(best_den, num) > MULT16_32_Q15(den, best_num))
             {
                best_den = den;
                best_num = num;
                best_id = j;
             }
             if (MULT16_32_Q15(best_den, num) > MULT16_32_Q15(den, best_num))
             {
                best_den = den;
                best_num = num;
                best_id = j;
             }
-         }
+         } while (++j<N); /* Promises we loop at least once */
       } else {
          for (j=0;j<N;j++)
          {
       } else {
          for (j=0;j<N;j++)
          {
@@ -275,17 +277,18 @@ void intra_prediction(celt_norm_t *x, celt_mask_t *W, int N, int K, celt_norm_t
       celt_word32_t xy=0, yy=0;
       celt_word32_t num;
       celt_word16_t den;
       celt_word32_t xy=0, yy=0;
       celt_word32_t num;
       celt_word16_t den;
-      /* If this doesn't generate a double-MAC on supported architectures, 
+      /* OPT: If this doesn't generate a double-MAC (on supported architectures),
          complain to your compilor vendor */
          complain to your compilor vendor */
-      for (j=0;j<N;j++)
-      {
+      j=0;
+      do {
          xy = MAC16_16(xy, x[j], Y[i+N-j-1]);
          yy = MAC16_16(yy, Y[i+N-j-1], Y[i+N-j-1]);
          xy = MAC16_16(xy, x[j], Y[i+N-j-1]);
          yy = MAC16_16(yy, Y[i+N-j-1], Y[i+N-j-1]);
-      }
+      } while (++j<N); /* Promises we loop at least once */
       /* Using xy^2/yy as the score but without having to do the division */
       num = MULT16_16(ROUND16(xy,14),ROUND16(xy,14));
       den = ROUND16(yy,14);
       /* If you're really desperate for speed, just use xy as the score */
       /* Using xy^2/yy as the score but without having to do the division */
       num = MULT16_16(ROUND16(xy,14),ROUND16(xy,14));
       den = ROUND16(yy,14);
       /* If you're really desperate for speed, just use xy as the score */
+      /* OPT: Make sure to use a conditional move here */
       if (MULT16_32_Q15(best_den, num) >  MULT16_32_Q15(den, best_num))
       {
          best_num = num;
       if (MULT16_32_Q15(best_den, num) >  MULT16_32_Q15(den, best_num))
       {
          best_num = num;