The following int foo (int a, int b) { return ((a & (1 << 25)) ? 5 : 4); } compiled with -O2 results in: mov.l .L4,r1 mov #-1,r0 tst r1,r4 negc r0,r0 rts add #4,r0 // r0 = 1 - T + 4 // = 5 - T .L5: .align 2 .L4: .long 33554432 The negc insn calculates 0 - reg - T, which can be used to calculate const_int + T. In fact, it is already used to calculate 1 - T as a replacement for SH2A movrt. The resulting code should look something like this: mov.l .L4,r1 mov #-5,r0 tst r1,r4 rts negc r0,r0 Combine is looking for a pattern: Failed to match this instruction: (set (reg:SI 162 [ D.1652 ]) (plus:SI (zero_extract:SI (reg:SI 4 r4 [ a ]) (const_int 1 [0x1]) (const_int 25 [0x19])) (const_int 4 [0x4]))) Which could be implemented with treg_set_expr.
For some cases where T+const_int is calculated, like ... int foo (int a, int b) { return a == b ? 5 : 4; } comiled with -O2: cmp/eq r5,r4 movt r0 rts add #4,r0 .. the dependency of the comparison and the T bit store can be reduced: cmp/eq r5,r4 mov #2,r0 rts addc r0,r0 This works only for even constants.
(In reply to Oleg Endo from comment #0) > Combine is looking for a pattern: > > Failed to match this instruction: > (set (reg:SI 162 [ D.1652 ]) > (plus:SI (zero_extract:SI (reg:SI 4 r4 [ a ]) > (const_int 1 [0x1]) > (const_int 25 [0x19])) > (const_int 4 [0x4]))) > > Which could be implemented with treg_set_expr. In this case, the treg_set_expr should be only matched if it will expand into a negating T bit store. For that a new predicate "neg_treg_set_expr" should be added. sh_recog_treg_set_expr should get an additional parameter whether it should match positive, negative or both forms.