This is the mail archive of the gcc-patches@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]

Fix postreload_combine miscompilation (PR 69941)


This is a transformation which looks for

(set reg1 const)
(set reg2 (plus reg2 reg1))

and tries to replace all further uses of reg2 with (plus reg2 reg1). The problem here is that one of the uses is in a narrower mode, inside a zero_extend, so we produce wrong results.

The fix seems rather straightforward, verifying all uses have a mode matching the set. Bootstrapped and tested on x86_64-linux, ok?


Bernd
	PR rtl-optimization/69941
	* postreload.c (reload_combine_recognize_pattern): Ensure all uses of
	the reg share its mode.

testsuite/
	PR rtl-optimization/69941
	* gcc.dg/torture/pr69941.c: New test.

Index: gcc/postreload.c
===================================================================
--- gcc/postreload.c	(revision 233451)
+++ gcc/postreload.c	(working copy)
@@ -1057,7 +1057,6 @@ static bool
 reload_combine_recognize_pattern (rtx_insn *insn)
 {
   rtx set, reg, src;
-  unsigned int regno;
 
   set = single_set (insn);
   if (set == NULL_RTX)
@@ -1068,7 +1067,20 @@ reload_combine_recognize_pattern (rtx_in
   if (!REG_P (reg) || REG_NREGS (reg) != 1)
     return false;
 
-  regno = REGNO (reg);
+  unsigned int regno = REGNO (reg);
+  machine_mode mode = GET_MODE (reg);
+
+  if (reg_state[regno].use_index < 0
+      || reg_state[regno].use_index >= RELOAD_COMBINE_MAX_USES)
+    return false;
+
+  for (int i = reg_state[regno].use_index;
+       i < RELOAD_COMBINE_MAX_USES; i++)
+    {
+      struct reg_use *use = reg_state[regno].reg_use + i;
+      if (GET_MODE (*use->usep) != mode)
+	return false;
+    }
 
   /* Look for (set (REGX) (CONST_INT))
      (set (REGX) (PLUS (REGX) (REGY)))
@@ -1090,8 +1102,6 @@ reload_combine_recognize_pattern (rtx_in
       && REG_P (XEXP (src, 1))
       && rtx_equal_p (XEXP (src, 0), reg)
       && !rtx_equal_p (XEXP (src, 1), reg)
-      && reg_state[regno].use_index >= 0
-      && reg_state[regno].use_index < RELOAD_COMBINE_MAX_USES
       && last_label_ruid < reg_state[regno].use_ruid)
     {
       rtx base = XEXP (src, 1);
Index: gcc/testsuite/gcc.dg/torture/pr69941.c
===================================================================
--- gcc/testsuite/gcc.dg/torture/pr69941.c	(revision 0)
+++ gcc/testsuite/gcc.dg/torture/pr69941.c	(working copy)
@@ -0,0 +1,30 @@
+/* { dg-do run } */
+ 
+int a = 0;
+int b = 0;
+int c = 0;
+int e = 0;
+int f = 0;
+int *g = &e;
+ 
+int fn1() { return b ? a : b; }
+ 
+int main() {
+  int h = fn1() <= 0x8000000000000000ULL; // h = 1;
+ 
+  int k = f; // k = 0;
+ 
+  long i = h ? k : k / h; // i = 0;
+ 
+  long l = (unsigned short)(i - 0x1800); // l = 0xe800
+ 
+  i = l ? l : c; // i = 0xe800;
+ 
+  *g = i; // *g = 0xe800; e = 0xe800;
+ 
+  unsigned char result = e >> 9; // result = 0x74;
+
+  if ((int)result != 0x74)
+    __builtin_abort ();
+  return 0;
+}


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