------- Comment #3 from uros at kss-loka dot si 2006-09-08 05:47 ------- I have been playing with following patch to optabs.c that forces operands in functions expand_sync_operation(), expand_sync_fetch_operation() and expand_sync_lock_test_and_set() into registers through subregs of word-mode temp registers. The testcase in the description is then expanded as:
;; __sync_fetch_and_add_1 (&s, 255) [tail call] (insn 10 8 11 (set (reg:SI 58) (const_int 255 [0xff])) -1 (nil) (nil)) (insn 11 10 0 (parallel [ (set (mem/v:QI (symbol_ref:SI ("s") <var_decl 0x402410b0 s>) [-1 S1 A8]) (unspec_volatile:QI [ (plus:QI (mem/v:QI (symbol_ref:SI ("s") <var_decl 0x402410b0 s>) [-1 S1 A8]) (subreg:QI (reg:SI 58) 0)) ] 13)) (clobber (reg:CC 17 flags)) ]) -1 (nil) (nil)) and RTL optimizers are able to optimize this back into: (insn:HI 11 8 12 2 (parallel [ (set (mem/v:QI (symbol_ref:SI ("s") <var_decl 0x402410b0 s>) [-1 S1 A8]) (unspec_volatile:QI [ (plus:QI (mem/v:QI (symbol_ref:SI ("s") <var_decl 0x402410b0 s>) [-1 S1 A8]) (const_int -1 [0xffffffff])) ] 13)) (clobber (reg:CC 17 flags)) ]) 924 {sync_addqi} (insn_list:REG_DEP_TRUE 10 (nil)) (nil)) This results in expected asm code: tests: lock addb $-1, s ret However, the patch does not cover all backup code-paths in sync_* expanders, so in some cases an integer argument can still be forced into register in the "wrong way". --cut here-- Index: optabs.c =================================================================== --- optabs.c (revision 116739) +++ optabs.c (working copy) @@ -6023,7 +6023,7 @@ if (GET_MODE (val) != VOIDmode && GET_MODE (val) != mode) val = convert_modes (mode, GET_MODE (val), val, 1); if (!insn_data[icode].operand[1].predicate (val, mode)) - val = force_reg (mode, val); + val = gen_lowpart (mode, copy_to_mode_reg (word_mode, val)); insn = GEN_FCN (icode) (mem, val); if (insn) @@ -6156,7 +6156,7 @@ if (GET_MODE (val) != VOIDmode && GET_MODE (val) != mode) val = convert_modes (mode, GET_MODE (val), val, 1); if (!insn_data[icode].operand[2].predicate (val, mode)) - val = force_reg (mode, val); + val = gen_lowpart (mode, copy_to_mode_reg (word_mode, val)); insn = GEN_FCN (icode) (target, mem, val); if (insn) @@ -6243,7 +6243,7 @@ if (GET_MODE (val) != VOIDmode && GET_MODE (val) != mode) val = convert_modes (mode, GET_MODE (val), val, 1); if (!insn_data[icode].operand[2].predicate (val, mode)) - val = force_reg (mode, val); + val = gen_lowpart (mode, copy_to_mode_reg (word_mode, val)); insn = GEN_FCN (icode) (target, mem, val); if (insn) --cut here-- -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=28924