4 ms·
Is it always safe to make this change without considering the surrounding code? If you start with this code: testl %ebx, %ebx # Set zero flag if %ebx is
by abbeyj 5y ago
Is it always safe to make this change without considering the surrounding code? If you start with this code:
testl %ebx, %ebx # Set zero flag if %ebx is zero
movl $0, %eax # Set %eax to zero
jz somewhere # Jump if %ebx was zero
then after optimization you get this:
testl %ebx, %ebx # Set zero flag if %ebx is zero
xorl %eax, %eax # Set %eax to zero *and set zero flag*
jz somewhere # Jump always
Maybe this is OK because TCC doesn't (currently) generate any code like this.
- kazinator 5y agoGreat point. Now if the program were divided into basic blocks, then any jump based on flags would necessarily be the last instruction of the current basic block. Suppose that the program has the property that flags are always consumed in the same basic block. Then the control info is enough. So whenever we replace movl $0, eax, by xor, we can just check whether or not we are in a basic block that ends with a jump conditional on the Z flag. If that doesn't hold, we need data flow info. For each instruction, we can know from doing data flow analysis whether there are any live flags: CPU flags whose current values are used down later in the program. E.g. say we have: movl $0, %eax movl $0, %ecx movl abc, %esi clz Here, data flow analysis tells us that the Z flag is dead at the movl instruction, because the only possible execution path reaches a clz, and nothing uses the Z flag before then. Thus we are free to clobber it. Moreover, when we do so, the data flow picture doesn't change. The Z flag is dead at the movl, and is still dead when that is replaced by xorl. The optimization doesn't require a recalculation of the data flow info.