This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[IA-64] Fix latent problem in FP div code
- From: Eric Botcazou <ebotcazou at adacore dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Thu, 19 Aug 2010 00:31:01 +0200
- Subject: [IA-64] Fix latent problem in FP div code
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.
--
Eric Botcazou
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"))]