optimization blocks (csapp chapter 5.1)

p_511

编译器在没有指示下,会做‘ safe optimization',因此有些优化在没有参数的指示下是不会对代码做优化的,故在程序中应该避免某一类代码,因为它们妨碍了编译器做优化。

optimization blocks: aspects of programs that can severely limit the opportunities for a compiler to generate optimized code;

两类optimization blocks:

1、memory aliasing

 pointers may generate the same memory location is known as memory aliasing. In performing only safe optimizations, the compiler must assume that different pointers may be aliased, limiting the set of possible optimizations.

// from cmu
/* Sum rows is of n X n matrix a
   and store in vector b  */
void sum_rows1(int  *a, int  *b, int n) {
    int i, j;
    for (i = 0; i < n; i++) {
    b[i] = 0;
    for (j = 0; j < n; j++)
        b[i] += a[i*n + j];
    }
}

/*如果我们调用时为
  int A[9];
  int* B = A + 3;
  sum_rows1(A, B);
  如果编译器将其优化成如下类的形式,显然有背原意
   void sum_rows2(int *a, int *b, int n) {
    int i, j;
    for (i = 0; i < n; i++) {
    double val = 0;
    for (j = 0; j < n; j++)
        val += a[i*n + j];
         b[i] = val;
    }
}*/

/* 简化了 sum_rows1: .L4: movl %ebp, %ecx movl $0, (%edx,%ebp,4) movl $0, %eax .L3: movl (%esi,%eax,4), %ebx ;(%esi, %eax, 4) : &a[i*n + j] addl %ebx, (%edx,%ecx,4) ;(%edx, %ecx, 4) : &b[i] addl $1, %eax ;%eax : j cmpl %edi, %eax ;%edi : n jne .L3 addl $1, %ebp ;%ebp : i addl (%esp), %esi cmpl %edi, %ebp jne .L4 */
//书上例子
//当xp = yp时,twiddle1 与 twiddle2显然不同,因此编译器不会做一些优化,以免将twiddle1优化成与twiddle2相同的功能函数
void twiddle1(int *xp, int* yp)
{
     *xp += *yp;
     *xp += *yp;   
}

void twiddle2(int *xp, int* yp)
{
      *xp += 2* *yp;
}

2、procedure calls

    Most compilers do not try to determine whether a function is free of side effects and hence is a candidate for optimizations.Instead, the compiler assumes the worst case and leaves function call intact(原封不动)

//经典(from cmu)
void lower(char* s)
{
      int i = 0;
      for (i = 0; i < strlen(s); i++)
            if(s[i] >= 'A' && s[i] <= 'Z')
                  s[i] -= ('A' - 'a');      
}

//编译器为何不把strlen(s)提取出来,作为一个临时量,这样就可以减少函数调用了?

//Why couldn’t compiler move strlen out of  inner loop?
//      (1)Procedure may have side effects
//                 Alters global state each time called
//       (2)Function may not return same value for given arguments
//                  Depends on other parts of global state
//                  Procedure lower could interact with strlen

//Warning:1)Compiler treats procedure call as a black box
          (2)Weak optimizations near them
//书上的例子
int f(void);

int func1(void)
{
     return f() + f() + f() + f();
//procedure call不可优化成4*f(), 否则就错了
}

int func2(void)
{
     return 4 * f();   
}

int counter = 0;

int f(void)
{
     return counter++;
}
原文地址:https://www.cnblogs.com/openix/p/3199264.html