OSDN Git Service

2010-04-09 Steve Ellcey <sje@cup.hp.com>
[pf3gnuchains/gcc-fork.git] / gcc / config / ia64 / ia64.c
index 28abf27..dc6ca52 100644 (file)
@@ -1,5 +1,6 @@
 /* Definitions of target machine for GNU compiler.
-   Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+   Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
+   2009, 2010
    Free Software Foundation, Inc.
    Contributed by James E. Wilson <wilson@cygnus.com> and
                  David Mosberger <davidm@hpl.hp.com>.
@@ -41,6 +42,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "function.h"
 #include "ggc.h"
 #include "basic-block.h"
+#include "libfuncs.h"
 #include "toplev.h"
 #include "sched-int.h"
 #include "timevar.h"
@@ -57,16 +59,12 @@ along with GCC; see the file COPYING3.  If not see
 #include "params.h"
 #include "dbgcnt.h"
 #include "tm-constrs.h"
+#include "sel-sched.h"
 
 /* This is used for communication between ASM_OUTPUT_LABEL and
    ASM_OUTPUT_LABELREF.  */
 int ia64_asm_output_label = 0;
 
-/* Define the information needed to generate branch and scc insns.  This is
-   stored from the compare operation.  */
-struct rtx_def * ia64_compare_op0;
-struct rtx_def * ia64_compare_op1;
-
 /* Register names for ia64_expand_prologue.  */
 static const char * const ia64_reg_numbers[96] =
 { "r32", "r33", "r34", "r35", "r36", "r37", "r38", "r39",
@@ -172,12 +170,19 @@ static int ia64_first_cycle_multipass_dfa_lookahead_guard (rtx);
 static bool ia64_first_cycle_multipass_dfa_lookahead_guard_spec (const_rtx);
 static int ia64_dfa_new_cycle (FILE *, int, rtx, int, int, int *);
 static void ia64_h_i_d_extended (void);
+static void * ia64_alloc_sched_context (void);
+static void ia64_init_sched_context (void *, bool);
+static void ia64_set_sched_context (void *);
+static void ia64_clear_sched_context (void *);
+static void ia64_free_sched_context (void *);
 static int ia64_mode_to_int (enum machine_mode);
 static void ia64_set_sched_flags (spec_info_t);
+static ds_t ia64_get_insn_spec_ds (rtx);
+static ds_t ia64_get_insn_checked_ds (rtx);
+static bool ia64_skip_rtx_p (const_rtx);
 static int ia64_speculate_insn (rtx, ds_t, rtx *);
-static rtx ia64_gen_spec_insn (rtx, ds_t, int, bool, bool);
-static bool ia64_needs_block_p (const_rtx);
-static rtx ia64_gen_check (rtx, rtx, bool);
+static bool ia64_needs_block_p (int);
+static rtx ia64_gen_spec_check (rtx, rtx, ds_t);
 static int ia64_spec_check_p (rtx);
 static int ia64_spec_check_src_p (rtx);
 static rtx gen_tls_get_addr (void);
@@ -195,6 +200,7 @@ static rtx gen_movdi_x (rtx, rtx, rtx);
 static rtx gen_fr_spill_x (rtx, rtx, rtx);
 static rtx gen_fr_restore_x (rtx, rtx, rtx);
 
+static bool ia64_can_eliminate (const int, const int);
 static enum machine_mode hfa_element_mode (const_tree, bool);
 static void ia64_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode,
                                         tree, int *, int);
@@ -222,7 +228,7 @@ static void ia64_output_function_epilogue (FILE *, HOST_WIDE_INT);
 static void ia64_output_function_end_prologue (FILE *);
 
 static int ia64_issue_rate (void);
-static int ia64_adjust_cost (rtx, rtx, rtx, int);
+static int ia64_adjust_cost_2 (rtx, int, rtx, int, dw_t);
 static void ia64_sched_init (FILE *, int, int);
 static void ia64_sched_init_global (FILE *, int, int);
 static void ia64_sched_finish_global (FILE *, int);
@@ -248,6 +254,7 @@ static int get_max_pos (state_t);
 static int get_template (state_t, int);
 
 static rtx get_next_important_insn (rtx, rtx);
+static bool important_for_bundling_p (rtx);
 static void bundling (FILE *, int, rtx, rtx);
 
 static void ia64_output_mi_thunk (FILE *, tree, HOST_WIDE_INT,
@@ -270,6 +277,12 @@ static void ia64_sysv4_init_libfuncs (void)
      ATTRIBUTE_UNUSED;
 static void ia64_vms_init_libfuncs (void)
      ATTRIBUTE_UNUSED;
+static void ia64_soft_fp_init_libfuncs (void)
+     ATTRIBUTE_UNUSED;
+static bool ia64_vms_valid_pointer_mode (enum machine_mode mode)
+     ATTRIBUTE_UNUSED;
+static tree ia64_vms_common_object_attribute (tree *, tree, tree, int, bool *)
+     ATTRIBUTE_UNUSED;
 
 static tree ia64_handle_model_attribute (tree *, tree, tree, int, bool *);
 static tree ia64_handle_version_id_attribute (tree *, tree, tree, int, bool *);
@@ -284,6 +297,13 @@ static const char *ia64_invalid_conversion (const_tree, const_tree);
 static const char *ia64_invalid_unary_op (int, const_tree);
 static const char *ia64_invalid_binary_op (int, const_tree, const_tree);
 static enum machine_mode ia64_c_mode_for_suffix (char);
+static enum machine_mode ia64_promote_function_mode (const_tree,
+                                                    enum machine_mode,
+                                                    int *,
+                                                    const_tree,
+                                                    int);
+static void ia64_trampoline_init (rtx, tree, rtx);
+static void ia64_override_options_after_change (void);
 \f
 /* Table of valid machine attributes.  */
 static const struct attribute_spec ia64_attribute_table[] =
@@ -291,6 +311,9 @@ static const struct attribute_spec ia64_attribute_table[] =
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
   { "syscall_linkage", 0, 0, false, true,  true,  NULL },
   { "model",          1, 1, true, false, false, ia64_handle_model_attribute },
+#if TARGET_ABI_OPEN_VMS
+  { "common_object",   1, 1, true, false, false, ia64_vms_common_object_attribute},
+#endif
   { "version_id",      1, 1, true, false, false,
     ia64_handle_version_id_attribute },
   { NULL,             0, 0, false, false, false, NULL }
@@ -333,8 +356,8 @@ static const struct attribute_spec ia64_attribute_table[] =
 #undef TARGET_IN_SMALL_DATA_P
 #define TARGET_IN_SMALL_DATA_P  ia64_in_small_data_p
 
-#undef TARGET_SCHED_ADJUST_COST
-#define TARGET_SCHED_ADJUST_COST ia64_adjust_cost
+#undef TARGET_SCHED_ADJUST_COST_2
+#define TARGET_SCHED_ADJUST_COST_2 ia64_adjust_cost_2
 #undef TARGET_SCHED_ISSUE_RATE
 #define TARGET_SCHED_ISSUE_RATE ia64_issue_rate
 #undef TARGET_SCHED_VARIABLE_ISSUE
@@ -373,9 +396,30 @@ static const struct attribute_spec ia64_attribute_table[] =
 #undef TARGET_SCHED_H_I_D_EXTENDED
 #define TARGET_SCHED_H_I_D_EXTENDED ia64_h_i_d_extended
 
+#undef TARGET_SCHED_ALLOC_SCHED_CONTEXT
+#define TARGET_SCHED_ALLOC_SCHED_CONTEXT ia64_alloc_sched_context
+
+#undef TARGET_SCHED_INIT_SCHED_CONTEXT
+#define TARGET_SCHED_INIT_SCHED_CONTEXT ia64_init_sched_context
+
+#undef TARGET_SCHED_SET_SCHED_CONTEXT
+#define TARGET_SCHED_SET_SCHED_CONTEXT ia64_set_sched_context
+
+#undef TARGET_SCHED_CLEAR_SCHED_CONTEXT
+#define TARGET_SCHED_CLEAR_SCHED_CONTEXT ia64_clear_sched_context
+
+#undef TARGET_SCHED_FREE_SCHED_CONTEXT
+#define TARGET_SCHED_FREE_SCHED_CONTEXT ia64_free_sched_context
+
 #undef TARGET_SCHED_SET_SCHED_FLAGS
 #define TARGET_SCHED_SET_SCHED_FLAGS ia64_set_sched_flags
 
+#undef TARGET_SCHED_GET_INSN_SPEC_DS
+#define TARGET_SCHED_GET_INSN_SPEC_DS ia64_get_insn_spec_ds
+
+#undef TARGET_SCHED_GET_INSN_CHECKED_DS
+#define TARGET_SCHED_GET_INSN_CHECKED_DS ia64_get_insn_checked_ds
+
 #undef TARGET_SCHED_SPECULATE_INSN
 #define TARGET_SCHED_SPECULATE_INSN ia64_speculate_insn
 
@@ -383,12 +427,15 @@ static const struct attribute_spec ia64_attribute_table[] =
 #define TARGET_SCHED_NEEDS_BLOCK_P ia64_needs_block_p
 
 #undef TARGET_SCHED_GEN_SPEC_CHECK
-#define TARGET_SCHED_GEN_SPEC_CHECK ia64_gen_check
+#define TARGET_SCHED_GEN_SPEC_CHECK ia64_gen_spec_check
 
 #undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD_GUARD_SPEC
 #define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD_GUARD_SPEC\
   ia64_first_cycle_multipass_dfa_lookahead_guard_spec
 
+#undef TARGET_SCHED_SKIP_RTX_P
+#define TARGET_SCHED_SKIP_RTX_P ia64_skip_rtx_p
+
 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
 #define TARGET_FUNCTION_OK_FOR_SIBCALL ia64_function_ok_for_sibcall
 #undef TARGET_ARG_PARTIAL_BYTES
@@ -427,17 +474,8 @@ static const struct attribute_spec ia64_attribute_table[] =
 #define TARGET_ASM_OUTPUT_DWARF_DTPREL ia64_output_dwarf_dtprel
 #endif
 
-/* ??? ABI doesn't allow us to define this.  */
-#if 0
-#undef TARGET_PROMOTE_FUNCTION_ARGS
-#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true
-#endif
-
-/* ??? ABI doesn't allow us to define this.  */
-#if 0
-#undef TARGET_PROMOTE_FUNCTION_RETURN
-#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true
-#endif
+#undef TARGET_PROMOTE_FUNCTION_MODE
+#define TARGET_PROMOTE_FUNCTION_MODE ia64_promote_function_mode
 
 /* ??? Investigate.  */
 #if 0
@@ -493,6 +531,15 @@ static const struct attribute_spec ia64_attribute_table[] =
 #undef TARGET_C_MODE_FOR_SUFFIX
 #define TARGET_C_MODE_FOR_SUFFIX ia64_c_mode_for_suffix
 
+#undef TARGET_CAN_ELIMINATE
+#define TARGET_CAN_ELIMINATE ia64_can_eliminate
+
+#undef TARGET_TRAMPOLINE_INIT
+#define TARGET_TRAMPOLINE_INIT ia64_trampoline_init
+
+#undef TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE
+#define TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE ia64_override_options_after_change
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 \f
 typedef enum
@@ -551,8 +598,8 @@ ia64_handle_model_attribute (tree *node, tree name, tree args,
     }
   else
     {
-      warning (OPT_Wattributes, "invalid argument of %qs attribute",
-              IDENTIFIER_POINTER (name));
+      warning (OPT_Wattributes, "invalid argument of %qE attribute",
+              name);
       *no_add_attrs = true;
     }
 
@@ -563,8 +610,9 @@ ia64_handle_model_attribute (tree *node, tree name, tree args,
           == FUNCTION_DECL)
          && !TREE_STATIC (decl))
        {
-         error ("%Jan address area attribute cannot be specified for "
-                "local variables", decl);
+         error_at (DECL_SOURCE_LOCATION (decl),
+                   "an address area attribute cannot be specified for "
+                   "local variables");
          *no_add_attrs = true;
        }
       area = ia64_get_addr_area (decl);
@@ -577,14 +625,15 @@ ia64_handle_model_attribute (tree *node, tree name, tree args,
       break;
 
     case FUNCTION_DECL:
-      error ("%Jaddress area attribute cannot be specified for functions",
-            decl);
+      error_at (DECL_SOURCE_LOCATION (decl),
+               "address area attribute cannot be specified for "
+               "functions");
       *no_add_attrs = true;
       break;
 
     default:
-      warning (OPT_Wattributes, "%qs attribute ignored",
-              IDENTIFIER_POINTER (name));
+      warning (OPT_Wattributes, "%qE attribute ignored",
+              name);
       *no_add_attrs = true;
       break;
     }
@@ -592,6 +641,95 @@ ia64_handle_model_attribute (tree *node, tree name, tree args,
   return NULL_TREE;
 }
 
