[IA-64] Fix latent problem in FP div code

Submitted by Eric Botcazou on Aug. 18, 2010, 10:31 p.m.

Details

Message ID 201008190031.01724.ebotcazou@adacore.com
State New
Headers show

Commit Message

Eric Botcazou Aug. 18, 2010, 10:31 p.m.
Hi,

a couple of years ago I submitted a fix for a problem we ran into in the FP 
div code on IA-64: http://gcc.gnu.org/ml/gcc-patches/2008-06/msg00904.html
It didn't get much attention and the problem is still visible as of today on 
the 4.3 branch with the testcase I provided.

The issue is mitigated by IRA these days but I think that it is still latent.
Moreover the new FP sqrt code suffers from the same problem because frsqrta, 
like frcpa, only sets one predicate register.

Hence the attached patch, tested on ia64-suse-linux, OK for mainline?


2010-08-18  Eric Botcazou  <ebotcazou@adacore.com>

	* config/ia64/ia64.h (HARD_REGNO_NREGS): Return 1 for CCImode in
	general purpose registers.
	(HARD_REGNO_MODE_OK): Accept CCImode in general purpose registers.
	* config/ia64/ia64.md (*movcci): Change to named pattern.  Deal
	with general purpose registers and memory operands.  Add associated
	CCImode post-reload splitter.
	* config/ia64/div.md: Change BImode to CCImode throughout.

Comments

Steve Ellcey Aug. 20, 2010, 9:51 p.m.
> 2010-08-18  Eric Botcazou  <ebotcazou@adacore.com>
> 
>         * config/ia64/ia64.h (HARD_REGNO_NREGS): Return 1 for CCImode in
>         general purpose registers.
>         (HARD_REGNO_MODE_OK): Accept CCImode in general purpose registers.
>         * config/ia64/ia64.md (*movcci): Change to named pattern.  Deal
>         with general purpose registers and memory operands.  Add associated
>         CCImode post-reload splitter.
>         * config/ia64/div.md: Change BImode to CCImode throughout.

Eric,

The patch looks good to me.  Go ahead and check it in.

Steve Ellcey
sje@cup.hp.com
Eric Botcazou Aug. 21, 2010, 1:45 p.m.
> The patch looks good to me.  Go ahead and check it in.

Thanks, will do shortly.  FWIW we have been using the previous patch in our 
4.3 based compiler for a couple of years without any problems so far.

Patch hide | download patch | download mbox

