From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 28945 invoked by alias); 1 Jan 2010 17:28:00 -0000 Received: (qmail 28910 invoked by uid 48); 1 Jan 2010 17:27:46 -0000 Date: Fri, 01 Jan 2010 17:28:00 -0000 Subject: [Bug middle-end/42574] New: Address of global variable is calculated multiple times; CSE doesn't work properly X-Bugzilla-Reason: CC Message-ID: Reply-To: gcc-bugzilla@gcc.gnu.org To: gcc-bugs@gcc.gnu.org From: "sliao at google dot com" Mailing-List: contact gcc-bugs-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-bugs-owner@gcc.gnu.org X-SW-Source: 2010-01/txt/msg00041.txt.bz2 The following code (by Alex Vod.) struct A { char a[400]; float* c; }; struct A glob; void func(); void func1(float*); int func2(float*, int*); void func3(float*); void test(int *p) { func1(glob.c); if (func2(glob.c, p)) { func(); } func3(glob.c); } is compiled by gcc 4.2.1 to 56 bytes and 4.4.0 to 64 bytes. The problem is that it calculates address glob.c *twice*, but there is no need to - it doesn't change as glob is a global variable. gcc 4.2.1 output: push {r4, r5, r6, lr} ldr r3, .L5 ldr r2, .L5+4 .LPIC0: add r3, pc ldr r5, [r3, r2] mov r6, #200 lsl r6, r6, #1 mov r4, r0 ldr r0, [r5, r6] bl func1 ldr r0, [r5, r6] mov r1, r4 bl func2 cmp r0, #0 beq .L2 bl func .L2: ldr r0, [r5, r6] bl func3 @ sp needed for prologue pop {r4, r5, r6, pc} gcc 4.4.0 output: push {r3, r4, r5, r6, r7, lr} ldr r4, .L5 ldr r3, .L5+4 .LPIC0: add r4, pc ldr r6, [r4, r3] mov r5, #200 lsl r5, r5, #1 mov r7, r0 ldr r0, [r6, r5] bl func1 ldr r0, [r6, r5] mov r1, r7 bl func2 cmp r0, #0 beq .L2 bl func .L2: ldr r3, .L5+4 @ sp needed for prologue ldr r2, [r4, r3] mov r3, #200 // this is the calculation of glob.c address lsl r3, r3, #1 // it is redundant, as r5 already contains #400 ldr r0, [r2, r3] bl func3 pop {r3, r4, r5, r6, r7, pc} I believe gcc 4.2.1 works correctly due to RTL CSE pass. Before CSE: ;; Start of basic block 4, registers live: (nil) (code_label 34 33 35 4 2 "" [1 uses]) (note 35 34 37 4 [bb 4] NOTE_INSN_BASIC_BLOCK) (insn 37 35 38 4 (set (reg:SI 113) // put attention to this insn (unspec:SI [ (symbol_ref:SI ("glob") ) ] 3)) 148 {pic_load_addr_thumb} (nil) (nil)) (insn 38 37 39 4 (set (reg/f:SI 112) // put attention to this insn (mem/u/c:SI (plus:SI (reg:SI 103) (reg:SI 113)) [0 S4 A32])) 146 {*thumb_movsi_insn} (nil) (expr_list:REG_EQUAL (symbol_ref:SI ("glob") ) (nil))) (insn 39 38 40 4 (set (reg:SI 114) // put attention to this insn (const_int 400 [0x190])) 146 {*thumb_movsi_insn} (nil) (nil)) (insn 40 39 41 4 (set (reg:SI 115 [ glob.c ]) (mem/s/f/c:SI (plus:SI (reg/f:SI 112) (reg:SI 114)) [5 glob.c+0 S4 A32])) 146 {*thumb_movsi_insn} (nil) (nil)) (insn 41 40 42 4 (set (reg:SI 0 r0 [ glob.c ]) (reg:SI 115 [ glob.c ])) 146 {*thumb_movsi_insn} (nil) (nil)) (call_insn 42 41 43 4 (parallel [ (call (mem:SI (symbol_ref:SI ("func3") [flags 0x41] ) [0 S4 A32]) (const_int 0 [0x0])) (use (const_int 0 [0x0])) (clobber (reg:SI 14 lr)) ]) 231 {*call_insn} (nil) (nil) (expr_list:REG_DEP_TRUE (use (reg:SI 0 r0 [ glob.c ])) (nil))) ;; End of basic block 4, registers live: after CSE: ;; Start of basic block 4, registers live: (nil) (code_label 34 33 35 4 2 "" [1 uses]) (note 35 34 40 4 [bb 4] NOTE_INSN_BASIC_BLOCK) (insn 40 35 41 4 (set (reg:SI 115 [ glob.c ]) // all mentioned instructions were removed (mem/s/f/c:SI (plus:SI (reg/f:SI 104) (reg:SI 106)) [5 glob.c+0 S4 A32])) 146 {*thumb_movsi_insn} (nil) (nil)) (insn 41 40 42 4 (set (reg:SI 0 r0 [ glob.c ]) (reg:SI 115 [ glob.c ])) 146 {*thumb_movsi_insn} (nil) (nil)) (call_insn 42 41 43 4 (parallel [ (call (mem:SI (symbol_ref:SI ("func3") [flags 0x41] ) [0 S 4 A32]) (const_int 0 [0x0])) (use (const_int 0 [0x0])) (clobber (reg:SI 14 lr)) ]) 231 {*call_insn} (nil) (nil) (expr_list:REG_DEP_TRUE (use (reg:SI 0 r0 [ glob.c ])) (nil))) ;; End of basic block 4, registers live: For some reason, this CSE pass doesn't work in gcc 4.3.1 or gcc-4.4.0 -- Summary: Address of global variable is calculated multiple times; CSE doesn't work properly Product: gcc Version: 4.4.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: middle-end AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: sliao at google dot com GCC build triplet: i686-linux GCC host triplet: i686-linux GCC target triplet: arm-eabi http://gcc.gnu.org/bugzilla/show_bug.cgi?id=42574