+/* The section must have global and overlaid attributes.  */
+#define SECTION_VMS_OVERLAY SECTION_MACH_DEP
+
+/* Part of the low level implementation of DEC Ada pragma Common_Object which
+   enables the shared use of variables stored in overlaid linker areas
+   corresponding to the use of Fortran COMMON.  */
+
+static tree
+ia64_vms_common_object_attribute (tree *node, tree name, tree args,
+                                 int flags ATTRIBUTE_UNUSED,
+                                 bool *no_add_attrs)
+{
+    tree decl = *node;
+    tree id, val;
+    if (! DECL_P (decl))
+      abort ();
+  
+    DECL_COMMON (decl) = 1;
+    id = TREE_VALUE (args);
+    if (TREE_CODE (id) == IDENTIFIER_NODE)
+      val = build_string (IDENTIFIER_LENGTH (id), IDENTIFIER_POINTER (id));
+    else if (TREE_CODE (id) == STRING_CST)
+      val = id;
+    else
+      {
+       warning (OPT_Wattributes,
+                "%qE attribute requires a string constant argument", name);
+       *no_add_attrs = true;
+       return NULL_TREE;
+      }
+    DECL_SECTION_NAME (decl) = val;
+    return NULL_TREE;
+}
+
+/* Part of the low level implementation of DEC Ada pragma Common_Object.  */
+
+void
+ia64_vms_output_aligned_decl_common (FILE *file, tree decl, const char *name,
+                                    unsigned HOST_WIDE_INT size,
+                                    unsigned int align)
+{
+  tree attr = DECL_ATTRIBUTES (decl);
+
+  /* As common_object attribute set DECL_SECTION_NAME check it before
+     looking up the attribute.  */
+  if (DECL_SECTION_NAME (decl) && attr)
+    attr = lookup_attribute ("common_object", attr);
+  else
+    attr = NULL_TREE;
+
+  if (!attr)
+    {
+      /*  Code from elfos.h.  */
+      fprintf (file, "%s", COMMON_ASM_OP);
+      assemble_name (file, name);
+      fprintf (file, ","HOST_WIDE_INT_PRINT_UNSIGNED",%u\n",
+              size, align / BITS_PER_UNIT);
+    }
+  else
+    {
+      ASM_OUTPUT_ALIGN (file, floor_log2 (align / BITS_PER_UNIT));
+      ASM_OUTPUT_LABEL (file, name);
+      ASM_OUTPUT_SKIP (file, size ? size : 1);
+    }
+}
+
+/* Definition of TARGET_ASM_NAMED_SECTION for VMS.  */
+
+void
+ia64_vms_elf_asm_named_section (const char *name, unsigned int flags,
+                               tree decl)
+{
+  if (!(flags & SECTION_VMS_OVERLAY))
+    {
+      default_elf_asm_named_section (name, flags, decl);
+      return;
+    }
+  if (flags != (SECTION_VMS_OVERLAY | SECTION_WRITE))
+    abort ();
+
+  if (flags & SECTION_DECLARED)
+    {
+      fprintf (asm_out_file, "\t.section\t%s\n", name);
+      return;
+    }
+
+  fprintf (asm_out_file, "\t.section\t%s,\"awgO\"\n", name);
+}
+
 static void
 ia64_encode_addr_area (tree decl, rtx symbol)
 {
@@ -702,7 +840,7 @@ ia64_depz_field_mask (rtx rop, rtx rshift)
 static enum tls_model
 tls_symbolic_operand_type (rtx addr)
 {
-  enum tls_model tls_kind = 0;
+  enum tls_model tls_kind = TLS_MODEL_NONE;
 
   if (GET_CODE (addr) == CONST)
     {
@@ -729,7 +867,8 @@ ia64_legitimate_constant_p (rtx x)
       return true;
 
     case CONST_DOUBLE:
-      if (GET_MODE (x) == VOIDmode)
+      if (GET_MODE (x) == VOIDmode || GET_MODE (x) == SFmode
+         || GET_MODE (x) == DFmode)
        return true;
       return satisfies_constraint_G (x);
 
@@ -1276,9 +1415,7 @@ ia64_split_tmode_move (rtx operands[])
       && (GET_CODE (XEXP (EXP, 0)) == POST_MODIFY                      \
          || GET_CODE (XEXP (EXP, 0)) == POST_INC                       \
          || GET_CODE (XEXP (EXP, 0)) == POST_DEC))                     \
-    REG_NOTES (INSN) = gen_rtx_EXPR_LIST (REG_INC,                     \
-                                         XEXP (XEXP (EXP, 0), 0),      \
-                                         REG_NOTES (INSN))
+    add_reg_note (insn, REG_INC, XEXP (XEXP (EXP, 0), 0))
 
   insn = emit_insn (gen_rtx_SET (VOIDmode, out[0], in[0]));
   MAYBE_ADD_REG_INC_NOTE (insn, in[0]);
@@ -1459,28 +1596,28 @@ ia64_expand_movxf_movrf (enum machine_mode mode, rtx operands[])
   return false;
 }
 
-/* Emit comparison instruction if necessary, returning the expression
-   that holds the compare result in the proper mode.  */
+/* Emit comparison instruction if necessary, replacing *EXPR, *OP0, *OP1
+   with the expression that holds the compare result (in VOIDmode).  */
 
 static GTY(()) rtx cmptf_libfunc;
 
-rtx
-ia64_expand_compare (enum rtx_code code, enum machine_mode mode)
+void
+ia64_expand_compare (rtx *expr, rtx *op0, rtx *op1)
 {
-  rtx op0 = ia64_compare_op0, op1 = ia64_compare_op1;
+  enum rtx_code code = GET_CODE (*expr);
   rtx cmp;
 
   /* If we have a BImode input, then we already have a compare result, and
      do not need to emit another comparison.  */
-  if (GET_MODE (op0) == BImode)
+  if (GET_MODE (*op0) == BImode)
     {
-      gcc_assert ((code == NE || code == EQ) && op1 == const0_rtx);
-      cmp = op0;
+      gcc_assert ((code == NE || code == EQ) && *op1 == const0_rtx);
+      cmp = *op0;
     }
   /* HPUX TFmode compare requires a library call to _U_Qfcmp, which takes a
      magic number as its third argument, that indicates what to do.
      The return value is an integer to be compared against zero.  */
-  else if (GET_MODE (op0) == TFmode)
+  else if (TARGET_HPUX && GET_MODE (*op0) == TFmode)
     {
       enum qfcmp_magic {
        QCMP_INV = 1,   /* Raise FP_INVALID on SNaN as a side effect.  */
@@ -1488,11 +1625,12 @@ ia64_expand_compare (enum rtx_code code, enum machine_mode mode)
        QCMP_EQ = 4,
        QCMP_LT = 8,
        QCMP_GT = 16
-      } magic;
+      };
+      int magic;
       enum rtx_code ncode;
       rtx ret, insns;
       
-      gcc_assert (cmptf_libfunc && GET_MODE (op1) == TFmode);
+      gcc_assert (cmptf_libfunc && GET_MODE (*op1) == TFmode);
       switch (code)
        {
          /* 1 = equal, 0 = not equal.  Equality operators do
@@ -1517,7 +1655,7 @@ ia64_expand_compare (enum rtx_code code, enum machine_mode mode)
       start_sequence ();
 
       ret = emit_library_call_value (cmptf_libfunc, 0, LCT_CONST, DImode, 3,
-                                    op0, TFmode, op1, TFmode,
+                                    *op0, TFmode, *op1, TFmode,
                                     GEN_INT (magic), DImode);
       cmp = gen_reg_rtx (BImode);
       emit_insn (gen_rtx_SET (VOIDmode, cmp,
@@ -1528,18 +1666,20 @@ ia64_expand_compare (enum rtx_code code, enum machine_mode mode)
       end_sequence ();
 
       emit_libcall_block (insns, cmp, cmp,
-                         gen_rtx_fmt_ee (code, BImode, op0, op1));
+                         gen_rtx_fmt_ee (code, BImode, *op0, *op1));
       code = NE;
     }
   else
     {
       cmp = gen_reg_rtx (BImode);
       emit_insn (gen_rtx_SET (VOIDmode, cmp,
-                             gen_rtx_fmt_ee (code, BImode, op0, op1)));
+                             gen_rtx_fmt_ee (code, BImode, *op0, *op1)));
       code = NE;
     }
 
-  return gen_rtx_fmt_ee (code, mode, cmp, const0_rtx);
+  *expr = gen_rtx_fmt_ee (code, VOIDmode, cmp, const0_rtx);
+  *op0 = cmp;
+  *op1 = const0_rtx;
 }
 
 /* Generate an integral vector comparison.  Return true if the condition has
@@ -1593,25 +1733,18 @@ ia64_expand_vecint_compare (enum rtx_code code, enum machine_mode mode,
          {
            rtx t1, t2, mask;
 
-           /* Perform a parallel modulo subtraction.  */
-           t1 = gen_reg_rtx (V2SImode);
-           emit_insn (gen_subv2si3 (t1, op0, op1));
-
-           /* Extract the original sign bit of op0.  */
-           mask = GEN_INT (-0x80000000);
+           /* Subtract (-(INT MAX) - 1) from both operands to make
+              them signed.  */
+           mask = GEN_INT (0x80000000);
            mask = gen_rtx_CONST_VECTOR (V2SImode, gen_rtvec (2, mask, mask));
-           mask = force_reg (V2SImode, mask);
-           t2 = gen_reg_rtx (V2SImode);
-           emit_insn (gen_andv2si3 (t2, op0, mask));
-
-           /* XOR it back into the result of the subtraction.  This results
-              in the sign bit set iff we saw unsigned underflow.  */
-           x = gen_reg_rtx (V2SImode);
-           emit_insn (gen_xorv2si3 (x, t1, t2));
-
+           mask = force_reg (mode, mask);
+           t1 = gen_reg_rtx (mode);
+           emit_insn (gen_subv2si3 (t1, op0, mask));
+           t2 = gen_reg_rtx (mode);
+           emit_insn (gen_subv2si3 (t2, op1, mask));
+           op0 = t1;
+           op1 = t2;
            code = GT;
-           op0 = x;
-           op1 = CONST0_RTX (mode);
          }
          break;
 
@@ -1890,6 +2023,10 @@ ia64_expand_call (rtx retval, rtx addr, rtx nextarg ATTRIBUTE_UNUSED,
 
   if (sibcall_p)
     use_reg (&CALL_INSN_FUNCTION_USAGE (insn), b0);
+
+  if (TARGET_ABI_OPEN_VMS)
+    use_reg (&CALL_INSN_FUNCTION_USAGE (insn),
+            gen_rtx_REG (DImode, GR_REG (25)));
 }
 
 static void
@@ -1911,7 +2048,7 @@ get_reg (enum ia64_frame_regs r)
 static bool
 is_emitted (int regno)
 {
-  enum ia64_frame_regs r;
+  unsigned int r;
 
   for (r = reg_fp; r < number_of_ia64_frame_regs; r++)
     if (emitted_frame_related_regs[r] == regno)
@@ -2108,11 +2245,13 @@ ia64_expand_atomic_op (enum rtx_code code, rtx mem, rtx val,
   new_reg = cmp_reg;
   if (code == NOT)
     {
-      new_reg = expand_simple_unop (DImode, NOT, new_reg, NULL_RTX, true);
-      code = AND;
+      new_reg = expand_simple_binop (DImode, AND, new_reg, val, NULL_RTX,
+                                    true, OPTAB_DIRECT);
+      new_reg = expand_simple_unop (DImode, code, new_reg, NULL_RTX, true);
     }
-  new_reg = expand_simple_binop (DImode, code, new_reg, val, NULL_RTX,
-                                true, OPTAB_DIRECT);
+  else
+    new_reg = expand_simple_binop (DImode, code, new_reg, val, NULL_RTX,
+                                  true, OPTAB_DIRECT);
 
   if (mode != DImode)
     new_reg = gen_lowpart (mode, new_reg);
@@ -2600,6 +2739,14 @@ ia64_compute_frame_size (HOST_WIDE_INT size)
   current_frame_info.initialized = reload_completed;
 }
 
+/* Worker function for TARGET_CAN_ELIMINATE.  */
+
+bool
+ia64_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
+{
+  return (to == BR_REG (0) ? current_function_is_leaf : true);
+}
+
 /* Compute the initial difference between the specified pair of registers.  */
 
 HOST_WIDE_INT
@@ -2733,9 +2880,8 @@ spill_restore_mem (rtx reg, HOST_WIDE_INT cfa_off)
                                   gen_rtx_PLUS (DImode,
                                                 spill_fill_data.iter_reg[iter],
                                                 disp_rtx));
-         REG_NOTES (spill_fill_data.prev_insn[iter])
-           = gen_rtx_EXPR_LIST (REG_INC, spill_fill_data.iter_reg[iter],
-                                REG_NOTES (spill_fill_data.prev_insn[iter]));
+         add_reg_note (spill_fill_data.prev_insn[iter],
+                       REG_INC, spill_fill_data.iter_reg[iter]);
        }
       else
        {
@@ -2852,13 +2998,11 @@ do_spill (rtx (*move_fn) (rtx, rtx, rtx), rtx reg, HOST_WIDE_INT cfa_off,
          off = current_frame_info.total_size - cfa_off;
        }
 
-      REG_NOTES (insn)
-       = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
-               gen_rtx_SET (VOIDmode,
-                            gen_rtx_MEM (GET_MODE (reg),
-                                         plus_constant (base, off)),
-                            frame_reg),
-               REG_NOTES (insn));
+      add_reg_note (insn, REG_FRAME_RELATED_EXPR,
+                   gen_rtx_SET (VOIDmode,
+                                gen_rtx_MEM (GET_MODE (reg),
+                                             plus_constant (base, off)),
+                                frame_reg));
     }
 }
 
@@ -3058,16 +3202,12 @@ ia64_expand_prologue (void)
        {
          RTX_FRAME_RELATED_P (insn) = 1;
          if (GET_CODE (offset) != CONST_INT)
-           {
-             REG_NOTES (insn)
-               = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
-                       gen_rtx_SET (VOIDmode,
-                                    stack_pointer_rtx,
-                                    gen_rtx_PLUS (DImode,
-                                                  stack_pointer_rtx,
-                                                  frame_size_rtx)),
-                       REG_NOTES (insn));
-           }
+           add_reg_note (insn, REG_FRAME_RELATED_EXPR,
+                         gen_rtx_SET (VOIDmode,
+                                      stack_pointer_rtx,
+                                      gen_rtx_PLUS (DImode,
+                                                    stack_pointer_rtx,
+                                                    frame_size_rtx)));
        }
 
       /* ??? At this point we must generate a magic insn that appears to
@@ -3134,10 +3274,8 @@ ia64_expand_prologue (void)
          /* ??? Denote pr spill/fill by a DImode move that modifies all
             64 hard registers.  */
          RTX_FRAME_RELATED_P (insn) = 1;
-         REG_NOTES (insn)
-           = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
-                       gen_rtx_SET (VOIDmode, alt_reg, reg),
-                       REG_NOTES (insn));
+         add_reg_note (insn, REG_FRAME_RELATED_EXPR,
+                       gen_rtx_SET (VOIDmode, alt_reg, reg));
 
          /* Even if we're not going to generate an epilogue, we still
             need to save the register so that EH works.  */
@@ -3496,16 +3634,12 @@ ia64_expand_epilogue (int sibcall_p)
 
       RTX_FRAME_RELATED_P (insn) = 1;
       if (GET_CODE (offset) != CONST_INT)
-       {
-         REG_NOTES (insn)
-           = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
-                       gen_rtx_SET (VOIDmode,
-                                    stack_pointer_rtx,
-                                    gen_rtx_PLUS (DImode,
-                                                  stack_pointer_rtx,
-                                                  frame_size_rtx)),
-                       REG_NOTES (insn));
-       }
+       add_reg_note (insn, REG_FRAME_RELATED_EXPR,
+                     gen_rtx_SET (VOIDmode,
+                                  stack_pointer_rtx,
+                                  gen_rtx_PLUS (DImode,
+                                                stack_pointer_rtx,
+                                                frame_size_rtx)));
     }
 
   if (cfun->machine->ia64_eh_epilogue_bsp)
@@ -3636,7 +3770,7 @@ int
 ia64_hard_regno_rename_ok (int from, int to)
 {
   /* Don't clobber any of the registers we reserved for the prologue.  */
-  enum ia64_frame_regs r;
+  unsigned int r;
 
   for (r = reg_fp; r <= reg_save_ar_lc; r++)
     if (to == current_frame_info.r[r] 
@@ -3812,10 +3946,35 @@ ia64_dbx_register_number (int regno)
     return regno;
 }
 
-void
-ia64_initialize_trampoline (rtx addr, rtx fnaddr, rtx static_chain)
+/* Implement TARGET_TRAMPOLINE_INIT.
+
+   The trampoline should set the static chain pointer to value placed
+   into the trampoline and should branch to the specified routine.
+   To make the normal indirect-subroutine calling convention work,
+   the trampoline must look like a function descriptor; the first
+   word being the target address and the second being the target's
+   global pointer.
+
+   We abuse the concept of a global pointer by arranging for it
+   to point to the data we need to load.  The complete trampoline
+   has the following form:
+
+               +-------------------+ \
+       TRAMP:  | __ia64_trampoline | |
+               +-------------------+  > fake function descriptor
+               | TRAMP+16          | |
+               +-------------------+ /
+               | target descriptor |
+               +-------------------+
+               | static link       |
+               +-------------------+
+*/
+
+static void
+ia64_trampoline_init (rtx m_tramp, tree fndecl, rtx static_chain)
 {
-  rtx addr_reg, eight = GEN_INT (8);
+  rtx fnaddr = XEXP (DECL_RTL (fndecl), 0);
+  rtx addr, addr_reg, tramp, eight = GEN_INT (8);
 
   /* The Intel assembler requires that the global __ia64_trampoline symbol
      be declared explicitly */
@@ -3832,30 +3991,45 @@ ia64_initialize_trampoline (rtx addr, rtx fnaddr, rtx static_chain)
     }
 
   /* Make sure addresses are Pmode even if we are in ILP32 mode. */
-  addr = convert_memory_address (Pmode, addr);
+  addr = convert_memory_address (Pmode, XEXP (m_tramp, 0));
   fnaddr = convert_memory_address (Pmode, fnaddr);
   static_chain = convert_memory_address (Pmode, static_chain);
 
   /* Load up our iterator.  */
-  addr_reg = gen_reg_rtx (Pmode);
-  emit_move_insn (addr_reg, addr);
+  addr_reg = copy_to_reg (addr);
+  m_tramp = adjust_automodify_address (m_tramp, Pmode, addr_reg, 0);
 
   /* The first two words are the fake descriptor:
      __ia64_trampoline, ADDR+16.  */
-  emit_move_insn (gen_rtx_MEM (Pmode, addr_reg),
-                 gen_rtx_SYMBOL_REF (Pmode, "__ia64_trampoline"));
+  tramp = gen_rtx_SYMBOL_REF (Pmode, "__ia64_trampoline");
+  if (TARGET_ABI_OPEN_VMS)
+    {
+      /* HP decided to break the ELF ABI on VMS (to deal with an ambiguity
+        in the Macro-32 compiler) and changed the semantics of the LTOFF22
+        relocation against function symbols to make it identical to the
+        LTOFF_FPTR22 relocation.  Emit the latter directly to stay within
+        strict ELF and dereference to get the bare code address.  */
+      rtx reg = gen_reg_rtx (Pmode);
+      SYMBOL_REF_FLAGS (tramp) |= SYMBOL_FLAG_FUNCTION;
+      emit_move_insn (reg, tramp);
+      emit_move_insn (reg, gen_rtx_MEM (Pmode, reg));
+      tramp = reg;
+   }
+  emit_move_insn (m_tramp, tramp);
   emit_insn (gen_adddi3 (addr_reg, addr_reg, eight));
+  m_tramp = adjust_automodify_address (m_tramp, VOIDmode, NULL, 8);
 
-  emit_move_insn (gen_rtx_MEM (Pmode, addr_reg),
-                 copy_to_reg (plus_constant (addr, 16)));
+  emit_move_insn (m_tramp, force_reg (Pmode, plus_constant (addr, 16)));
   emit_insn (gen_adddi3 (addr_reg, addr_reg, eight));
+  m_tramp = adjust_automodify_address (m_tramp, VOIDmode, NULL, 8);
 
   /* The third word is the target descriptor.  */
-  emit_move_insn (gen_rtx_MEM (Pmode, addr_reg), fnaddr);
+  emit_move_insn (m_tramp, force_reg (Pmode, fnaddr));
   emit_insn (gen_adddi3 (addr_reg, addr_reg, eight));
+  m_tramp = adjust_automodify_address (m_tramp, VOIDmode, NULL, 8);
 
   /* The fourth word is the static chain.  */
-  emit_move_insn (gen_rtx_MEM (Pmode, addr_reg), static_chain);
+  emit_move_insn (m_tramp, static_chain);
 }
 \f
 /* Do any needed setup for a variadic function.  CUM has not been updated
@@ -4000,7 +4174,8 @@ ia64_function_arg_words (tree type, enum machine_mode mode)
 static int
 ia64_function_arg_offset (CUMULATIVE_ARGS *cum, tree type, int words)
 {
-  if ((cum->words & 1) == 0)
+  /* No registers are skipped on VMS.  */
+  if (TARGET_ABI_OPEN_VMS || (cum->words & 1) == 0)
     return 0;
 
   if (type
@@ -4025,6 +4200,24 @@ ia64_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
   int offset = ia64_function_arg_offset (cum, type, words);
   enum machine_mode hfa_mode = VOIDmode;
 
+  /* For OPEN VMS, emit the instruction setting up the argument register here,
+     when we know this will be together with the other arguments setup related
+     insns.  This is not the conceptually best place to do this, but this is
+     the easiest as we have convenient access to cumulative args info.  */
+
+  if (TARGET_ABI_OPEN_VMS && mode == VOIDmode && type == void_type_node
+      && named == 1)
+    {
+      unsigned HOST_WIDE_INT regval = cum->words;
+      int i;
+
+      for (i = 0; i < 8; i++)
+       regval |= ((int) cum->atypes[i]) << (i * 3 + 8);
+
+      emit_move_insn (gen_rtx_REG (DImode, GR_REG (25)),
+                     GEN_INT (regval));
+    }
+
   /* If all argument slots are used, then it must go on the stack.  */
   if (cum->words + offset >= MAX_ARGUMENT_SLOTS)
     return 0;
@@ -4114,6 +4307,15 @@ ia64_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
        }
       return gen_rtx_PARALLEL (mode, gen_rtvec_v (i, loc));
     }
