This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug middle-end/42574] New: Address of global variable is calculated multiple times; CSE doesn't work properly
- From: "sliao at google dot com" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: 1 Jan 2010 17:27:46 -0000
- Subject: [Bug middle-end/42574] New: Address of global variable is calculated multiple times; CSE doesn't work properly
- Reply-to: gcc-bugzilla at gcc dot gnu dot org
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") <var_decl 0xf7d5a000 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") <var_decl 0xf7d5a000 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] <function_decl
0xf7d5c100 func3>) [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] <function_decl
0xf7d5c100 func3>) [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