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]

Fix ia64-hpux (ia64-*?) bootstrap failures


There's been several latent bugs in the intrinsics corresponding to
the IA64 atomic memory operations for some time.  Now they have
escalated to real bugs breaking bootstrap on ia64-hpux and possibly
other ia64 targets.

The AR.CCV register (which is an implicit argument to the cmpxchg
instruction) is always examined - by the hardware - in DImode, even if
the memory access is narrower.  It's the compiler's responsibility to
zero-extend values loaded into that register.  The machine description
failed to reflect this, and the builtin expanders were not generating
the necessary zero-extend instructions.  I confess it isn't clear to
me why, but this did not merely cause runtime failures; it caused
unrecognizable insns.

Fixing the machine description to model the hardware properly, and the
expanders to feed arguments in the proper modes, makes the
unrecognizable insns go away.  It also solves the compile- and runtime
failures of ia64-sync-[124].c on ia64-hpux (-4 only in ilp32 mode)
which have been present for a couple weeks.

Part of the change to ia64_expand_compare_and_swap may not be obvious.
expand_expr is not guaranteed to return an RTX with the requested
mode.  If copy_to_mode_reg's input is in the wrong mode, it does not
convert; it aborts.  So we have to call convert_to_mode in between.

Bootstrapped ia64-hp-hpux11.22.

zw

        * config/ia64/ia64.md (cmpxchg_acq_si): Mark operand 3 as DImode.
        * config/ia64/ia64.c (ia64_expand_fetch_and_op,
        ia64_expand_op_and_fetch): Make sure the REG for ar.ccv is
        DImode.   Use convert_move to load ar.ccv.
        (ia64_expand_compare_and_swap): Likewise.  
        If expand_expr doesn't put 'old' and 'new' in the proper
        modes, run them through convert_to_mode.

===================================================================
Index: config/ia64/ia64.md
--- config/ia64/ia64.md	14 Oct 2003 19:25:54 -0000	1.113
+++ config/ia64/ia64.md	21 Oct 2003 21:07:18 -0000
@@ -5388,7 +5388,7 @@
    (set (match_operand:SI 1 "not_postinc_memory_operand" "+S")
         (unspec:SI [(match_dup 1)
                     (match_operand:SI 2 "gr_register_operand" "r")
-		    (match_operand 3 "ar_ccv_reg_operand" "")]
+		    (match_operand:DI 3 "ar_ccv_reg_operand" "")]
 		   UNSPEC_CMPXCHG_ACQ))]
   ""
   "cmpxchg4.acq %0 = %1, %2, %3"
===================================================================
Index: config/ia64/ia64.c
--- config/ia64/ia64.c	14 Oct 2003 19:25:49 -0000	1.254
+++ config/ia64/ia64.c	21 Oct 2003 21:07:17 -0000
@@ -7885,13 +7885,14 @@ ia64_expand_fetch_and_op (optab binoptab
     }
 
   tmp = gen_reg_rtx (mode);
-  ccv = gen_rtx_REG (mode, AR_CCV_REGNUM);
+  /* ar.ccv must always be loaded with a zero-extended DImode value.  */
+  ccv = gen_rtx_REG (DImode, AR_CCV_REGNUM);
   emit_move_insn (tmp, mem);
 
   label = gen_label_rtx ();
   emit_label (label);
   emit_move_insn (ret, tmp);
-  emit_move_insn (ccv, tmp);
+  convert_move (ccv, tmp, /*unsignedp=*/1);
 
   /* Perform the specific operation.  Special case NAND by noticing
      one_cmpl_optab instead.  */
@@ -7951,14 +7952,15 @@ ia64_expand_op_and_fetch (optab binoptab
   emit_insn (gen_mf ());
   tmp = gen_reg_rtx (mode);
   old = gen_reg_rtx (mode);
-  ccv = gen_rtx_REG (mode, AR_CCV_REGNUM);
+  /* ar.ccv must always be loaded with a zero-extended DImode value.  */
+  ccv = gen_rtx_REG (DImode, AR_CCV_REGNUM);
 
   emit_move_insn (tmp, mem);
 
   label = gen_label_rtx ();
   emit_label (label);
   emit_move_insn (old, tmp);
-  emit_move_insn (ccv, tmp);
+  convert_move (ccv, tmp, /*unsignedp=*/1);
 
   /* Perform the specific operation.  Special case NAND by noticing
      one_cmpl_optab instead.  */
@@ -8007,6 +8009,11 @@ ia64_expand_compare_and_swap (enum machi
   mem = gen_rtx_MEM (mode, force_reg (ptr_mode, mem));
   MEM_VOLATILE_P (mem) = 1;
 
+  if (GET_MODE (old) != mode)
+    old = convert_to_mode (mode, old, /*unsignedp=*/1);
+  if (GET_MODE (new) != mode)
+    new = convert_to_mode (mode, new, /*unsignedp=*/1);
+
   if (! register_operand (old, mode))
     old = copy_to_mode_reg (mode, old);
   if (! register_operand (new, mode))
@@ -8018,14 +8025,7 @@ ia64_expand_compare_and_swap (enum machi
     tmp = gen_reg_rtx (mode);
 
   ccv = gen_rtx_REG (DImode, AR_CCV_REGNUM);
-  if (mode == DImode)
-    emit_move_insn (ccv, old);
-  else
-    {
-      rtx ccvtmp = gen_reg_rtx (DImode);
-      emit_insn (gen_zero_extendsidi2 (ccvtmp, old));
-      emit_move_insn (ccv, ccvtmp);
-    }
+  convert_move (ccv, old, /*unsignedp=*/1);
   emit_insn (gen_mf ());
   if (mode == SImode)
     insn = gen_cmpxchg_acq_si (tmp, mem, new, ccv);


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