+  
+  /* On OpenVMS variable argument is either in Rn or Fn.  */
+  else if (TARGET_ABI_OPEN_VMS && named == 0)
+    {
+      if (FLOAT_MODE_P (mode))
+       return gen_rtx_REG (mode, FR_ARG_FIRST + cum->words);
+      else
+       return gen_rtx_REG (mode, basereg + cum->words);
+    }
 
   /* Integral and aggregates go in general registers.  If we have run out of
      FR registers, then FP values must also go in general registers.  This can
@@ -4206,6 +4408,22 @@ ia64_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode,
   return (MAX_ARGUMENT_SLOTS - cum->words - offset) * UNITS_PER_WORD;
 }
 
+/* Return ivms_arg_type based on machine_mode.  */
+
+static enum ivms_arg_type
+ia64_arg_type (enum machine_mode mode)
+{
+  switch (mode)
+    {
+    case SFmode:
+      return FS;
+    case DFmode:
+      return FT;
+    default:
+      return I64;
+    }
+}
+
 /* Update CUM to point after this argument.  This is patterned after
    ia64_function_arg.  */
 
@@ -4219,8 +4437,12 @@ ia64_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
 
   /* If all arg slots are already full, then there is nothing to do.  */
   if (cum->words >= MAX_ARGUMENT_SLOTS)
-    return;
+    {
+      cum->words += words + offset;
+      return;
+    }
 
+  cum->atypes[cum->words] = ia64_arg_type (mode);
   cum->words += words + offset;
 
   /* Check for and handle homogeneous FP aggregates.  */
@@ -4263,6 +4485,13 @@ ia64_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
       cum->fp_regs = fp_regs;
     }
 
+  /* On OpenVMS variable argument is either in Rn or Fn.  */
+  else if (TARGET_ABI_OPEN_VMS && named == 0)
+    {
+      cum->int_regs = cum->words;
+      cum->fp_regs = cum->words;
+    }
+
   /* Integral and aggregates go in general registers.  So do TFmode FP values.
      If we have run out of FR registers, then other FP values must also go in
      general registers.  This can happen when we have a SFmode HFA.  */
@@ -4328,8 +4557,9 @@ ia64_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
     return false;
 
   /* We must always return with our current GP.  This means we can
-     only sibcall to functions defined in the current module.  */
-  return decl && (*targetm.binds_local_p) (decl);
+     only sibcall to functions defined in the current module unless
+     TARGET_CONST_GP is set to true.  */
+  return (decl && (*targetm.binds_local_p) (decl)) || TARGET_CONST_GP;
 }
 \f
 
@@ -4406,10 +4636,11 @@ ia64_return_in_memory (const_tree valtype, const_tree fntype ATTRIBUTE_UNUSED)
 /* Return rtx for register that holds the function return value.  */
 
 rtx
-ia64_function_value (const_tree valtype, const_tree func ATTRIBUTE_UNUSED)
+ia64_function_value (const_tree valtype, const_tree func)
 {
   enum machine_mode mode;
   enum machine_mode hfa_mode;
+  int unsignedp;
 
   mode = TYPE_MODE (valtype);
   hfa_mode = hfa_element_mode (valtype, 0);
@@ -4480,6 +4711,10 @@ ia64_function_value (const_tree valtype, const_tree func ATTRIBUTE_UNUSED)
          return gen_rtx_PARALLEL (mode, gen_rtvec_v (i, loc));
        }
 
+      mode = ia64_promote_function_mode (valtype, mode, &unsignedp,
+                                        func ? TREE_TYPE (func) : NULL_TREE,
+                                        true);
+
       return gen_rtx_REG (mode, GR_RET_FIRST);
     }
 }
@@ -4517,6 +4752,7 @@ ia64_print_operand_address (FILE * stream ATTRIBUTE_UNUSED,
    e    Print 64 - constant, for DImode rotates.
    F   A floating point constant 0.0 emitted as f0, or 1.0 emitted as f1, or
         a floating point register emitted normally.
+   G   A floating point constant.
    I   Invert a predicate register by adding 1.
    J    Select the proper predicate register for a condition.
    j    Select the inverse predicate register for a condition.
@@ -4604,6 +4840,24 @@ ia64_print_operand (FILE * file, rtx x, int code)
       fputs (str, file);
       return;
 
+    case 'G':
+      {
+       long val[4];
+       REAL_VALUE_TYPE rv;
+       REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
+       real_to_target (val, &rv, GET_MODE (x));
+       if (GET_MODE (x) == SFmode)
+         fprintf (file, "0x%08lx", val[0] & 0xffffffff);
+       else if (GET_MODE (x) == DFmode)
+         fprintf (file, "0x%08lx%08lx", (WORDS_BIG_ENDIAN ? val[0] : val[1])
+                                         & 0xffffffff,
+                                        (WORDS_BIG_ENDIAN ? val[1] : val[0])
+                                         & 0xffffffff);
+       else
+         output_operand_lossage ("invalid %%G mode");
+      }
+      return;
+
     case 'I':
       fputs (reg_names [REGNO (x) + 1], file);
       return;
@@ -5194,9 +5448,6 @@ ia64_handle_option (size_t code, const char *arg, int value)
          }
        const processor_alias_table[] =
          {
-           {"itanium", PROCESSOR_ITANIUM},
-           {"itanium1", PROCESSOR_ITANIUM},
-           {"merced", PROCESSOR_ITANIUM},
            {"itanium2", PROCESSOR_ITANIUM2},
            {"mckinley", PROCESSOR_ITANIUM2},
          };
@@ -5227,15 +5478,54 @@ ia64_override_options (void)
   if (TARGET_AUTO_PIC)
     target_flags |= MASK_CONST_GP;
 
-  if (TARGET_INLINE_SQRT == INL_MIN_LAT)
-    {
-      warning (0, "not yet implemented: latency-optimized inline square root");
-      TARGET_INLINE_SQRT = INL_MAX_THR;
-    }
+  /* Numerous experiment shows that IRA based loop pressure
+     calculation works better for RTL loop invariant motion on targets
+     with enough (>= 32) registers.  It is an expensive optimization.
+     So it is on only for peak performance.  */
+  if (optimize >= 3)
+    flag_ira_loop_pressure = 1;
+
 
   ia64_section_threshold = g_switch_set ? g_switch_value : IA64_DEFAULT_GVALUE;
 
   init_machine_status = ia64_init_machine_status;
+
+  if (align_functions <= 0)
+    align_functions = 64;
+  if (align_loops <= 0)
+    align_loops = 32;
+  if (TARGET_ABI_OPEN_VMS)
+    flag_no_common = 1;
+
+  ia64_override_options_after_change();
+}
+
+/* Implement targetm.override_options_after_change.  */
+
+static void
+ia64_override_options_after_change (void)
+{
+  ia64_flag_schedule_insns2 = flag_schedule_insns_after_reload;
+  flag_schedule_insns_after_reload = 0;
+
+  if (optimize >= 3
+      && ! sel_sched_switch_set)
+    {
+      flag_selective_scheduling2 = 1;
+      flag_sel_sched_pipelining = 1;
+    }
+  if (mflag_sched_control_spec == 2)
+    {
+      /* Control speculation is on by default for the selective scheduler,
+         but not for the Haifa scheduler.  */
+      mflag_sched_control_spec = flag_selective_scheduling2 ? 1 : 0;
+    }
+  if (flag_sel_sched_pipelining && flag_auto_inc_dec)
+    {
+      /* FIXME: remove this when we'd implement breaking autoinsns as
+         a transformation.  */
+      flag_auto_inc_dec = 0;
+    }
 }
 
 /* Initialize the record of emitted frame related registers.  */
@@ -5259,6 +5549,8 @@ ia64_safe_itanium_class (rtx insn)
 {
   if (recog_memoized (insn) >= 0)
     return get_attr_itanium_class (insn);
+  else if (DEBUG_INSN_P (insn))
+    return ITANIUM_CLASS_IGNORE;
   else
     return ITANIUM_CLASS_UNKNOWN;
 }
@@ -5890,6 +6182,7 @@ rtx_needs_barrier (rtx x, struct reg_flags flags, int pred)
        case UNSPEC_FR_SQRT_RECIP_APPROX_RES:
        case UNSPEC_LDA:
        case UNSPEC_LDS:
+       case UNSPEC_LDS_A:
        case UNSPEC_LDSA:
        case UNSPEC_CHKACLR:
         case UNSPEC_CHKS:
@@ -6014,6 +6307,7 @@ group_barrier_needed (rtx insn)
   switch (GET_CODE (insn))
     {
     case NOTE:
+    case DEBUG_INSN:
       break;
 
     case BARRIER:
@@ -6095,6 +6389,7 @@ group_barrier_needed (rtx insn)
         asm.  */
       if (! need_barrier)
        need_barrier = rws_access_regno (REG_VOLATILE, flags, 0);
+
       break;
 
     default:
@@ -6170,7 +6465,7 @@ emit_insn_group_barriers (FILE *dump)
          init_insn_group_barriers ();
          last_label = 0;
        }
-      else if (INSN_P (insn))
+      else if (NONDEBUG_INSN_P (insn))
        {
          insns_since_last_label = 1;
 
@@ -6218,7 +6513,7 @@ emit_all_insn_group_barriers (FILE *dump ATTRIBUTE_UNUSED)
 
          init_insn_group_barriers ();
        }
-      else if (INSN_P (insn))
+      else if (NONDEBUG_INSN_P (insn))
        {
          if (recog_memoized (insn) == CODE_FOR_insn_group_barrier)
            init_insn_group_barriers ();
@@ -6293,14 +6588,6 @@ static state_t prev_cycle_state = NULL;
 
 static char *stops_p = NULL;
 
-/* The following array element values are ZERO for non-speculative
-   instructions and hold corresponding speculation check number for
-   speculative instructions.  */
-static int *spec_check_no = NULL;
-
-/* Size of spec_check_no array.  */
-static int max_uid = 0;
-
 /* The following variable is used to set up the mentioned above array.  */
 
 static int stop_before_p = 0;
@@ -6310,20 +6597,15 @@ static int stop_before_p = 0;
 
 static int clocks_length;
 
-/* The following array element values are cycles on which the
-   corresponding insn will be issued.  The array is used only for
-   Itanium1.  */
-
-static int *clocks;
-
-/* The following array element values are numbers of cycles should be
-   added to improve insn scheduling for MM_insns for Itanium1.  */
-
-static int *add_cycles;
-
 /* The following variable value is number of data speculations in progress.  */
 static int pending_data_specs = 0;
 
+/* Number of memory references on current and three future processor cycles.  */
+static char mem_ops_in_group[4];
+
+/* Number of current processor cycle (from scheduler's point of view).  */
+static int current_cycle;
+
 static rtx ia64_single_set (rtx);
 static void ia64_emit_insn_before (rtx, rtx);
 
@@ -6373,20 +6655,44 @@ ia64_single_set (rtx insn)
   return ret;
 }
 
-/* Adjust the cost of a scheduling dependency.  Return the new cost of
-   a dependency LINK or INSN on DEP_INSN.  COST is the current cost.  */
-
+/* Adjust the cost of a scheduling dependency.
+   Return the new cost of a dependency of type DEP_TYPE or INSN on DEP_INSN.
+   COST is the current cost, DW is dependency weakness.  */
 static int
-ia64_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
+ia64_adjust_cost_2 (rtx insn, int dep_type1, rtx dep_insn, int cost, dw_t dw)
 {
+  enum reg_note dep_type = (enum reg_note) dep_type1;
   enum attr_itanium_class dep_class;
   enum attr_itanium_class insn_class;
 
-  if (REG_NOTE_KIND (link) != REG_DEP_OUTPUT)
-    return cost;
-
   insn_class = ia64_safe_itanium_class (insn);
   dep_class = ia64_safe_itanium_class (dep_insn);
+
+  /* Treat true memory dependencies separately.  Ignore apparent true
+     dependence between store and call (call has a MEM inside a SYMBOL_REF).  */
+  if (dep_type == REG_DEP_TRUE
+      && (dep_class == ITANIUM_CLASS_ST || dep_class == ITANIUM_CLASS_STF)
+      && (insn_class == ITANIUM_CLASS_BR || insn_class == ITANIUM_CLASS_SCALL))
+    return 0;
+
+  if (dw == MIN_DEP_WEAK)
+    /* Store and load are likely to alias, use higher cost to avoid stall.  */
+    return PARAM_VALUE (PARAM_SCHED_MEM_TRUE_DEP_COST);
+  else if (dw > MIN_DEP_WEAK)
+    {
+      /* Store and load are less likely to alias.  */
+      if (mflag_sched_fp_mem_deps_zero_cost && dep_class == ITANIUM_CLASS_STF)
+       /* Assume there will be no cache conflict for floating-point data.
+          For integer data, L1 conflict penalty is huge (17 cycles), so we
+          never assume it will not cause a conflict.  */
+       return 0;
+      else
+       return cost;
+    }
+
+  if (dep_type != REG_DEP_OUTPUT)
+    return cost;
+
   if (dep_class == ITANIUM_CLASS_ST || dep_class == ITANIUM_CLASS_STF
       || insn_class == ITANIUM_CLASS_ST || insn_class == ITANIUM_CLASS_STF)
     return 0;
@@ -6471,7 +6777,7 @@ ia64_sched_init (FILE *dump ATTRIBUTE_UNUSED,
 #ifdef ENABLE_CHECKING
   rtx insn;
 
-  if (reload_completed)
+  if (!sel_sched_p () && reload_completed)
     for (insn = NEXT_INSN (current_sched_info->prev_head);
         insn != current_sched_info->next_tail;
         insn = NEXT_INSN (insn))
@@ -6479,6 +6785,9 @@ ia64_sched_init (FILE *dump ATTRIBUTE_UNUSED,
 #endif
   last_scheduled_insn = NULL_RTX;
   init_insn_group_barriers ();
+
+  current_cycle = 0;
+  memset (mem_ops_in_group, 0, sizeof (mem_ops_in_group));
 }
 
 /* We're beginning a scheduling pass.  Check assertion.  */
@@ -6488,7 +6797,7 @@ ia64_sched_init_global (FILE *dump ATTRIBUTE_UNUSED,
                         int sched_verbose ATTRIBUTE_UNUSED,
                         int max_ready ATTRIBUTE_UNUSED)
 {  
-  gcc_assert (!pending_data_specs);
+  gcc_assert (pending_data_specs == 0);
 }
 
 /* Scheduling pass is now finished.  Free/reset static variable.  */
@@ -6496,9 +6805,41 @@ static void
 ia64_sched_finish_global (FILE *dump ATTRIBUTE_UNUSED,
                          int sched_verbose ATTRIBUTE_UNUSED)
 {
-  free (spec_check_no);
-  spec_check_no = 0;
-  max_uid = 0;
+  gcc_assert (pending_data_specs == 0);
+}
+
+/* Return TRUE if INSN is a load (either normal or speculative, but not a
+   speculation check), FALSE otherwise.  */
+static bool
+is_load_p (rtx insn)
+{
+  enum attr_itanium_class insn_class = ia64_safe_itanium_class (insn);
+
+  return
+   ((insn_class == ITANIUM_CLASS_LD || insn_class == ITANIUM_CLASS_FLD)
+    && get_attr_check_load (insn) == CHECK_LOAD_NO);
+}
+
+/* If INSN is a memory reference, memoize it in MEM_OPS_IN_GROUP global array
+   (taking account for 3-cycle cache reference postponing for stores: Intel
+   Itanium 2 Reference Manual for Software Development and Optimization,
+   6.7.3.1).  */
+static void
+record_memory_reference (rtx insn)
+{
+  enum attr_itanium_class insn_class = ia64_safe_itanium_class (insn);
+
+  switch (insn_class) {
+    case ITANIUM_CLASS_FLD:
+    case ITANIUM_CLASS_LD:
+      mem_ops_in_group[current_cycle % 4]++;
+      break;
+    case ITANIUM_CLASS_STF:
+    case ITANIUM_CLASS_ST:
+      mem_ops_in_group[(current_cycle + 3) % 4]++;
+      break;
+    default:;
+  }
 }
 
 /* We are about to being issuing insns for this clock cycle.
@@ -6506,7 +6847,7 @@ ia64_sched_finish_global (FILE *dump ATTRIBUTE_UNUSED,
 
 static int
 ia64_dfa_sched_reorder (FILE *dump, int sched_verbose, rtx *ready,
-                       int *pn_ready, int clock_var ATTRIBUTE_UNUSED,
+                       int *pn_ready, int clock_var,
                        int reorder_type)
 {
   int n_asms;
@@ -6586,6 +6927,27 @@ ia64_dfa_sched_reorder (FILE *dump, int sched_verbose, rtx *ready,
       ready += deleted;
     }
 
+  current_cycle = clock_var;
+  if (reload_completed && mem_ops_in_group[clock_var % 4] >= ia64_max_memory_insns)
+    {
+      int moved = 0;
+
+      insnp = e_ready;
+      /* Move down loads/stores, preserving relative order.  */
+      while (insnp-- > ready + moved)
+       while (insnp >= ready + moved)
+         {
+           rtx insn = *insnp;
+           if (! is_load_p (insn))
+             break;
+           memmove (ready + 1, ready, (insnp - ready) * sizeof (rtx));
+           *ready = insn;
+           moved++;
+         }
+      n_ready -= moved;
+      ready += moved;
+    }
+
   return 1;
 }
 
