This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: std::pow implementation


Op di 29-07-2003, om 14:04 schreef Gabriel Dos Reis:
> Richard Guenther <rguenth@tat.physik.uni-tuebingen.de> writes:
> 
> | for my scientific app. If this ends up the same way as the
> | __attribute__((leafify)) discussion, I'll stop complaining now and instead
> | just file a PR for the record.
> 
> I bet your application will benefit much more from a better inlining
> support in the compiler than obfuscating the library.
> (Note that it need not be a sophisticated inliner).  We get to that point
> because, at some point it was decided that the compiler knows better
> than the programmer.

Can you stop bashing and be reasonable for once?  If you were so great
you would have declated __cmath_power inline in the first place.

If I do that, and compile with the tree-ssa branch at -O3 for this test
case:

=============================================
namespace std 
{
  // NB inline keyword which is not in libstdc++v3 __cmath_power
  template<typename _Tp>
    inline _Tp
    __cmath_power(_Tp __x, unsigned int __n)
    {
      _Tp __y = __n % 2 ? __x : 1;

      while (__n >>= 1)
        {
          __x = __x * __x;
          if (__n % 2)
            __y = __y * __x;
        }

      return __y;
    }

  template<typename _Tp>
    inline _Tp
    __pow_helper(_Tp __x, int __n)
    {
      return __n < 0
        ? _Tp(1)/__cmath_power(__x, -__n)
        : __cmath_power(__x, __n);
    }

  inline double 
  pow(double __x, int __i)
  { return __pow_helper(__x, __i); }
} 

double foo(double x)
{
  return std::pow(x, 2);
}
=============================================

I get the following tree dump after inlining:

=============================================
;; Function double foo(double) (_Z3food)

double foo(double) (x)
{
  double retval.12;
  double retval.11;
  double retval.10;
  double retval.9;

  {
    {
      int __i;
      double __x;
      double <UVb60>;

      __x = x;
      __i = 2;
      {
        double T.1;

        {
          {
            int __n;
            double __x;
            double <UVe70>;

            __x = __x;
            __n = __i;
            {
              double iftmp.4;
              int T.5;
              unsigned int T.6;
              double T.7;
              unsigned int __n.8;

              {
                if (__n < 0)
                  {
                    T.5 = -__n;
                    T.6 = (unsigned int)T.5;
                    {
                      unsigned int __n;
                      double __x;
                      double <UV5380>;

                      __x = __x;
                      __n = T.6;
                      {
                        double iftmp.2;
                        unsigned int T.3;

                        {
                          double __y;

                          T.3 = __n % 2;
                          if (T.3 != 0)
                            {
                              iftmp.2 = __x
                            }
                          else
                            {
                              iftmp.2 = 1.0e+0
                            };
                          __y = iftmp.2;
                          while (1)
                            {
                              __n = __n >> 1;
                              if (__n == 0)
                                {
                                  goto <UL5540>;
                                }
                              else
                                {
                                  (void)0
                                };
                              {
                                {
                                  __x = __x * __x;
                                  {
                                    T.3 = __n % 2;
                                    if (T.3 != 0)
                                      {
                                        {
                                          __y = __y * __x
                                        }
                                      }
                                    else
                                      {
                                        (void)0
                                      }
                                  }
                                }
                              }
                            };
                          <UL5540>:;;
                          {
                            <UV5380> = __y;
                            goto <UL5310>;
                          }
                        }
                      };
                      <UL5310>:;;
                      retval.11 = <UV5380>
                    };
                    T.7 = retval.11;
                    iftmp.4 = 1.0e+0 / T.7
                  }
                else
                  {
                    __n.8 = (unsigned int)__n;
                    {
                      unsigned int __n;
                      double __x;
                      double <UV57e0>;

                      __x = __x;
                      __n = __n.8;
                      {
                        double iftmp.2;
                        unsigned int T.3;

                        {
                          double __y;

                          T.3 = __n % 2;
                          if (T.3 != 0)
                            {
                              iftmp.2 = __x
                            }
                          else
                            {
                              iftmp.2 = 1.0e+0
                            };
                          __y = iftmp.2;
                          while (1)
                            {
                              __n = __n >> 1;
                              if (__n == 0)
                                {
                                  goto <UL59a0>;
                                }
                              else
                                {
                                  (void)0
                                };
                              {
                                {
                                  __x = __x * __x;
                                  {
                                    T.3 = __n % 2;
                                    if (T.3 != 0)
                                      {
                                        {
                                          __y = __y * __x
                                        }
                                      }
                                    else
                                      {
                                        (void)0
                                      }
                                  }
                                }
                              }
                            };
                          <UL59a0>:;;
                          {
                            <UV57e0> = __y;
                            goto <UL5770>;
                          }
                        }
                      };
                      <UL5770>:;;
                      retval.12 = <UV57e0>
                    };
                    iftmp.4 = retval.12
                  };
                (void)0;
                {
                  <UVe70> = iftmp.4;
                  goto <ULe00>;
                }
              }
            };
            <ULe00>:;;
            retval.10 = <UVe70>
          };
          T.1 = retval.10;
          (void)0;
          {
            <UVb60> = T.1;
            goto <ULaf0>;
          }
        }
      };
      <ULaf0>:;;
      retval.9 = <UVb60>
    };
    return retval.9;
  }
}
=============================================

which looks like this after tree-optimizing:

=============================================

;; Function double foo(double) (_Z3food)

double foo(double) (x)
{
  {
    {
      if (0)
        {
          {
            (void)0
          }
        }
      else
        {
          {
            unsigned int __n;
            double __x;

            {
              unsigned int T.3;

              {
                double __y;

                __x = x;
                __y = 1.0e+0;
                __n = 2;
                while (1)
                  {
                    __n = __n >> 1;
                    if (__n == 0)
                      {
                        goto <UL59a0>;
                      }
                    else
                      {
                        (void)0
                      };
                    __x = __x * __x;
                    T.3 = __n % 2;
                    if (T.3 != 0)
                      {
                        __y = __y * __x
                      }
                    else
                      {
                        (void)0
                      }
                  };
                <UL59a0>:;
              }
            };
            <UL5770>:;
          }
        };
      <ULe00>:;
    };
    <ULaf0>:;
  };
  return __y;
}
=============================================


Now cut away all the redundant labels and other cruft, and you end up
with:


;; Function double foo(double) (_Z3food)

double foo(double) (x)
{
  unsigned int __n;
  double __x;
  unsigned int T.3;
  double __y;

  __x = x;
  __y = 1.0e+0;
  __n = 2;
  while (1)
    {
      __n = __n >> 1;
      if (__n == 0)
	goto <UL59a0>;

      __x = __x * __x;
      T.3 = __n % 2;

      if (T.3 != 0)
	__y = __y * __x
    }
  <UL59a0>:;
  return __y;
}

which is exactly what you want, is it not??

Gr.
Steven


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]