This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[IA-64] Work around thinko in 'x' constraint implementation
- From: Eric Botcazou <ebotcazou at adacore dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 6 Mar 2012 23:07:45 +0100
- Subject: [IA-64] Work around thinko in 'x' constraint implementation
We have a regression on one of the testcases of our internal testsuite on IA-64
with a 4.7-based compiler, which is of the form:
test_vec_madd.adb: In function 'Test_Vec_Madd':
test_vec_madd.adb:160:5: error: could not split insn
(insn 887 4859 889 16 (set (reg:TI 158 f30 [orig:417 m ] [417])
(mem/c:TI (reg/f:DI 14 r14 [1025]) [0 S16 A128])) /gnu/lib/gcc/ia64-hp-
openvms/4_7_0/adainclude/g-altcon.adb:277 125 {movti_internal}
(nil))
+===========================GNAT BUG DETECTED==============================+
| Pro 7.1.0w (20120221-head) (ia64-hp-openvms) GCC error: |
| in final_scan_insn, at final.c:2716 |
| Error detected around test_vec_madd.adb:160:5|
The compiler aborts during the final pass because it couldn't split the insn.
The pattern for movti_internal is:
(define_insn_and_split "movti_internal"
[(set (match_operand:TI 0 "destination_operand" "=r, *fm,*x,*f, Q")
(match_operand:TI 1 "general_operand" "r*fim,r, Q, *fOQ,*f"))]
"ia64_move_ok (operands[0], operands[1])"
"@
#
#
ldfp8 %X0 = %1%P1
#
#"
"reload_completed && !ia64_load_pair_ok(operands[0], operands[1])"
[(const_int 0)]
The problem is that the operands satisfy ia64_load_pair_ok so the splitter
cannot be invoked on them. The root cause is a discrepancy between this
predicate and how the 'x' constraint is interpreted. The predicate uses
FP_REGNO_P to check the destination and this returns true for %f30 (but would
return false for the immediately following register %f31). But recog
interprets the 'x' constraint as meaning that every hard register in the
destination must be in the FP_REGS class; now the mode is TImode so both %f30
and %f31 are taken into account and %f31 isn't in the FP_REGS class, so the
operand is rejected.
AFAICS the problem dates back to the introduction of the code (r102463), so I'm
not sure that we want to rewrite it at this point. That's why the attached
patch is a simple workaround that just avoid ICEing.
Bootstrapped/regtested on IA-64/Linux, OK for the mainline? Do we also want it
for 4.7.1 (I assume that some RA change makes the issue visible in 4.7.x)?
2012-03-06 Eric Botcazou <ebotcazou@adacore.com>
* config/ia64/ia64.c (ia64_load_pair_ok): Return 0 if the second member
of the destination isn't also a FP_REGS register.
--
Eric Botcazou
Index: config/ia64/ia64.c
===================================================================
--- config/ia64/ia64.c (revision 184852)
+++ config/ia64/ia64.c (working copy)
@@ -885,7 +887,11 @@ ia64_move_ok (rtx dst, rtx src)
int
ia64_load_pair_ok (rtx dst, rtx src)
{
- if (GET_CODE (dst) != REG || !FP_REGNO_P (REGNO (dst)))
+ /* ??? There is a thinko in the implementation of the "x" constraint and the
+ FP_REGS class. The constraint will also reject (reg f30:TI) so we must
+ also return false for it. */
+ if (GET_CODE (dst) != REG
+ || !(FP_REGNO_P (REGNO (dst)) && FP_REGNO_P (REGNO (dst) + 1)))
return 0;
if (GET_CODE (src) != MEM || MEM_VOLATILE_P (src))
return 0;