This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug middle-end/42691] New: Wrong REG_EQUAL note is added to SUBREG node


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]