Aurelien Buhrig <aurelien.buhrig.gcc@xxxxxxxxx> writes: > Lets consider the lt comparison. > My target has V and N hardware flags which are respectively set when an > overflow occurs and when the result is negative. > It can branch when N xor V == 1, but can also branch when N == 1. The > difference is that the first test really compares (lt r0 r1) (taking > into account the overflow) whereas the latter compares the "truncated" > result of the sub with 0, which are different when an overflow occurs. > So, from the hardware point of view, one comparison, two different lt > meanings... > > So the question is more about the RTL difference there would be between > (set (pc) (if_then_else (lt (sub r0 r1) (const_int 0)) (label_ref) (pc))) > and > (set (pc) (if_then_else (lt r0 r1) (label_ref) (pc))) > and the ability / correctness to merge both insn (if different) with a > (sub r0 r1) (in combine or cse pass). The first one (lt (sub r0 r1) (const_int 0)) can be combined with a sub insn, if the result of the sub insn is not used. The second one can not. > And the main question is: can the N==1 test be useful for the backend? > For instance, in C, I think an overflow has undefined behavior, so > testing for an overflowed result seems meaningless. Signed overflow is undefined, but unsigned overflow wraps. So it is possible to write valid code that could use an overflow flag using unsigned types. But it's uncommon. > If it is useless, perhaps I should change the hardware behavior (yes, I > can) so that to replace the branch negative to something more useful > such as a branch GT. For now, a cbranch GT is implemented by changing > the comparison operands and emitting a cbranch GE or LT, but it is not > possible to combine a sub with (gt result 0) cbranch. So perhaps I could > save some comparison insns. I think that from the compiler's perspective the most useful sorts of conditional branches are the ones that say "if Rn COND Rm then jump", where COND is any of EQ, NE, LE, LT, GT, GE, ULE, ULT, UGT, UGE (of course symmetry lets you drop GT, GE, UGT, UGE for integers, and of course you don't need the U variants for floating point). Anything involving condition flags is harder to generate code for, although I understand that it permits additional pipelining in the processor. If the processor has to have condition flags then I suspect that the best results will come from instructions that store the results of the condition in a general register, and conditional branches that can test any general register against zero. Ian