@@ -6608,8 +6970,6 @@ ia64_sched_reorder2 (FILE *dump ATTRIBUTE_UNUSED,
                     int sched_verbose ATTRIBUTE_UNUSED, rtx *ready,
                     int *pn_ready, int clock_var)
 {
-  if (ia64_tune == PROCESSOR_ITANIUM && reload_completed && last_scheduled_insn)
-    clocks [INSN_UID (last_scheduled_insn)] = clock_var;
   return ia64_dfa_sched_reorder (dump, sched_verbose, ready, pn_ready,
                                 clock_var, 1);
 }
@@ -6623,9 +6983,9 @@ ia64_variable_issue (FILE *dump ATTRIBUTE_UNUSED,
                     rtx insn ATTRIBUTE_UNUSED,
                     int can_issue_more ATTRIBUTE_UNUSED)
 {
-  if (current_sched_info->flags & DO_SPECULATION)
+  if (sched_deps_info->generate_spec_deps && !sel_sched_p ())
     /* Modulo scheduling does not extend h_i_d when emitting
-       new instructions.  Deal with it.  */
+       new instructions.  Don't use h_i_d, if we don't have to.  */
     {
       if (DONE_SPEC (insn) & BEGIN_DATA)
        pending_data_specs++;
@@ -6633,6 +6993,9 @@ ia64_variable_issue (FILE *dump ATTRIBUTE_UNUSED,
        pending_data_specs--;
     }
 
+  if (DEBUG_INSN_P (insn))
+    return 1;
+
   last_scheduled_insn = insn;
   memcpy (prev_cycle_state, curr_state, dfa_state_size);
   if (reload_completed)
@@ -6644,6 +7007,8 @@ ia64_variable_issue (FILE *dump ATTRIBUTE_UNUSED,
        init_insn_group_barriers ();
       stops_p [INSN_UID (insn)] = stop_before_p;
       stop_before_p = 0;
+
+      record_memory_reference (insn);
     }
   return 1;
 }
@@ -6654,10 +7019,13 @@ ia64_variable_issue (FILE *dump ATTRIBUTE_UNUSED,
 static int
 ia64_first_cycle_multipass_dfa_lookahead_guard (rtx insn)
 {
-  gcc_assert (insn  && INSN_P (insn));
+  gcc_assert (insn && INSN_P (insn));
   return ((!reload_completed
           || !safe_group_barrier_needed (insn))
-         && ia64_first_cycle_multipass_dfa_lookahead_guard_spec (insn));
+         && ia64_first_cycle_multipass_dfa_lookahead_guard_spec (insn)
+         && (!mflag_sched_mem_insns_hard_limit
+             || !is_load_p (insn)
+             || mem_ops_in_group[current_cycle % 4] < ia64_max_memory_insns));
 }
 
 /* We are choosing insn from the ready queue.  Return nonzero if INSN
@@ -6679,6 +7047,26 @@ ia64_first_cycle_multipass_dfa_lookahead_guard_spec (const_rtx insn)
 
 static rtx dfa_pre_cycle_insn;
 
+/* Returns 1 when a meaningful insn was scheduled between the last group
+   barrier and LAST.  */
+static int
+scheduled_good_insn (rtx last)
+{
+  if (last && recog_memoized (last) >= 0)
+    return 1;
+
+  for ( ;
+       last != NULL && !NOTE_INSN_BASIC_BLOCK_P (last)
+       && !stops_p[INSN_UID (last)];
+       last = PREV_INSN (last))
+    /* We could hit a NOTE_INSN_DELETED here which is actually outside
+       the ebb we're scheduling.  */
+    if (INSN_P (last) && recog_memoized (last) >= 0)
+      return 1;
+
+  return 0;
+}
+
 /* We are about to being issuing INSN.  Return nonzero if we cannot
    issue it on given cycle CLOCK and return zero if we should not sort
    the ready queue on the next clock start.  */
@@ -6687,20 +7075,37 @@ static int
 ia64_dfa_new_cycle (FILE *dump, int verbose, rtx insn, int last_clock,
                    int clock, int *sort_p)
 {
-  int setup_clocks_p = FALSE;
-
   gcc_assert (insn && INSN_P (insn));
-  if ((reload_completed && safe_group_barrier_needed (insn))
+
+  if (DEBUG_INSN_P (insn))
+    return 0;
+
+  /* When a group barrier is needed for insn, last_scheduled_insn
+     should be set.  */
+  gcc_assert (!(reload_completed && safe_group_barrier_needed (insn))
+              || last_scheduled_insn);
+
+  if ((reload_completed
+       && (safe_group_barrier_needed (insn)
+          || (mflag_sched_stop_bits_after_every_cycle
+              && last_clock != clock
+              && last_scheduled_insn
+              && scheduled_good_insn (last_scheduled_insn))))
       || (last_scheduled_insn
          && (GET_CODE (last_scheduled_insn) == CALL_INSN
              || GET_CODE (PATTERN (last_scheduled_insn)) == ASM_INPUT
              || asm_noperands (PATTERN (last_scheduled_insn)) >= 0)))
     {
       init_insn_group_barriers ();
+
       if (verbose && dump)
        fprintf (dump, "//    Stop should be before %d%s\n", INSN_UID (insn),
                 last_clock == clock ? " + cycle advance" : "");
+
       stop_before_p = 1;
+      current_cycle = clock;
+      mem_ops_in_group[current_cycle % 4] = 0;
+
       if (last_clock == clock)
        {
          state_transition (curr_state, dfa_stop_insn);
@@ -6711,49 +7116,19 @@ ia64_dfa_new_cycle (FILE *dump, int verbose, rtx insn, int last_clock,
            *sort_p = 0;
          return 1;
        }
-      else if (reload_completed)
-       setup_clocks_p = TRUE;
-      if (GET_CODE (PATTERN (last_scheduled_insn)) == ASM_INPUT
-         || asm_noperands (PATTERN (last_scheduled_insn)) >= 0)
-       state_reset (curr_state);
-      else
-       {
-         memcpy (curr_state, prev_cycle_state, dfa_state_size);
-         state_transition (curr_state, dfa_stop_insn);
-         state_transition (curr_state, dfa_pre_cycle_insn);
-         state_transition (curr_state, NULL);
-       }
-    }
-  else if (reload_completed)
-    setup_clocks_p = TRUE;
-  if (setup_clocks_p && ia64_tune == PROCESSOR_ITANIUM
-      && GET_CODE (PATTERN (insn)) != ASM_INPUT
-      && asm_noperands (PATTERN (insn)) < 0)
-    {
-      enum attr_itanium_class c = ia64_safe_itanium_class (insn);
 
-      if (c != ITANIUM_CLASS_MMMUL && c != ITANIUM_CLASS_MMSHF)
+      if (last_scheduled_insn)
        {
-         sd_iterator_def sd_it;
-         dep_t dep;
-         int d = -1;
-
-         FOR_EACH_DEP (insn, SD_LIST_BACK, sd_it, dep)
-           if (DEP_TYPE (dep) == REG_DEP_TRUE)
-             {
-               enum attr_itanium_class dep_class;
-               rtx dep_insn = DEP_PRO (dep);
-
-               dep_class = ia64_safe_itanium_class (dep_insn);
-               if ((dep_class == ITANIUM_CLASS_MMMUL
-                    || dep_class == ITANIUM_CLASS_MMSHF)
-                   && last_clock - clocks [INSN_UID (dep_insn)] < 4
-                   && (d < 0
-                       || last_clock - clocks [INSN_UID (dep_insn)] < d))
-                 d = last_clock - clocks [INSN_UID (dep_insn)];
-             }
-         if (d >= 0)
-           add_cycles [INSN_UID (insn)] = 3 - d;
+         if (GET_CODE (PATTERN (last_scheduled_insn)) == ASM_INPUT
+             || asm_noperands (PATTERN (last_scheduled_insn)) >= 0)
+           state_reset (curr_state);
+         else
+           {
+             memcpy (curr_state, prev_cycle_state, dfa_state_size);
+             state_transition (curr_state, dfa_stop_insn);
+             state_transition (curr_state, dfa_pre_cycle_insn);
+             state_transition (curr_state, NULL);
+           }
        }
     }
   return 0;
@@ -6764,64 +7139,248 @@ ia64_dfa_new_cycle (FILE *dump, int verbose, rtx insn, int last_clock,
 static void
 ia64_h_i_d_extended (void)
 {
-  if (current_sched_info->flags & DO_SPECULATION)
-    {
-      int new_max_uid = get_max_uid () + 1;
-
-      spec_check_no = (int *) xrecalloc (spec_check_no, new_max_uid,
-                                max_uid, sizeof (*spec_check_no));
-      max_uid = new_max_uid;
-    }
-
   if (stops_p != NULL) 
     {
-      int new_clocks_length = get_max_uid () + 1;
-      
+      int new_clocks_length = get_max_uid () * 3 / 2;
       stops_p = (char *) xrecalloc (stops_p, new_clocks_length, clocks_length, 1);
-      
-      if (ia64_tune == PROCESSOR_ITANIUM)
-       {
-         clocks = (int *) xrecalloc (clocks, new_clocks_length, clocks_length,
-                                     sizeof (int));
-         add_cycles = (int *) xrecalloc (add_cycles, new_clocks_length,
-                                         clocks_length, sizeof (int));
-       }
-      
       clocks_length = new_clocks_length;
     }
 }
+\f
 
-/* Constants that help mapping 'enum machine_mode' to int.  */
-enum SPEC_MODES
-  {
-    SPEC_MODE_INVALID = -1,
-    SPEC_MODE_FIRST = 0,
-    SPEC_MODE_FOR_EXTEND_FIRST = 1,
-    SPEC_MODE_FOR_EXTEND_LAST = 3,
-    SPEC_MODE_LAST = 8
-  };
+/* This structure describes the data used by the backend to guide scheduling.
+   When the current scheduling point is switched, this data should be saved
+   and restored later, if the scheduler returns to this point.  */
+struct _ia64_sched_context
+{
+  state_t prev_cycle_state;
+  rtx last_scheduled_insn;
+  struct reg_write_state rws_sum[NUM_REGS];
+  struct reg_write_state rws_insn[NUM_REGS];
+  int first_instruction;
+  int pending_data_specs;
+  int current_cycle;
+  char mem_ops_in_group[4];
+};
+typedef struct _ia64_sched_context *ia64_sched_context_t;
 
-/* Return index of the MODE.  */
-static int
-ia64_mode_to_int (enum machine_mode mode)
+/* Allocates a scheduling context.  */
+static void *
+ia64_alloc_sched_context (void)
 {
-  switch (mode)
-    {
-    case BImode: return 0; /* SPEC_MODE_FIRST  */
-    case QImode: return 1; /* SPEC_MODE_FOR_EXTEND_FIRST  */
-    case HImode: return 2;
-    case SImode: return 3; /* SPEC_MODE_FOR_EXTEND_LAST  */
-    case DImode: return 4;
-    case SFmode: return 5;
-    case DFmode: return 6;
-    case XFmode: return 7;
-    case TImode:
-      /* ??? This mode needs testing.  Bypasses for ldfp8 instruction are not
-        mentioned in itanium[12].md.  Predicate fp_register_operand also
-        needs to be defined.  Bottom line: better disable for now.  */
-      return SPEC_MODE_INVALID;
-    default:     return SPEC_MODE_INVALID;
-    }
+  return xmalloc (sizeof (struct _ia64_sched_context));
+}
+
+/* Initializes the _SC context with clean data, if CLEAN_P, and from
+   the global context otherwise.  */
+static void
+ia64_init_sched_context (void *_sc, bool clean_p)
+{
+  ia64_sched_context_t sc = (ia64_sched_context_t) _sc;
+
+  sc->prev_cycle_state = xmalloc (dfa_state_size);
+  if (clean_p)
+    {
+      state_reset (sc->prev_cycle_state);
+      sc->last_scheduled_insn = NULL_RTX;
+      memset (sc->rws_sum, 0, sizeof (rws_sum));
+      memset (sc->rws_insn, 0, sizeof (rws_insn));
+      sc->first_instruction = 1;
+      sc->pending_data_specs = 0;
+      sc->current_cycle = 0;
+      memset (sc->mem_ops_in_group, 0, sizeof (mem_ops_in_group));
+    }
+  else
+    {
+      memcpy (sc->prev_cycle_state, prev_cycle_state, dfa_state_size);
+      sc->last_scheduled_insn = last_scheduled_insn;
+      memcpy (sc->rws_sum, rws_sum, sizeof (rws_sum));
+      memcpy (sc->rws_insn, rws_insn, sizeof (rws_insn));
+      sc->first_instruction = first_instruction;
+      sc->pending_data_specs = pending_data_specs;
+      sc->current_cycle = current_cycle;
+      memcpy (sc->mem_ops_in_group, mem_ops_in_group, sizeof (mem_ops_in_group));
+    }
+}
+
+/* Sets the global scheduling context to the one pointed to by _SC.  */
+static void
+ia64_set_sched_context (void *_sc)
+{
+  ia64_sched_context_t sc = (ia64_sched_context_t) _sc;
+
+  gcc_assert (sc != NULL);
+
+  memcpy (prev_cycle_state, sc->prev_cycle_state, dfa_state_size);
+  last_scheduled_insn = sc->last_scheduled_insn;
+  memcpy (rws_sum, sc->rws_sum, sizeof (rws_sum));
+  memcpy (rws_insn, sc->rws_insn, sizeof (rws_insn));
+  first_instruction = sc->first_instruction;
+  pending_data_specs = sc->pending_data_specs;
+  current_cycle = sc->current_cycle;
+  memcpy (mem_ops_in_group, sc->mem_ops_in_group, sizeof (mem_ops_in_group));
+}
+
+/* Clears the data in the _SC scheduling context.  */
+static void
+ia64_clear_sched_context (void *_sc)
+{
+  ia64_sched_context_t sc = (ia64_sched_context_t) _sc;
+  
+  free (sc->prev_cycle_state);
+  sc->prev_cycle_state = NULL;
+}
+
+/* Frees the _SC scheduling context.  */
+static void
+ia64_free_sched_context (void *_sc)
+{
+  gcc_assert (_sc != NULL);
+
+  free (_sc);
+}
+
+typedef rtx (* gen_func_t) (rtx, rtx);
+
+/* Return a function that will generate a load of mode MODE_NO
+   with speculation types TS.  */
+static gen_func_t
+get_spec_load_gen_function (ds_t ts, int mode_no)
+{
+  static gen_func_t gen_ld_[] = {
+    gen_movbi,
+    gen_movqi_internal,
+    gen_movhi_internal,
+    gen_movsi_internal,
+    gen_movdi_internal,
+    gen_movsf_internal,
+    gen_movdf_internal,
+    gen_movxf_internal,
+    gen_movti_internal,
+    gen_zero_extendqidi2,
+    gen_zero_extendhidi2,
+    gen_zero_extendsidi2,
+  };
+
+  static gen_func_t gen_ld_a[] = {
+    gen_movbi_advanced,
+    gen_movqi_advanced,
+    gen_movhi_advanced,
+    gen_movsi_advanced,
+    gen_movdi_advanced,
+    gen_movsf_advanced,
+    gen_movdf_advanced,
+    gen_movxf_advanced,
+    gen_movti_advanced,
+    gen_zero_extendqidi2_advanced,
+    gen_zero_extendhidi2_advanced,
+    gen_zero_extendsidi2_advanced,
+  };
+  static gen_func_t gen_ld_s[] = {
+    gen_movbi_speculative,
+    gen_movqi_speculative,
+    gen_movhi_speculative,
+    gen_movsi_speculative,
+    gen_movdi_speculative,
+    gen_movsf_speculative,
+    gen_movdf_speculative,
+    gen_movxf_speculative,
+    gen_movti_speculative,
+    gen_zero_extendqidi2_speculative,
+    gen_zero_extendhidi2_speculative,
+    gen_zero_extendsidi2_speculative,
+  };
+  static gen_func_t gen_ld_sa[] = {
+    gen_movbi_speculative_advanced,
+    gen_movqi_speculative_advanced,
+    gen_movhi_speculative_advanced,
+    gen_movsi_speculative_advanced,
+    gen_movdi_speculative_advanced,
+    gen_movsf_speculative_advanced,
+    gen_movdf_speculative_advanced,
+    gen_movxf_speculative_advanced,
+    gen_movti_speculative_advanced,
+    gen_zero_extendqidi2_speculative_advanced,
+    gen_zero_extendhidi2_speculative_advanced,
+    gen_zero_extendsidi2_speculative_advanced,
+  };
+  static gen_func_t gen_ld_s_a[] = {
+    gen_movbi_speculative_a,
+    gen_movqi_speculative_a,
+    gen_movhi_speculative_a,
+    gen_movsi_speculative_a,
+    gen_movdi_speculative_a,
+    gen_movsf_speculative_a,
+    gen_movdf_speculative_a,
+    gen_movxf_speculative_a,
+    gen_movti_speculative_a,
+    gen_zero_extendqidi2_speculative_a,
+    gen_zero_extendhidi2_speculative_a,
+    gen_zero_extendsidi2_speculative_a,
+  };
+
+  gen_func_t *gen_ld;
+
+  if (ts & BEGIN_DATA)
+    {
+      if (ts & BEGIN_CONTROL)
+       gen_ld = gen_ld_sa;
+      else
+       gen_ld = gen_ld_a;
+    }
+  else if (ts & BEGIN_CONTROL)
+    {
+      if ((spec_info->flags & SEL_SCHED_SPEC_DONT_CHECK_CONTROL)
+         || ia64_needs_block_p (ts))
+       gen_ld = gen_ld_s;
+      else
+       gen_ld = gen_ld_s_a;
+    }
+  else if (ts == 0)
+    gen_ld = gen_ld_;
+  else
+    gcc_unreachable ();
+
+  return gen_ld[mode_no];
+}
+
+/* Constants that help mapping 'enum machine_mode' to int.  */
+enum SPEC_MODES
+  {
+    SPEC_MODE_INVALID = -1,
+    SPEC_MODE_FIRST = 0,
+    SPEC_MODE_FOR_EXTEND_FIRST = 1,
+    SPEC_MODE_FOR_EXTEND_LAST = 3,
+    SPEC_MODE_LAST = 8
+  };
+
+enum
+  {
+    /* Offset to reach ZERO_EXTEND patterns.  */
+    SPEC_GEN_EXTEND_OFFSET = SPEC_MODE_LAST - SPEC_MODE_FOR_EXTEND_FIRST + 1
+  };
+
+/* Return index of the MODE.  */
+static int
+ia64_mode_to_int (enum machine_mode mode)
+{
+  switch (mode)
+    {
+    case BImode: return 0; /* SPEC_MODE_FIRST  */
+    case QImode: return 1; /* SPEC_MODE_FOR_EXTEND_FIRST  */
+    case HImode: return 2;
+    case SImode: return 3; /* SPEC_MODE_FOR_EXTEND_LAST  */
+    case DImode: return 4;
+    case SFmode: return 5;
+    case DFmode: return 6;
+    case XFmode: return 7;
+    case TImode:
+      /* ??? This mode needs testing.  Bypasses for ldfp8 instruction are not
+        mentioned in itanium[12].md.  Predicate fp_register_operand also
+        needs to be defined.  Bottom line: better disable for now.  */
+      return SPEC_MODE_INVALID;
+    default:     return SPEC_MODE_INVALID;
+    }
 }
 
 /* Provide information about speculation capabilities.  */
@@ -6831,25 +7390,29 @@ ia64_set_sched_flags (spec_info_t spec_info)
   unsigned int *flags = &(current_sched_info->flags);
 
   if (*flags & SCHED_RGN
-      || *flags & SCHED_EBB)  
+      || *flags & SCHED_EBB
+      || *flags & SEL_SCHED)
     {
       int mask = 0;
 
       if ((mflag_sched_br_data_spec && !reload_completed && optimize > 0)
-         || (mflag_sched_ar_data_spec && reload_completed))
+          || (mflag_sched_ar_data_spec && reload_completed))
        {
          mask |= BEGIN_DATA;
-         
-         if ((mflag_sched_br_in_data_spec && !reload_completed)
-             || (mflag_sched_ar_in_data_spec && reload_completed))
+
+         if (!sel_sched_p ()
+             && ((mflag_sched_br_in_data_spec && !reload_completed)
+                 || (mflag_sched_ar_in_data_spec && reload_completed)))
            mask |= BE_IN_DATA;
        }
       
-      if (mflag_sched_control_spec)
+      if (mflag_sched_control_spec
+          && (!sel_sched_p ()
+             || reload_completed))
        {
          mask |= BEGIN_CONTROL;
          
-         if (mflag_sched_in_control_spec)
+         if (!sel_sched_p () && mflag_sched_in_control_spec)
            mask |= BE_IN_CONTROL;
        }
 
@@ -6867,17 +7430,17 @@ ia64_set_sched_flags (spec_info_t spec_info)
          if ((mask & DATA_SPEC) && mflag_sched_prefer_non_data_spec_insns)
            spec_info->flags |= PREFER_NON_DATA_SPEC;
 
-         if ((mask & CONTROL_SPEC)
-             && mflag_sched_prefer_non_control_spec_insns)
-           spec_info->flags |= PREFER_NON_CONTROL_SPEC;
-
-         if (mflag_sched_spec_verbose)
+         if (mask & CONTROL_SPEC)
            {
-             if (sched_verbose >= 1)
-               spec_info->dump = sched_dump;
-             else
-               spec_info->dump = stderr;
+             if (mflag_sched_prefer_non_control_spec_insns)
+               spec_info->flags |= PREFER_NON_CONTROL_SPEC;
+
+             if (sel_sched_p () && mflag_sel_sched_dont_check_control_spec)
+               spec_info->flags |= SEL_SCHED_SPEC_DONT_CHECK_CONTROL;
            }
+
+         if (sched_verbose >= 1)
+           spec_info->dump = sched_dump;
          else
            spec_info->dump = 0;
          
@@ -6885,306 +7448,288 @@ ia64_set_sched_flags (spec_info_t spec_info)
            spec_info->flags |= COUNT_SPEC_IN_CRITICAL_PATH;
        }
     }
+  else
+    spec_info->mask = 0;
 }
 
-/* Implement targetm.sched.speculate_insn hook.
-   Check if the INSN can be TS speculative.
-   If 'no' - return -1.
-   If 'yes' - generate speculative pattern in the NEW_PAT and return 1.
-   If current pattern of the INSN already provides TS speculation, return 0.  */
+/* If INSN is an appropriate load return its mode.
+   Return -1 otherwise.  */
 static int
-ia64_speculate_insn (rtx insn, ds_t ts, rtx *new_pat)
-{  
-  rtx pat, reg, mem, mem_reg;
-  int mode_no, gen_p = 1;
+get_mode_no_for_insn (rtx insn)
+{
+  rtx reg, mem, mode_rtx;
+  int mode_no;
   bool extend_p;
-  
-  gcc_assert (!(ts & ~BEGIN_SPEC) && ts);
-           
-  pat = PATTERN (insn);
 
-  if (GET_CODE (pat) == COND_EXEC)
-    pat = COND_EXEC_CODE (pat);
+  extract_insn_cached (insn);
 
-  /* This should be a SET ...  */
-  if (GET_CODE (pat) != SET)
-    return -1;
+  /* We use WHICH_ALTERNATIVE only after reload.  This will
+     guarantee that reload won't touch a speculative insn.  */
 
-  reg = SET_DEST (pat);
-  /* ... to the general/fp register ...  */
-  if (!REG_P (reg) || !(GR_REGNO_P (REGNO (reg)) || FP_REGNO_P (REGNO (reg))))
+  if (recog_data.n_operands != 2)
     return -1;
 
-  /* ... from the mem ...  */
-  mem = SET_SRC (pat);
+  reg = recog_data.operand[0];
+  mem = recog_data.operand[1];
 
-  /* ... that can, possibly, be a zero_extend ...  */
-  if (GET_CODE (mem) == ZERO_EXTEND)
+  /* We should use MEM's mode since REG's mode in presence of
+     ZERO_EXTEND will always be DImode.  */
+  if (get_attr_speculable1 (insn) == SPECULABLE1_YES)
+    /* Process non-speculative ld.  */
     {
-      mem = XEXP (mem, 0);
-      extend_p = true;      
+      if (!reload_completed)
+       {
+         /* Do not speculate into regs like ar.lc.  */
+         if (!REG_P (reg) || AR_REGNO_P (REGNO (reg)))
+           return -1;
+
+         if (!MEM_P (mem))
+           return -1;
+
+         {
+           rtx mem_reg = XEXP (mem, 0);
+
+           if (!REG_P (mem_reg))
+             return -1;
+         }
+
+         mode_rtx = mem;
+       }
+      else if (get_attr_speculable2 (insn) == SPECULABLE2_YES)
+       {
+         gcc_assert (REG_P (reg) && MEM_P (mem));
+         mode_rtx = mem;
+       }
+      else
+       return -1;
+    }
+  else if (get_attr_data_speculative (insn) == DATA_SPECULATIVE_YES
+          || get_attr_control_speculative (insn) == CONTROL_SPECULATIVE_YES
+          || get_attr_check_load (insn) == CHECK_LOAD_YES)
+    /* Process speculative ld or ld.c.  */
+    {
+      gcc_assert (REG_P (reg) && MEM_P (mem));
+      mode_rtx = mem;
     }
   else
-    extend_p = false;
-
-  /* ... or a speculative load.  */
-  if (GET_CODE (mem) == UNSPEC)
     {
-      int code;
-      
-      code = XINT (mem, 1);
-      if (code != UNSPEC_LDA && code != UNSPEC_LDS && code != UNSPEC_LDSA)
-       return -1;
-
-      if ((code == UNSPEC_LDA && !(ts & BEGIN_CONTROL))
-         || (code == UNSPEC_LDS && !(ts & BEGIN_DATA))
-         || code == UNSPEC_LDSA)
-       gen_p = 0;
+      enum attr_itanium_class attr_class = get_attr_itanium_class (insn);
 
-      mem = XVECEXP (mem, 0, 0);
-      gcc_assert (MEM_P (mem));
+      if (attr_class == ITANIUM_CLASS_CHK_A
+         || attr_class == ITANIUM_CLASS_CHK_S_I
+         || attr_class == ITANIUM_CLASS_CHK_S_F)
+       /* Process chk.  */
+       mode_rtx = reg;
+      else
+       return -1;
     }
 
-  /* Source should be a mem ...  */
-  if (!MEM_P (mem))
-    return -1;
+  mode_no = ia64_mode_to_int (GET_MODE (mode_rtx));
 
-  /* ... addressed by a register.  */
-  mem_reg = XEXP (mem, 0);
-  if (!REG_P (mem_reg))
-    return -1;
-     
-  /* We should use MEM's mode since REG's mode in presence of ZERO_EXTEND
-     will always be DImode.  */
-  mode_no = ia64_mode_to_int (GET_MODE (mem));
-  
-  if (mode_no == SPEC_MODE_INVALID
-      || (extend_p
-         && !(SPEC_MODE_FOR_EXTEND_FIRST <= mode_no
-              && mode_no <= SPEC_MODE_FOR_EXTEND_LAST)))
+  if (mode_no == SPEC_MODE_INVALID)
     return -1;
 
-  extract_insn_cached (insn);
-  gcc_assert (reg == recog_data.operand[0] && mem == recog_data.operand[1]);
+  extend_p = (GET_MODE (reg) != GET_MODE (mode_rtx));
+
+  if (extend_p)
+    {
+      if (!(SPEC_MODE_FOR_EXTEND_FIRST <= mode_no
+           && mode_no <= SPEC_MODE_FOR_EXTEND_LAST))
+       return -1;
 
-  *new_pat = ia64_gen_spec_insn (insn, ts, mode_no, gen_p != 0, extend_p);
+      mode_no += SPEC_GEN_EXTEND_OFFSET;
+    }
 
-  return gen_p;
+  return mode_no;
 }
 
-enum
-  {
-    /* Offset to reach ZERO_EXTEND patterns.  */
-    SPEC_GEN_EXTEND_OFFSET = SPEC_MODE_LAST - SPEC_MODE_FOR_EXTEND_FIRST + 1,
-    /* Number of patterns for each speculation mode.  */
-    SPEC_N = (SPEC_MODE_LAST
-              + SPEC_MODE_FOR_EXTEND_LAST - SPEC_MODE_FOR_EXTEND_FIRST + 2)
-  };
+/* If X is an unspec part of a speculative load, return its code.
+   Return -1 otherwise.  */
+static int
+get_spec_unspec_code (const_rtx x)
+{
+  if (GET_CODE (x) != UNSPEC)
+    return -1;
 
-enum SPEC_GEN_LD_MAP
   {
-    /* Offset to ld.a patterns.  */
-    SPEC_GEN_A = 0 * SPEC_N,
-    /* Offset to ld.s patterns.  */
-    SPEC_GEN_S = 1 * SPEC_N,
-    /* Offset to ld.sa patterns.  */
-    SPEC_GEN_SA = 2 * SPEC_N,
-    /* Offset to ld.sa patterns.  For this patterns corresponding ld.c will
-       mutate to chk.s.  */
-    SPEC_GEN_SA_FOR_S = 3 * SPEC_N
-  };
+    int code;
 
-/* These offsets are used to get (4 * SPEC_N).  */
-enum SPEC_GEN_CHECK_OFFSET
-  {
-    SPEC_GEN_CHKA_FOR_A_OFFSET = 4 * SPEC_N - SPEC_GEN_A,
-    SPEC_GEN_CHKA_FOR_SA_OFFSET = 4 * SPEC_N - SPEC_GEN_SA
-  };
+    code = XINT (x, 1);
 
-/* If GEN_P is true, calculate the index of needed speculation check and return
-   speculative pattern for INSN with speculative mode TS, machine mode
-   MODE_NO and with ZERO_EXTEND (if EXTEND_P is true).
-   If GEN_P is false, just calculate the index of needed speculation check.  */
-static rtx
-ia64_gen_spec_insn (rtx insn, ds_t ts, int mode_no, bool gen_p, bool extend_p)
+    switch (code)
+      {
+      case UNSPEC_LDA:
+      case UNSPEC_LDS:
+      case UNSPEC_LDS_A:
+      case UNSPEC_LDSA:
+       return code;
+
+      default:
+       return -1;
+      }
+  }
+}
+
+/* Implement skip_rtx_p hook.  */
+static bool
+ia64_skip_rtx_p (const_rtx x)
 {
-  rtx pat, new_pat;
-  int load_no;
-  int shift = 0;
+  return get_spec_unspec_code (x) != -1;
+}
 
-  static rtx (* const gen_load[]) (rtx, rtx) = {
-    gen_movbi_advanced,
-    gen_movqi_advanced,
-    gen_movhi_advanced,
-    gen_movsi_advanced,
-    gen_movdi_advanced,
-    gen_movsf_advanced,
-    gen_movdf_advanced,
-    gen_movxf_advanced,
-    gen_movti_advanced,
-    gen_zero_extendqidi2_advanced,
-    gen_zero_extendhidi2_advanced,
-    gen_zero_extendsidi2_advanced,
+/* If INSN is a speculative load, return its UNSPEC code.
+   Return -1 otherwise.  */
+static int
+get_insn_spec_code (const_rtx insn)
+{
+  rtx pat, reg, mem;
 
-    gen_movbi_speculative,
-    gen_movqi_speculative,
-    gen_movhi_speculative,
-    gen_movsi_speculative,
-    gen_movdi_speculative,
-    gen_movsf_speculative,
-    gen_movdf_speculative,
-    gen_movxf_speculative,
-    gen_movti_speculative,
-    gen_zero_extendqidi2_speculative,
-    gen_zero_extendhidi2_speculative,
-    gen_zero_extendsidi2_speculative,
+  pat = PATTERN (insn);
 
-    gen_movbi_speculative_advanced,
-    gen_movqi_speculative_advanced,
-    gen_movhi_speculative_advanced,
-    gen_movsi_speculative_advanced,
-    gen_movdi_speculative_advanced,
-    gen_movsf_speculative_advanced,
-    gen_movdf_speculative_advanced,
-    gen_movxf_speculative_advanced,
-    gen_movti_speculative_advanced,
-    gen_zero_extendqidi2_speculative_advanced,
-    gen_zero_extendhidi2_speculative_advanced,
-    gen_zero_extendsidi2_speculative_advanced,
+  if (GET_CODE (pat) == COND_EXEC)
+    pat = COND_EXEC_CODE (pat);
 
-    gen_movbi_speculative_advanced,
-    gen_movqi_speculative_advanced,
-    gen_movhi_speculative_advanced,
-    gen_movsi_speculative_advanced,
-    gen_movdi_speculative_advanced,
-    gen_movsf_speculative_advanced,
-    gen_movdf_speculative_advanced,
-    gen_movxf_speculative_advanced,
-    gen_movti_speculative_advanced,
-    gen_zero_extendqidi2_speculative_advanced,
-    gen_zero_extendhidi2_speculative_advanced,
-    gen_zero_extendsidi2_speculative_advanced
-  };
+  if (GET_CODE (pat) != SET)
+    return -1;
 
-  load_no = extend_p ? mode_no + SPEC_GEN_EXTEND_OFFSET : mode_no;
+  reg = SET_DEST (pat);
+  if (!REG_P (reg))
+    return -1;
 
-  if (ts & BEGIN_DATA)
+  mem = SET_SRC (pat);
+  if (GET_CODE (mem) == ZERO_EXTEND)
+    mem = XEXP (mem, 0);
+
+  return get_spec_unspec_code (mem);
+}
+
+/* If INSN is a speculative load, return a ds with the speculation types.
+   Otherwise [if INSN is a normal instruction] return 0.  */
+static ds_t
+ia64_get_insn_spec_ds (rtx insn)
+{
+  int code = get_insn_spec_code (insn);
+
+  switch (code)
     {
-      /* We don't need recovery because even if this is ld.sa
-        ALAT entry will be allocated only if NAT bit is set to zero. 
-        So it is enough to use ld.c here.  */    
+    case UNSPEC_LDA:
+      return BEGIN_DATA;
 
-      if (ts & BEGIN_CONTROL)
-       {             
-         load_no += SPEC_GEN_SA;
+    case UNSPEC_LDS:
+    case UNSPEC_LDS_A:
+      return BEGIN_CONTROL;
 
-         if (!mflag_sched_ldc)
-           shift = SPEC_GEN_CHKA_FOR_SA_OFFSET;
-       }
-      else
-       {
-         load_no += SPEC_GEN_A;
+    case UNSPEC_LDSA:
+      return BEGIN_DATA | BEGIN_CONTROL;
 
-         if (!mflag_sched_ldc)         
-           shift = SPEC_GEN_CHKA_FOR_A_OFFSET;
-       }
+    default:
+      return 0;
     }
-  else if (ts & BEGIN_CONTROL)
+}
+
+/* If INSN is a speculative load return a ds with the speculation types that
+   will be checked.
+   Otherwise [if INSN is a normal instruction] return 0.  */
+static ds_t
+ia64_get_insn_checked_ds (rtx insn)
+{
+  int code = get_insn_spec_code (insn);
+
+  switch (code)
     {
-      /* ld.sa can be used instead of ld.s to avoid basic block splitting.  */
-      if (!mflag_control_ldc)
-       load_no += SPEC_GEN_S;
-      else
-       {
-         gcc_assert (mflag_sched_ldc);
-         load_no += SPEC_GEN_SA_FOR_S;
-       }
-    }
-  else
-    gcc_unreachable ();
+    case UNSPEC_LDA:
+      return BEGIN_DATA | BEGIN_CONTROL;
+
+    case UNSPEC_LDS:
+      return BEGIN_CONTROL;
+
+    case UNSPEC_LDS_A:
+    case UNSPEC_LDSA:
+      return BEGIN_DATA | BEGIN_CONTROL;
+
+    default:
+      return 0;
+    }
+}
 
