「操作系统」: Conditional Move Instructions(trap)
Not all conditional expressions can be compiled using conditional moves. Most significantly, the abstract code we have shown evaluates both then-expr and else-expr regardless of the test outcome. If one of those two expressions could possibly generate an error condition or a side effect, this could lead to invalid behavior. As an illustration, consider the following C function:
1 int cread(int *xp){ 2 return (xp ? *xp : 0); 3 }
At first, this seems like a good candidate to compile using a conditional move to read the value designated by pointer xp, as shown in the following assembly code:
1 #Invalid implementation of function cread 2 #xp in register %edx 3 movl $0, %eax 4 testl %edx, %edx 5 cmovne (%edx), %eax
This implementation is invalid, however, since the dereferencing of xp by the cmovne instruction occurs even when the test fails, causing a null pointer dereferencing error.
Instead, this code must be compiled using branching code.
A similar case holds when either of the two branches causes a side effect, as illustrated by the following function:
1 /*Global variable*/ 2 int lcount = 0; 3 int absdiff_se(int x. int y){ 4 return x < y ? (lcount++, y-x) : x-y; 5 }
This function increments global variable lcount as part of then-expr. Thus, branching code must be used to ensure this side effect only occurs when the test condition holds.
Usingconditional moves also does not always improve code effciency. For example, if either the then-expr or the else-expr evaluation requires a significant computation, then this effort is wasted when the corresponding condition does not hold. Compilers must take into account the relative performance of wasted computation verus the potential for performance penalty due to branch misprediction. In truth, they do not know how well the branches will follow predictable patterns. GCC only uses conditional moves when the two expressions can be computed very easily, for example, with single add instructions.GCC uses conditional control transfers even in many cases where the cost of branch misprediction would exceed even more complex computations.