user-0 提问: C移除分支预测

回复:
user: user-1
content: int func(int a) { if(a>32767)    return 32767; if(a<-32768)    return -32768; else      return a; } int func2(int a ) {   int sz = sizeof(int) * CHAR_BIT - 1;   int bigger = ~((a >> sz) | ((a - 32767) >> sz));  // if a > 32767, bigger == 0xffffffff, else bigger ==0;   int smaller  = (a >> sz) & ((a + 32768) >> sz); // if a < -32768, smaller == 0xffffffff, else smaller ==0;   int res = 0;   res += bigger & 32767;   res += smaller & (-32768);   res += (~bigger) & (~smaller) & a;   return res;  }

user: user-1
content: 引用 9 楼 fefe82 的回复:[quote=引用 4 楼 asxqy714 的回复:] [quote=引用 3 楼 fefe82 的回复:] [quote=引用 2 楼 asxqy714 的回复:] [quote=引用 1 楼 fefe82 的回复:] 哪些属于条件执行指令？ ? :  算吗？ if else while swicth 这些需要判断的都是条件执行指令[/quote]  return a>32767 ? 32767 : (a<-32768 ? -32768 : a);[/quote] 有没有类似 if (data[c] >= 128)     sum += data[c]; 替换为： int t = (data[c] - 128) >> 31; sum += ~t & data[c]; 这样的方法[/quote] 这个不对。  如果 data[c] == 0x80000000 （ 绝对值最大的负数）， data[c] - 128 = 0xeffffff80, t = 0, ~t = 0xffffffff[/quote]  大概应该改成 int t = (data[c] >> 31) | (data[c] - 128) >> 31

user: user-0
content: 引用 14 楼 fefe82 的回复:最多连续回复三次，终于可以继续了 ... 顺带回复7楼 ==================== 最后，让我们看看我们的这些努力在现在的 CPU 和 编译器 下是多么的没有意义：  原始的带有 if 的 func 会被编译成下面的样子 （gcc -O2）(%edi 是参数, %eax 是返回值）    cmp    $0xffff8000,%edi   mov    $0xffff8000,%eax   mov    $0x7fff,%edx   cmovge %edi,%eax   cmp    $0x7fff,%eax   cmovg  %edx,%eax   retq  两个减法(cmp)，其余全部是 mov 类指令，没有分支，没有其它运算 ... 再一次学习了

user: user-2
content: C 的话，inline 函数，都改成 宏定义

user: user-1
content: 引用 4 楼 asxqy714 的回复:[quote=引用 3 楼 fefe82 的回复:] [quote=引用 2 楼 asxqy714 的回复:] [quote=引用 1 楼 fefe82 的回复:] 哪些属于条件执行指令？ ? :  算吗？ if else while swicth 这些需要判断的都是条件执行指令[/quote]  return a>32767 ? 32767 : (a<-32768 ? -32768 : a);[/quote] 有没有类似 if (data[c] >= 128)     sum += data[c]; 替换为： int t = (data[c] - 128) >> 31; sum += ~t & data[c]; 这样的方法[/quote] 这个不对。  如果 data[c] == 0x80000000 （ 绝对值最大的负数）， data[c] - 128 = 0xeffffff80, t = 0, ~t = 0xffffffff

user: user-2
content: inline bool is_plus_long(int a) { return a>32767; } inline bool is_neg_long(int a)｛return a<-32768;｝ inline bool is_short(int a){return !is_plus_long(a) && !is_neg_long(a);} //func 的实现 inline int make_short(int a){          return is_plus_long( a )*32767 + is_neg_long( a )*(-32768) + is_short (a) *a; }  用乘法 实现 分支效果 比较指令可以优化为 非跳转指令 如此即可 不过这种优化，真的有必要么？

user: user-0
content: 引用 5 楼 fefe82 的回复:[quote=引用 4 楼 asxqy714 的回复:] [quote=引用 3 楼 fefe82 的回复:] [quote=引用 2 楼 asxqy714 的回复:] [quote=引用 1 楼 fefe82 的回复:] 哪些属于条件执行指令？ ? :  算吗？ if else while swicth 这些需要判断的都是条件执行指令[/quote]  return a>32767 ? 32767 : (a<-32768 ? -32768 : a);[/quote] 有没有类似 if (data[c] >= 128)     sum += data[c]; 替换为： int t = (data[c] - 128) >> 31; sum += ~t & data[c]; 这样的方法[/quote]  The result of E1 >> E2 is E1 right-shifted E2 bit positions. If E1 has an unsigned type or if E1 has a signed type and a nonnegative value, the value of the result is the integral part of the quotient of E1 / 2E2. If E1 has a signed type and a negative value, the resulting value is implementation-defined.[/quote] 还和编译器有关

user: user-1
content: 最多连续回复三次，终于可以继续了 ... 顺带回复7楼 ==================== 最后，让我们看看我们的这些努力在现在的 CPU 和 编译器 下是多么的没有意义：  原始的带有 if 的 func 会被编译成下面的样子 （gcc -O2）(%edi 是参数, %eax 是返回值）    cmp    $0xffff8000,%edi   mov    $0xffff8000,%eax   mov    $0x7fff,%edx   cmovge %edi,%eax   cmp    $0x7fff,%eax   cmovg  %edx,%eax   retq  两个减法(cmp)，其余全部是 mov 类指令，没有分支，没有其它运算 ...

user: user-1
content: 引用 4 楼 asxqy714 的回复:[quote=引用 3 楼 fefe82 的回复:] [quote=引用 2 楼 asxqy714 的回复:] [quote=引用 1 楼 fefe82 的回复:] 哪些属于条件执行指令？ ? :  算吗？ if else while swicth 这些需要判断的都是条件执行指令[/quote]  return a>32767 ? 32767 : (a<-32768 ? -32768 : a);[/quote] 有没有类似 if (data[c] >= 128)     sum += data[c]; 替换为： int t = (data[c] - 128) >> 31; sum += ~t & data[c]; 这样的方法[/quote]  The result of E1 >> E2 is E1 right-shifted E2 bit positions. If E1 has an unsigned type or if E1 has a signed type and a nonnegative value, the value of the result is the integral part of the quotient of E1 / 2E2. If E1 has a signed type and a negative value, the resulting value is implementation-defined.

user: user-0
content: 引用 11 楼 fefe82 的回复:  int func(int a) { if(a>32767)    return 32767; if(a<-32768)    return -32768; else      return a; } int func2(int a ) {   int sz = sizeof(int) * CHAR_BIT - 1;   int bigger = ~((a >> sz) | ((a - 32767) >> sz));  // if a > 32767, bigger == 0xffffffff, else bigger ==0;   int smaller  = (a >> sz) & ((a + 32768) >> sz); // if a < -32768, smaller == 0xffffffff, else smaller ==0;   int res = 0;   res += bigger & 32767;   res += smaller & (-32768);   res += (~bigger) & (~smaller) & a;   return res;  }  这个正是我想要的，学习了，十分感谢！

user: user-0
content: 引用 7 楼 user-2 的回复:inline bool is_plus_long(int a) { return a>32767; } inline bool is_neg_long(int a)｛return a<-32768;｝ inline bool is_short(int a){return !is_plus_long(a) && !is_neg_long(a);} //func 的实现 inline int make_short(int a){          return is_plus_long( a )*32767 + is_neg_long( a )*(-32768) + is_short (a) *a; }  用乘法 实现 分支效果 比较指令可以优化为 非跳转指令 如此即可 不过这种优化，真的有必要么？ 感谢你的回答，小白一个，做一个面试题，没遇到过这种问题，主要是要学会决解这种问题的思想。再次感谢！

user: user-0
content: 引用 3 楼 fefe82 的回复:[quote=引用 2 楼 asxqy714 的回复:] [quote=引用 1 楼 fefe82 的回复:] 哪些属于条件执行指令？ ? :  算吗？ if else while swicth 这些需要判断的都是条件执行指令[/quote]  return a>32767 ? 32767 : (a<-32768 ? -32768 : a);[/quote] 有没有类似 if (data[c] >= 128)     sum += data[c]; 替换为： int t = (data[c] - 128) >> 31; sum += ~t & data[c]; 这样的方法

user: user-1
content: 引用 2 楼 asxqy714 的回复:[quote=引用 1 楼 fefe82 的回复:] 哪些属于条件执行指令？ ? :  算吗？ if else while swicth 这些需要判断的都是条件执行指令[/quote]  return a>32767 ? 32767 : (a<-32768 ? -32768 : a);

user: user-0
content: 引用 1 楼 fefe82 的回复:哪些属于条件执行指令？ ? :  算吗？ if else while swicth 这些需要判断的都是条件执行指令

user: user-1
content: 哪些属于条件执行指令？ ? :  算吗？