-  /* Set the desired check index.  We add '1', because zero element in this
-     array means, that instruction with such uid is non-speculative.  */
-  spec_check_no[INSN_UID (insn)] = load_no + shift + 1;
+/* If GEN_P is true, calculate the index of needed speculation check and return
+   speculative pattern for INSN with speculative mode TS, machine mode
+   MODE_NO and with ZERO_EXTEND (if EXTEND_P is true).
+   If GEN_P is false, just calculate the index of needed speculation check.  */
+static rtx
+ia64_gen_spec_load (rtx insn, ds_t ts, int mode_no)
+{
+  rtx pat, new_pat;
+  gen_func_t gen_load;
 
-  if (!gen_p)
-    return 0;
+  gen_load = get_spec_load_gen_function (ts, mode_no);
 
-  new_pat = gen_load[load_no] (copy_rtx (recog_data.operand[0]),
-                              copy_rtx (recog_data.operand[1]));
+  new_pat = gen_load (copy_rtx (recog_data.operand[0]),
+                     copy_rtx (recog_data.operand[1]));
 
   pat = PATTERN (insn);
   if (GET_CODE (pat) == COND_EXEC)
-    new_pat = gen_rtx_COND_EXEC (VOIDmode, copy_rtx 
-                                (COND_EXEC_TEST (pat)), new_pat);
+    new_pat = gen_rtx_COND_EXEC (VOIDmode, copy_rtx (COND_EXEC_TEST (pat)),
+                                new_pat);
 
   return new_pat;
 }
 
