This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
PATCH: PR middle-end/33181: [4.3 Regression] Revision 127766 generates bad cmov
- From: "H.J. Lu" <hjl at lucon dot org>
- To: gcc-patches at gcc dot gnu dot org
- Date: Sun, 26 Aug 2007 07:59:22 -0700
- Subject: 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;
+}