The first if-conversion pass causes performance drop on arm. For example on this code:
int f(int c) { int z = 0; if( c ) z = 0x66667777; else z = 0x99998888; return z; } It tries to transform the conditional code to if_then_else using the emit_conditional_move function. But emit_conditional_move decides that doing it directly is a bad idea (because the constants are big for arm and movsicc cannot accept them) so it creates two additional pseudos and moves the assignments of constants out of the block producing the following sequence of instructions: 45 r137:SI=0xffffffff99998888 46 r138:SI=0x66667777 47 cc:CC=cmp(r135:SI,0x0) 48 r133:SI={(cc:CC==0x0)?r137:SI:r138:SI} Then split2 converts if_then_else to cond_exec: 46 r3:SI=0x66667777 REG_EQUIV: 0x66667777 52 r2:SI=0xffffffff99998888 REG_EQUIV: 0xffffffff99998888 56 cc:CC=cmp(r0:SI,0x0) 57 (!cc:CC) r0:SI=r2:SI 58 (cc:CC) r0:SI=r3:SI Then the assignments of constants are converted to ldr's (or movt and movw on cortex-a8) that will be executed unconditionally. And there is no pass to put them back under conditional execution (and on cortex-a8 it's even harder to do since there will be two instructions for each load of a constant). RTL after split2 on cortex-a8: 53 r2:SI=0x8888 REG_EQUAL: 0x8888 56 r3:SI=0x7777 REG_EQUAL: 0x7777 54 zero_extract(r2:SI,0x10,0x10)=0x9999 57 zero_extract(r3:SI,0x10,0x10)=0x6666 63 cc:CC=cmp(r0:SI,0x0) 64 (!cc:CC) r0:SI=r2:SI 65 (cc:CC) r0:SI=r3:SI So what can we do? We can make the if-conversion pass avoid emitting conditional moves when it results in using additional registers. But although we know it's good on arm, we cannot say the same for other architectures. However we can add a flag and enable it on arm by default. Alternatively we can add some peephole optimization. (Or may be modify some pass to put a pair of instructions under cond_exec). So what would be the best solution? -- Sergey.