-/* Offset to branchy checks.  */
-enum { SPEC_GEN_CHECK_MUTATION_OFFSET = 5 * SPEC_N };
-
-/* Return nonzero, if INSN needs branchy recovery check.  */
 static bool
-ia64_needs_block_p (const_rtx insn)
+insn_can_be_in_speculative_p (rtx insn ATTRIBUTE_UNUSED,
+                             ds_t ds ATTRIBUTE_UNUSED)
 {
-  int check_no;
+  return false;
+}
 
-  check_no = spec_check_no[INSN_UID(insn)] - 1;
-  gcc_assert (0 <= check_no && check_no < SPEC_GEN_CHECK_MUTATION_OFFSET);
+/* Implement targetm.sched.speculate_insn hook.
+   Check if the INSN can be TS speculative.
+   If 'no' - return -1.
+   If 'yes' - generate speculative pattern in the NEW_PAT and return 1.
+   If current pattern of the INSN already provides TS speculation,
+   return 0.  */
+static int
+ia64_speculate_insn (rtx insn, ds_t ts, rtx *new_pat)
+{  
+  int mode_no;
+  int res;
+  
+  gcc_assert (!(ts & ~SPECULATIVE));
 
-  return ((SPEC_GEN_S <= check_no && check_no < SPEC_GEN_S + SPEC_N)
-         || (4 * SPEC_N <= check_no && check_no < 4 * SPEC_N + SPEC_N));
-}
+  if (ia64_spec_check_p (insn))
+    return -1;
 
-/* Generate (or regenerate, if (MUTATE_P)) recovery check for INSN.
-   If (LABEL != 0 || MUTATE_P), generate branchy recovery check.
-   Otherwise, generate a simple check.  */
-static rtx
-ia64_gen_check (rtx insn, rtx label, bool mutate_p)
-{
-  rtx op1, pat, check_pat;
+  if ((ts & BE_IN_SPEC)
+      && !insn_can_be_in_speculative_p (insn, ts))
+    return -1;
 
-  static rtx (* const gen_check[]) (rtx, rtx) = {
-    gen_movbi_clr,
-    gen_movqi_clr,
-    gen_movhi_clr,
-    gen_movsi_clr,
-    gen_movdi_clr,
-    gen_movsf_clr,
-    gen_movdf_clr,
-    gen_movxf_clr,
-    gen_movti_clr,
-    gen_zero_extendqidi2_clr,
-    gen_zero_extendhidi2_clr,
-    gen_zero_extendsidi2_clr,
+  mode_no = get_mode_no_for_insn (insn);
 
-    gen_speculation_check_bi,
-    gen_speculation_check_qi,
-    gen_speculation_check_hi,
-    gen_speculation_check_si,
-    gen_speculation_check_di,
-    gen_speculation_check_sf,
-    gen_speculation_check_df,
-    gen_speculation_check_xf,
-    gen_speculation_check_ti,
-    gen_speculation_check_di,
-    gen_speculation_check_di,
-    gen_speculation_check_di,
+  if (mode_no != SPEC_MODE_INVALID)
+    {
+      if (ia64_get_insn_spec_ds (insn) == ds_get_speculation_types (ts))
+       res = 0;
+      else
+       {
+         res = 1;
+         *new_pat = ia64_gen_spec_load (insn, ts, mode_no);
+       }
+    }
+  else
+    res = -1;
 
-    gen_movbi_clr,
-    gen_movqi_clr,
-    gen_movhi_clr,
-    gen_movsi_clr,
-    gen_movdi_clr,
-    gen_movsf_clr,
-    gen_movdf_clr,
-    gen_movxf_clr,
-    gen_movti_clr,
-    gen_zero_extendqidi2_clr,
-    gen_zero_extendhidi2_clr,
-    gen_zero_extendsidi2_clr,
+  return res;
+}
 
+/* Return a function that will generate a check for speculation TS with mode
+   MODE_NO.
+   If simple check is needed, pass true for SIMPLE_CHECK_P.
+   If clearing check is needed, pass true for CLEARING_CHECK_P.  */
+static gen_func_t
+get_spec_check_gen_function (ds_t ts, int mode_no,
+                            bool simple_check_p, bool clearing_check_p)
+{
+  static gen_func_t gen_ld_c_clr[] = {
     gen_movbi_clr,
     gen_movqi_clr,
     gen_movhi_clr,
@@ -7197,36 +7742,22 @@ ia64_gen_check (rtx insn, rtx label, bool mutate_p)
     gen_zero_extendqidi2_clr,
     gen_zero_extendhidi2_clr,
     gen_zero_extendsidi2_clr,
-
-    gen_advanced_load_check_clr_bi,
-    gen_advanced_load_check_clr_qi,
-    gen_advanced_load_check_clr_hi,
-    gen_advanced_load_check_clr_si,
-    gen_advanced_load_check_clr_di,
-    gen_advanced_load_check_clr_sf,
-    gen_advanced_load_check_clr_df,
-    gen_advanced_load_check_clr_xf,
-    gen_advanced_load_check_clr_ti,
-    gen_advanced_load_check_clr_di,
-    gen_advanced_load_check_clr_di,
-    gen_advanced_load_check_clr_di,
-
-    /* Following checks are generated during mutation.  */
-    gen_advanced_load_check_clr_bi,
-    gen_advanced_load_check_clr_qi,
-    gen_advanced_load_check_clr_hi,
-    gen_advanced_load_check_clr_si,
-    gen_advanced_load_check_clr_di,
-    gen_advanced_load_check_clr_sf,
-    gen_advanced_load_check_clr_df,
-    gen_advanced_load_check_clr_xf,
-    gen_advanced_load_check_clr_ti,
-    gen_advanced_load_check_clr_di,
-    gen_advanced_load_check_clr_di,
-    gen_advanced_load_check_clr_di,
-
-    0,0,0,0,0,0,0,0,0,0,0,0,
-
+  };
+  static gen_func_t gen_ld_c_nc[] = {
+    gen_movbi_nc,
+    gen_movqi_nc,
+    gen_movhi_nc,
+    gen_movsi_nc,
+    gen_movdi_nc,
+    gen_movsf_nc,
+    gen_movdf_nc,
+    gen_movxf_nc,
+    gen_movti_nc,
+    gen_zero_extendqidi2_nc,
+    gen_zero_extendhidi2_nc,
+    gen_zero_extendsidi2_nc,
+  };
+  static gen_func_t gen_chk_a_clr[] = {
     gen_advanced_load_check_clr_bi,
     gen_advanced_load_check_clr_qi,
     gen_advanced_load_check_clr_hi,
@@ -7239,7 +7770,22 @@ ia64_gen_check (rtx insn, rtx label, bool mutate_p)
     gen_advanced_load_check_clr_di,
     gen_advanced_load_check_clr_di,
     gen_advanced_load_check_clr_di,
-
+  };
+  static gen_func_t gen_chk_a_nc[] = {
+    gen_advanced_load_check_nc_bi,
+    gen_advanced_load_check_nc_qi,
+    gen_advanced_load_check_nc_hi,
+    gen_advanced_load_check_nc_si,
+    gen_advanced_load_check_nc_di,
+    gen_advanced_load_check_nc_sf,
+    gen_advanced_load_check_nc_df,
+    gen_advanced_load_check_nc_xf,
+    gen_advanced_load_check_nc_ti,
+    gen_advanced_load_check_nc_di,
+    gen_advanced_load_check_nc_di,
+    gen_advanced_load_check_nc_di,
+  };
+  static gen_func_t gen_chk_s[] = {
     gen_speculation_check_bi,
     gen_speculation_check_qi,
     gen_speculation_check_hi,
@@ -7251,49 +7797,96 @@ ia64_gen_check (rtx insn, rtx label, bool mutate_p)
     gen_speculation_check_ti,
     gen_speculation_check_di,
     gen_speculation_check_di,
-    gen_speculation_check_di
+    gen_speculation_check_di,
   };
 
-  extract_insn_cached (insn);
+  gen_func_t *gen_check;
 
-  if (label)
-    {
-      gcc_assert (mutate_p || ia64_needs_block_p (insn));
-      op1 = label;
-    }
-  else
+  if (ts & BEGIN_DATA)
     {
-      gcc_assert (!mutate_p && !ia64_needs_block_p (insn));
-      op1 = copy_rtx (recog_data.operand[1]);
+      /* We don't need recovery because even if this is ld.sa
+        ALAT entry will be allocated only if NAT bit is set to zero.
+        So it is enough to use ld.c here.  */
+
+      if (simple_check_p)
+       {
+         gcc_assert (mflag_sched_spec_ldc);
+
+         if (clearing_check_p)
+           gen_check = gen_ld_c_clr;
+         else
+           gen_check = gen_ld_c_nc;
+       }
+      else
+       {
+         if (clearing_check_p)
+           gen_check = gen_chk_a_clr;
+         else
+           gen_check = gen_chk_a_nc;
+       }
     }
-      
-  if (mutate_p)
-    /* INSN is ld.c.
-       Find the speculation check number by searching for original
-       speculative load in the RESOLVED_DEPS list of INSN.
-       As long as patterns are unique for each instruction, this can be
-       accomplished by matching ORIG_PAT fields.  */
+  else if (ts & BEGIN_CONTROL)
     {
-      sd_iterator_def sd_it;
-      dep_t dep;
-      int check_no = 0;
-      rtx orig_pat = ORIG_PAT (insn);
-
-      FOR_EACH_DEP (insn, SD_LIST_RES_BACK, sd_it, dep)
+      if (simple_check_p)
+       /* We might want to use ld.sa -> ld.c instead of
+          ld.s -> chk.s.  */
        {
-         rtx x = DEP_PRO (dep);
+         gcc_assert (!ia64_needs_block_p (ts));
 
-         if (ORIG_PAT (x) == orig_pat)
-           check_no = spec_check_no[INSN_UID (x)];
+         if (clearing_check_p)
+           gen_check = gen_ld_c_clr;
+         else
+           gen_check = gen_ld_c_nc;
+       }
+      else
+       {
+         gen_check = gen_chk_s;
        }
-      gcc_assert (check_no);
+    }
+  else
+    gcc_unreachable ();
+
+  gcc_assert (mode_no >= 0);
+  return gen_check[mode_no];
+}
+
+/* Return nonzero, if INSN needs branchy recovery check.  */
+static bool
+ia64_needs_block_p (ds_t ts)
+{
+  if (ts & BEGIN_DATA)
+    return !mflag_sched_spec_ldc;
+
+  gcc_assert ((ts & BEGIN_CONTROL) != 0);
 
-      spec_check_no[INSN_UID (insn)] = (check_no
-                                       + SPEC_GEN_CHECK_MUTATION_OFFSET);
+  return !(mflag_sched_spec_control_ldc && mflag_sched_spec_ldc);
+}
+
+/* Generate (or regenerate, if (MUTATE_P)) recovery check for INSN.
+   If (LABEL != 0 || MUTATE_P), generate branchy recovery check.
+   Otherwise, generate a simple check.  */
+static rtx
+ia64_gen_spec_check (rtx insn, rtx label, ds_t ds)
+{
+  rtx op1, pat, check_pat;
+  gen_func_t gen_check;
+  int mode_no;
+
+  mode_no = get_mode_no_for_insn (insn);
+  gcc_assert (mode_no >= 0);
+
+  if (label)
+    op1 = label;
+  else
+    {
+      gcc_assert (!ia64_needs_block_p (ds));
+      op1 = copy_rtx (recog_data.operand[1]);
     }
+      
+  gen_check = get_spec_check_gen_function (ds, mode_no, label == NULL_RTX,
+                                          true);
 
-  check_pat = (gen_check[spec_check_no[INSN_UID (insn)] - 1]
-              (copy_rtx (recog_data.operand[0]), op1));
+  check_pat = gen_check (copy_rtx (recog_data.operand[0]), op1);
     
   pat = PATTERN (insn);
   if (GET_CODE (pat) == COND_EXEC)
@@ -7334,9 +7927,11 @@ ia64_spec_check_src_p (rtx src)
              
              code = XINT (t, 1);
             
-             if (code == UNSPEC_CHKACLR
-                 || code == UNSPEC_CHKS
-                 || code == UNSPEC_LDCCLR)
+             if (code == UNSPEC_LDCCLR
+                 || code == UNSPEC_LDCNC
+                 || code == UNSPEC_CHKACLR
+                 || code == UNSPEC_CHKANC
+                 || code == UNSPEC_CHKS)
                {
                  gcc_assert (code != 0);
                  return code;
@@ -7367,6 +7962,7 @@ struct bundle_state
   int accumulated_insns_num; /* number of all previous insns including
                                nops.  L is considered as 2 insns */
   int branch_deviation; /* deviation of previous branches from 3rd slots  */
+  int middle_bundle_stops; /* number of stop bits in the middle of bundles */
   struct bundle_state *next;  /* next state with the same insn_num  */
   struct bundle_state *originator; /* originator (previous insn state)  */
   /* All bundle states are in the following chain.  */
@@ -7497,7 +8093,7 @@ insert_bundle_state (struct bundle_state *bundle_state)
 {
   void **entry_ptr;
 
-  entry_ptr = htab_find_slot (bundle_state_table, bundle_state, 1);
+  entry_ptr = htab_find_slot (bundle_state_table, bundle_state, INSERT);
   if (*entry_ptr == NULL)
     {
       bundle_state->next = index_to_bundle_states [bundle_state->insn_num];
@@ -7512,9 +8108,15 @@ insert_bundle_state (struct bundle_state *bundle_state)
                   || (((struct bundle_state *)
                        *entry_ptr)->accumulated_insns_num
                       == bundle_state->accumulated_insns_num
-                      && ((struct bundle_state *)
-                          *entry_ptr)->branch_deviation
-                      > bundle_state->branch_deviation))))
+                      && (((struct bundle_state *)
+                           *entry_ptr)->branch_deviation
+                          > bundle_state->branch_deviation
+                          || (((struct bundle_state *)
+                               *entry_ptr)->branch_deviation
+                              == bundle_state->branch_deviation
+                              && ((struct bundle_state *)
+                                  *entry_ptr)->middle_bundle_stops
+                              > bundle_state->middle_bundle_stops))))))
 
     {
       struct bundle_state temp;
@@ -7608,6 +8210,7 @@ issue_nops_and_insn (struct bundle_state *originator, int before_nops_num,
   curr_state->accumulated_insns_num
     = originator->accumulated_insns_num + before_nops_num;
   curr_state->branch_deviation = originator->branch_deviation;
+  curr_state->middle_bundle_stops = originator->middle_bundle_stops;
   gcc_assert (insn);
   if (INSN_CODE (insn) == CODE_FOR_insn_group_barrier)
     {
@@ -7617,6 +8220,8 @@ issue_nops_and_insn (struct bundle_state *originator, int before_nops_num,
       if (!try_issue_insn (curr_state, insn))
        return;
       memcpy (temp_dfa_state, curr_state->dfa_state, dfa_state_size);
+      if (curr_state->accumulated_insns_num % 3 != 0)
+       curr_state->middle_bundle_stops++;
       if (state_transition (temp_dfa_state, dfa_pre_cycle_insn) >= 0
          && curr_state->accumulated_insns_num % 3 != 0)
        {
@@ -7792,6 +8397,16 @@ get_template (state_t state, int pos)
     }
 }
 
+/* True when INSN is important for bundling.  */
+static bool
+important_for_bundling_p (rtx insn)
+{
+  return (INSN_P (insn)
+         && ia64_safe_itanium_class (insn) != ITANIUM_CLASS_IGNORE
+         && GET_CODE (PATTERN (insn)) != USE
+         && GET_CODE (PATTERN (insn)) != CLOBBER);
+}
+
 /* The following function returns an insn important for insn bundling
    followed by INSN and before TAIL.  */
 
@@ -7799,10 +8414,7 @@ static rtx
 get_next_important_insn (rtx insn, rtx tail)
 {
   for (; insn && insn != tail; insn = NEXT_INSN (insn))
-    if (INSN_P (insn)
-       && ia64_safe_itanium_class (insn) != ITANIUM_CLASS_IGNORE
-       && GET_CODE (PATTERN (insn)) != USE
-       && GET_CODE (PATTERN (insn)) != CLOBBER)
+    if (important_for_bundling_p (insn))
       return insn;
   return NULL_RTX;
 }
@@ -7845,9 +8457,7 @@ ia64_add_bundle_selector_before (int template0, rtx insn)
              if (find_reg_note (insn, REG_EH_REGION, NULL_RTX))
                note = NULL_RTX;
              else
-               REG_NOTES (insn)
-                 = gen_rtx_EXPR_LIST (REG_EH_REGION, XEXP (note, 0),
-                                      REG_NOTES (insn));
+               add_reg_note (insn, REG_EH_REGION, XEXP (note, 0));
            }
        }
     }
