Behavior of Instruction combination pass

venkat venkat@acmet.com
Fri Jun 5 11:27:00 GMT 2009


Hi,

I am working on a GCC port for a 32 bit RISC. I have a doubt regarding the
assembly code generated by the ported compiler for the below test case.

(----- Snip starts -----)
signed char g_scOperand;
signed char g_scResult;
#define CONSTANT_16_BIT     (short) 0x8000

void vMulSignedCharGlobalWith16BitImmediateValue( void ) {
    g_scResult = g_scOperand * CONSTANT_16_BIT;

}
(----- Snip ends -----)

The result of multiplication is stored in a byte size variable 'g_scResult'.
As the LSB value for 'CONSTANT_16_BIT' is zero, the result of multiplication
can be optimized to 0.

I used -O3 option. The ported compiler generates the following RTL after the
Instruction combination pass.

(----- Snip starts -----)
(insn 5 2 6 2 ../test/test.c:6 (set (reg/f:SI 43)
        (high:SI (symbol_ref:SI ("g_scOperand") <var_decl 0xb7ce3000
g_scOperand>))) 27 {*load_high_of_splittable_symbol} (nil))

(insn 6 5 8 2 ../test/test.c:6 (set (reg:SI 41)
        (sign_extend:SI (mem:QI (lo_sum:SI (reg/f:SI 43)
                    (symbol_ref:SI ("g_scOperand") <var_decl 0xb7ce3000
g_scOperand>)) [0 S1 A8]))) 22 {*extendqisi2} (expr_list:REG_DEAD (reg/f:SI
43)
        (expr_list:REG_EQUAL (sign_extend:SI (mem/c/i:QI (symbol_ref:SI
("g_scOperand") <var_decl 0xb7ce3000 g_scOperand>) [0 g_scOperand+0 S1 A8]))
            (nil))))

(insn 8 6 9 2 ../test/test.c:6 (set (reg:SI 45)
        (ashift:SI (reg:SI 41)
            (const_int 15 [0xf]))) 5 {ashlsi3} (expr_list:REG_DEAD (reg:SI
41)
        (expr_list:REG_EQUAL (ashift:SI (reg:SI 41)
                (const_int 15 [0xf]))
            (nil))))

(insn 9 8 10 2 ../test/test.c:6 (set (reg:SI 46)
        (neg:SI (reg:SI 45))) 18 {negsi2} (expr_list:REG_DEAD (reg:SI 45)
        (nil)))

(insn 10 9 0 2 ../test/test.c:6 (set (mem/c/i:QI (symbol_ref:SI
("g_scResult") <var_decl 0xb7ce305c g_scResult>) [0 g_scResult+0 S1 A8])
        (subreg:QI (reg:SI 46) 3)) 29 {*movqi} (expr_list:REG_DEAD (reg:SI
46)
        (nil)))

(----- Snip ends -----)

The multiplication is taking place as follows.
1. Load variable 'g_scOperand' value to register.
2. 0x8000 is power of 2 (2 raised to 15). Hence multiplication is done by
left shifting the register content by 15 times.
3. Since 0x8000 is cast to 'signed short' and it should be treated as
negative number. So the register content is negated.
4. The byte value of the result is stored to the variable 'g_scResult'.

The negation is taking place using the 'negsi2' pattern as shown below.

(define_insn "negsi2"
  [(set (match_operand:SI 0 "register_operand"         "=b")
        (neg:SI (match_operand:SI 1 "register_operand" " b")))]
 ""
 "subu\t%0,$0,%1"
)

But, if I remove machine description for 'negsi2', GCC is able to optimize
the multiplication operation. GCC uses subtraction pattern for performing
the negation.

The Instruction combination pass is able to combine all the instructions
into one as shown below.

(----- Snip starts -----) 
(insn 11 10 0 2 ../test/test.c:6 (set (mem/c/i:QI (symbol_ref:SI
("g_scResult") <var_decl 0xb7cf805c g_scResult>) [0 g_scResult+0 S1 A8])
        (const_int 0 [0x0])) 28 {*movqi} (nil))
(----- Snip ends -----)

I am not able to understand why GCC is not optimizing the result of
operation to 0 when 'negsi2' is defined.

Please help.



More information about the Gcc-help mailing list