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