@@ -7889,9 +8499,7 @@ ia64_add_bundle_selector_before (int template0, rtx insn)
    automaton state for each insn in chosen bundle states.
 
    So the algorithm makes two (forward and backward) passes through
-   EBB.  There is an additional forward pass through EBB for Itanium1
-   processor.  This pass inserts more nops to make dependency between
-   a producer insn and MMMUL/MMSHF at least 4 cycles long.  */
+   EBB.  */
 
 static void
 bundling (FILE *dump, int verbose, rtx prev_head_insn, rtx tail)
@@ -7927,6 +8535,7 @@ bundling (FILE *dump, int verbose, rtx prev_head_insn, rtx tail)
   curr_state->cost = 0;
   curr_state->accumulated_insns_num = 0;
   curr_state->branch_deviation = 0;
+  curr_state->middle_bundle_stops = 0;
   curr_state->next = NULL;
   curr_state->originator = NULL;
   state_reset (curr_state->dfa_state);
@@ -7949,7 +8558,8 @@ bundling (FILE *dump, int verbose, rtx prev_head_insn, rtx tail)
          if (INSN_P (next_insn)
              && ia64_safe_itanium_class (next_insn) != ITANIUM_CLASS_IGNORE
              && GET_CODE (PATTERN (next_insn)) != USE
-             && GET_CODE (PATTERN (next_insn)) != CLOBBER)
+             && GET_CODE (PATTERN (next_insn)) != CLOBBER
+             && INSN_CODE (next_insn) != CODE_FOR_insn_group_barrier)
            {
              PUT_MODE (next_insn, TImode);
              break;
@@ -7988,14 +8598,7 @@ bundling (FILE *dump, int verbose, rtx prev_head_insn, rtx tail)
               || (GET_MODE (next_insn) == TImode
                   && INSN_CODE (insn) != CODE_FOR_insn_group_barrier));
          if (type == TYPE_F || type == TYPE_B || type == TYPE_L
-             || type == TYPE_S
-             /* We need to insert 2 nops for cases like M_MII.  To
-                guarantee issuing all insns on the same cycle for
-                Itanium 1, we need to issue 2 nops after the first M
-                insn (MnnMII where n is a nop insn).  */
-             || ((type == TYPE_M || type == TYPE_A)
-                 && ia64_tune == PROCESSOR_ITANIUM
-                 && !bundle_end_p && pos == 1))
+             || type == TYPE_S)
            issue_nops_and_insn (curr_state, 2, insn, bundle_end_p,
                                 only_bundle_end_p);
          issue_nops_and_insn (curr_state, 1, insn, bundle_end_p,
@@ -8023,16 +8626,15 @@ bundling (FILE *dump, int verbose, rtx prev_head_insn, rtx tail)
 
            fprintf
              (dump,
-              "//    Bundle state %d (orig %d, cost %d, nops %d/%d, insns %d, branch %d, state %d) for %d\n",
+              "//    Bundle state %d (orig %d, cost %d, nops %d/%d, insns %d, branch %d, mid.stops %d state %d) for %d\n",
               curr_state->unique_num,
               (curr_state->originator == NULL
                ? -1 : curr_state->originator->unique_num),
               curr_state->cost,
               curr_state->before_nops_num, curr_state->after_nops_num,
               curr_state->accumulated_insns_num, curr_state->branch_deviation,
-              (ia64_tune == PROCESSOR_ITANIUM
-               ? ((struct DFA_chip *) curr_state->dfa_state)->oneb_automaton_state
-               : ((struct DFA_chip *) curr_state->dfa_state)->twob_automaton_state),
+              curr_state->middle_bundle_stops,
+              ((struct DFA_chip *) curr_state->dfa_state)->twob_automaton_state,
               INSN_UID (insn));
          }
     }
@@ -8056,10 +8658,15 @@ bundling (FILE *dump, int verbose, rtx prev_head_insn, rtx tail)
                    < best_state->accumulated_insns_num
                    || (curr_state->accumulated_insns_num
                        == best_state->accumulated_insns_num
-                       && curr_state->branch_deviation
-                       < best_state->branch_deviation)))))
+                       && (curr_state->branch_deviation
+                           < best_state->branch_deviation
+                           || (curr_state->branch_deviation
+                               == best_state->branch_deviation
+                               && curr_state->middle_bundle_stops
+                               < best_state->middle_bundle_stops)))))))
       best_state = curr_state;
   /* Second (backward) pass: adding nops and templates.  */
+  gcc_assert (best_state);
   insn_num = best_state->before_nops_num;
   template0 = template1 = -1;
   for (curr_state = best_state;
@@ -8082,16 +8689,15 @@ bundling (FILE *dump, int verbose, rtx prev_head_insn, rtx tail)
 
          fprintf
            (dump,
-            "//    Best %d (orig %d, cost %d, nops %d/%d, insns %d, branch %d, state %d) for %d\n",
+            "//    Best %d (orig %d, cost %d, nops %d/%d, insns %d, branch %d, mid.stops %d, state %d) for %d\n",
             curr_state->unique_num,
             (curr_state->originator == NULL
              ? -1 : curr_state->originator->unique_num),
             curr_state->cost,
             curr_state->before_nops_num, curr_state->after_nops_num,
             curr_state->accumulated_insns_num, curr_state->branch_deviation,
-            (ia64_tune == PROCESSOR_ITANIUM
-             ? ((struct DFA_chip *) curr_state->dfa_state)->oneb_automaton_state
-             : ((struct DFA_chip *) curr_state->dfa_state)->twob_automaton_state),
+            curr_state->middle_bundle_stops,
+            ((struct DFA_chip *) curr_state->dfa_state)->twob_automaton_state,
             INSN_UID (insn));
        }
       /* Find the position in the current bundle window.  The window can
@@ -8190,103 +8796,57 @@ bundling (FILE *dump, int verbose, rtx prev_head_insn, rtx tail)
            }
        }
     }
-  if (ia64_tune == PROCESSOR_ITANIUM)
-    /* Insert additional cycles for MM-insns (MMMUL and MMSHF).
-       Itanium1 has a strange design, if the distance between an insn
-       and dependent MM-insn is less 4 then we have a 6 additional
-       cycles stall.  So we make the distance equal to 4 cycles if it
-       is less.  */
-    for (insn = get_next_important_insn (NEXT_INSN (prev_head_insn), tail);
-        insn != NULL_RTX;
-        insn = next_insn)
+
+#ifdef ENABLE_CHECKING
+  {
+    /* Assert right calculation of middle_bundle_stops.  */
+    int num = best_state->middle_bundle_stops;
+    bool start_bundle = true, end_bundle = false;
+
+    for (insn = NEXT_INSN (prev_head_insn);
+        insn && insn != tail;
+        insn = NEXT_INSN (insn))
       {
-       gcc_assert (INSN_P (insn)
-                   && ia64_safe_itanium_class (insn) != ITANIUM_CLASS_IGNORE
-                   && GET_CODE (PATTERN (insn)) != USE
-                   && GET_CODE (PATTERN (insn)) != CLOBBER);
-       next_insn = get_next_important_insn (NEXT_INSN (insn), tail);
-       if (INSN_UID (insn) < clocks_length && add_cycles [INSN_UID (insn)])
-         /* We found a MM-insn which needs additional cycles.  */
+       if (!INSN_P (insn))
+         continue;
+       if (recog_memoized (insn) == CODE_FOR_bundle_selector)
+         start_bundle = true;
+       else
          {
-           rtx last;
-           int i, j, n;
-           int pred_stop_p;
-
-           /* Now we are searching for a template of the bundle in
-              which the MM-insn is placed and the position of the
-              insn in the bundle (0, 1, 2).  Also we are searching
-              for that there is a stop before the insn.  */
-           last = prev_active_insn (insn);
-           pred_stop_p = recog_memoized (last) == CODE_FOR_insn_group_barrier;
-           if (pred_stop_p)
-             last = prev_active_insn (last);
-           n = 0;
-           for (;; last = prev_active_insn (last))
-             if (recog_memoized (last) == CODE_FOR_bundle_selector)
-               {
-                 template0 = XINT (XVECEXP (PATTERN (last), 0, 0), 0);
-                 if (template0 == 9)
-                   /* The insn is in MLX bundle.  Change the template
-                      onto MFI because we will add nops before the
-                      insn.  It simplifies subsequent code a lot.  */
-                   PATTERN (last)
-                     = gen_bundle_selector (const2_rtx); /* -> MFI */
-                 break;
-               }
-             else if (recog_memoized (last) != CODE_FOR_insn_group_barrier
-                      && (ia64_safe_itanium_class (last)
-                          != ITANIUM_CLASS_IGNORE))
-               n++;
-           /* Some check of correctness: the stop is not at the
-              bundle start, there are no more 3 insns in the bundle,
-              and the MM-insn is not at the start of bundle with
-              template MLX.  */
-           gcc_assert ((!pred_stop_p || n)
-                       && n <= 2
-                       && (template0 != 9 || !n));
-           /* Put nops after the insn in the bundle.  */
-           for (j = 3 - n; j > 0; j --)
-             ia64_emit_insn_before (gen_nop (), insn);
-           /* It takes into account that we will add more N nops
-              before the insn lately -- please see code below.  */
-           add_cycles [INSN_UID (insn)]--;
-           if (!pred_stop_p || add_cycles [INSN_UID (insn)])
-             ia64_emit_insn_before (gen_insn_group_barrier (GEN_INT (3)),
-                                    insn);
-           if (pred_stop_p)
-             add_cycles [INSN_UID (insn)]--;
-           for (i = add_cycles [INSN_UID (insn)]; i > 0; i--)
-             {
-               /* Insert "MII;" template.  */
-               ia64_emit_insn_before (gen_bundle_selector (const0_rtx),
-                                      insn);
-               ia64_emit_insn_before (gen_nop (), insn);
-               ia64_emit_insn_before (gen_nop (), insn);
-               if (i > 1)
-                 {
-                   /* To decrease code size, we use "MI;I;"
-                      template.  */
-                   ia64_emit_insn_before
-                     (gen_insn_group_barrier (GEN_INT (3)), insn);
-                   i--;
-                 }
-               ia64_emit_insn_before (gen_nop (), insn);
-               ia64_emit_insn_before (gen_insn_group_barrier (GEN_INT (3)),
-                                      insn);
-             }
-           /* Put the MM-insn in the same slot of a bundle with the
-              same template as the original one.  */
-           ia64_add_bundle_selector_before (template0, insn);
-           /* To put the insn in the same slot, add necessary number
-              of nops.  */
-           for (j = n; j > 0; j --)
-             ia64_emit_insn_before (gen_nop (), insn);
-           /* Put the stop if the original bundle had it.  */
-           if (pred_stop_p)
-             ia64_emit_insn_before (gen_insn_group_barrier (GEN_INT (3)),
-                                    insn);
+           rtx next_insn;
+
+           for (next_insn = NEXT_INSN (insn);
+                next_insn && next_insn != tail;
+                next_insn = NEXT_INSN (next_insn))
+             if (INSN_P (next_insn)
+                 && (ia64_safe_itanium_class (next_insn)
+                     != ITANIUM_CLASS_IGNORE
+                     || recog_memoized (next_insn)
+                     == CODE_FOR_bundle_selector)
+                 && GET_CODE (PATTERN (next_insn)) != USE
+                 && GET_CODE (PATTERN (next_insn)) != CLOBBER)
+               break;
+
+           end_bundle = next_insn == NULL_RTX
+            || next_insn == tail
+            || (INSN_P (next_insn)
+                && recog_memoized (next_insn)
+                == CODE_FOR_bundle_selector);
+           if (recog_memoized (insn) == CODE_FOR_insn_group_barrier
+               && !start_bundle && !end_bundle
+               && next_insn
+               && GET_CODE (PATTERN (next_insn)) != ASM_INPUT
+               && asm_noperands (PATTERN (next_insn)) < 0)
+             num--;
+
+           start_bundle = false;
          }
       }
+
+    gcc_assert (num == 0);
+  }
+#endif
+
   free (index_to_bundle_states);
   finish_bundle_state_table ();
   bundling_p = 0;
@@ -8324,7 +8884,7 @@ final_emit_insn_group_barriers (FILE *dump ATTRIBUTE_UNUSED)
 {
   rtx insn;
   int need_barrier_p = 0;
-  rtx prev_insn = NULL_RTX;
+  int seen_good_insn = 0;
 
   init_insn_group_barriers ();
 
@@ -8345,18 +8905,21 @@ final_emit_insn_group_barriers (FILE *dump ATTRIBUTE_UNUSED)
            emit_insn_after (gen_insn_group_barrier (GEN_INT (3)), last);
 
          init_insn_group_barriers ();
+         seen_good_insn = 0;
          need_barrier_p = 0;
-         prev_insn = NULL_RTX;
        }
-      else if (INSN_P (insn))
+      else if (NONDEBUG_INSN_P (insn))
        {
          if (recog_memoized (insn) == CODE_FOR_insn_group_barrier)
            {
              init_insn_group_barriers ();
+             seen_good_insn = 0;
              need_barrier_p = 0;
-             prev_insn = NULL_RTX;
            }
-         else if (need_barrier_p || group_barrier_needed (insn))
+         else if (need_barrier_p || group_barrier_needed (insn)
+                  || (mflag_sched_stop_bits_after_every_cycle
+                      && GET_MODE (insn) == TImode
+                      && seen_good_insn))
            {
              if (TARGET_EARLY_STOP_BITS)
                {
@@ -8380,19 +8943,28 @@ final_emit_insn_group_barriers (FILE *dump ATTRIBUTE_UNUSED)
                       last != insn;
                       last = NEXT_INSN (last))
                    if (INSN_P (last))
-                     group_barrier_needed (last);
+                     {
+                       group_barrier_needed (last);
+                       if (recog_memoized (last) >= 0
+                           && important_for_bundling_p (last))
+                         seen_good_insn = 1;
+                     }
                }
              else
                {
                  emit_insn_before (gen_insn_group_barrier (GEN_INT (3)),
                                    insn);
                  init_insn_group_barriers ();
+                 seen_good_insn = 0;
                }
              group_barrier_needed (insn);
-             prev_insn = NULL_RTX;
+             if (recog_memoized (insn) >= 0
+                 && important_for_bundling_p (insn))
+               seen_good_insn = 1;
            }
-         else if (recog_memoized (insn) >= 0)
-           prev_insn = insn;
+         else if (recog_memoized (insn) >= 0
+                  && important_for_bundling_p (insn))
+           seen_good_insn = 1;
          need_barrier_p = (GET_CODE (insn) == CALL_INSN
                            || GET_CODE (PATTERN (insn)) == ASM_INPUT
                            || asm_noperands (PATTERN (insn)) >= 0);
