Behavior of Instruction combination pass

Georg-Johann Lay avr@gjlay.de
Fri Jun 5 12:29:00 GMT 2009


venkat schrieb:
> 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.

Look at what combine does (or tries to do). Use -fdump-rtl-combine-details.

Probably costs are not stated approprialtely.

Georg-Johann



More information about the Gcc-help mailing list