Index: config/ia64/div.md
===================================================================
--- config/ia64/div.md	(revision 163220)
+++ config/ia64/div.md	(working copy)
@@ -37,7 +37,7 @@ 
 
 (define_insn "addrf3_cond"
   [(set (match_operand:RF 0 "fr_register_operand" "=f,f")
-        (if_then_else:RF (ne:RF (match_operand:BI 1 "register_operand"  "c,c")
+        (if_then_else:RF (ne:RF (match_operand:CCI 1 "register_operand"  "c,c")
                                 (const_int 0))
           (plus:RF
             (match_operand:RF 2 "fr_reg_or_fp01_operand" "fG,fG")
@@ -52,7 +52,7 @@  (define_insn "addrf3_cond"
 
 (define_insn "subrf3_cond"
   [(set (match_operand:RF 0 "fr_register_operand" "=f,f")
-        (if_then_else:RF (ne:RF (match_operand:BI 1 "register_operand"  "c,c")
+        (if_then_else:RF (ne:RF (match_operand:CCI 1 "register_operand"  "c,c")
                                 (const_int 0))
           (minus:RF
             (match_operand:RF 2 "fr_reg_or_fp01_operand" "fG,fG")
@@ -67,7 +67,7 @@  (define_insn "subrf3_cond"
 
 (define_insn "mulrf3_cond"
   [(set (match_operand:RF 0 "fr_register_operand" "=f,f")
-        (if_then_else:RF (ne:RF (match_operand:BI 1 "register_operand"  "c,c")
+        (if_then_else:RF (ne:RF (match_operand:CCI 1 "register_operand"  "c,c")
                                 (const_int 0))
           (mult:RF
             (match_operand:RF 2 "fr_reg_or_fp01_operand" "fG,fG")
@@ -84,7 +84,7 @@  (define_insn "mulrf3_cond"
 
 (define_insn "nmulrf3_cond"
   [(set (match_operand:RF 0 "fr_register_operand" "=f,f")
-        (if_then_else:RF (ne:RF (match_operand:BI 1 "register_operand"  "c,c")
+        (if_then_else:RF (ne:RF (match_operand:CCI 1 "register_operand"  "c,c")
                                 (const_int 0))
           (neg:RF (mult:RF
             (match_operand:RF 2 "fr_reg_or_fp01_operand" "fG,fG")
@@ -101,7 +101,7 @@  (define_insn "nmulrf3_cond"
 
 (define_insn "m1addrf4_cond"
   [(set (match_operand:RF 0 "fr_register_operand" "=f,f")
-        (if_then_else:RF (ne:RF (match_operand:BI 1 "register_operand"  "c,c")
+        (if_then_else:RF (ne:RF (match_operand:CCI 1 "register_operand"  "c,c")
                                 (const_int 0))
           (plus:RF
             (mult:RF
@@ -118,7 +118,7 @@  (define_insn "m1addrf4_cond"
 
 (define_insn "m1subrf4_cond"
   [(set (match_operand:RF 0 "fr_register_operand" "=f,f")
-        (if_then_else:RF (ne:RF (match_operand:BI 1 "register_operand"  "c,c")
+        (if_then_else:RF (ne:RF (match_operand:CCI 1 "register_operand"  "c,c")
                                 (const_int 0))
           (minus:RF
             (mult:RF
@@ -137,7 +137,7 @@  (define_insn "m1subrf4_cond"
 
 (define_insn "m2addrf4_cond"
   [(set (match_operand:RF 0 "fr_register_operand" "=f,f")
-        (if_then_else:RF (ne:RF (match_operand:BI 1 "register_operand"  "c,c")
+        (if_then_else:RF (ne:RF (match_operand:CCI 1 "register_operand"  "c,c")
                                 (const_int 0))
           (plus:RF
             (match_operand:RF 2 "fr_reg_or_fp01_operand" "fG,fG")
@@ -154,7 +154,7 @@  (define_insn "m2addrf4_cond"
 
 (define_insn "m2subrf4_cond"
   [(set (match_operand:RF 0 "fr_register_operand" "=f,f")
-        (if_then_else:RF (ne:RF (match_operand:BI 1 "register_operand"  "c,c")
+        (if_then_else:RF (ne:RF (match_operand:CCI 1 "register_operand"  "c,c")
                                 (const_int 0))
           (minus:RF
             (match_operand:RF 2 "fr_reg_or_fp01_operand" "fG,fG")
@@ -255,8 +255,8 @@  (define_insn "recip_approx_rf"
         (unspec:RF [(match_operand:RF 1 "fr_reg_or_fp01_operand" "fG")
 		    (match_operand:RF 2 "fr_reg_or_fp01_operand" "fG")]
 		   UNSPEC_FR_RECIP_APPROX_RES))
-   (set (match_operand:BI 3 "register_operand" "=c")
-        (unspec:BI [(match_dup 1) (match_dup 2)] UNSPEC_FR_RECIP_APPROX))
+   (set (match_operand:CCI 3 "register_operand" "=c")
+        (unspec:CCI [(match_dup 1) (match_dup 2)] UNSPEC_FR_RECIP_APPROX))
    (use (match_operand:SI 4 "const_int_operand" ""))]
   ""
   "frcpa.s%4 %0, %3 = %F1, %F2"
@@ -297,7 +297,7 @@  (define_expand "divsf3_internal_thr"
   rtx q     = gen_reg_rtx (RFmode);
   rtx r     = gen_reg_rtx (RFmode);
   rtx q_res = gen_reg_rtx (RFmode);
-  rtx cond  = gen_reg_rtx (BImode);
+  rtx cond  = gen_reg_rtx (CCImode);
   rtx zero    = CONST0_RTX (RFmode);
   rtx one     = CONST1_RTX (RFmode);
   rtx status0 = CONST0_RTX (SImode);
@@ -345,7 +345,7 @@  (define_expand "divsf3_internal_lat"
   rtx q1        = gen_reg_rtx (RFmode);
   rtx r         = gen_reg_rtx (RFmode);
   rtx q_res     = gen_reg_rtx (RFmode);
-  rtx cond      = gen_reg_rtx (BImode);
+  rtx cond      = gen_reg_rtx (CCImode);
   rtx zero      = CONST0_RTX (RFmode);
   rtx one       = CONST1_RTX (RFmode);
   rtx status0   = CONST0_RTX (SImode);
@@ -414,7 +414,7 @@  (define_expand "divdf3_internal_thr"
   rtx y3    = gen_reg_rtx (RFmode);
   rtx q     = gen_reg_rtx (RFmode);
   rtx r     = gen_reg_rtx (RFmode);
-  rtx cond  = gen_reg_rtx (BImode);
+  rtx cond  = gen_reg_rtx (CCImode);
   rtx zero    = CONST0_RTX (RFmode);
   rtx one     = CONST1_RTX (RFmode);
   rtx status0 = CONST0_RTX (SImode);
@@ -471,7 +471,7 @@  (define_expand "divdf3_internal_lat"
   rtx e3        = gen_reg_rtx (RFmode);
   rtx q         = gen_reg_rtx (RFmode);
   rtx r1        = gen_reg_rtx (RFmode);
-  rtx cond      = gen_reg_rtx (BImode);
+  rtx cond      = gen_reg_rtx (CCImode);
   rtx zero      = CONST0_RTX (RFmode);
   rtx one       = CONST1_RTX (RFmode);
   rtx status0   = CONST0_RTX (SImode);
@@ -535,7 +535,7 @@  (define_expand "divxf3"
   rtx q         = gen_reg_rtx (RFmode);
   rtx r         = gen_reg_rtx (RFmode);
   rtx r1        = gen_reg_rtx (RFmode);
-  rtx cond      = gen_reg_rtx (BImode);
+  rtx cond      = gen_reg_rtx (CCImode);
   rtx zero      = CONST0_RTX (RFmode);
   rtx one       = CONST1_RTX (RFmode);
   rtx status0   = CONST0_RTX (SImode);
@@ -702,7 +702,7 @@  (define_expand "divsi3_internal"
   rtx e1        = gen_reg_rtx (RFmode);
   rtx q         = gen_reg_rtx (RFmode);
   rtx q1        = gen_reg_rtx (RFmode);
-  rtx cond      = gen_reg_rtx (BImode);
+  rtx cond      = gen_reg_rtx (CCImode);
   rtx zero      = CONST0_RTX (RFmode);
   rtx one       = CONST1_RTX (RFmode);
   rtx status1   = CONST1_RTX (SImode);
@@ -844,7 +844,7 @@  (define_expand "divdi3_internal_lat"
   rtx q1        = gen_reg_rtx (RFmode);
   rtx q2        = gen_reg_rtx (RFmode);
   rtx r         = gen_reg_rtx (RFmode);
-  rtx cond      = gen_reg_rtx (BImode);
+  rtx cond      = gen_reg_rtx (CCImode);
   rtx zero      = CONST0_RTX (RFmode);
   rtx one       = CONST1_RTX (RFmode);
   rtx status1   = CONST1_RTX (SImode);
@@ -888,7 +888,7 @@  (define_expand "divdi3_internal_thr"
   rtx e1        = gen_reg_rtx (RFmode);
   rtx q2        = gen_reg_rtx (RFmode);
   rtx r         = gen_reg_rtx (RFmode);
-  rtx cond      = gen_reg_rtx (BImode);
+  rtx cond      = gen_reg_rtx (CCImode);
   rtx zero      = CONST0_RTX (RFmode);
   rtx one       = CONST1_RTX (RFmode);
   rtx status1   = CONST1_RTX (SImode);
@@ -920,8 +920,8 @@  (define_insn "sqrt_approx_rf"
   [(set (match_operand:RF 0 "fr_register_operand" "=f")
                 (unspec:RF [(match_operand:RF 1 "fr_reg_or_fp01_operand" "fG")]
 			   UNSPEC_FR_SQRT_RECIP_APPROX_RES))
-   (set (match_operand:BI 2 "register_operand" "=c")
-        (unspec:BI [(match_dup 1)] UNSPEC_FR_SQRT_RECIP_APPROX))
+   (set (match_operand:CCI 2 "register_operand" "=c")
+        (unspec:CCI [(match_dup 1)] UNSPEC_FR_SQRT_RECIP_APPROX))
    (use (match_operand:SI 3 "const_int_operand" ""))]
   ""
   "frsqrta.s%3 %0, %2 = %F1"
@@ -958,7 +958,7 @@  (define_expand "sqrtsf2_internal_thr"
   rtx h         = gen_reg_rtx (RFmode);
   rtx d         = gen_reg_rtx (RFmode);
   rtx g2        = gen_reg_rtx (RFmode);
-  rtx cond      = gen_reg_rtx (BImode);
+  rtx cond      = gen_reg_rtx (CCImode);
   rtx zero      = CONST0_RTX (RFmode);
   rtx one       = CONST1_RTX (RFmode);
   rtx c1        = ia64_dconst_0_5();
@@ -1021,7 +1021,7 @@  (define_expand "sqrtsf2_internal_lat"
   rtx h         = gen_reg_rtx (RFmode);
   rtx h1        = gen_reg_rtx (RFmode);
   rtx d         = gen_reg_rtx (RFmode);
-  rtx cond      = gen_reg_rtx (BImode);
+  rtx cond      = gen_reg_rtx (CCImode);
   rtx zero      = CONST0_RTX (RFmode);
   rtx one       = CONST1_RTX (RFmode);
   rtx c1        = ia64_dconst_0_5();
@@ -1104,7 +1104,7 @@  (define_expand "sqrtdf2_internal_thr"
   rtx h2        = gen_reg_rtx (RFmode);
   rtx d         = gen_reg_rtx (RFmode);
   rtx d1        = gen_reg_rtx (RFmode);
-  rtx cond      = gen_reg_rtx (BImode);
+  rtx cond      = gen_reg_rtx (CCImode);
   rtx zero      = CONST0_RTX (RFmode);
   rtx c1        = ia64_dconst_0_5();
   rtx reg_df_c1	= gen_reg_rtx (DFmode);
@@ -1171,7 +1171,7 @@  (define_expand "sqrtxf2"
   rtx h3        = gen_reg_rtx (RFmode);
   rtx d         = gen_reg_rtx (RFmode);
   rtx d1        = gen_reg_rtx (RFmode);
-  rtx cond      = gen_reg_rtx (BImode);
+  rtx cond      = gen_reg_rtx (CCImode);
   rtx zero      = CONST0_RTX (RFmode);
   rtx c1        = ia64_dconst_0_5();
   rtx reg_df_c1	= gen_reg_rtx (DFmode);
Index: config/ia64/ia64.h
===================================================================
--- config/ia64/ia64.h	(revision 163220)
+++ config/ia64/ia64.h	(working copy)
@@ -646,7 +646,7 @@  while (0)
 #define HARD_REGNO_NREGS(REGNO, MODE)					\
   ((REGNO) == PR_REG (0) && (MODE) == DImode ? 64			\
    : PR_REGNO_P (REGNO) && (MODE) == BImode ? 2				\
-   : PR_REGNO_P (REGNO) && (MODE) == CCImode ? 1			\
+   : (PR_REGNO_P (REGNO) || GR_REGNO_P (REGNO)) && (MODE) == CCImode ? 1\
    : FR_REGNO_P (REGNO) && (MODE) == XFmode ? 1				\
    : FR_REGNO_P (REGNO) && (MODE) == RFmode ? 1				\
    : FR_REGNO_P (REGNO) && (MODE) == XCmode ? 2				\
@@ -664,7 +664,7 @@  while (0)
    : PR_REGNO_P (REGNO) ?					\
      (MODE) == BImode || GET_MODE_CLASS (MODE) == MODE_CC	\
    : GR_REGNO_P (REGNO) ?					\
-     (MODE) != CCImode && (MODE) != XFmode && (MODE) != XCmode && (MODE) != RFmode \
+     (MODE) != XFmode && (MODE) != XCmode && (MODE) != RFmode	\
    : AR_REGNO_P (REGNO) ? (MODE) == DImode			\
    : BR_REGNO_P (REGNO) ? (MODE) == DImode			\
    : 0)
Index: config/ia64/ia64.md
===================================================================
--- config/ia64/ia64.md	(revision 163220)
+++ config/ia64/ia64.md	(working copy)
@@ -217,17 +217,34 @@  (define_attr "speculable2" "no,yes" (con
 ;; Set of a single predicate register.  This is only used to implement
 ;; pr-to-pr move and complement.
 
-(define_insn "*movcci"
-  [(set (match_operand:CCI 0 "register_operand" "=c,c,c")
-	(match_operand:CCI 1 "nonmemory_operand" "O,n,c"))]
+(define_insn "movcci"
+  [(set (match_operand:CCI 0 "destination_operand" "=c,c,?c,?*r, c,*r,*m,*r")
+	(match_operand:CCI 1 "move_operand"        " O,n, c,  c,*r,*m,*r,*r"))]
   ""
   "@
    cmp.ne %0, p0 = r0, r0
    cmp.eq %0, p0 = r0, r0
-   (%1) cmp.eq.unc %0, p0 = r0, r0"
-  [(set_attr "itanium_class" "icmp")
+   (%1) cmp.eq.unc %0, p0 = r0, r0
+   #
+   tbit.nz %0, p0 = %1, 0
+   ld1%O1 %0 = %1%P1
+   st1%Q0 %0 = %1%P0
+   mov %0 = %1"
+  [(set_attr "itanium_class" "icmp,icmp,icmp,unknown,tbit,ld,st,ialu")
    (set_attr "predicable" "no")])
 
+(define_split
+  [(set (match_operand:CCI 0 "register_operand" "")
+	(match_operand:CCI 1 "register_operand" ""))]
+  "reload_completed
+   && GET_CODE (operands[0]) == REG && GR_REGNO_P (REGNO (operands[0]))
+   && GET_CODE (operands[1]) == REG && PR_REGNO_P (REGNO (operands[1]))"
+  [(set (match_dup 2) (const_int 0))
+   (cond_exec (ne (match_dup 3) (const_int 0))
+     (set (match_dup 2) (const_int 1)))]
+  "operands[2] = gen_rtx_REG (BImode, REGNO (operands[0]));
+   operands[3] = gen_rtx_REG (BImode, REGNO (operands[1]));")
+
 (define_insn "movbi"
   [(set (match_operand:BI 0 "destination_operand" "=c,c,?c,?*r, c,*r,*r,*m,*r")
 	(match_operand:BI 1 "move_operand"        " O,n, c,  c,*r, n,*m,*r,*r"))]