@@ -8501,7 +9073,8 @@ ia64_ld_address_bypass_p (rtx producer, rtx consumer)
     {
       int c = XINT (mem, 1);
 
-      gcc_assert (c == UNSPEC_LDA || c == UNSPEC_LDS || c == UNSPEC_LDSA);
+      gcc_assert (c == UNSPEC_LDA || c == UNSPEC_LDS || c == UNSPEC_LDS_A
+                 || c == UNSPEC_LDSA);
       mem = XVECEXP (mem, 0, 0);
     }
 
@@ -8598,7 +9171,8 @@ ia64_reorg (void)
   if (optimize == 0)
     split_all_insns ();
 
-  if (optimize && ia64_flag_schedule_insns2 && dbg_cnt (ia64_sched2))
+  if (optimize && ia64_flag_schedule_insns2
+      && dbg_cnt (ia64_sched2))
     {
       timevar_push (TV_SCHED2);
       ia64_final_schedule = 1;
@@ -8609,11 +9183,7 @@ ia64_reorg (void)
       recog_memoized (ia64_nop);
       clocks_length = get_max_uid () + 1;
       stops_p = XCNEWVEC (char, clocks_length);
-      if (ia64_tune == PROCESSOR_ITANIUM)
-       {
-         clocks = XCNEWVEC (int, clocks_length);
-         add_cycles = XCNEWVEC (int, clocks_length);
-       }
+
       if (ia64_tune == PROCESSOR_ITANIUM2)
        {
          pos_1 = get_cpu_unit_code ("2_1");
@@ -8672,15 +9242,19 @@ ia64_reorg (void)
          _1mfb_ = get_cpu_unit_code ("1b_1mfb.");
          _1mlx_ = get_cpu_unit_code ("1b_1mlx.");
        }
-      schedule_ebbs ();
+
+      if (flag_selective_scheduling2
+         && !maybe_skip_selective_scheduling ())
+        run_selective_scheduling ();
+      else
+       schedule_ebbs ();
+
+      /* Redo alignment computation, as it might gone wrong.  */
+      compute_alignments ();
+
       /* We cannot reuse this one because it has been corrupted by the
         evil glat.  */
       finish_bundle_states ();
-      if (ia64_tune == PROCESSOR_ITANIUM)
-       {
-         free (add_cycles);
-         free (clocks);
-       }
       free (stops_p);
       stops_p = NULL;
       emit_insn_group_barriers (dump_file);
@@ -8704,20 +9278,24 @@ ia64_reorg (void)
       insn = get_last_insn ();
       if (! INSN_P (insn))
         insn = prev_active_insn (insn);
-      /* Skip over insns that expand to nothing.  */
-      while (GET_CODE (insn) == INSN && get_attr_empty (insn) == EMPTY_YES)
-        {
-         if (GET_CODE (PATTERN (insn)) == UNSPEC_VOLATILE
-             && XINT (PATTERN (insn), 1) == UNSPECV_INSN_GROUP_BARRIER)
-           saw_stop = 1;
-         insn = prev_active_insn (insn);
-       }
-      if (GET_CODE (insn) == CALL_INSN)
+      if (insn)
        {
-         if (! saw_stop)
-           emit_insn (gen_insn_group_barrier (GEN_INT (3)));
-         emit_insn (gen_break_f ());
-         emit_insn (gen_insn_group_barrier (GEN_INT (3)));
+         /* Skip over insns that expand to nothing.  */
+         while (GET_CODE (insn) == INSN
+                && get_attr_empty (insn) == EMPTY_YES)
+           {
+             if (GET_CODE (PATTERN (insn)) == UNSPEC_VOLATILE
+                 && XINT (PATTERN (insn), 1) == UNSPECV_INSN_GROUP_BARRIER)
+               saw_stop = 1;
+             insn = prev_active_insn (insn);
+           }
+         if (GET_CODE (insn) == CALL_INSN)
+           {
+             if (! saw_stop)
+               emit_insn (gen_insn_group_barrier (GEN_INT (3)));
+             emit_insn (gen_break_f ());
+             emit_insn (gen_insn_group_barrier (GEN_INT (3)));
+           }
        }
     }
 
@@ -8776,7 +9354,7 @@ ia64_epilogue_uses (int regno)
 int
 ia64_eh_uses (int regno)
 {
-  enum ia64_frame_regs r;
+  unsigned int r;
 
   if (! reload_completed)
     return 0;
@@ -8878,15 +9456,18 @@ ia64_emit_deleted_label_after_insn (rtx insn)
 /* Define the CFA after INSN with the steady-state definition.  */
 
 static void
-ia64_dwarf2out_def_steady_cfa (rtx insn)
+ia64_dwarf2out_def_steady_cfa (rtx insn, bool frame)
 {
   rtx fp = frame_pointer_needed
     ? hard_frame_pointer_rtx
     : stack_pointer_rtx;
+  const char *label = ia64_emit_deleted_label_after_insn (insn);
+
+  if (!frame)
+    return;
 
   dwarf2out_def_cfa
-    (ia64_emit_deleted_label_after_insn (insn),
-     REGNO (fp),
+    (label, REGNO (fp),
      ia64_initial_elimination_offset
      (REGNO (arg_pointer_rtx), REGNO (fp))
      + ARG_POINTER_CFA_OFFSET (current_function_decl));
@@ -8979,8 +9560,7 @@ process_set (FILE *asm_out_file, rtx pat, rtx insn, bool unwind, bool frame)
              if (unwind)
                fprintf (asm_out_file, "\t.fframe "HOST_WIDE_INT_PRINT_DEC"\n",
                         -INTVAL (op1));
-             if (frame)
-               ia64_dwarf2out_def_steady_cfa (insn);
+             ia64_dwarf2out_def_steady_cfa (insn, frame);
            }
          else
            process_epilogue (asm_out_file, insn, unwind, frame);
@@ -9038,8 +9618,7 @@ process_set (FILE *asm_out_file, rtx pat, rtx insn, bool unwind, bool frame)
          if (unwind)
            fprintf (asm_out_file, "\t.vframe r%d\n",
                     ia64_dbx_register_number (dest_regno));
-         if (frame)
-           ia64_dwarf2out_def_steady_cfa (insn);
+         ia64_dwarf2out_def_steady_cfa (insn, frame);
          return 1;
 
        default:
@@ -9184,8 +9763,8 @@ process_for_unwind_directive (FILE *asm_out_file, rtx insn)
                  fprintf (asm_out_file, "\t.copy_state %d\n",
                           cfun->machine->state_num);
                }
-             if (IA64_CHANGE_CFA_IN_EPILOGUE && frame)
-               ia64_dwarf2out_def_steady_cfa (insn);
+             if (IA64_CHANGE_CFA_IN_EPILOGUE)
+               ia64_dwarf2out_def_steady_cfa (insn, frame);
              need_copy_state = false;
            }
        }
@@ -9228,7 +9807,11 @@ process_for_unwind_directive (FILE *asm_out_file, rtx insn)
 enum ia64_builtins
 {
   IA64_BUILTIN_BSP,
-  IA64_BUILTIN_FLUSHRS
+  IA64_BUILTIN_COPYSIGNQ,
+  IA64_BUILTIN_FABSQ,
+  IA64_BUILTIN_FLUSHRS,
+  IA64_BUILTIN_INFQ,
+  IA64_BUILTIN_HUGE_VALQ
 };
 
 void
@@ -9252,16 +9835,52 @@ ia64_init_builtins (void)
   /* The __float128 type.  */
   if (!TARGET_HPUX)
     {
+      tree ftype, decl;
       tree float128_type = make_node (REAL_TYPE);
+
       TYPE_PRECISION (float128_type) = 128;
       layout_type (float128_type);
       (*lang_hooks.types.register_builtin_type) (float128_type, "__float128");
+
+      /* TFmode support builtins.  */
+      ftype = build_function_type (float128_type, void_list_node);
+      add_builtin_function ("__builtin_infq", ftype,
+                           IA64_BUILTIN_INFQ, BUILT_IN_MD,
+                           NULL, NULL_TREE);
+
+      add_builtin_function ("__builtin_huge_valq", ftype,
+                           IA64_BUILTIN_HUGE_VALQ, BUILT_IN_MD,
+                           NULL, NULL_TREE);
+
+      ftype = build_function_type_list (float128_type,
+                                       float128_type,
+                                       NULL_TREE);
+      decl = add_builtin_function ("__builtin_fabsq", ftype,
+                                  IA64_BUILTIN_FABSQ, BUILT_IN_MD,
+                                  "__fabstf2", NULL_TREE);
+      TREE_READONLY (decl) = 1;
+
+      ftype = build_function_type_list (float128_type,
+                                       float128_type,
+                                       float128_type,
+                                       NULL_TREE);
+      decl = add_builtin_function ("__builtin_copysignq", ftype,
+                                  IA64_BUILTIN_COPYSIGNQ, BUILT_IN_MD,
+                                  "__copysigntf3", NULL_TREE);
+      TREE_READONLY (decl) = 1;
     }
   else
     /* Under HPUX, this is a synonym for "long double".  */
     (*lang_hooks.types.register_builtin_type) (long_double_type_node,
                                               "__float128");
 
+  /* Fwrite on VMS is non-standard.  */
+  if (TARGET_ABI_OPEN_VMS)
+    {
+      implicit_built_in_decls[(int) BUILT_IN_FWRITE] = NULL_TREE;
+      implicit_built_in_decls[(int) BUILT_IN_FWRITE_UNLOCKED] = NULL_TREE;
+    }
+
 #define def_builtin(name, type, code)                                  \
   add_builtin_function ((name), (type), (code), BUILT_IN_MD,   \
                       NULL, NULL_TREE)
@@ -9313,8 +9932,30 @@ ia64_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
       emit_insn (gen_flushrs ());
       return const0_rtx;
 
+    case IA64_BUILTIN_INFQ:
+    case IA64_BUILTIN_HUGE_VALQ:
+      {
+       REAL_VALUE_TYPE inf;
+       rtx tmp;
+
+       real_inf (&inf);
+       tmp = CONST_DOUBLE_FROM_REAL_VALUE (inf, mode);
+
+       tmp = validize_mem (force_const_mem (mode, tmp));
+
+       if (target == 0)
+         target = gen_reg_rtx (mode);
+
+       emit_move_insn (target, tmp);
+       return target;
+      }
+
+    case IA64_BUILTIN_FABSQ:
+    case IA64_BUILTIN_COPYSIGNQ:
+      return expand_call (exp, target, ignore);
+
     default:
-      break;
+      gcc_unreachable ();
     }
 
   return NULL_RTX;
@@ -9352,6 +9993,10 @@ ia64_asm_output_external (FILE *file, tree decl, const char *name)
       int need_visibility = ((*targetm.binds_local_p) (decl)
                             && maybe_assemble_visibility (decl));
 
+#ifdef DO_CRTL_NAMES
+      DO_CRTL_NAMES;
+#endif
+
       /* GNU as does not need anything here, but the HP linker does
         need something for external functions.  */
       if ((TARGET_HPUX_LD || !TARGET_GNU_AS)
@@ -9454,6 +10099,11 @@ ia64_vms_init_libfuncs (void)
   set_optab_libfunc (smod_optab, DImode, "OTS$REM_L");
   set_optab_libfunc (umod_optab, SImode, "OTS$REM_UI");
   set_optab_libfunc (umod_optab, DImode, "OTS$REM_UL");
+  abort_libfunc = init_one_libfunc ("decc$abort");
+  memcmp_libfunc = init_one_libfunc ("decc$memcmp");
+#ifdef MEM_LIBFUNCS_INIT
+  MEM_LIBFUNCS_INIT;
+#endif
 }
 
 /* Rename the TFmode libfuncs available from soft-fp in glibc using
@@ -9477,6 +10127,19 @@ ia64_sysv4_init_libfuncs (void)
   /* We leave out _U_Qfmin, _U_Qfmax and _U_Qfabs since soft-fp in
      glibc doesn't have them.  */
 }
+
+/* Use soft-fp.  */
+
+static void
+ia64_soft_fp_init_libfuncs (void)
+{
+}
+
+static bool
+ia64_vms_valid_pointer_mode (enum machine_mode mode)
+{
+  return (mode == SImode || mode == DImode);
+}
 \f
 /* For HPUX, it is illegal to have relocations in shared segments.  */
 
@@ -9526,6 +10189,12 @@ ia64_section_type_flags (tree decl, const char *name, int reloc)
       || strncmp (name, ".gnu.linkonce.sb.", 17) == 0)
     flags = SECTION_SMALL;
 
+#if TARGET_ABI_OPEN_VMS
+  if (decl && DECL_ATTRIBUTES (decl)
+      && lookup_attribute ("common_object", DECL_ATTRIBUTES (decl)))
+    flags |= SECTION_VMS_OVERLAY;
+#endif
+
   flags |= default_section_type_flags (decl, name, reloc);
   return flags;
 }
@@ -9691,7 +10360,6 @@ ia64_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
   final_start_function (insn, file, 1);
   final (insn, file, 1);
   final_end_function ();
-  free_after_compilation (cfun);
 
   reload_completed = 0;
   epilogue_completed = 0;
@@ -9703,7 +10371,8 @@ static rtx
 ia64_struct_value_rtx (tree fntype,
                       int incoming ATTRIBUTE_UNUSED)
 {
-  if (fntype && ia64_struct_retval_addr_is_first_parm_p (fntype))
+  if (TARGET_ABI_OPEN_VMS ||
+      (fntype && ia64_struct_retval_addr_is_first_parm_p (fntype)))
     return NULL_RTX;
   return gen_rtx_REG (Pmode, GR_REG (8));
 }
@@ -9727,7 +10396,7 @@ ia64_scalar_mode_supported_p (enum machine_mode mode)
       return true;
 
     case TFmode:
-      return TARGET_HPUX;
+      return true;
 
     default:
       return false;
@@ -9922,13 +10591,6 @@ void
 ia64_optimization_options (int level ATTRIBUTE_UNUSED,
                            int size ATTRIBUTE_UNUSED)
 {
-  /* Disable the second machine independent scheduling pass and use one for the
-     IA-64.  This needs to be here instead of in OVERRIDE_OPTIONS because this
-     is done whenever the optimization is changed via #pragma GCC optimize or
-     attribute((optimize(...))).  */
-  ia64_flag_schedule_insns2 = flag_schedule_insns_after_reload;
-  flag_schedule_insns_after_reload = 0;
-
   /* Let the scheduler form additional regions.  */
   set_param_value ("max-sched-extend-regions-iters", 2);
 
@@ -9936,6 +10598,7 @@ ia64_optimization_options (int level ATTRIBUTE_UNUSED,
   set_param_value ("simultaneous-prefetches", 6);
   set_param_value ("l1-cache-line-size", 32);
 
+  set_param_value("sched-mem-true-dep-cost", 4);
 }
 
 /* HP-UX version_id attribute.
@@ -9974,4 +10637,70 @@ ia64_c_mode_for_suffix (char suffix)
   return VOIDmode;
 }
 
+static enum machine_mode
+ia64_promote_function_mode (const_tree type,
+                           enum machine_mode mode,
+                           int *punsignedp,
+                           const_tree funtype,
+                           int for_return)
+{
+  /* Special processing required for OpenVMS ...  */
+
+  if (!TARGET_ABI_OPEN_VMS)
+    return default_promote_function_mode(type, mode, punsignedp, funtype,
+                                        for_return);
+
+  /* HP OpenVMS Calling Standard dated June, 2004, that describes
+     HP OpenVMS I64 Version 8.2EFT,
+     chapter 4 "OpenVMS I64 Conventions"
+     section 4.7 "Procedure Linkage"
+     subsection 4.7.5.2, "Normal Register Parameters"
+
+     "Unsigned integral (except unsigned 32-bit), set, and VAX floating-point
+     values passed in registers are zero-filled; signed integral values as
+     well as unsigned 32-bit integral values are sign-extended to 64 bits.
+     For all other types passed in the general registers, unused bits are
+     undefined."  */
+
+  if (!AGGREGATE_TYPE_P (type)
+      && GET_MODE_CLASS (mode) == MODE_INT
+      && GET_MODE_SIZE (mode) < UNITS_PER_WORD)
+    {
+      if (mode == SImode)
+       *punsignedp = 0;
+      return DImode;
+    }
+  else
+    return promote_mode (type, mode, punsignedp);
+}
+   
+static GTY(()) rtx ia64_dconst_0_5_rtx;
+
+rtx
+ia64_dconst_0_5 (void)
+{
+  if (! ia64_dconst_0_5_rtx)
+    {
+      REAL_VALUE_TYPE rv;
+      real_from_string (&rv, "0.5");
+      ia64_dconst_0_5_rtx = const_double_from_real_value (rv, DFmode);
+    }
+  return ia64_dconst_0_5_rtx;
+}
+
+static GTY(()) rtx ia64_dconst_0_375_rtx;
+
+rtx
+ia64_dconst_0_375 (void)
+{
+  if (! ia64_dconst_0_375_rtx)
+    {
+      REAL_VALUE_TYPE rv;
+      real_from_string (&rv, "0.375");
+      ia64_dconst_0_375_rtx = const_double_from_real_value (rv, DFmode);
+    }
+  return ia64_dconst_0_375_rtx;
+}
+
+
 #include "gt-ia64.h"