Hi all, This patch improves RTL if-conversion on sequences that perform a conditional select on integer constants. Most of the smart logic to do that already exists in the noce_try_store_flag_constants function. However, currently that function is tried after noce_try_cmove. noce_try_cmove is a simple catch-all function that just loads the two immediates and performs a conditional select between them. It returns true and then the caller noce_process_if_block doesn't try any other transformations, completely skipping the more aggressive transformations that noce_try_store_flag_constants allows! Calling noce_try_store_flag_constants before noce_try_cmove allows for the smarter if-conversion transformations to be used. An example that occurs a lot in the gcc code itself is for the C code: int foo (int a, int b) { return ((a & (1 << 25)) ? 5 : 4); } i.e. test a bit in a and return 5 or 4. Currently on aarch64 this generates the naive: and w2, w0, 33554432 // mask away all bits except bit 25 mov w1, 4 cmp w2, wzr mov w0, 5 csel w0, w0, w1, ne whereas with this patch this can be transformed into the much better: ubfx x0, x0, 25, 1 // extract bit 25 add w0, w0, 4 Another issue I encountered is that the code that claims to perform the transformation: /* if (test) x = 3; else x = 4; => x = 3 + (test == 0); */ doesn't seem to do exactly that in all cases. In fact for that case it will try something like: x = 4 - (test == 0) which is suboptimal for targets like aarch64 which have a conditional increment operation. This patch tweaks that code to always try to generate an addition of the condition rather than a subtraction. Anyway, for code: int fooinc (int x) { return x ? 1025 : 1026; } we currently generate: mov w2, 1025 mov w1, 1026 cmp w0, wzr csel w0, w2, w1, ne whereas with this patch we will generate: cmp w0, wzr cset w0, eq add w0, w0, 1025 Bootstrapped and tested on arm, aarch64, x86_64. Ok for trunk? Thanks, Kyrill P.S. noce_try_store_flag_constants is currently gated on !targetm.have_conditional_execution () but I don't see any reason to restrict it on targets with conditional execution. For example, I think the first example above would show a benefit on arm if it was enabled there. But that can be a separate investigation. 2015-07-29 Kyrylo Tkachov * ifcvt.c (noce_try_store_flag_constants): Reverse when diff is -STORE_FLAG and condition is reversable. Prefer to add to the flag value. (noce_process_if_block): Try noce_try_store_flag_constants before noce_try_cmove. 2015-07-29 Kyrylo Tkachov * gcc.target/aarch64/csel_bfx_1.c: New test. * gcc.target/aarch64/csel_imms_inc_1.c: Likewise.