This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug middle-end/42691] New: Wrong REG_EQUAL note is added to SUBREG node
- From: "jingyu at google dot com" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: 11 Jan 2010 19:45:29 -0000
- Subject: [Bug middle-end/42691] New: Wrong REG_EQUAL note is added to SUBREG node
- Reply-to: gcc-bugzilla at gcc dot gnu dot org
A wrong REG_EQUAL is attached to SUBREG during forward propagation.
Before fwprop1
(insn 56 55 57 3 double.cpp:12 (set (reg/v:DI 180 [ _D_inf ])
(const_int 0 [0x0])) 164 {*thumb1_movdi_insn} (nil))
(insn 60 59 61 3 double.cpp:12 (set (reg:SI 189)
(const_int 2146435072 [0x7ff00000])) 168 {*thumb1_movsi_insn} (nil))
(insn 62 61 63 3 double.cpp:12 (set (subreg:SI (reg/v:DI 180 [ _D_inf ]) 4)
(reg:SI 189)) 168 {*thumb1_movsi_insn} (nil))
After fwprop1, a note "REG_EQUAL (const_int 2146435072 [0x7ff00000]" is
attached to insn 62.
(insn 56 54 60 3 double.cpp:12 (set (reg/v:DI 180 [ _D_inf ])
(const_int 0 [0x0])) 164 {*thumb1_movdi_insn} (nil))
(insn 60 56 62 3 double.cpp:12 (set (reg:SI 189)
(const_int 2146435072 [0x7ff00000])) 168 {*thumb1_movsi_insn} (nil))
(insn 62 60 63 3 double.cpp:12 (set (subreg:SI (reg/v:DI 180 [ _D_inf ]) 4)
(reg:SI 189)) 168 {*thumb1_movsi_insn} (expr_list:REG_EQUAL (const_int
2
146435072 [0x7ff00000])
(nil)))
Then at combine pass, when the three insns are combined into one insn, the
operand of the set note becomes [0x7ff0000000000000], but the REG_EQUAL note is
still [0x7ff00000].
(insn 62 155 63 3 double.cpp:12 (set (reg/v:DI 180 [ _D_inf ])
(const_int 9218868437227405312 [0x7ff0000000000000])) 164
{*thumb1_movdi_insn} (expr_list:REG_EQUAL (const_int 2146435072 [0x7ff00000])
(nil)))
If the wrong REG_EQUAL is not used in later optimization, then nothing wrong is
observed. However, we find a case that the bug is triggered at ira pass.
What happens is at ira pass, in reload() (reload1.c), gcc tries to find "SET
REG(regno) = const N". When gcc finds one, it records constant equivalent in
reg_equiv_constant so that the use of the register will be substituted by
find_reloads. gcc puts "reg_equiv_constant[regno]=x". However, notice that, "x"
here is the value from the REG_EQUAL note, not the SET operand. In our case,
the value in reg 180 is 0x7ff0000000000000, but gcc says
reg_equiv_constant[180]=0x7ff00000. Later, when gcc tries to simplify the
SUBREG for insn 65, it picks the wrong value in reg_equiv_const[180] and passes
the wrong value to insn 65.
(insn 65 64 66 3 double.cpp:13 (set (reg:DF 2 r2)
(subreg:DF (reg/v:DI 180 [ _D_inf ]) 0)) 183 {*thumb_movdf_insn} (nil))
becomes
(insn 65 64 66 3 double.cpp:13 (set (reg:DF 2 r2)
(const_double:DF 1.06047983010398252661938461763305382790433594771e-314
[0x0.ffep-1043])) 183 {*thumb_movdf_insn} (nil))
The const_double in insn 65 is wrong.
test case double.cpp:
union _D_rep {
unsigned short rep[4];
double val;
};
int add(double* key, double* table)
{
unsigned i = 0;
double* deletedEntry = 0;
while (1) {
double* entry = table + i;
_D_rep _D_inf = {{ 0, 0, 0, 0x7ff0 }};
if (*entry == _D_inf.val)
break;
if (*entry == *key)
return 0;
_D_rep _D_inf2 = {{ 0, 0, 0, 0x7ff0 }};
if (_D_inf2.val)
deletedEntry = entry;
i++;
}
if (deletedEntry)
return 1;
return 0;
}
The command is:
arm-eabi-g++ -Os -mthumb double.cpp -c -o double.o
--
Summary: Wrong REG_EQUAL note is added to SUBREG node
Product: gcc
Version: 4.5.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: middle-end
AssignedTo: unassigned at gcc dot gnu dot org
ReportedBy: jingyu at google dot com
GCC build triplet: X86_64-linux-gnu
GCC host triplet: X86_64-linux-gnu
GCC target triplet: arm-unknown-eabi
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=42691