------- 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

Reply via email to