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]

PATCH: PR middle-end/33181: [4.3 Regression] Revision 127766 generates bad cmov


As Uros pointed out in PR 33181:

---
The problem is in the way ifcvt handles IFs without ELSE blocks.
Compiling c
testcase with -O2 -ffast-math (on x86_64 target), we hit check for
else_bb in
noce_process_if_block(). We continue into line 2196 of ifcvt.c, where
we try to
find a store before condition using:

      prev_insn = prev_nonnote_insn (if_info->cond_earliest);

The problem is, that in gcc-4.3, we have:

;; Pred edge  5 [100.0%]  (fallthru)
;; Pred edge  4 [100.0%]  (fallthru)
(code_label 26 25 27 6 5 "" [0 uses])

(note 27 26 28 6 [bb 6] NOTE_INSN_BASIC_BLOCK)

(insn 28 27 32 6 pr33181.c:14 (set (mem:SI (reg/v/f:DI 59 [ stat ]) [2
S4 A32])
        (reg:SI 58 [ iftmp.0 ])) 47 {*movsi_1} (expr_list:REG_DEAD
(reg/v/f:DI
59 [ stat ])
        (expr_list:REG_DEAD (reg:SI 58 [ iftmp.0 ])
            (nil))))
;; End of basic block 6 -> ( 9)
;; lr  out       6 [bp] 7 [sp] 16 [argp] 20 [frame]
;; live  out     6 [bp] 7 [sp] 16 [argp] 20 [frame]


;; Succ edge  9 [100.0%]  (fallthru)

;; Start of basic block ( 2) -> 7
;; bb 7 artificial_defs: { }
;; bb 7 artificial_uses: { u35(6){ }u36(7){ }u37(16){ }u38(20){ }}
;; lr  in        6 [bp] 7 [sp] 16 [argp] 20 [frame] 59 60 61
;; lr  use       6 [bp] 7 [sp] 16 [argp] 20 [frame] 60 61
;; lr  def       17 [flags]
;; live  in      6 [bp] 7 [sp] 16 [argp] 20 [frame] 59 60 61
;; live  gen     17 [flags]
;; live  kill

;; Pred edge  2 [50.0%]  (fallthru)
(note 32 28 33 7 [bb 7] NOTE_INSN_BASIC_BLOCK)

(insn 33 32 34 7 pr33181.c:15 (set (reg:CCFP 17 flags)
        (compare:CCFP (reg/v:DF 60 [ newUpper ])
            (reg/v:DF 61 [ lower ]))) 35 {*cmpfp_i_sse}
(expr_list:REG_DEAD
(reg/v:DF 61 [ lower ])
        (expr_list:REG_DEAD (reg/v:DF 60 [ newUpper ])
            (nil))))

So, previous non-note insn from (insn 33) is (insn 28)(!!) in a totally
unrelated BB, leading to all sort of strange things.
---

This patch checks if the previous non-note insn is in the same basic
block. I am testing it on Linux/x86-64 now. OK to install if pass?

Thanks.


H.J.
----
gcc/

2007-08-26  H.J. Lu  <hongjiu.lu@intel.com>

	PR middle-end/33181
	* ifcvt.c (noce_process_if_block): Don't move insn across
	basic block.

2007-08-26  H.J. Lu  <hongjiu.lu@intel.com>

	PR middle-end/33181
	* gcc.dg/ifelse-2.c: New.

--- gcc/ifcvt.c.cmov	2007-08-24 06:02:57.000000000 -0700
+++ gcc/ifcvt.c	2007-08-26 07:35:50.000000000 -0700
@@ -2198,6 +2198,7 @@ noce_process_if_block (struct noce_if_in
 	 COND_EARLIEST to JUMP.  Make sure the relevant data is still
 	 intact.  */
       if (! insn_b
+	  || BLOCK_NUM (insn_b) != BLOCK_NUM (if_info->cond_earliest)
 	  || !NONJUMP_INSN_P (insn_b)
 	  || (set_b = single_set (insn_b)) == NULL_RTX
 	  || ! rtx_equal_p (x, SET_DEST (set_b))
--- gcc/testsuite/gcc.dg/ifelse-2.c.cmov	2007-08-26 07:51:51.000000000 -0700
+++ gcc/testsuite/gcc.dg/ifelse-2.c	2007-08-26 07:52:19.000000000 -0700
@@ -0,0 +1,34 @@
+/*
+{ dg-do run }
+{ dg-options "-O2" }
+*/
+
+extern void abort (void);
+
+enum Status
+{
+  P_ON_LOWER = -4,
+  P_ON_UPPER = -2,
+  P_FREE = -1
+};
+
+void
+foo (enum Status *stat, double newUpper, double lower, double max)
+{
+  if (newUpper >= max)
+    *stat = P_FREE;
+  else if (newUpper == lower)
+    *stat = P_ON_LOWER;
+}
+
+int
+main ()
+{
+  enum Status stat = P_ON_UPPER;
+
+  foo (&stat, 5.0, -10.0, 10.0);
+
+  if (stat != P_ON_UPPER)
+    abort ();
+  return 0;
+}


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