Home | History | Annotate | Line # | Download | only in tilepro
tilepro.cc revision 1.1
      1 /* Subroutines used for code generation on the Tilera TILEPro.
      2    Copyright (C) 2011-2022 Free Software Foundation, Inc.
      3    Contributed by Walter Lee (walt (at) tilera.com)
      4 
      5    This file is part of GCC.
      6 
      7    GCC is free software; you can redistribute it and/or modify it
      8    under the terms of the GNU General Public License as published
      9    by the Free Software Foundation; either version 3, or (at your
     10    option) any later version.
     11 
     12    GCC is distributed in the hope that it will be useful, but WITHOUT
     13    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     14    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
     15    License for more details.
     16 
     17    You should have received a copy of the GNU General Public License
     18    along with GCC; see the file COPYING3.  If not see
     19    <http://www.gnu.org/licenses/>.  */
     20 
     21 #define IN_TARGET_CODE 1
     22 
     23 #include "config.h"
     24 #include "system.h"
     25 #include "coretypes.h"
     26 #include "backend.h"
     27 #include "target.h"
     28 #include "rtl.h"
     29 #include "tree.h"
     30 #include "gimple.h"
     31 #include "df.h"
     32 #include "memmodel.h"
     33 #include "tm_p.h"
     34 #include "stringpool.h"
     35 #include "attribs.h"
     36 #include "expmed.h"
     37 #include "optabs.h"
     38 #include "regs.h"
     39 #include "emit-rtl.h"
     40 #include "recog.h"
     41 #include "diagnostic.h"
     42 #include "output.h"
     43 #include "insn-attr.h"
     44 #include "alias.h"
     45 #include "explow.h"
     46 #include "calls.h"
     47 #include "varasm.h"
     48 #include "expr.h"
     49 #include "langhooks.h"
     50 #include "cfgrtl.h"
     51 #include "tm-constrs.h"
     52 #include "dwarf2.h"
     53 #include "fold-const.h"
     54 #include "stor-layout.h"
     55 #include "gimplify.h"
     56 #include "tilepro-builtins.h"
     57 #include "tilepro-multiply.h"
     58 #include "builtins.h"
     59 
     60 /* This file should be included last.  */
     61 #include "target-def.h"
     62 
     63 /* SYMBOL_REF for GOT */
     64 static GTY(()) rtx g_got_symbol = NULL;
     65 
     66 /* Report whether we're printing out the first address fragment of a
     67    POST_INC or POST_DEC memory reference, from TARGET_PRINT_OPERAND to
     68    TARGET_PRINT_OPERAND_ADDRESS.  */
     69 static bool output_memory_autoinc_first;
     70 
     71 
     72 
     74 /* Option handling  */
     75 
     76 /* Implement TARGET_OPTION_OVERRIDE.  */
     77 static void
     78 tilepro_option_override (void)
     79 {
     80   /* When modulo scheduling is enabled, we still rely on regular
     81      scheduler for bundling.  */
     82   if (flag_modulo_sched)
     83     flag_resched_modulo_sched = 1;
     84 }
     85 
     86 
     88 
     89 /* Implement TARGET_SCALAR_MODE_SUPPORTED_P.  */
     90 static bool
     91 tilepro_scalar_mode_supported_p (scalar_mode mode)
     92 {
     93   switch (mode)
     94     {
     95     case E_QImode:
     96     case E_HImode:
     97     case E_SImode:
     98     case E_DImode:
     99       return true;
    100 
    101     case E_SFmode:
    102     case E_DFmode:
    103       return true;
    104 
    105     default:
    106       return false;
    107     }
    108 }
    109 
    110 
    111 /* Implement TARGET_VECTOR_MODE_SUPPORTED_P.  */
    112 static bool
    113 tile_vector_mode_supported_p (machine_mode mode)
    114 {
    115   return mode == V4QImode || mode == V2HImode;
    116 }
    117 
    118 
    119 /* Implement TARGET_CANNOT_FORCE_CONST_MEM.  */
    120 static bool
    121 tilepro_cannot_force_const_mem (machine_mode mode ATTRIBUTE_UNUSED,
    122 				rtx x ATTRIBUTE_UNUSED)
    123 {
    124   return true;
    125 }
    126 
    127 
    128 /* Implement TARGET_FUNCTION_OK_FOR_SIBCALL.  */
    129 static bool
    130 tilepro_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
    131 {
    132   return decl != NULL;
    133 }
    134 
    135 
    136 /* Implement TARGET_PASS_BY_REFERENCE.  Variable sized types are
    137    passed by reference.  */
    138 static bool
    139 tilepro_pass_by_reference (cumulative_args_t, const function_arg_info &arg)
    140 {
    141   return (arg.type
    142 	  && TYPE_SIZE (arg.type)
    143 	  && TREE_CODE (TYPE_SIZE (arg.type)) != INTEGER_CST);
    144 }
    145 
    146 
    147 /* Implement TARGET_RETURN_IN_MEMORY.  */
    148 static bool
    149 tilepro_return_in_memory (const_tree type, const_tree fndecl ATTRIBUTE_UNUSED)
    150 {
    151   return !IN_RANGE (int_size_in_bytes (type),
    152 		    0, TILEPRO_NUM_RETURN_REGS * UNITS_PER_WORD);
    153 }
    154 
    155 
    156 /* Implement TARGET_FUNCTION_ARG_BOUNDARY.  */
    157 static unsigned int
    158 tilepro_function_arg_boundary (machine_mode mode, const_tree type)
    159 {
    160   unsigned int alignment;
    161 
    162   alignment = type ? TYPE_ALIGN (type) : GET_MODE_ALIGNMENT (mode);
    163   if (alignment < PARM_BOUNDARY)
    164     alignment = PARM_BOUNDARY;
    165   if (alignment > STACK_BOUNDARY)
    166     alignment = STACK_BOUNDARY;
    167   return alignment;
    168 }
    169 
    170 
    171 /* Implement TARGET_FUNCTION_ARG.  */
    172 static rtx
    173 tilepro_function_arg (cumulative_args_t cum_v, const function_arg_info &arg)
    174 {
    175   CUMULATIVE_ARGS cum = *get_cumulative_args (cum_v);
    176   int byte_size = arg.promoted_size_in_bytes ();
    177   bool doubleword_aligned_p;
    178 
    179   if (cum >= TILEPRO_NUM_ARG_REGS)
    180     return NULL_RTX;
    181 
    182   /* See whether the argument has doubleword alignment.  */
    183   doubleword_aligned_p =
    184     tilepro_function_arg_boundary (arg.mode, arg.type) > BITS_PER_WORD;
    185 
    186   if (doubleword_aligned_p)
    187     cum += cum & 1;
    188 
    189   /* The ABI does not allow parameters to be passed partially in reg
    190      and partially in stack.  */
    191   if ((cum + (byte_size + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
    192       > TILEPRO_NUM_ARG_REGS)
    193     return NULL_RTX;
    194 
    195   return gen_rtx_REG (arg.mode, cum);
    196 }
    197 
    198 
    199 /* Implement TARGET_FUNCTION_ARG_ADVANCE.  */
    200 static void
    201 tilepro_function_arg_advance (cumulative_args_t cum_v,
    202 			      const function_arg_info &arg)
    203 {
    204   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
    205 
    206   int byte_size = arg.promoted_size_in_bytes ();
    207   int word_size = (byte_size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
    208   bool doubleword_aligned_p;
    209 
    210   /* See whether the argument has doubleword alignment.  */
    211   doubleword_aligned_p =
    212     tilepro_function_arg_boundary (arg.mode, arg.type) > BITS_PER_WORD;
    213 
    214   if (doubleword_aligned_p)
    215     *cum += *cum & 1;
    216 
    217   /* If the current argument does not fit in the pretend_args space,
    218      skip over it.  */
    219   if (*cum < TILEPRO_NUM_ARG_REGS
    220       && *cum + word_size > TILEPRO_NUM_ARG_REGS)
    221     *cum = TILEPRO_NUM_ARG_REGS;
    222 
    223   *cum += word_size;
    224 }
    225 
    226 
    227 /* Implement TARGET_FUNCTION_VALUE.  */
    228 static rtx
    229 tilepro_function_value (const_tree valtype, const_tree fn_decl_or_type,
    230 			bool outgoing ATTRIBUTE_UNUSED)
    231 {
    232   machine_mode mode;
    233   int unsigned_p;
    234 
    235   mode = TYPE_MODE (valtype);
    236   unsigned_p = TYPE_UNSIGNED (valtype);
    237 
    238   mode = promote_function_mode (valtype, mode, &unsigned_p,
    239 				fn_decl_or_type, 1);
    240 
    241   return gen_rtx_REG (mode, 0);
    242 }
    243 
    244 
    245 /* Implement TARGET_LIBCALL_VALUE.  */
    246 static rtx
    247 tilepro_libcall_value (machine_mode mode,
    248 		       const_rtx fun ATTRIBUTE_UNUSED)
    249 {
    250   return gen_rtx_REG (mode, 0);
    251 }
    252 
    253 
    254 /* Implement FUNCTION_VALUE_REGNO_P.  */
    255 static bool
    256 tilepro_function_value_regno_p (const unsigned int regno)
    257 {
    258   return regno < TILEPRO_NUM_RETURN_REGS;
    259 }
    260 
    261 
    262 /* Implement TARGET_BUILD_BUILTIN_VA_LIST.  */
    263 static tree
    264 tilepro_build_builtin_va_list (void)
    265 {
    266   tree f_args, f_skip, record, type_decl;
    267   bool owp;
    268 
    269   record = lang_hooks.types.make_type (RECORD_TYPE);
    270 
    271   type_decl = build_decl (BUILTINS_LOCATION, TYPE_DECL,
    272 			  get_identifier ("__va_list_tag"), record);
    273 
    274   f_args = build_decl (BUILTINS_LOCATION, FIELD_DECL,
    275 		       get_identifier ("__args"), ptr_type_node);
    276   f_skip = build_decl (BUILTINS_LOCATION, FIELD_DECL,
    277 		       get_identifier ("__skip"), ptr_type_node);
    278 
    279   DECL_FIELD_CONTEXT (f_args) = record;
    280 
    281   DECL_FIELD_CONTEXT (f_skip) = record;
    282 
    283   TREE_CHAIN (record) = type_decl;
    284   TYPE_NAME (record) = type_decl;
    285   TYPE_FIELDS (record) = f_args;
    286   TREE_CHAIN (f_args) = f_skip;
    287 
    288   /* We know this is being padded and we want it too.  It is an
    289      internal type so hide the warnings from the user.  */
    290   owp = warn_padded;
    291   warn_padded = false;
    292 
    293   layout_type (record);
    294 
    295   warn_padded = owp;
    296 
    297   /* The correct type is an array type of one element.  */
    298   return record;
    299 }
    300 
    301 
    302 /* Implement TARGET_EXPAND_BUILTIN_VA_START.  */
    303 static void
    304 tilepro_va_start (tree valist, rtx nextarg ATTRIBUTE_UNUSED)
    305 {
    306   tree f_args, f_skip;
    307   tree args, skip, t;
    308 
    309   f_args = TYPE_FIELDS (TREE_TYPE (valist));
    310   f_skip = TREE_CHAIN (f_args);
    311 
    312   args =
    313     build3 (COMPONENT_REF, TREE_TYPE (f_args), valist, f_args, NULL_TREE);
    314   skip =
    315     build3 (COMPONENT_REF, TREE_TYPE (f_skip), valist, f_skip, NULL_TREE);
    316 
    317   /* Find the __args area.  */
    318   t = make_tree (TREE_TYPE (args), virtual_incoming_args_rtx);
    319   t = fold_build_pointer_plus_hwi (t,
    320 				   UNITS_PER_WORD *
    321 				   (crtl->args.info - TILEPRO_NUM_ARG_REGS));
    322 
    323   if (crtl->args.pretend_args_size > 0)
    324     t = fold_build_pointer_plus_hwi (t, -STACK_POINTER_OFFSET);
    325 
    326   t = build2 (MODIFY_EXPR, TREE_TYPE (args), args, t);
    327   TREE_SIDE_EFFECTS (t) = 1;
    328   expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
    329 
    330   /* Find the __skip area.  */
    331   t = make_tree (TREE_TYPE (skip), virtual_incoming_args_rtx);
    332   t = fold_build_pointer_plus_hwi (t, -STACK_POINTER_OFFSET);
    333   t = build2 (MODIFY_EXPR, TREE_TYPE (skip), skip, t);
    334   TREE_SIDE_EFFECTS (t) = 1;
    335   expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
    336 }
    337 
    338 
    339 /* Implement TARGET_SETUP_INCOMING_VARARGS.  */
    340 static void
    341 tilepro_setup_incoming_varargs (cumulative_args_t cum,
    342 				const function_arg_info &arg,
    343 				int *pretend_args, int no_rtl)
    344 {
    345   CUMULATIVE_ARGS local_cum = *get_cumulative_args (cum);
    346   int first_reg;
    347 
    348   /* The caller has advanced CUM up to, but not beyond, the last named
    349      argument.  Advance a local copy of CUM past the last "real" named
    350      argument, to find out how many registers are left over.  */
    351   targetm.calls.function_arg_advance (pack_cumulative_args (&local_cum), arg);
    352   first_reg = local_cum;
    353 
    354   if (local_cum < TILEPRO_NUM_ARG_REGS)
    355     {
    356       *pretend_args = UNITS_PER_WORD * (TILEPRO_NUM_ARG_REGS - first_reg);
    357 
    358       if (!no_rtl)
    359 	{
    360 	  alias_set_type set = get_varargs_alias_set ();
    361 	  rtx tmp =
    362 	    gen_rtx_MEM (BLKmode, plus_constant (Pmode, \
    363 						 virtual_incoming_args_rtx,
    364 						 -STACK_POINTER_OFFSET -
    365 						 UNITS_PER_WORD *
    366 						 (TILEPRO_NUM_ARG_REGS -
    367 						  first_reg)));
    368 	  MEM_NOTRAP_P (tmp) = 1;
    369 	  set_mem_alias_set (tmp, set);
    370 	  move_block_from_reg (first_reg, tmp,
    371 			       TILEPRO_NUM_ARG_REGS - first_reg);
    372 	}
    373     }
    374   else
    375     *pretend_args = 0;
    376 }
    377 
    378 
    379 /* Implement TARGET_GIMPLIFY_VA_ARG_EXPR.  Gimplify va_arg by updating
    380    the va_list structure VALIST as required to retrieve an argument of
    381    type TYPE, and returning that argument.
    382 
    383    ret = va_arg(VALIST, TYPE);
    384 
    385    generates code equivalent to:
    386 
    387     paddedsize = (sizeof(TYPE) + 3) & -4;
    388     if ((VALIST.__args + paddedsize > VALIST.__skip)
    389 	& (VALIST.__args <= VALIST.__skip))
    390       addr = VALIST.__skip + STACK_POINTER_OFFSET;
    391     else
    392       addr = VALIST.__args;
    393     VALIST.__args = addr + paddedsize;
    394     ret = *(TYPE *)addr;                                          */
    395 static tree
    396 tilepro_gimplify_va_arg_expr (tree valist, tree type, gimple_seq * pre_p,
    397 			      gimple_seq * post_p ATTRIBUTE_UNUSED)
    398 {
    399   tree f_args, f_skip;
    400   tree args, skip;
    401   HOST_WIDE_INT size, rsize;
    402   tree addr, tmp;
    403   bool pass_by_reference_p;
    404 
    405   f_args = TYPE_FIELDS (va_list_type_node);
    406   f_skip = TREE_CHAIN (f_args);
    407 
    408   args =
    409     build3 (COMPONENT_REF, TREE_TYPE (f_args), valist, f_args, NULL_TREE);
    410   skip =
    411     build3 (COMPONENT_REF, TREE_TYPE (f_skip), valist, f_skip, NULL_TREE);
    412 
    413   addr = create_tmp_var (ptr_type_node, "va_arg");
    414 
    415   /* if an object is dynamically sized, a pointer to it is passed
    416      instead of the object itself.  */
    417   pass_by_reference_p = pass_va_arg_by_reference (type);
    418 
    419   if (pass_by_reference_p)
    420     type = build_pointer_type (type);
    421 
    422   size = int_size_in_bytes (type);
    423   rsize = ((size + UNITS_PER_WORD - 1) / UNITS_PER_WORD) * UNITS_PER_WORD;
    424 
    425   /* If the alignment of the type is greater than the default for a
    426      parameter, align to STACK_BOUNDARY.  */
    427   if (TYPE_ALIGN (type) > PARM_BOUNDARY)
    428     {
    429       /* Assert the only case we generate code for: when
    430          stack boundary = 2 * parm boundary.  */
    431       gcc_assert (STACK_BOUNDARY == PARM_BOUNDARY * 2);
    432 
    433       tmp = build2 (BIT_AND_EXPR, sizetype,
    434 		    fold_convert (sizetype, unshare_expr (args)),
    435 		    size_int (PARM_BOUNDARY / 8));
    436       tmp = build2 (POINTER_PLUS_EXPR, ptr_type_node,
    437 		    unshare_expr (args), tmp);
    438 
    439       gimplify_assign (unshare_expr (args), tmp, pre_p);
    440     }
    441 
    442   /* Build conditional expression to calculate addr. The expression
    443      will be gimplified later.  */
    444   tmp = fold_build_pointer_plus_hwi (unshare_expr (args), rsize);
    445   tmp = build2 (TRUTH_AND_EXPR, boolean_type_node,
    446 		build2 (GT_EXPR, boolean_type_node, tmp, unshare_expr (skip)),
    447 		build2 (LE_EXPR, boolean_type_node, unshare_expr (args),
    448 			unshare_expr (skip)));
    449 
    450   tmp = build3 (COND_EXPR, ptr_type_node, tmp,
    451 		build2 (POINTER_PLUS_EXPR, ptr_type_node, unshare_expr (skip),
    452 			size_int (STACK_POINTER_OFFSET)),
    453 		unshare_expr (args));
    454 
    455   gimplify_assign (addr, tmp, pre_p);
    456 
    457   /* Update VALIST.__args.  */
    458   tmp = fold_build_pointer_plus_hwi (addr, rsize);
    459   gimplify_assign (unshare_expr (args), tmp, pre_p);
    460 
    461   addr = fold_convert (build_pointer_type (type), addr);
    462 
    463   if (pass_by_reference_p)
    464     addr = build_va_arg_indirect_ref (addr);
    465 
    466   return build_va_arg_indirect_ref (addr);
    467 }
    468 
    469 
    471 
    472 /* Implement TARGET_RTX_COSTS.  */
    473 static bool
    474 tilepro_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno,
    475 		   int *total, bool speed)
    476 {
    477   int code = GET_CODE (x);
    478 
    479   switch (code)
    480     {
    481     case CONST_INT:
    482       /* If this is an 8-bit constant, return zero since it can be
    483          used nearly anywhere with no cost.  If it is a valid operand
    484          for an ADD or AND, likewise return 0 if we know it will be
    485          used in that context.  Otherwise, return 2 since it might be
    486          used there later.  All other constants take at least two
    487          insns.  */
    488       if (satisfies_constraint_I (x))
    489 	{
    490 	  *total = 0;
    491 	  return true;
    492 	}
    493       else if (outer_code == PLUS && add_operand (x, VOIDmode))
    494 	{
    495 	  /* Slightly penalize large constants even though we can add
    496 	     them in one instruction, because it forces the use of
    497 	     2-wide bundling mode.  */
    498 	  *total = 1;
    499 	  return true;
    500 	}
    501       else if (move_operand (x, SImode))
    502 	{
    503 	  /* We can materialize in one move.  */
    504 	  *total = COSTS_N_INSNS (1);
    505 	  return true;
    506 	}
    507       else
    508 	{
    509 	  /* We can materialize in two moves.  */
    510 	  *total = COSTS_N_INSNS (2);
    511 	  return true;
    512 	}
    513 
    514       return false;
    515 
    516     case CONST:
    517     case LABEL_REF:
    518     case SYMBOL_REF:
    519       *total = COSTS_N_INSNS (2);
    520       return true;
    521 
    522     case CONST_DOUBLE:
    523       *total = COSTS_N_INSNS (4);
    524       return true;
    525 
    526     case HIGH:
    527       *total = 0;
    528       return true;
    529 
    530     case MEM:
    531       /* If outer-code was a sign or zero extension, a cost of
    532          COSTS_N_INSNS (1) was already added in, so account for
    533          that.  */
    534       if (outer_code == ZERO_EXTEND || outer_code == SIGN_EXTEND)
    535 	*total = COSTS_N_INSNS (1);
    536       else
    537 	*total = COSTS_N_INSNS (2);
    538       return true;
    539 
    540     case PLUS:
    541       /* Convey that s[123]a are efficient.  */
    542       if (GET_CODE (XEXP (x, 0)) == MULT
    543 	  && cint_248_operand (XEXP (XEXP (x, 0), 1), VOIDmode))
    544 	{
    545 	  *total = (rtx_cost (XEXP (XEXP (x, 0), 0), mode,
    546 			      (enum rtx_code) outer_code, opno, speed)
    547 		    + rtx_cost (XEXP (x, 1), mode,
    548 				(enum rtx_code) outer_code, opno, speed)
    549 		    + COSTS_N_INSNS (1));
    550 	  return true;
    551 	}
    552       return false;
    553 
    554     case MULT:
    555       *total = COSTS_N_INSNS (2);
    556       return false;
    557 
    558     case SIGN_EXTEND:
    559     case ZERO_EXTEND:
    560       if (outer_code == MULT)
    561 	*total = 0;
    562       else
    563 	*total = COSTS_N_INSNS (1);
    564       return false;
    565 
    566     case DIV:
    567     case UDIV:
    568     case MOD:
    569     case UMOD:
    570       /* These are handled by software and are very expensive.  */
    571       *total = COSTS_N_INSNS (100);
    572       return false;
    573 
    574     case UNSPEC:
    575     case UNSPEC_VOLATILE:
    576       {
    577 	int num = XINT (x, 1);
    578 
    579 	if (num <= TILEPRO_LAST_LATENCY_1_INSN)
    580 	  *total = COSTS_N_INSNS (1);
    581 	else if (num <= TILEPRO_LAST_LATENCY_2_INSN)
    582 	  *total = COSTS_N_INSNS (2);
    583 	else if (num > TILEPRO_LAST_LATENCY_INSN)
    584 	  {
    585 	    if (outer_code == PLUS)
    586 	      *total = 0;
    587 	    else
    588 	      *total = COSTS_N_INSNS (1);
    589 	  }
    590 	else
    591 	  {
    592 	    switch (num)
    593 	      {
    594 	      case UNSPEC_BLOCKAGE:
    595 	      case UNSPEC_NETWORK_BARRIER:
    596 		*total = 0;
    597 		break;
    598 
    599 	      case UNSPEC_LNK_AND_LABEL:
    600 	      case UNSPEC_MF:
    601 	      case UNSPEC_NETWORK_RECEIVE:
    602 	      case UNSPEC_NETWORK_SEND:
    603 	      case UNSPEC_TLS_GD_ADD:
    604 		*total = COSTS_N_INSNS (1);
    605 		break;
    606 
    607 	      case UNSPEC_TLS_IE_LOAD:
    608 		*total = COSTS_N_INSNS (2);
    609 		break;
    610 
    611 	      case UNSPEC_SP_SET:
    612 		*total = COSTS_N_INSNS (3);
    613 		break;
    614 
    615 	      case UNSPEC_SP_TEST:
    616 		*total = COSTS_N_INSNS (4);
    617 		break;
    618 
    619 	      case UNSPEC_LATENCY_L2:
    620 		*total = COSTS_N_INSNS (8);
    621 		break;
    622 
    623 	      case UNSPEC_TLS_GD_CALL:
    624 		*total = COSTS_N_INSNS (30);
    625 		break;
    626 
    627 	      case UNSPEC_LATENCY_MISS:
    628 		*total = COSTS_N_INSNS (80);
    629 		break;
    630 
    631 	      default:
    632 		*total = COSTS_N_INSNS (1);
    633 	      }
    634 	  }
    635 	return true;
    636       }
    637 
    638     default:
    639       return false;
    640     }
    641 }
    642 
    643 
    645 
    646 /* Returns an SImode integer rtx with value VAL.  */
    647 static rtx
    648 gen_int_si (HOST_WIDE_INT val)
    649 {
    650   return gen_int_mode (val, SImode);
    651 }
    652 
    653 
    654 /* Create a temporary variable to hold a partial result, to enable
    655    CSE.  */
    656 static rtx
    657 create_temp_reg_if_possible (machine_mode mode, rtx default_reg)
    658 {
    659   return can_create_pseudo_p ()? gen_reg_rtx (mode) : default_reg;
    660 }
    661 
    662 
    663 /* Functions to save and restore machine-specific function data.  */
    664 static struct machine_function *
    665 tilepro_init_machine_status (void)
    666 {
    667   return ggc_cleared_alloc<machine_function> ();
    668 }
    669 
    670 
    671 /* Do anything needed before RTL is emitted for each function.  */
    672 void
    673 tilepro_init_expanders (void)
    674 {
    675   /* Arrange to initialize and mark the machine per-function
    676      status.  */
    677   init_machine_status = tilepro_init_machine_status;
    678 
    679   if (cfun && cfun->machine && flag_pic)
    680     {
    681       static int label_num = 0;
    682 
    683       char text_label_name[32];
    684 
    685       struct machine_function *machine = cfun->machine;
    686 
    687       ASM_GENERATE_INTERNAL_LABEL (text_label_name, "L_PICLNK", label_num++);
    688 
    689       machine->text_label_symbol =
    690 	gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (text_label_name));
    691 
    692       machine->text_label_rtx =
    693 	gen_rtx_REG (Pmode, TILEPRO_PIC_TEXT_LABEL_REGNUM);
    694 
    695       machine->got_rtx = gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM);
    696 
    697       machine->calls_tls_get_addr = false;
    698     }
    699 }
    700 
    701 
    702 /* Return true if X contains a thread-local symbol.  */
    703 static bool
    704 tilepro_tls_referenced_p (rtx x)
    705 {
    706   if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS)
    707     x = XEXP (XEXP (x, 0), 0);
    708 
    709   if (GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (x))
    710     return true;
    711 
    712   /* That's all we handle in tilepro_legitimize_tls_address for
    713      now.  */
    714   return false;
    715 }
    716 
    717 
    718 /* Return true if X requires a scratch register.  It is given that
    719    flag_pic is on and that X satisfies CONSTANT_P.  */
    720 static int
    721 tilepro_pic_address_needs_scratch (rtx x)
    722 {
    723   if (GET_CODE (x) == CONST
    724       && GET_CODE (XEXP (x, 0)) == PLUS
    725       && (GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
    726 	  || GET_CODE (XEXP (XEXP (x, 0), 0)) == LABEL_REF)
    727       && CONST_INT_P (XEXP (XEXP (x, 0), 1)))
    728     return true;
    729 
    730   return false;
    731 }
    732 
    733 
    734 /* Implement TARGET_LEGITIMATE_CONSTANT_P.  This is all constants for
    735    which we are willing to load the value into a register via a move
    736    pattern.  TLS cannot be treated as a constant because it can
    737    include a function call.  */
    738 static bool
    739 tilepro_legitimate_constant_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x)
    740 {
    741   switch (GET_CODE (x))
    742     {
    743     case CONST:
    744     case SYMBOL_REF:
    745       return !tilepro_tls_referenced_p (x);
    746 
    747     default:
    748       return true;
    749     }
    750 }
    751 
    752 
    753 /* Return true if the constant value X is a legitimate general operand
    754    when generating PIC code.  It is given that flag_pic is on and that
    755    X satisfies CONSTANT_P.  */
    756 bool
    757 tilepro_legitimate_pic_operand_p (rtx x)
    758 {
    759   if (tilepro_pic_address_needs_scratch (x))
    760     return false;
    761 
    762   if (tilepro_tls_referenced_p (x))
    763     return false;
    764 
    765   return true;
    766 }
    767 
    768 
    769 /* Return true if the rtx X can be used as an address operand.  */
    770 static bool
    771 tilepro_legitimate_address_p (machine_mode ARG_UNUSED (mode), rtx x,
    772 			      bool strict)
    773 {
    774   if (GET_CODE (x) == SUBREG)
    775     x = SUBREG_REG (x);
    776 
    777   switch (GET_CODE (x))
    778     {
    779     case POST_INC:
    780     case POST_DEC:
    781       if (GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD)
    782 	return false;
    783 
    784       x = XEXP (x, 0);
    785       break;
    786 
    787     case POST_MODIFY:
    788       if (GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD)
    789 	return false;
    790 
    791       if (GET_CODE (XEXP (x, 1)) != PLUS)
    792 	return false;
    793 
    794       if (!rtx_equal_p (XEXP (x, 0), XEXP (XEXP (x, 1), 0)))
    795 	return false;
    796 
    797       if (!satisfies_constraint_I (XEXP (XEXP (x, 1), 1)))
    798 	return false;
    799 
    800       x = XEXP (x, 0);
    801       break;
    802 
    803     case REG:
    804       break;
    805 
    806     default:
    807       return false;
    808     }
    809 
    810   /* Check if x is a valid reg.  */
    811   if (!REG_P (x))
    812     return false;
    813 
    814   if (strict)
    815     return REGNO_OK_FOR_BASE_P (REGNO (x));
    816   else
    817     return true;
    818 }
    819 
    820 
    821 /* Return the rtx containing SYMBOL_REF to the text label.  */
    822 static rtx
    823 tilepro_text_label_symbol (void)
    824 {
    825   return cfun->machine->text_label_symbol;
    826 }
    827 
    828 
    829 /* Return the register storing the value of the text label.  */
    830 static rtx
    831 tilepro_text_label_rtx (void)
    832 {
    833   return cfun->machine->text_label_rtx;
    834 }
    835 
    836 
    837 /* Return the register storing the value of the global offset
    838    table.  */
    839 static rtx
    840 tilepro_got_rtx (void)
    841 {
    842   return cfun->machine->got_rtx;
    843 }
    844 
    845 
    846 /* Return the SYMBOL_REF for _GLOBAL_OFFSET_TABLE_.  */
    847 static rtx
    848 tilepro_got_symbol (void)
    849 {
    850   if (g_got_symbol == NULL)
    851     g_got_symbol = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
    852 
    853   return g_got_symbol;
    854 }
    855 
    856 
    857 /* Return a reference to the got to be used by tls references.  */
    858 static rtx
    859 tilepro_tls_got (void)
    860 {
    861   rtx temp;
    862   if (flag_pic)
    863     {
    864       crtl->uses_pic_offset_table = 1;
    865       return tilepro_got_rtx ();
    866     }
    867 
    868   temp = gen_reg_rtx (Pmode);
    869   emit_move_insn (temp, tilepro_got_symbol ());
    870 
    871   return temp;
    872 }
    873 
    874 
    875 /* ADDR contains a thread-local SYMBOL_REF.  Generate code to compute
    876    this (thread-local) address.  */
    877 static rtx
    878 tilepro_legitimize_tls_address (rtx addr)
    879 {
    880   rtx ret;
    881 
    882   gcc_assert (can_create_pseudo_p ());
    883 
    884   if (GET_CODE (addr) == SYMBOL_REF)
    885     switch (SYMBOL_REF_TLS_MODEL (addr))
    886       {
    887       case TLS_MODEL_GLOBAL_DYNAMIC:
    888       case TLS_MODEL_LOCAL_DYNAMIC:
    889 	{
    890 	  rtx r0, temp1, temp2, temp3, got;
    891 	  rtx_insn *last;
    892 
    893 	  ret = gen_reg_rtx (Pmode);
    894 	  r0 = gen_rtx_REG (Pmode, 0);
    895 	  temp1 = gen_reg_rtx (Pmode);
    896 	  temp2 = gen_reg_rtx (Pmode);
    897 	  temp3 = gen_reg_rtx (Pmode);
    898 
    899 	  got = tilepro_tls_got ();
    900 	  emit_insn (gen_tls_gd_addhi (temp1, got, addr));
    901 	  emit_insn (gen_tls_gd_addlo (temp2, temp1, addr));
    902 	  emit_move_insn (r0, temp2);
    903 	  emit_insn (gen_tls_gd_call (addr));
    904 	  emit_move_insn (temp3, r0);
    905 	  last = emit_insn (gen_tls_gd_add (ret, temp3, addr));
    906 	  set_unique_reg_note (last, REG_EQUAL, copy_rtx (addr));
    907 	  break;
    908 	}
    909       case TLS_MODEL_INITIAL_EXEC:
    910 	{
    911 	  rtx temp1, temp2, temp3, got;
    912 	  rtx_insn *last;
    913 
    914 	  ret = gen_reg_rtx (Pmode);
    915 	  temp1 = gen_reg_rtx (Pmode);
    916 	  temp2 = gen_reg_rtx (Pmode);
    917 	  temp3 = gen_reg_rtx (Pmode);
    918 
    919 	  got = tilepro_tls_got ();
    920 	  emit_insn (gen_tls_ie_addhi (temp1, got, addr));
    921 	  emit_insn (gen_tls_ie_addlo (temp2, temp1, addr));
    922 	  emit_insn (gen_tls_ie_load (temp3, temp2, addr));
    923 	  last =
    924 	    emit_move_insn(ret,
    925 			   gen_rtx_PLUS (Pmode,
    926 					 gen_rtx_REG (Pmode,
    927 						      THREAD_POINTER_REGNUM),
    928 					 temp3));
    929 	  set_unique_reg_note (last, REG_EQUAL, copy_rtx (addr));
    930 	  break;
    931 	}
    932       case TLS_MODEL_LOCAL_EXEC:
    933 	{
    934 	  rtx temp1;
    935 	  rtx_insn *last;
    936 
    937 	  ret = gen_reg_rtx (Pmode);
    938 	  temp1 = gen_reg_rtx (Pmode);
    939 
    940 	  emit_insn (gen_tls_le_addhi (temp1,
    941 				       gen_rtx_REG (Pmode,
    942 						    THREAD_POINTER_REGNUM),
    943 				       addr));
    944 	  last = emit_insn (gen_tls_le_addlo (ret, temp1, addr));
    945 	  set_unique_reg_note (last, REG_EQUAL, copy_rtx (addr));
    946 	  break;
    947 	}
    948       default:
    949 	gcc_unreachable ();
    950       }
    951   else if (GET_CODE (addr) == CONST)
    952     {
    953       rtx base, offset;
    954 
    955       gcc_assert (GET_CODE (XEXP (addr, 0)) == PLUS);
    956 
    957       base = tilepro_legitimize_tls_address (XEXP (XEXP (addr, 0), 0));
    958       offset = XEXP (XEXP (addr, 0), 1);
    959 
    960       base = force_operand (base, NULL_RTX);
    961       ret = force_reg (Pmode, gen_rtx_PLUS (Pmode, base, offset));
    962     }
    963   else
    964     gcc_unreachable ();
    965 
    966   return ret;
    967 }
    968 
    969 
    970 /* Legitimize PIC addresses.  If the address is already
    971    position-independent, we return ORIG.  Newly generated
    972    position-independent addresses go into a reg.  This is REG if
    973    nonzero, otherwise we allocate register(s) as necessary.  */
    974 static rtx
    975 tilepro_legitimize_pic_address (rtx orig,
    976 				machine_mode mode ATTRIBUTE_UNUSED,
    977 				rtx reg)
    978 {
    979   if (GET_CODE (orig) == SYMBOL_REF)
    980     {
    981       rtx address, pic_ref;
    982 
    983       if (reg == 0)
    984 	{
    985 	  gcc_assert (can_create_pseudo_p ());
    986 	  reg = gen_reg_rtx (Pmode);
    987 	}
    988 
    989       if (SYMBOL_REF_LOCAL_P (orig))
    990 	{
    991 	  /* If not during reload, allocate another temp reg here for
    992 	     loading in the address, so that these instructions can be
    993 	     optimized properly.  */
    994 	  rtx temp_reg = create_temp_reg_if_possible (Pmode, reg);
    995 	  rtx text_label_symbol = tilepro_text_label_symbol ();
    996 	  rtx text_label_rtx = tilepro_text_label_rtx ();
    997 
    998 	  emit_insn (gen_addli_pcrel (temp_reg, text_label_rtx, orig,
    999 				      text_label_symbol));
   1000 	  emit_insn (gen_auli_pcrel (temp_reg, temp_reg, orig,
   1001 				     text_label_symbol));
   1002 
   1003 	  /* Note: this is conservative.  We use the text_label but we
   1004 	     don't use the pic_offset_table.  However, in some cases
   1005 	     we may need the pic_offset_table (see
   1006 	     tilepro_fixup_pcrel_references).  */
   1007 	  crtl->uses_pic_offset_table = 1;
   1008 
   1009 	  address = temp_reg;
   1010 
   1011 	  emit_move_insn (reg, address);
   1012 	  return reg;
   1013 	}
   1014       else
   1015 	{
   1016 	  /* If not during reload, allocate another temp reg here for
   1017 	     loading in the address, so that these instructions can be
   1018 	     optimized properly.  */
   1019 	  rtx temp_reg = create_temp_reg_if_possible (Pmode, reg);
   1020 
   1021 	  gcc_assert (flag_pic);
   1022 	  if (flag_pic == 1)
   1023 	    {
   1024 	      emit_insn (gen_add_got16 (temp_reg,
   1025 					tilepro_got_rtx (), orig));
   1026 	    }
   1027 	  else
   1028 	    {
   1029 	      rtx temp_reg2 = create_temp_reg_if_possible (Pmode, reg);
   1030 	      emit_insn (gen_addhi_got32 (temp_reg2,
   1031 					  tilepro_got_rtx (), orig));
   1032 	      emit_insn (gen_addlo_got32 (temp_reg, temp_reg2, orig));
   1033 	    }
   1034 
   1035 	  address = temp_reg;
   1036 
   1037 	  pic_ref = gen_const_mem (Pmode, address);
   1038 	  crtl->uses_pic_offset_table = 1;
   1039 	  emit_move_insn (reg, pic_ref);
   1040 	  /* The following put a REG_EQUAL note on this insn, so that
   1041 	     it can be optimized by loop.  But it causes the label to
   1042 	     be optimized away.  */
   1043 	  /* set_unique_reg_note (insn, REG_EQUAL, orig); */
   1044 	  return reg;
   1045 	}
   1046     }
   1047   else if (GET_CODE (orig) == CONST)
   1048     {
   1049       rtx base, offset;
   1050 
   1051       if (GET_CODE (XEXP (orig, 0)) == PLUS
   1052 	  && XEXP (XEXP (orig, 0), 0) == tilepro_got_rtx ())
   1053 	return orig;
   1054 
   1055       if (reg == 0)
   1056 	{
   1057 	  gcc_assert (can_create_pseudo_p ());
   1058 	  reg = gen_reg_rtx (Pmode);
   1059 	}
   1060 
   1061       gcc_assert (GET_CODE (XEXP (orig, 0)) == PLUS);
   1062       base = tilepro_legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode,
   1063 					     reg);
   1064       offset =
   1065 	tilepro_legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
   1066 					base == reg ? 0 : reg);
   1067 
   1068       if (CONST_INT_P (offset))
   1069 	{
   1070 	  if (can_create_pseudo_p ())
   1071 	    offset = force_reg (Pmode, offset);
   1072 	  else
   1073 	    /* If we reach here, then something is seriously
   1074 	       wrong.  */
   1075 	    gcc_unreachable ();
   1076 	}
   1077 
   1078       if (can_create_pseudo_p ())
   1079 	return force_reg (Pmode, gen_rtx_PLUS (Pmode, base, offset));
   1080       else
   1081 	gcc_unreachable ();
   1082     }
   1083   else if (GET_CODE (orig) == LABEL_REF)
   1084     {
   1085       rtx address, temp_reg;
   1086       rtx text_label_symbol;
   1087       rtx text_label_rtx;
   1088 
   1089       if (reg == 0)
   1090 	{
   1091 	  gcc_assert (can_create_pseudo_p ());
   1092 	  reg = gen_reg_rtx (Pmode);
   1093 	}
   1094 
   1095       /* If not during reload, allocate another temp reg here for
   1096          loading in the address, so that these instructions can be
   1097          optimized properly.  */
   1098       temp_reg = create_temp_reg_if_possible (Pmode, reg);
   1099       text_label_symbol = tilepro_text_label_symbol ();
   1100       text_label_rtx = tilepro_text_label_rtx ();
   1101 
   1102       emit_insn (gen_addli_pcrel (temp_reg, text_label_rtx, orig,
   1103 				  text_label_symbol));
   1104       emit_insn (gen_auli_pcrel (temp_reg, temp_reg, orig,
   1105 				 text_label_symbol));
   1106 
   1107       /* Note: this is conservative.  We use the text_label but we
   1108          don't use the pic_offset_table.  */
   1109       crtl->uses_pic_offset_table = 1;
   1110 
   1111       address = temp_reg;
   1112 
   1113       emit_move_insn (reg, address);
   1114 
   1115       return reg;
   1116     }
   1117 
   1118   return orig;
   1119 }
   1120 
   1121 
   1122 /* Implement TARGET_LEGITIMIZE_ADDRESS.  */
   1123 static rtx
   1124 tilepro_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
   1125 			    machine_mode mode)
   1126 {
   1127   if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD
   1128       && symbolic_operand (x, Pmode) && tilepro_tls_referenced_p (x))
   1129     {
   1130       return tilepro_legitimize_tls_address (x);
   1131     }
   1132   else if (flag_pic)
   1133     {
   1134       return tilepro_legitimize_pic_address (x, mode, 0);
   1135     }
   1136   else
   1137     return x;
   1138 }
   1139 
   1140 
   1141 /* Implement TARGET_DELEGITIMIZE_ADDRESS.  */
   1142 static rtx
   1143 tilepro_delegitimize_address (rtx x)
   1144 {
   1145   x = delegitimize_mem_from_attrs (x);
   1146 
   1147   if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == UNSPEC)
   1148     {
   1149       switch (XINT (XEXP (x, 0), 1))
   1150 	{
   1151 	case UNSPEC_PCREL_SYM:
   1152 	case UNSPEC_GOT16_SYM:
   1153 	case UNSPEC_GOT32_SYM:
   1154 	case UNSPEC_TLS_GD:
   1155 	case UNSPEC_TLS_IE:
   1156 	  x = XVECEXP (XEXP (x, 0), 0, 0);
   1157 	  break;
   1158 	}
   1159     }
   1160 
   1161   return x;
   1162 }
   1163 
   1164 
   1165 /* Emit code to load the PIC register.  */
   1166 static void
   1167 load_pic_register (bool delay_pic_helper ATTRIBUTE_UNUSED)
   1168 {
   1169   int orig_flag_pic = flag_pic;
   1170 
   1171   rtx got_symbol = tilepro_got_symbol ();
   1172   rtx text_label_symbol = tilepro_text_label_symbol ();
   1173   rtx text_label_rtx = tilepro_text_label_rtx ();
   1174   flag_pic = 0;
   1175 
   1176   emit_insn (gen_insn_lnk_and_label (text_label_rtx, text_label_symbol));
   1177 
   1178   emit_insn (gen_addli_pcrel (tilepro_got_rtx (),
   1179 			      text_label_rtx, got_symbol, text_label_symbol));
   1180 
   1181   emit_insn (gen_auli_pcrel (tilepro_got_rtx (),
   1182 			     tilepro_got_rtx (),
   1183 			     got_symbol, text_label_symbol));
   1184 
   1185   flag_pic = orig_flag_pic;
   1186 
   1187   /* Need to emit this whether or not we obey regdecls, since
   1188      setjmp/longjmp can cause life info to screw up.  ??? In the case
   1189      where we don't obey regdecls, this is not sufficient since we may
   1190      not fall out the bottom.  */
   1191   emit_use (tilepro_got_rtx ());
   1192 }
   1193 
   1194 
   1195 /* Return the simd variant of the constant NUM of mode MODE, by
   1196    replicating it to fill an interger of mode SImode.  NUM is first
   1197    truncated to fit in MODE.  */
   1198 rtx
   1199 tilepro_simd_int (rtx num, machine_mode mode)
   1200 {
   1201   HOST_WIDE_INT n = 0;
   1202 
   1203   gcc_assert (CONST_INT_P (num));
   1204 
   1205   n = INTVAL (num);
   1206 
   1207   switch (mode)
   1208     {
   1209     case E_QImode:
   1210       n = 0x01010101 * (n & 0x000000FF);
   1211       break;
   1212     case E_HImode:
   1213       n = 0x00010001 * (n & 0x0000FFFF);
   1214       break;
   1215     case E_SImode:
   1216       break;
   1217     case E_DImode:
   1218       break;
   1219     default:
   1220       gcc_unreachable ();
   1221     }
   1222 
   1223   return gen_int_si (n);
   1224 }
   1225 
   1226 
   1227 /* Split one or more DImode RTL references into pairs of SImode
   1228    references.  The RTL can be REG, offsettable MEM, integer constant,
   1229    or CONST_DOUBLE.  "operands" is a pointer to an array of DImode RTL
   1230    to split and "num" is its length.  lo_half and hi_half are output
   1231    arrays that parallel "operands".  */
   1232 void
   1233 split_di (rtx operands[], int num, rtx lo_half[], rtx hi_half[])
   1234 {
   1235   while (num--)
   1236     {
   1237       rtx op = operands[num];
   1238 
   1239       /* simplify_subreg refuse to split volatile memory addresses,
   1240          but we still have to handle it.  */
   1241       if (MEM_P (op))
   1242 	{
   1243 	  lo_half[num] = adjust_address (op, SImode, 0);
   1244 	  hi_half[num] = adjust_address (op, SImode, 4);
   1245 	}
   1246       else
   1247 	{
   1248 	  lo_half[num] = simplify_gen_subreg (SImode, op,
   1249 					      GET_MODE (op) == VOIDmode
   1250 					      ? DImode : GET_MODE (op), 0);
   1251 	  hi_half[num] = simplify_gen_subreg (SImode, op,
   1252 					      GET_MODE (op) == VOIDmode
   1253 					      ? DImode : GET_MODE (op), 4);
   1254 	}
   1255     }
   1256 }
   1257 
   1258 
   1259 /* Returns true iff val can be moved into a register in one
   1260    instruction.  And if it can, it emits the code to move the
   1261    constant.
   1262 
   1263    If three_wide_only is true, this insists on an instruction that
   1264    works in a bundle containing three instructions.  */
   1265 static bool
   1266 expand_set_cint32_one_inst (rtx dest_reg,
   1267 			    HOST_WIDE_INT val, bool three_wide_only)
   1268 {
   1269   val = trunc_int_for_mode (val, SImode);
   1270 
   1271   if (val == trunc_int_for_mode (val, QImode))
   1272     {
   1273       /* Success! */
   1274       emit_move_insn (dest_reg, GEN_INT (val));
   1275       return true;
   1276     }
   1277   else if (!three_wide_only)
   1278     {
   1279       rtx imm_op = GEN_INT (val);
   1280 
   1281       if (satisfies_constraint_J (imm_op)
   1282 	  || satisfies_constraint_K (imm_op)
   1283 	  || satisfies_constraint_N (imm_op)
   1284 	  || satisfies_constraint_P (imm_op))
   1285 	{
   1286 	  emit_move_insn (dest_reg, imm_op);
   1287 	  return true;
   1288 	}
   1289     }
   1290 
   1291   return false;
   1292 }
   1293 
   1294 
   1295 /* Implement SImode rotatert.  */
   1296 static HOST_WIDE_INT
   1297 rotate_right (HOST_WIDE_INT n, int count)
   1298 {
   1299   unsigned HOST_WIDE_INT x = n & 0xFFFFFFFF;
   1300   if (count == 0)
   1301     return x;
   1302   return ((x >> count) | (x << (32 - count))) & 0xFFFFFFFF;
   1303 }
   1304 
   1305 
   1306 /* Return true iff n contains exactly one contiguous sequence of 1
   1307    bits, possibly wrapping around from high bits to low bits.  */
   1308 bool
   1309 tilepro_bitfield_operand_p (HOST_WIDE_INT n, int *first_bit, int *last_bit)
   1310 {
   1311   int i;
   1312 
   1313   if (n == 0)
   1314     return false;
   1315 
   1316   for (i = 0; i < 32; i++)
   1317     {
   1318       unsigned HOST_WIDE_INT x = rotate_right (n, i);
   1319       if (!(x & 1))
   1320 	continue;
   1321 
   1322       /* See if x is a power of two minus one, i.e. only consecutive 1
   1323          bits starting from bit 0.  */
   1324       if ((x & (x + 1)) == 0)
   1325 	{
   1326 	  if (first_bit != NULL)
   1327 	    *first_bit = i;
   1328 	  if (last_bit != NULL)
   1329 	    *last_bit = (i + exact_log2 (x ^ (x >> 1))) & 31;
   1330 
   1331 	  return true;
   1332 	}
   1333     }
   1334 
   1335   return false;
   1336 }
   1337 
   1338 
   1339 /* Create code to move the CONST_INT value in src_val to dest_reg.  */
   1340 static void
   1341 expand_set_cint32 (rtx dest_reg, rtx src_val)
   1342 {
   1343   HOST_WIDE_INT val;
   1344   int leading_zeroes, trailing_zeroes;
   1345   int lower, upper;
   1346   int three_wide_only;
   1347   rtx temp;
   1348 
   1349   gcc_assert (CONST_INT_P (src_val));
   1350   val = trunc_int_for_mode (INTVAL (src_val), SImode);
   1351 
   1352   /* See if we can generate the constant in one instruction.  */
   1353   if (expand_set_cint32_one_inst (dest_reg, val, false))
   1354     return;
   1355 
   1356   /* Create a temporary variable to hold a partial result, to enable
   1357      CSE.  */
   1358   temp = create_temp_reg_if_possible (SImode, dest_reg);
   1359 
   1360   leading_zeroes = 31 - floor_log2 (val & 0xFFFFFFFF);
   1361   trailing_zeroes = exact_log2 (val & -val);
   1362 
   1363   lower = trunc_int_for_mode (val, HImode);
   1364   upper = trunc_int_for_mode ((val - lower) >> 16, HImode);
   1365 
   1366   /* First try all three-wide instructions that generate a constant
   1367      (i.e. movei) followed by various shifts and rotates. If none of
   1368      those work, try various two-wide ways of generating a constant
   1369      followed by various shifts and rotates.  */
   1370   for (three_wide_only = 1; three_wide_only >= 0; three_wide_only--)
   1371     {
   1372       int count;
   1373 
   1374       if (expand_set_cint32_one_inst (temp, val >> trailing_zeroes,
   1375 				      three_wide_only))
   1376 	{
   1377 	  /* 0xFFFFA500 becomes:
   1378 	     movei temp, 0xFFFFFFA5
   1379 	     shli dest, temp, 8  */
   1380 	  emit_move_insn (dest_reg,
   1381 			  gen_rtx_ASHIFT (SImode, temp,
   1382 					  GEN_INT (trailing_zeroes)));
   1383 	  return;
   1384 	}
   1385 
   1386       if (expand_set_cint32_one_inst (temp, val << leading_zeroes,
   1387 				      three_wide_only))
   1388 	{
   1389 	  /* 0x7FFFFFFF becomes:
   1390 	     movei temp, -2
   1391 	     shri dest, temp, 1  */
   1392 	  emit_move_insn (dest_reg,
   1393 			  gen_rtx_LSHIFTRT (SImode, temp,
   1394 					    GEN_INT (leading_zeroes)));
   1395 	  return;
   1396 	}
   1397 
   1398       /* Try rotating a one-instruction immediate, since rotate is
   1399          3-wide.  */
   1400       for (count = 1; count < 32; count++)
   1401 	{
   1402 	  HOST_WIDE_INT r = rotate_right (val, count);
   1403 	  if (expand_set_cint32_one_inst (temp, r, three_wide_only))
   1404 	    {
   1405 	      /* 0xFFA5FFFF becomes:
   1406 	         movei temp, 0xFFFFFFA5
   1407 	         rli dest, temp, 16  */
   1408 	      emit_move_insn (dest_reg,
   1409 			      gen_rtx_ROTATE (SImode, temp, GEN_INT (count)));
   1410 	      return;
   1411 	    }
   1412 	}
   1413 
   1414       if (lower == trunc_int_for_mode (lower, QImode))
   1415 	{
   1416 	  /* We failed to use two 3-wide instructions, but the low 16
   1417 	     bits are a small number so just use a 2-wide + 3-wide
   1418 	     auli + addi pair rather than anything more exotic.
   1419 
   1420 	     0x12340056 becomes:
   1421 	     auli temp, zero, 0x1234
   1422 	     addi dest, temp, 0x56  */
   1423 	  break;
   1424 	}
   1425     }
   1426 
   1427   /* Fallback case: use a auli + addli/addi pair.  */
   1428   emit_move_insn (temp, GEN_INT (upper << 16));
   1429   emit_move_insn (dest_reg, (gen_rtx_PLUS (SImode, temp, GEN_INT (lower))));
   1430 }
   1431 
   1432 
   1433 /* Load OP1, a 32-bit constant, into OP0, a register.  We know it
   1434    can't be done in one insn when we get here, the move expander
   1435    guarantees this.  */
   1436 void
   1437 tilepro_expand_set_const32 (rtx op0, rtx op1)
   1438 {
   1439   machine_mode mode = GET_MODE (op0);
   1440   rtx temp;
   1441 
   1442   if (CONST_INT_P (op1))
   1443     {
   1444       /* TODO: I don't know if we want to split large constants now,
   1445          or wait until later (with a define_split).
   1446 
   1447          Does splitting early help CSE?  Does it harm other
   1448          optimizations that might fold loads? */
   1449       expand_set_cint32 (op0, op1);
   1450     }
   1451   else
   1452     {
   1453       temp = create_temp_reg_if_possible (mode, op0);
   1454 
   1455       /* A symbol, emit in the traditional way.  */
   1456       emit_move_insn (temp, gen_rtx_HIGH (mode, op1));
   1457       emit_move_insn (op0, gen_rtx_LO_SUM (mode, temp, op1));
   1458     }
   1459 }
   1460 
   1461 
   1462 /* Expand a move instruction.  Return true if all work is done.  */
   1463 bool
   1464 tilepro_expand_mov (machine_mode mode, rtx *operands)
   1465 {
   1466   /* Handle sets of MEM first.  */
   1467   if (MEM_P (operands[0]))
   1468     {
   1469       if (can_create_pseudo_p ())
   1470 	operands[0] = validize_mem (operands[0]);
   1471 
   1472       if (reg_or_0_operand (operands[1], mode))
   1473 	return false;
   1474 
   1475       if (!reload_in_progress)
   1476 	operands[1] = force_reg (mode, operands[1]);
   1477     }
   1478 
   1479   /* Fixup TLS cases.  */
   1480   if (CONSTANT_P (operands[1]) && tilepro_tls_referenced_p (operands[1]))
   1481     {
   1482       operands[1] = tilepro_legitimize_tls_address (operands[1]);
   1483       return false;
   1484     }
   1485 
   1486   /* Fixup PIC cases.  */
   1487   if (flag_pic && CONSTANT_P (operands[1]))
   1488     {
   1489       if (tilepro_pic_address_needs_scratch (operands[1]))
   1490 	operands[1] = tilepro_legitimize_pic_address (operands[1], mode, 0);
   1491 
   1492       if (symbolic_operand (operands[1], mode))
   1493 	{
   1494 	  operands[1] = tilepro_legitimize_pic_address (operands[1],
   1495 							mode,
   1496 							(reload_in_progress ?
   1497 							 operands[0] :
   1498 							 NULL_RTX));
   1499 	  return false;
   1500 	}
   1501     }
   1502 
   1503   /* Fixup for UNSPEC addresses.  */
   1504   if (flag_pic
   1505       && GET_CODE (operands[1]) == HIGH
   1506       && GET_CODE (XEXP (operands[1], 0)) == CONST
   1507       && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == UNSPEC)
   1508     {
   1509       rtx unspec = XEXP (XEXP (operands[1], 0), 0);
   1510       int unspec_num = XINT (unspec, 1);
   1511       if (unspec_num == UNSPEC_PCREL_SYM)
   1512 	{
   1513 	  emit_insn (gen_auli_pcrel (operands[0], const0_rtx,
   1514 				     XVECEXP (unspec, 0, 0),
   1515 				     XVECEXP (unspec, 0, 1)));
   1516 	  return true;
   1517 	}
   1518       else if (flag_pic == 2 && unspec_num == UNSPEC_GOT32_SYM)
   1519 	{
   1520 	  emit_insn (gen_addhi_got32 (operands[0], const0_rtx,
   1521 				      XVECEXP (unspec, 0, 0)));
   1522 	  return true;
   1523 	}
   1524       else if (HAVE_AS_TLS && unspec_num == UNSPEC_TLS_GD)
   1525 	{
   1526 	  emit_insn (gen_tls_gd_addhi (operands[0], const0_rtx,
   1527 				       XVECEXP (unspec, 0, 0)));
   1528 	  return true;
   1529 	}
   1530       else if (HAVE_AS_TLS && unspec_num == UNSPEC_TLS_IE)
   1531 	{
   1532 	  emit_insn (gen_tls_ie_addhi (operands[0], const0_rtx,
   1533 				       XVECEXP (unspec, 0, 0)));
   1534 	  return true;
   1535 	}
   1536       else if (HAVE_AS_TLS && unspec_num == UNSPEC_TLS_LE)
   1537 	{
   1538 	  emit_insn (gen_tls_le_addhi (operands[0], const0_rtx,
   1539 				       XVECEXP (unspec, 0, 0)));
   1540 	  return true;
   1541 	}
   1542     }
   1543 
   1544   /* Accept non-constants and valid constants unmodified.  */
   1545   if (!CONSTANT_P (operands[1])
   1546       || GET_CODE (operands[1]) == HIGH || move_operand (operands[1], mode))
   1547     return false;
   1548 
   1549   /* Split large integers.  */
   1550   if (GET_MODE_SIZE (mode) <= 4)
   1551     {
   1552       tilepro_expand_set_const32 (operands[0], operands[1]);
   1553       return true;
   1554     }
   1555 
   1556   return false;
   1557 }
   1558 
   1559 
   1560 /* Expand the "insv" pattern.  */
   1561 void
   1562 tilepro_expand_insv (rtx operands[4])
   1563 {
   1564   rtx first_rtx = operands[2];
   1565   HOST_WIDE_INT first = INTVAL (first_rtx);
   1566   HOST_WIDE_INT width = INTVAL (operands[1]);
   1567   rtx v = operands[3];
   1568 
   1569   /* Shift the inserted bits into position.  */
   1570   if (first != 0)
   1571     {
   1572       if (CONST_INT_P (v))
   1573 	{
   1574 	  /* Shift the constant into mm position.  */
   1575 	  v = gen_int_si (INTVAL (v) << first);
   1576 	}
   1577       else
   1578 	{
   1579 	  /* Shift over the value to be inserted.  */
   1580 	  rtx tmp = gen_reg_rtx (SImode);
   1581 	  emit_insn (gen_ashlsi3 (tmp, v, first_rtx));
   1582 	  v = tmp;
   1583 	}
   1584     }
   1585 
   1586   /* Insert the shifted bits using an 'mm' insn.  */
   1587   emit_insn (gen_insn_mm (operands[0], v, operands[0], first_rtx,
   1588 			  GEN_INT (first + width - 1)));
   1589 }
   1590 
   1591 
   1592 /* Expand unaligned loads.  */
   1593 void
   1594 tilepro_expand_unaligned_load (rtx dest_reg, rtx mem, HOST_WIDE_INT bitsize,
   1595 			       HOST_WIDE_INT bit_offset, bool sign)
   1596 {
   1597   machine_mode mode;
   1598   rtx addr_lo, addr_hi;
   1599   rtx mem_lo, mem_hi, hi;
   1600   rtx mema, wide_result;
   1601   int last_byte_offset;
   1602   HOST_WIDE_INT byte_offset = bit_offset / BITS_PER_UNIT;
   1603 
   1604   mode = GET_MODE (dest_reg);
   1605 
   1606   hi = gen_reg_rtx (mode);
   1607 
   1608   if (bitsize == 2 * BITS_PER_UNIT && (bit_offset % BITS_PER_UNIT) == 0)
   1609     {
   1610       rtx lo;
   1611 
   1612       /* When just loading a two byte value, we can load the two bytes
   1613          individually and combine them efficiently.  */
   1614 
   1615       mem_lo = adjust_address (mem, QImode, byte_offset);
   1616       mem_hi = adjust_address (mem, QImode, byte_offset + 1);
   1617 
   1618       lo = gen_reg_rtx (mode);
   1619       emit_insn (gen_zero_extendqisi2 (lo, mem_lo));
   1620 
   1621       if (sign)
   1622 	{
   1623 	  rtx tmp = gen_reg_rtx (mode);
   1624 
   1625 	  /* Do a signed load of the second byte then shift and OR it
   1626 	     in.  */
   1627 	  emit_insn (gen_extendqisi2 (gen_lowpart (SImode, hi), mem_hi));
   1628 	  emit_insn (gen_ashlsi3 (gen_lowpart (SImode, tmp),
   1629 				  gen_lowpart (SImode, hi), GEN_INT (8)));
   1630 	  emit_insn (gen_iorsi3 (gen_lowpart (SImode, dest_reg),
   1631 				 gen_lowpart (SImode, lo),
   1632 				 gen_lowpart (SImode, tmp)));
   1633 	}
   1634       else
   1635 	{
   1636 	  /* Do two unsigned loads and use intlb to interleave
   1637 	     them.  */
   1638 	  emit_insn (gen_zero_extendqisi2 (gen_lowpart (SImode, hi), mem_hi));
   1639 	  emit_insn (gen_insn_intlb (gen_lowpart (SImode, dest_reg),
   1640 				     gen_lowpart (SImode, hi),
   1641 				     gen_lowpart (SImode, lo)));
   1642 	}
   1643 
   1644       return;
   1645     }
   1646 
   1647   mema = XEXP (mem, 0);
   1648 
   1649   /* AND addresses cannot be in any alias set, since they may
   1650      implicitly alias surrounding code.  Ideally we'd have some alias
   1651      set that covered all types except those with alignment 8 or
   1652      higher.  */
   1653   addr_lo = force_reg (Pmode, plus_constant (Pmode, mema, byte_offset));
   1654   mem_lo = change_address (mem, mode,
   1655 			   gen_rtx_AND (Pmode, addr_lo, GEN_INT (-4)));
   1656   set_mem_alias_set (mem_lo, 0);
   1657 
   1658   /* Load the high word at an address that will not fault if the low
   1659      address is aligned and at the very end of a page.  */
   1660   last_byte_offset = (bit_offset + bitsize - 1) / BITS_PER_UNIT;
   1661   addr_hi = force_reg (Pmode, plus_constant (Pmode, mema, last_byte_offset));
   1662   mem_hi = change_address (mem, mode,
   1663 			   gen_rtx_AND (Pmode, addr_hi, GEN_INT (-4)));
   1664   set_mem_alias_set (mem_hi, 0);
   1665 
   1666   if (bitsize == 32)
   1667     {
   1668       addr_lo = make_safe_from (addr_lo, dest_reg);
   1669       wide_result = dest_reg;
   1670     }
   1671   else
   1672     {
   1673       wide_result = gen_reg_rtx (mode);
   1674     }
   1675 
   1676   /* Load hi first in case dest_reg is used in mema.  */
   1677   emit_move_insn (hi, mem_hi);
   1678   emit_move_insn (wide_result, mem_lo);
   1679 
   1680   emit_insn (gen_insn_dword_align (gen_lowpart (SImode, wide_result),
   1681 				   gen_lowpart (SImode, wide_result),
   1682 				   gen_lowpart (SImode, hi), addr_lo));
   1683 
   1684   if (bitsize != 32)
   1685     {
   1686       rtx extracted =
   1687 	extract_bit_field (gen_lowpart (SImode, wide_result),
   1688 			   bitsize, bit_offset % BITS_PER_UNIT,
   1689 			   !sign, gen_lowpart (SImode, dest_reg),
   1690 			   SImode, SImode, false, NULL);
   1691 
   1692       if (extracted != dest_reg)
   1693 	emit_move_insn (dest_reg, gen_lowpart (SImode, extracted));
   1694     }
   1695 }
   1696 
   1697 
   1698 /* Expand unaligned stores.  */
   1699 static void
   1700 tilepro_expand_unaligned_store (rtx mem, rtx src, HOST_WIDE_INT bitsize,
   1701 				HOST_WIDE_INT bit_offset)
   1702 {
   1703   HOST_WIDE_INT byte_offset = bit_offset / BITS_PER_UNIT;
   1704   HOST_WIDE_INT bytesize = bitsize / BITS_PER_UNIT;
   1705   HOST_WIDE_INT shift_amt;
   1706   HOST_WIDE_INT i;
   1707   rtx mem_addr;
   1708   rtx store_val;
   1709 
   1710   for (i = 0, shift_amt = 0; i < bytesize; i++, shift_amt += BITS_PER_UNIT)
   1711     {
   1712       mem_addr = adjust_address (mem, QImode, byte_offset + i);
   1713 
   1714       if (shift_amt)
   1715 	{
   1716 	  store_val = expand_simple_binop (SImode, LSHIFTRT,
   1717 					   gen_lowpart (SImode, src),
   1718 					   GEN_INT (shift_amt), NULL, 1,
   1719 					   OPTAB_LIB_WIDEN);
   1720 	  store_val = gen_lowpart (QImode, store_val);
   1721 	}
   1722       else
   1723 	{
   1724 	  store_val = gen_lowpart (QImode, src);
   1725 	}
   1726 
   1727       emit_move_insn (mem_addr, store_val);
   1728     }
   1729 }
   1730 
   1731 
   1732 /* Implement the movmisalign patterns.  One of the operands is a
   1733    memory that is not naturally aligned.  Emit instructions to load
   1734    it.  */
   1735 void
   1736 tilepro_expand_movmisalign (machine_mode mode, rtx *operands)
   1737 {
   1738   if (MEM_P (operands[1]))
   1739     {
   1740       rtx tmp;
   1741 
   1742       if (register_operand (operands[0], mode))
   1743 	tmp = operands[0];
   1744       else
   1745 	tmp = gen_reg_rtx (mode);
   1746 
   1747       tilepro_expand_unaligned_load (tmp, operands[1],
   1748 				     GET_MODE_BITSIZE (mode), 0, true);
   1749 
   1750       if (tmp != operands[0])
   1751 	emit_move_insn (operands[0], tmp);
   1752     }
   1753   else if (MEM_P (operands[0]))
   1754     {
   1755       if (!reg_or_0_operand (operands[1], mode))
   1756 	operands[1] = force_reg (mode, operands[1]);
   1757 
   1758       tilepro_expand_unaligned_store (operands[0], operands[1],
   1759 				      GET_MODE_BITSIZE (mode), 0);
   1760     }
   1761   else
   1762     gcc_unreachable ();
   1763 }
   1764 
   1765 
   1766 /* Implement the addsi3 pattern.  */
   1767 bool
   1768 tilepro_expand_addsi (rtx op0, rtx op1, rtx op2)
   1769 {
   1770   rtx temp;
   1771   HOST_WIDE_INT n;
   1772   HOST_WIDE_INT high;
   1773 
   1774   /* Skip anything that only takes one instruction.  */
   1775   if (add_operand (op2, SImode))
   1776     return false;
   1777 
   1778   /* We can only optimize ints here (it should be impossible to get
   1779      here with any other type, but it is harmless to check.  */
   1780   if (!CONST_INT_P (op2))
   1781     return false;
   1782 
   1783   temp = create_temp_reg_if_possible (SImode, op0);
   1784   n = INTVAL (op2);
   1785   high = (n + (n & 0x8000)) & ~0xffff;
   1786 
   1787   emit_move_insn (temp, gen_rtx_PLUS (SImode, op1, gen_int_si (high)));
   1788   emit_move_insn (op0, gen_rtx_PLUS (SImode, temp, gen_int_si (n - high)));
   1789 
   1790   return true;
   1791 }
   1792 
   1793 
   1794 /* Implement the allocate_stack pattern (alloca).  */
   1795 void
   1796 tilepro_allocate_stack (rtx op0, rtx op1)
   1797 {
   1798   /* Technically the correct way to initialize chain_loc is with
   1799    * gen_frame_mem() instead of gen_rtx_MEM(), but gen_frame_mem()
   1800    * sets the alias_set to that of a frame reference.  Some of our
   1801    * tests rely on some unsafe assumption about when the chaining
   1802    * update is done, we need to be conservative about reordering the
   1803    * chaining instructions.
   1804    */
   1805   rtx fp_addr = gen_reg_rtx (Pmode);
   1806   rtx fp_value = gen_reg_rtx (Pmode);
   1807   rtx fp_loc;
   1808 
   1809   emit_move_insn (fp_addr, gen_rtx_PLUS (Pmode, stack_pointer_rtx,
   1810 					 GEN_INT (UNITS_PER_WORD)));
   1811 
   1812   fp_loc = gen_frame_mem (Pmode, fp_addr);
   1813 
   1814   emit_move_insn (fp_value, fp_loc);
   1815 
   1816   op1 = force_reg (Pmode, op1);
   1817 
   1818   emit_move_insn (stack_pointer_rtx,
   1819 		  gen_rtx_MINUS (Pmode, stack_pointer_rtx, op1));
   1820 
   1821   emit_move_insn (fp_addr, gen_rtx_PLUS (Pmode, stack_pointer_rtx,
   1822 					 GEN_INT (UNITS_PER_WORD)));
   1823 
   1824   fp_loc = gen_frame_mem (Pmode, fp_addr);
   1825 
   1826   emit_move_insn (fp_loc, fp_value);
   1827 
   1828   emit_move_insn (op0, virtual_stack_dynamic_rtx);
   1829 }
   1830 
   1831 
   1833 
   1834 /* Multiplies */
   1835 
   1836 /* Returns the insn_code in ENTRY.  */
   1837 static enum insn_code
   1838 tilepro_multiply_get_opcode (const struct tilepro_multiply_insn_seq_entry
   1839 			     *entry)
   1840 {
   1841   return tilepro_multiply_insn_seq_decode_opcode[entry->compressed_opcode];
   1842 }
   1843 
   1844 
   1845 /* Returns the length of the 'op' array.  */
   1846 static int
   1847 tilepro_multiply_get_num_ops (const struct tilepro_multiply_insn_seq *seq)
   1848 {
   1849   /* The array either uses all of its allocated slots or is terminated
   1850      by a bogus opcode. Either way, the array size is the index of the
   1851      last valid opcode plus one.  */
   1852   int i;
   1853   for (i = tilepro_multiply_insn_seq_MAX_OPERATIONS - 1; i >= 0; i--)
   1854     if (tilepro_multiply_get_opcode (&seq->op[i]) != CODE_FOR_nothing)
   1855       return i + 1;
   1856 
   1857   /* An empty array is not allowed.  */
   1858   gcc_unreachable ();
   1859 }
   1860 
   1861 
   1862 /* We precompute a number of expression trees for multiplying by
   1863    constants.  This generates code for such an expression tree by
   1864    walking through the nodes in the tree (which are conveniently
   1865    pre-linearized) and emitting an instruction for each one.  */
   1866 static void
   1867 tilepro_expand_constant_multiply_given_sequence (rtx result, rtx src,
   1868 						 const struct
   1869 						 tilepro_multiply_insn_seq
   1870 						 *seq)
   1871 {
   1872   int i;
   1873   int num_ops;
   1874 
   1875   /* Keep track of the subexpressions computed so far, so later
   1876      instructions can refer to them.  We seed the array with zero and
   1877      the value being multiplied.  */
   1878   int num_subexprs = 2;
   1879   rtx subexprs[tilepro_multiply_insn_seq_MAX_OPERATIONS + 2];
   1880   subexprs[0] = const0_rtx;
   1881   subexprs[1] = src;
   1882 
   1883   /* Determine how many instructions we are going to generate.  */
   1884   num_ops = tilepro_multiply_get_num_ops (seq);
   1885   gcc_assert (num_ops > 0
   1886 	      && num_ops <= tilepro_multiply_insn_seq_MAX_OPERATIONS);
   1887 
   1888   for (i = 0; i < num_ops; i++)
   1889     {
   1890       const struct tilepro_multiply_insn_seq_entry *entry = &seq->op[i];
   1891 
   1892       /* Figure out where to store the output of this instruction.  */
   1893       const bool is_last_op = (i + 1 == num_ops);
   1894       rtx out = is_last_op ? result : gen_reg_rtx (SImode);
   1895 
   1896       enum insn_code opcode = tilepro_multiply_get_opcode (entry);
   1897       if (opcode == CODE_FOR_ashlsi3)
   1898 	{
   1899 	  /* Handle shift by immediate. This is a special case because
   1900 	     the meaning of the second operand is a constant shift
   1901 	     count rather than an operand index.  */
   1902 
   1903 	  /* Make sure the shift count is in range. Zero should not
   1904 	     happen.  */
   1905 	  const int shift_count = entry->rhs;
   1906 	  gcc_assert (shift_count > 0 && shift_count < 32);
   1907 
   1908 	  /* Emit the actual instruction.  */
   1909 	  emit_insn (GEN_FCN (opcode)
   1910 		     (out, subexprs[entry->lhs],
   1911 		      gen_rtx_CONST_INT (SImode, shift_count)));
   1912 	}
   1913       else
   1914 	{
   1915 	  /* Handle a normal two-operand instruction, such as add or
   1916 	     s1a.  */
   1917 
   1918 	  /* Make sure we are referring to a previously computed
   1919 	     subexpression.  */
   1920 	  gcc_assert (entry->rhs < num_subexprs);
   1921 
   1922 	  /* Emit the actual instruction.  */
   1923 	  emit_insn (GEN_FCN (opcode)
   1924 		     (out, subexprs[entry->lhs], subexprs[entry->rhs]));
   1925 	}
   1926 
   1927       /* Record this subexpression for use by later expressions.  */
   1928       subexprs[num_subexprs++] = out;
   1929     }
   1930 }
   1931 
   1932 
   1933 /* bsearch helper function.  */
   1934 static int
   1935 tilepro_compare_multipliers (const void *key, const void *t)
   1936 {
   1937   return *(const int *) key -
   1938     ((const struct tilepro_multiply_insn_seq *) t)->multiplier;
   1939 }
   1940 
   1941 
   1942 /* Returns the tilepro_multiply_insn_seq for multiplier, or NULL if
   1943    none exists.  */
   1944 static const struct tilepro_multiply_insn_seq *
   1945 tilepro_find_multiply_insn_seq_for_constant (int multiplier)
   1946 {
   1947   return ((const struct tilepro_multiply_insn_seq *)
   1948 	  bsearch (&multiplier, tilepro_multiply_insn_seq_table,
   1949 		   tilepro_multiply_insn_seq_table_size,
   1950 		   sizeof tilepro_multiply_insn_seq_table[0],
   1951 		   tilepro_compare_multipliers));
   1952 }
   1953 
   1954 
   1955 /* Try to a expand constant multiply in SImode by looking it up in a
   1956    precompiled table.  OP0 is the result operand, OP1 is the source
   1957    operand, and MULTIPLIER is the value of the constant.  Return true
   1958    if it succeeds.  */
   1959 static bool
   1960 tilepro_expand_const_mulsi (rtx op0, rtx op1, int multiplier)
   1961 {
   1962   /* See if we have precomputed an efficient way to multiply by this
   1963      constant.  */
   1964   const struct tilepro_multiply_insn_seq *seq =
   1965     tilepro_find_multiply_insn_seq_for_constant (multiplier);
   1966   if (seq != NULL)
   1967     {
   1968       tilepro_expand_constant_multiply_given_sequence (op0, op1, seq);
   1969       return true;
   1970     }
   1971   else
   1972     return false;
   1973 }
   1974 
   1975 
   1976 /* Expand the mulsi pattern.  */
   1977 bool
   1978 tilepro_expand_mulsi (rtx op0, rtx op1, rtx op2)
   1979 {
   1980   if (CONST_INT_P (op2))
   1981     {
   1982       HOST_WIDE_INT n = trunc_int_for_mode (INTVAL (op2), SImode);
   1983       return tilepro_expand_const_mulsi (op0, op1, n);
   1984     }
   1985   return false;
   1986 }
   1987 
   1988 
   1989 /* Expand a high multiply pattern in SImode.  RESULT, OP1, OP2 are the
   1990    operands, and SIGN is true if it's a signed multiply, and false if
   1991    it's an unsigned multiply.  */
   1992 static void
   1993 tilepro_expand_high_multiply (rtx result, rtx op1, rtx op2, bool sign)
   1994 {
   1995   rtx tmp0 = gen_reg_rtx (SImode);
   1996   rtx tmp1 = gen_reg_rtx (SImode);
   1997   rtx tmp2 = gen_reg_rtx (SImode);
   1998   rtx tmp3 = gen_reg_rtx (SImode);
   1999   rtx tmp4 = gen_reg_rtx (SImode);
   2000   rtx tmp5 = gen_reg_rtx (SImode);
   2001   rtx tmp6 = gen_reg_rtx (SImode);
   2002   rtx tmp7 = gen_reg_rtx (SImode);
   2003   rtx tmp8 = gen_reg_rtx (SImode);
   2004   rtx tmp9 = gen_reg_rtx (SImode);
   2005   rtx tmp10 = gen_reg_rtx (SImode);
   2006   rtx tmp11 = gen_reg_rtx (SImode);
   2007   rtx tmp12 = gen_reg_rtx (SImode);
   2008   rtx tmp13 = gen_reg_rtx (SImode);
   2009   rtx result_lo = gen_reg_rtx (SImode);
   2010 
   2011   if (sign)
   2012     {
   2013       emit_insn (gen_insn_mulhl_su (tmp0, op1, op2));
   2014       emit_insn (gen_insn_mulhl_su (tmp1, op2, op1));
   2015       emit_insn (gen_insn_mulll_uu (tmp2, op1, op2));
   2016       emit_insn (gen_insn_mulhh_ss (tmp3, op1, op2));
   2017     }
   2018   else
   2019     {
   2020       emit_insn (gen_insn_mulhl_uu (tmp0, op1, op2));
   2021       emit_insn (gen_insn_mulhl_uu (tmp1, op2, op1));
   2022       emit_insn (gen_insn_mulll_uu (tmp2, op1, op2));
   2023       emit_insn (gen_insn_mulhh_uu (tmp3, op1, op2));
   2024     }
   2025 
   2026   emit_move_insn (tmp4, (gen_rtx_ASHIFT (SImode, tmp0, GEN_INT (16))));
   2027 
   2028   emit_move_insn (tmp5, (gen_rtx_ASHIFT (SImode, tmp1, GEN_INT (16))));
   2029 
   2030   emit_move_insn (tmp6, (gen_rtx_PLUS (SImode, tmp4, tmp5)));
   2031   emit_move_insn (result_lo, (gen_rtx_PLUS (SImode, tmp2, tmp6)));
   2032 
   2033   emit_move_insn (tmp7, gen_rtx_LTU (SImode, tmp6, tmp4));
   2034   emit_move_insn (tmp8, gen_rtx_LTU (SImode, result_lo, tmp2));
   2035 
   2036   if (sign)
   2037     {
   2038       emit_move_insn (tmp9, (gen_rtx_ASHIFTRT (SImode, tmp0, GEN_INT (16))));
   2039       emit_move_insn (tmp10, (gen_rtx_ASHIFTRT (SImode, tmp1, GEN_INT (16))));
   2040     }
   2041   else
   2042     {
   2043       emit_move_insn (tmp9, (gen_rtx_LSHIFTRT (SImode, tmp0, GEN_INT (16))));
   2044       emit_move_insn (tmp10, (gen_rtx_LSHIFTRT (SImode, tmp1, GEN_INT (16))));
   2045     }
   2046 
   2047   emit_move_insn (tmp11, (gen_rtx_PLUS (SImode, tmp3, tmp7)));
   2048   emit_move_insn (tmp12, (gen_rtx_PLUS (SImode, tmp8, tmp9)));
   2049   emit_move_insn (tmp13, (gen_rtx_PLUS (SImode, tmp11, tmp12)));
   2050   emit_move_insn (result, (gen_rtx_PLUS (SImode, tmp13, tmp10)));
   2051 }
   2052 
   2053 
   2054 /* Implement smulsi3_highpart.  */
   2055 void
   2056 tilepro_expand_smulsi3_highpart (rtx op0, rtx op1, rtx op2)
   2057 {
   2058   tilepro_expand_high_multiply (op0, op1, op2, true);
   2059 }
   2060 
   2061 
   2062 /* Implement umulsi3_highpart.  */
   2063 void
   2064 tilepro_expand_umulsi3_highpart (rtx op0, rtx op1, rtx op2)
   2065 {
   2066   tilepro_expand_high_multiply (op0, op1, op2, false);
   2067 }
   2068 
   2069 
   2071 
   2072 /* Compare and branches  */
   2073 
   2074 /* Helper function to handle DImode for tilepro_emit_setcc_internal.  */
   2075 static bool
   2076 tilepro_emit_setcc_internal_di (rtx res, enum rtx_code code, rtx op0, rtx op1)
   2077 {
   2078   rtx operands[2], lo_half[2], hi_half[2];
   2079   rtx tmp, tmp0, tmp1, tmp2;
   2080   bool swap = false;
   2081 
   2082   /* Reduce the number of cases we need to handle by reversing the
   2083      operands.  */
   2084   switch (code)
   2085     {
   2086     case EQ:
   2087     case NE:
   2088     case LE:
   2089     case LT:
   2090     case LEU:
   2091     case LTU:
   2092       /* We handle these compares directly.  */
   2093       break;
   2094 
   2095     case GE:
   2096     case GT:
   2097     case GEU:
   2098     case GTU:
   2099       /* Reverse the operands.  */
   2100       swap = true;
   2101       break;
   2102 
   2103     default:
   2104       /* We should not have called this with any other code.  */
   2105       gcc_unreachable ();
   2106     }
   2107 
   2108   if (swap)
   2109     {
   2110       code = swap_condition (code);
   2111       tmp = op0, op0 = op1, op1 = tmp;
   2112     }
   2113 
   2114   operands[0] = op0;
   2115   operands[1] = op1;
   2116 
   2117   split_di (operands, 2, lo_half, hi_half);
   2118 
   2119   if (!reg_or_0_operand (lo_half[0], SImode))
   2120     lo_half[0] = force_reg (SImode, lo_half[0]);
   2121 
   2122   if (!reg_or_0_operand (hi_half[0], SImode))
   2123     hi_half[0] = force_reg (SImode, hi_half[0]);
   2124 
   2125   if (!CONST_INT_P (lo_half[1]) && !register_operand (lo_half[1], SImode))
   2126     lo_half[1] = force_reg (SImode, lo_half[1]);
   2127 
   2128   if (!CONST_INT_P (hi_half[1]) && !register_operand (hi_half[1], SImode))
   2129     hi_half[1] = force_reg (SImode, hi_half[1]);
   2130 
   2131   tmp0 = gen_reg_rtx (SImode);
   2132   tmp1 = gen_reg_rtx (SImode);
   2133   tmp2 = gen_reg_rtx (SImode);
   2134 
   2135   switch (code)
   2136     {
   2137     case EQ:
   2138       emit_insn (gen_insn_seq (tmp0, lo_half[0], lo_half[1]));
   2139       emit_insn (gen_insn_seq (tmp1, hi_half[0], hi_half[1]));
   2140       emit_insn (gen_andsi3 (res, tmp0, tmp1));
   2141       return true;
   2142     case NE:
   2143       emit_insn (gen_insn_sne (tmp0, lo_half[0], lo_half[1]));
   2144       emit_insn (gen_insn_sne (tmp1, hi_half[0], hi_half[1]));
   2145       emit_insn (gen_iorsi3 (res, tmp0, tmp1));
   2146       return true;
   2147     case LE:
   2148       emit_insn (gen_insn_slte (tmp0, hi_half[0], hi_half[1]));
   2149       emit_insn (gen_insn_seq (tmp1, hi_half[0], hi_half[1]));
   2150       emit_insn (gen_insn_slte_u (tmp2, lo_half[0], lo_half[1]));
   2151       emit_insn (gen_insn_mvnz (res, tmp0, tmp1, tmp2));
   2152       return true;
   2153     case LT:
   2154       if (operands[1] == const0_rtx)
   2155 	{
   2156 	  emit_insn (gen_lshrsi3 (res, hi_half[0], GEN_INT (31)));
   2157 	  return true;
   2158 	}
   2159       else
   2160 	{
   2161 	  emit_insn (gen_insn_slt (tmp0, hi_half[0], hi_half[1]));
   2162 	  emit_insn (gen_insn_seq (tmp1, hi_half[0], hi_half[1]));
   2163 	  emit_insn (gen_insn_slt_u (tmp2, lo_half[0], lo_half[1]));
   2164 	  emit_insn (gen_insn_mvnz (res, tmp0, tmp1, tmp2));
   2165 	}
   2166       return true;
   2167     case LEU:
   2168       emit_insn (gen_insn_slte_u (tmp0, hi_half[0], hi_half[1]));
   2169       emit_insn (gen_insn_seq (tmp1, hi_half[0], hi_half[1]));
   2170       emit_insn (gen_insn_slte_u (tmp2, lo_half[0], lo_half[1]));
   2171       emit_insn (gen_insn_mvnz (res, tmp0, tmp1, tmp2));
   2172       return true;
   2173     case LTU:
   2174       emit_insn (gen_insn_slt_u (tmp0, hi_half[0], hi_half[1]));
   2175       emit_insn (gen_insn_seq (tmp1, hi_half[0], hi_half[1]));
   2176       emit_insn (gen_insn_slt_u (tmp2, lo_half[0], lo_half[1]));
   2177       emit_insn (gen_insn_mvnz (res, tmp0, tmp1, tmp2));
   2178       return true;
   2179     default:
   2180       gcc_unreachable ();
   2181     }
   2182 
   2183   return false;
   2184 }
   2185 
   2186 
   2187 /* Certain simplifications can be done to make invalid setcc
   2188    operations valid.  Return the final comparison, or NULL if we can't
   2189    work.  */
   2190 static bool
   2191 tilepro_emit_setcc_internal (rtx res, enum rtx_code code, rtx op0, rtx op1,
   2192 			     machine_mode cmp_mode)
   2193 {
   2194   rtx tmp;
   2195   bool swap = false;
   2196 
   2197   if (cmp_mode == DImode)
   2198     {
   2199       return tilepro_emit_setcc_internal_di (res, code, op0, op1);
   2200     }
   2201 
   2202   /* The general case: fold the comparison code to the types of
   2203      compares that we have, choosing the branch as necessary.  */
   2204 
   2205   switch (code)
   2206     {
   2207     case EQ:
   2208     case NE:
   2209     case LE:
   2210     case LT:
   2211     case LEU:
   2212     case LTU:
   2213       /* We have these compares.  */
   2214       break;
   2215 
   2216     case GE:
   2217     case GT:
   2218     case GEU:
   2219     case GTU:
   2220       /* We do not have these compares, so we reverse the
   2221          operands.  */
   2222       swap = true;
   2223       break;
   2224 
   2225     default:
   2226       /* We should not have called this with any other code.  */
   2227       gcc_unreachable ();
   2228     }
   2229 
   2230   if (swap)
   2231     {
   2232       code = swap_condition (code);
   2233       tmp = op0, op0 = op1, op1 = tmp;
   2234     }
   2235 
   2236   if (!reg_or_0_operand (op0, SImode))
   2237     op0 = force_reg (SImode, op0);
   2238 
   2239   if (!CONST_INT_P (op1) && !register_operand (op1, SImode))
   2240     op1 = force_reg (SImode, op1);
   2241 
   2242   /* Return the setcc comparison.  */
   2243   emit_insn (gen_rtx_SET (res, gen_rtx_fmt_ee (code, SImode, op0, op1)));
   2244 
   2245   return true;
   2246 }
   2247 
   2248 
   2249 /* Implement cstore patterns.  */
   2250 bool
   2251 tilepro_emit_setcc (rtx operands[], machine_mode cmp_mode)
   2252 {
   2253   return
   2254     tilepro_emit_setcc_internal (operands[0], GET_CODE (operands[1]),
   2255 				 operands[2], operands[3], cmp_mode);
   2256 }
   2257 
   2258 
   2259 /* Return whether CODE is a signed comparison.  */
   2260 static bool
   2261 signed_compare_p (enum rtx_code code)
   2262 {
   2263   return (code == EQ || code == NE || code == LT || code == LE
   2264 	  || code == GT || code == GE);
   2265 }
   2266 
   2267 
   2268 /* Generate the comparison for an SImode conditional branch.  */
   2269 static rtx
   2270 tilepro_emit_cc_test (enum rtx_code code, rtx op0, rtx op1,
   2271 		      machine_mode cmp_mode, bool eq_ne_only)
   2272 {
   2273   enum rtx_code branch_code;
   2274   rtx temp;
   2275 
   2276   /* Check for a compare against zero using a comparison we can do
   2277      directly.  */
   2278   if (cmp_mode != DImode
   2279       && op1 == const0_rtx
   2280       && (code == EQ || code == NE
   2281 	  || (!eq_ne_only && signed_compare_p (code))))
   2282     {
   2283       op0 = force_reg (SImode, op0);
   2284       return gen_rtx_fmt_ee (code, VOIDmode, op0, const0_rtx);
   2285     }
   2286 
   2287   /* The general case: fold the comparison code to the types of
   2288      compares that we have, choosing the branch as necessary.  */
   2289   switch (code)
   2290     {
   2291     case EQ:
   2292     case LE:
   2293     case LT:
   2294     case LEU:
   2295     case LTU:
   2296       /* We have these compares.  */
   2297       branch_code = NE;
   2298       break;
   2299 
   2300     case NE:
   2301     case GE:
   2302     case GT:
   2303     case GEU:
   2304     case GTU:
   2305       /* These must be reversed (except NE, but let's
   2306          canonicalize).  */
   2307       code = reverse_condition (code);
   2308       branch_code = EQ;
   2309       break;
   2310 
   2311     default:
   2312       gcc_unreachable ();
   2313     }
   2314 
   2315   if (cmp_mode != DImode
   2316       && CONST_INT_P (op1) && (!satisfies_constraint_I (op1) || code == LEU))
   2317     {
   2318       HOST_WIDE_INT n = trunc_int_for_mode (INTVAL (op1), SImode);
   2319 
   2320       switch (code)
   2321 	{
   2322 	case EQ:
   2323 	  /* Subtract off the value we want to compare against and see
   2324 	     if we get zero.  This is cheaper than creating a constant
   2325 	     in a register. Except that subtracting -128 is more
   2326 	     expensive than seqi to -128, so we leave that alone.  */
   2327 	  /* ??? Don't do this when comparing against symbols,
   2328 	     otherwise we'll reduce (&x == 0x1234) to (&x-0x1234 ==
   2329 	     0), which will be declared false out of hand (at least
   2330 	     for non-weak).  */
   2331 	  if (!(symbolic_operand (op0, VOIDmode)
   2332 		|| (REG_P (op0) && REG_POINTER (op0))))
   2333 	    {
   2334 	      /* To compare against MIN_INT, we add MIN_INT and check
   2335 	         for 0.  */
   2336 	      HOST_WIDE_INT add;
   2337 	      if (n != -2147483647 - 1)
   2338 		add = -n;
   2339 	      else
   2340 		add = n;
   2341 
   2342 	      op0 = force_reg (SImode, op0);
   2343 	      temp = gen_reg_rtx (SImode);
   2344 	      emit_insn (gen_addsi3 (temp, op0, gen_int_si (add)));
   2345 	      return gen_rtx_fmt_ee (reverse_condition (branch_code),
   2346 				     VOIDmode, temp, const0_rtx);
   2347 	    }
   2348 	  break;
   2349 
   2350 	case LEU:
   2351 	  if (n == -1)
   2352 	    break;
   2353 	  /* FALLTHRU */
   2354 
   2355 	case LTU:
   2356 	  /* Change ((unsigned)x < 0x1000) into !((unsigned)x >> 12),
   2357 	     etc.  */
   2358 	  {
   2359 	    int first = exact_log2 (code == LTU ? n : n + 1);
   2360 	    if (first != -1)
   2361 	      {
   2362 		op0 = force_reg (SImode, op0);
   2363 		temp = gen_reg_rtx (SImode);
   2364 		emit_move_insn (temp,
   2365 				gen_rtx_LSHIFTRT (SImode, op0,
   2366 						  gen_int_si (first)));
   2367 		return gen_rtx_fmt_ee (reverse_condition (branch_code),
   2368 				       VOIDmode, temp, const0_rtx);
   2369 	      }
   2370 	  }
   2371 	  break;
   2372 
   2373 	default:
   2374 	  break;
   2375 	}
   2376     }
   2377 
   2378   /* Compute a flag saying whether we should branch.  */
   2379   temp = gen_reg_rtx (SImode);
   2380   tilepro_emit_setcc_internal (temp, code, op0, op1, cmp_mode);
   2381 
   2382   /* Return the branch comparison.  */
   2383   return gen_rtx_fmt_ee (branch_code, VOIDmode, temp, const0_rtx);
   2384 }
   2385 
   2386 
   2387 /* Generate the comparison for a conditional branch.  */
   2388 void
   2389 tilepro_emit_conditional_branch (rtx operands[], machine_mode cmp_mode)
   2390 {
   2391   rtx cmp_rtx =
   2392     tilepro_emit_cc_test (GET_CODE (operands[0]), operands[1], operands[2],
   2393 			  cmp_mode, false);
   2394   rtx branch_rtx = gen_rtx_SET (pc_rtx,
   2395 				gen_rtx_IF_THEN_ELSE (VOIDmode, cmp_rtx,
   2396 						      gen_rtx_LABEL_REF
   2397 						      (VOIDmode,
   2398 						       operands[3]),
   2399 						      pc_rtx));
   2400   emit_jump_insn (branch_rtx);
   2401 }
   2402 
   2403 
   2404 /* Implement the movsicc pattern.  */
   2405 rtx
   2406 tilepro_emit_conditional_move (rtx cmp)
   2407 {
   2408   return
   2409     tilepro_emit_cc_test (GET_CODE (cmp), XEXP (cmp, 0), XEXP (cmp, 1),
   2410 			  GET_MODE (XEXP (cmp, 0)), true);
   2411 }
   2412 
   2413 
   2414 /* Return true if INSN is annotated with a REG_BR_PROB note that
   2415    indicates it's a branch that's predicted taken.  */
   2416 static bool
   2417 cbranch_predicted_p (rtx_insn *insn)
   2418 {
   2419   rtx x = find_reg_note (insn, REG_BR_PROB, 0);
   2420 
   2421   if (x)
   2422     {
   2423       return profile_probability::from_reg_br_prob_note (XINT (x, 0))
   2424 	     >= profile_probability::even ();
   2425     }
   2426 
   2427   return false;
   2428 }
   2429 
   2430 
   2431 /* Output assembly code for a specific branch instruction, appending
   2432    the branch prediction flag to the opcode if appropriate.  */
   2433 static const char *
   2434 tilepro_output_simple_cbranch_with_opcode (rtx_insn *insn, const char *opcode,
   2435 					   int regop, bool netreg_p,
   2436 					   bool reverse_predicted)
   2437 {
   2438   static char buf[64];
   2439   sprintf (buf, "%s%s\t%%%c%d, %%l0", opcode,
   2440 	   (cbranch_predicted_p (insn) ^ reverse_predicted) ? "t" : "",
   2441 	   netreg_p ? 'N' : 'r', regop);
   2442   return buf;
   2443 }
   2444 
   2445 
   2446 /* Output assembly code for a specific branch instruction, appending
   2447    the branch prediction flag to the opcode if appropriate.  */
   2448 const char *
   2449 tilepro_output_cbranch_with_opcode (rtx_insn *insn, rtx *operands,
   2450 				    const char *opcode,
   2451 				    const char *rev_opcode,
   2452 				    int regop, bool netreg_p)
   2453 {
   2454   const char *branch_if_false;
   2455   rtx taken, not_taken;
   2456   bool is_simple_branch;
   2457 
   2458   gcc_assert (LABEL_P (operands[0]));
   2459 
   2460   is_simple_branch = true;
   2461   if (INSN_ADDRESSES_SET_P ())
   2462     {
   2463       int from_addr = INSN_ADDRESSES (INSN_UID (insn));
   2464       int to_addr = INSN_ADDRESSES (INSN_UID (operands[0]));
   2465       int delta = to_addr - from_addr;
   2466       is_simple_branch = IN_RANGE (delta, -524288, 524280);
   2467     }
   2468 
   2469   if (is_simple_branch)
   2470     {
   2471       /* Just a simple conditional branch.  */
   2472       return
   2473 	tilepro_output_simple_cbranch_with_opcode (insn, opcode, regop,
   2474 						   netreg_p, false);
   2475     }
   2476 
   2477   /* Generate a reversed branch around a direct jump.  This fallback
   2478      does not use branch-likely instructions.  */
   2479   not_taken = gen_label_rtx ();
   2480   taken = operands[0];
   2481 
   2482   /* Generate the reversed branch to NOT_TAKEN.  */
   2483   operands[0] = not_taken;
   2484   branch_if_false =
   2485     tilepro_output_simple_cbranch_with_opcode (insn, rev_opcode, regop,
   2486 					       netreg_p, true);
   2487   output_asm_insn (branch_if_false, operands);
   2488 
   2489   output_asm_insn ("j\t%l0", &taken);
   2490 
   2491   /* Output NOT_TAKEN.  */
   2492   targetm.asm_out.internal_label (asm_out_file, "L",
   2493 				  CODE_LABEL_NUMBER (not_taken));
   2494   return "";
   2495 }
   2496 
   2497 
   2498 /* Output assembly code for a conditional branch instruction.  */
   2499 const char *
   2500 tilepro_output_cbranch (rtx_insn *insn, rtx *operands, bool reversed)
   2501 {
   2502   enum rtx_code code = GET_CODE (operands[1]);
   2503   const char *opcode;
   2504   const char *rev_opcode;
   2505 
   2506   if (reversed)
   2507     code = reverse_condition (code);
   2508 
   2509   switch (code)
   2510     {
   2511     case NE:
   2512       opcode = "bnz";
   2513       rev_opcode = "bz";
   2514       break;
   2515     case EQ:
   2516       opcode = "bz";
   2517       rev_opcode = "bnz";
   2518       break;
   2519     case GE:
   2520       opcode = "bgez";
   2521       rev_opcode = "blz";
   2522       break;
   2523     case GT:
   2524       opcode = "bgz";
   2525       rev_opcode = "blez";
   2526       break;
   2527     case LE:
   2528       opcode = "blez";
   2529       rev_opcode = "bgz";
   2530       break;
   2531     case LT:
   2532       opcode = "blz";
   2533       rev_opcode = "bgez";
   2534       break;
   2535     default:
   2536       gcc_unreachable ();
   2537     }
   2538 
   2539   return
   2540     tilepro_output_cbranch_with_opcode (insn, operands, opcode, rev_opcode,
   2541 					2, false);
   2542 }
   2543 
   2544 
   2545 /* Implement the tablejump pattern.  */
   2546 void
   2547 tilepro_expand_tablejump (rtx op0, rtx op1)
   2548 {
   2549   if (flag_pic)
   2550     {
   2551       rtx table = gen_rtx_LABEL_REF (Pmode, op1);
   2552       rtx temp = gen_reg_rtx (Pmode);
   2553       rtx text_label_symbol = tilepro_text_label_symbol ();
   2554       rtx text_label_rtx = tilepro_text_label_rtx ();
   2555 
   2556       emit_insn (gen_addli_pcrel (temp, text_label_rtx,
   2557 				  table, text_label_symbol));
   2558       emit_insn (gen_auli_pcrel (temp, temp, table, text_label_symbol));
   2559       emit_move_insn (temp,
   2560 		      gen_rtx_PLUS (Pmode,
   2561 				    convert_to_mode (Pmode, op0, false),
   2562 				    temp));
   2563       op0 = temp;
   2564     }
   2565 
   2566   emit_jump_insn (gen_tablejump_aux (op0, op1));
   2567 }
   2568 
   2569 
   2570 /* Expand a builtin vector binary op, by calling gen function GEN with
   2571    operands in the proper modes.  DEST is converted to DEST_MODE, and
   2572    src0 and src1 (if DO_SRC1 is true) is converted to SRC_MODE.  */
   2573 void
   2574 tilepro_expand_builtin_vector_binop (rtx (*gen) (rtx, rtx, rtx),
   2575 				     machine_mode dest_mode,
   2576 				     rtx dest,
   2577 				     machine_mode src_mode,
   2578 				     rtx src0, rtx src1, bool do_src1)
   2579 {
   2580   dest = gen_lowpart (dest_mode, dest);
   2581 
   2582   if (src0 == const0_rtx)
   2583     src0 = CONST0_RTX (src_mode);
   2584   else
   2585     src0 = gen_lowpart (src_mode, src0);
   2586 
   2587   if (do_src1)
   2588     {
   2589       if (src1 == const0_rtx)
   2590 	src1 = CONST0_RTX (src_mode);
   2591       else
   2592 	src1 = gen_lowpart (src_mode, src1);
   2593     }
   2594 
   2595   emit_insn ((*gen) (dest, src0, src1));
   2596 }
   2597 
   2598 
   2600 
   2601 /* Intrinsics  */
   2602 
   2603 struct tile_builtin_info
   2604 {
   2605   enum insn_code icode;
   2606   tree fndecl;
   2607 };
   2608 
   2609 static struct tile_builtin_info tilepro_builtin_info[TILEPRO_BUILTIN_max] = {
   2610   { CODE_FOR_addsi3,                    NULL }, /* add */
   2611   { CODE_FOR_insn_addb,                 NULL }, /* addb */
   2612   { CODE_FOR_insn_addbs_u,              NULL }, /* addbs_u */
   2613   { CODE_FOR_insn_addh,                 NULL }, /* addh */
   2614   { CODE_FOR_insn_addhs,                NULL }, /* addhs */
   2615   { CODE_FOR_insn_addib,                NULL }, /* addib */
   2616   { CODE_FOR_insn_addih,                NULL }, /* addih */
   2617   { CODE_FOR_insn_addlis,               NULL }, /* addlis */
   2618   { CODE_FOR_ssaddsi3,                  NULL }, /* adds */
   2619   { CODE_FOR_insn_adiffb_u,             NULL }, /* adiffb_u */
   2620   { CODE_FOR_insn_adiffh,               NULL }, /* adiffh */
   2621   { CODE_FOR_andsi3,                    NULL }, /* and */
   2622   { CODE_FOR_insn_auli,                 NULL }, /* auli */
   2623   { CODE_FOR_insn_avgb_u,               NULL }, /* avgb_u */
   2624   { CODE_FOR_insn_avgh,                 NULL }, /* avgh */
   2625   { CODE_FOR_insn_bitx,                 NULL }, /* bitx */
   2626   { CODE_FOR_bswapsi2,                  NULL }, /* bytex */
   2627   { CODE_FOR_clzsi2,                    NULL }, /* clz */
   2628   { CODE_FOR_insn_crc32_32,             NULL }, /* crc32_32 */
   2629   { CODE_FOR_insn_crc32_8,              NULL }, /* crc32_8 */
   2630   { CODE_FOR_ctzsi2,                    NULL }, /* ctz */
   2631   { CODE_FOR_insn_drain,                NULL }, /* drain */
   2632   { CODE_FOR_insn_dtlbpr,               NULL }, /* dtlbpr */
   2633   { CODE_FOR_insn_dword_align,          NULL }, /* dword_align */
   2634   { CODE_FOR_insn_finv,                 NULL }, /* finv */
   2635   { CODE_FOR_insn_flush,                NULL }, /* flush */
   2636   { CODE_FOR_insn_fnop,                 NULL }, /* fnop */
   2637   { CODE_FOR_insn_icoh,                 NULL }, /* icoh */
   2638   { CODE_FOR_insn_ill,                  NULL }, /* ill */
   2639   { CODE_FOR_insn_info,                 NULL }, /* info */
   2640   { CODE_FOR_insn_infol,                NULL }, /* infol */
   2641   { CODE_FOR_insn_inthb,                NULL }, /* inthb */
   2642   { CODE_FOR_insn_inthh,                NULL }, /* inthh */
   2643   { CODE_FOR_insn_intlb,                NULL }, /* intlb */
   2644   { CODE_FOR_insn_intlh,                NULL }, /* intlh */
   2645   { CODE_FOR_insn_inv,                  NULL }, /* inv */
   2646   { CODE_FOR_insn_lb,                   NULL }, /* lb */
   2647   { CODE_FOR_insn_lb_u,                 NULL }, /* lb_u */
   2648   { CODE_FOR_insn_lh,                   NULL }, /* lh */
   2649   { CODE_FOR_insn_lh_u,                 NULL }, /* lh_u */
   2650   { CODE_FOR_insn_lnk,                  NULL }, /* lnk */
   2651   { CODE_FOR_insn_lw,                   NULL }, /* lw */
   2652   { CODE_FOR_insn_lw_na,                NULL }, /* lw_na */
   2653   { CODE_FOR_insn_lb_L2,                NULL }, /* lb_L2 */
   2654   { CODE_FOR_insn_lb_u_L2,              NULL }, /* lb_u_L2 */
   2655   { CODE_FOR_insn_lh_L2,                NULL }, /* lh_L2 */
   2656   { CODE_FOR_insn_lh_u_L2,              NULL }, /* lh_u_L2 */
   2657   { CODE_FOR_insn_lw_L2,                NULL }, /* lw_L2 */
   2658   { CODE_FOR_insn_lw_na_L2,             NULL }, /* lw_na_L2 */
   2659   { CODE_FOR_insn_lb_miss,              NULL }, /* lb_miss */
   2660   { CODE_FOR_insn_lb_u_miss,            NULL }, /* lb_u_miss */
   2661   { CODE_FOR_insn_lh_miss,              NULL }, /* lh_miss */
   2662   { CODE_FOR_insn_lh_u_miss,            NULL }, /* lh_u_miss */
   2663   { CODE_FOR_insn_lw_miss,              NULL }, /* lw_miss */
   2664   { CODE_FOR_insn_lw_na_miss,           NULL }, /* lw_na_miss */
   2665   { CODE_FOR_insn_maxb_u,               NULL }, /* maxb_u */
   2666   { CODE_FOR_insn_maxh,                 NULL }, /* maxh */
   2667   { CODE_FOR_insn_maxib_u,              NULL }, /* maxib_u */
   2668   { CODE_FOR_insn_maxih,                NULL }, /* maxih */
   2669   { CODE_FOR_memory_barrier,            NULL }, /* mf */
   2670   { CODE_FOR_insn_mfspr,                NULL }, /* mfspr */
   2671   { CODE_FOR_insn_minb_u,               NULL }, /* minb_u */
   2672   { CODE_FOR_insn_minh,                 NULL }, /* minh */
   2673   { CODE_FOR_insn_minib_u,              NULL }, /* minib_u */
   2674   { CODE_FOR_insn_minih,                NULL }, /* minih */
   2675   { CODE_FOR_insn_mm,                   NULL }, /* mm */
   2676   { CODE_FOR_insn_mnz,                  NULL }, /* mnz */
   2677   { CODE_FOR_insn_mnzb,                 NULL }, /* mnzb */
   2678   { CODE_FOR_insn_mnzh,                 NULL }, /* mnzh */
   2679   { CODE_FOR_movsi,                     NULL }, /* move */
   2680   { CODE_FOR_insn_movelis,              NULL }, /* movelis */
   2681   { CODE_FOR_insn_mtspr,                NULL }, /* mtspr */
   2682   { CODE_FOR_insn_mulhh_ss,             NULL }, /* mulhh_ss */
   2683   { CODE_FOR_insn_mulhh_su,             NULL }, /* mulhh_su */
   2684   { CODE_FOR_insn_mulhh_uu,             NULL }, /* mulhh_uu */
   2685   { CODE_FOR_insn_mulhha_ss,            NULL }, /* mulhha_ss */
   2686   { CODE_FOR_insn_mulhha_su,            NULL }, /* mulhha_su */
   2687   { CODE_FOR_insn_mulhha_uu,            NULL }, /* mulhha_uu */
   2688   { CODE_FOR_insn_mulhhsa_uu,           NULL }, /* mulhhsa_uu */
   2689   { CODE_FOR_insn_mulhl_ss,             NULL }, /* mulhl_ss */
   2690   { CODE_FOR_insn_mulhl_su,             NULL }, /* mulhl_su */
   2691   { CODE_FOR_insn_mulhl_us,             NULL }, /* mulhl_us */
   2692   { CODE_FOR_insn_mulhl_uu,             NULL }, /* mulhl_uu */
   2693   { CODE_FOR_insn_mulhla_ss,            NULL }, /* mulhla_ss */
   2694   { CODE_FOR_insn_mulhla_su,            NULL }, /* mulhla_su */
   2695   { CODE_FOR_insn_mulhla_us,            NULL }, /* mulhla_us */
   2696   { CODE_FOR_insn_mulhla_uu,            NULL }, /* mulhla_uu */
   2697   { CODE_FOR_insn_mulhlsa_uu,           NULL }, /* mulhlsa_uu */
   2698   { CODE_FOR_insn_mulll_ss,             NULL }, /* mulll_ss */
   2699   { CODE_FOR_insn_mulll_su,             NULL }, /* mulll_su */
   2700   { CODE_FOR_insn_mulll_uu,             NULL }, /* mulll_uu */
   2701   { CODE_FOR_insn_mullla_ss,            NULL }, /* mullla_ss */
   2702   { CODE_FOR_insn_mullla_su,            NULL }, /* mullla_su */
   2703   { CODE_FOR_insn_mullla_uu,            NULL }, /* mullla_uu */
   2704   { CODE_FOR_insn_mulllsa_uu,           NULL }, /* mulllsa_uu */
   2705   { CODE_FOR_insn_mvnz,                 NULL }, /* mvnz */
   2706   { CODE_FOR_insn_mvz,                  NULL }, /* mvz */
   2707   { CODE_FOR_insn_mz,                   NULL }, /* mz */
   2708   { CODE_FOR_insn_mzb,                  NULL }, /* mzb */
   2709   { CODE_FOR_insn_mzh,                  NULL }, /* mzh */
   2710   { CODE_FOR_insn_nap,                  NULL }, /* nap */
   2711   { CODE_FOR_nop,                       NULL }, /* nop */
   2712   { CODE_FOR_insn_nor,                  NULL }, /* nor */
   2713   { CODE_FOR_iorsi3,                    NULL }, /* or */
   2714   { CODE_FOR_insn_packbs_u,             NULL }, /* packbs_u */
   2715   { CODE_FOR_insn_packhb,               NULL }, /* packhb */
   2716   { CODE_FOR_insn_packhs,               NULL }, /* packhs */
   2717   { CODE_FOR_insn_packlb,               NULL }, /* packlb */
   2718   { CODE_FOR_popcountsi2,               NULL }, /* pcnt */
   2719   { CODE_FOR_insn_prefetch,             NULL }, /* prefetch */
   2720   { CODE_FOR_insn_prefetch_L1,          NULL }, /* prefetch_L1 */
   2721   { CODE_FOR_rotlsi3,                   NULL }, /* rl */
   2722   { CODE_FOR_insn_s1a,                  NULL }, /* s1a */
   2723   { CODE_FOR_insn_s2a,                  NULL }, /* s2a */
   2724   { CODE_FOR_insn_s3a,                  NULL }, /* s3a */
   2725   { CODE_FOR_insn_sadab_u,              NULL }, /* sadab_u */
   2726   { CODE_FOR_insn_sadah,                NULL }, /* sadah */
   2727   { CODE_FOR_insn_sadah_u,              NULL }, /* sadah_u */
   2728   { CODE_FOR_insn_sadb_u,               NULL }, /* sadb_u */
   2729   { CODE_FOR_insn_sadh,                 NULL }, /* sadh */
   2730   { CODE_FOR_insn_sadh_u,               NULL }, /* sadh_u */
   2731   { CODE_FOR_insn_sb,                   NULL }, /* sb */
   2732   { CODE_FOR_insn_seq,                  NULL }, /* seq */
   2733   { CODE_FOR_insn_seqb,                 NULL }, /* seqb */
   2734   { CODE_FOR_insn_seqh,                 NULL }, /* seqh */
   2735   { CODE_FOR_insn_seqib,                NULL }, /* seqib */
   2736   { CODE_FOR_insn_seqih,                NULL }, /* seqih */
   2737   { CODE_FOR_insn_sh,                   NULL }, /* sh */
   2738   { CODE_FOR_ashlsi3,                   NULL }, /* shl */
   2739   { CODE_FOR_insn_shlb,                 NULL }, /* shlb */
   2740   { CODE_FOR_insn_shlh,                 NULL }, /* shlh */
   2741   { CODE_FOR_insn_shlb,                 NULL }, /* shlib */
   2742   { CODE_FOR_insn_shlh,                 NULL }, /* shlih */
   2743   { CODE_FOR_lshrsi3,                   NULL }, /* shr */
   2744   { CODE_FOR_insn_shrb,                 NULL }, /* shrb */
   2745   { CODE_FOR_insn_shrh,                 NULL }, /* shrh */
   2746   { CODE_FOR_insn_shrb,                 NULL }, /* shrib */
   2747   { CODE_FOR_insn_shrh,                 NULL }, /* shrih */
   2748   { CODE_FOR_insn_slt,                  NULL }, /* slt */
   2749   { CODE_FOR_insn_slt_u,                NULL }, /* slt_u */
   2750   { CODE_FOR_insn_sltb,                 NULL }, /* sltb */
   2751   { CODE_FOR_insn_sltb_u,               NULL }, /* sltb_u */
   2752   { CODE_FOR_insn_slte,                 NULL }, /* slte */
   2753   { CODE_FOR_insn_slte_u,               NULL }, /* slte_u */
   2754   { CODE_FOR_insn_slteb,                NULL }, /* slteb */
   2755   { CODE_FOR_insn_slteb_u,              NULL }, /* slteb_u */
   2756   { CODE_FOR_insn_slteh,                NULL }, /* slteh */
   2757   { CODE_FOR_insn_slteh_u,              NULL }, /* slteh_u */
   2758   { CODE_FOR_insn_slth,                 NULL }, /* slth */
   2759   { CODE_FOR_insn_slth_u,               NULL }, /* slth_u */
   2760   { CODE_FOR_insn_sltib,                NULL }, /* sltib */
   2761   { CODE_FOR_insn_sltib_u,              NULL }, /* sltib_u */
   2762   { CODE_FOR_insn_sltih,                NULL }, /* sltih */
   2763   { CODE_FOR_insn_sltih_u,              NULL }, /* sltih_u */
   2764   { CODE_FOR_insn_sne,                  NULL }, /* sne */
   2765   { CODE_FOR_insn_sneb,                 NULL }, /* sneb */
   2766   { CODE_FOR_insn_sneh,                 NULL }, /* sneh */
   2767   { CODE_FOR_ashrsi3,                   NULL }, /* sra */
   2768   { CODE_FOR_insn_srab,                 NULL }, /* srab */
   2769   { CODE_FOR_insn_srah,                 NULL }, /* srah */
   2770   { CODE_FOR_insn_srab,                 NULL }, /* sraib */
   2771   { CODE_FOR_insn_srah,                 NULL }, /* sraih */
   2772   { CODE_FOR_subsi3,                    NULL }, /* sub */
   2773   { CODE_FOR_insn_subb,                 NULL }, /* subb */
   2774   { CODE_FOR_insn_subbs_u,              NULL }, /* subbs_u */
   2775   { CODE_FOR_insn_subh,                 NULL }, /* subh */
   2776   { CODE_FOR_insn_subhs,                NULL }, /* subhs */
   2777   { CODE_FOR_sssubsi3,                  NULL }, /* subs */
   2778   { CODE_FOR_insn_sw,                   NULL }, /* sw */
   2779   { CODE_FOR_insn_tblidxb0,             NULL }, /* tblidxb0 */
   2780   { CODE_FOR_insn_tblidxb1,             NULL }, /* tblidxb1 */
   2781   { CODE_FOR_insn_tblidxb2,             NULL }, /* tblidxb2 */
   2782   { CODE_FOR_insn_tblidxb3,             NULL }, /* tblidxb3 */
   2783   { CODE_FOR_insn_tns,                  NULL }, /* tns */
   2784   { CODE_FOR_insn_wh64,                 NULL }, /* wh64 */
   2785   { CODE_FOR_xorsi3,                    NULL }, /* xor */
   2786   { CODE_FOR_tilepro_network_barrier,   NULL }, /* network_barrier */
   2787   { CODE_FOR_tilepro_idn0_receive,      NULL }, /* idn0_receive */
   2788   { CODE_FOR_tilepro_idn1_receive,      NULL }, /* idn1_receive */
   2789   { CODE_FOR_tilepro_idn_send,          NULL }, /* idn_send */
   2790   { CODE_FOR_tilepro_sn_receive,        NULL }, /* sn_receive */
   2791   { CODE_FOR_tilepro_sn_send,           NULL }, /* sn_send */
   2792   { CODE_FOR_tilepro_udn0_receive,      NULL }, /* udn0_receive */
   2793   { CODE_FOR_tilepro_udn1_receive,      NULL }, /* udn1_receive */
   2794   { CODE_FOR_tilepro_udn2_receive,      NULL }, /* udn2_receive */
   2795   { CODE_FOR_tilepro_udn3_receive,      NULL }, /* udn3_receive */
   2796   { CODE_FOR_tilepro_udn_send,          NULL }, /* udn_send */
   2797 };
   2798 
   2799 
   2800 struct tilepro_builtin_def
   2801 {
   2802   const char *name;
   2803   enum tilepro_builtin code;
   2804   bool is_const;
   2805   /* The first character is the return type.  Subsequent characters
   2806      are the argument types. See char_to_type.  */
   2807   const char *type;
   2808 };
   2809 
   2810 
   2811 static const struct tilepro_builtin_def tilepro_builtins[] = {
   2812   { "__insn_add",             TILEPRO_INSN_ADD,         true,  "lll"   },
   2813   { "__insn_addb",            TILEPRO_INSN_ADDB,        true,  "lll"   },
   2814   { "__insn_addbs_u",         TILEPRO_INSN_ADDBS_U,     false, "lll"   },
   2815   { "__insn_addh",            TILEPRO_INSN_ADDH,        true,  "lll"   },
   2816   { "__insn_addhs",           TILEPRO_INSN_ADDHS,       false, "lll"   },
   2817   { "__insn_addi",            TILEPRO_INSN_ADD,         true,  "lll"   },
   2818   { "__insn_addib",           TILEPRO_INSN_ADDIB,       true,  "lll"   },
   2819   { "__insn_addih",           TILEPRO_INSN_ADDIH,       true,  "lll"   },
   2820   { "__insn_addli",           TILEPRO_INSN_ADD,         true,  "lll"   },
   2821   { "__insn_addlis",          TILEPRO_INSN_ADDLIS,      false, "lll"   },
   2822   { "__insn_adds",            TILEPRO_INSN_ADDS,        false, "lll"   },
   2823   { "__insn_adiffb_u",        TILEPRO_INSN_ADIFFB_U,    true,  "lll"   },
   2824   { "__insn_adiffh",          TILEPRO_INSN_ADIFFH,      true,  "lll"   },
   2825   { "__insn_and",             TILEPRO_INSN_AND,         true,  "lll"   },
   2826   { "__insn_andi",            TILEPRO_INSN_AND,         true,  "lll"   },
   2827   { "__insn_auli",            TILEPRO_INSN_AULI,        true,  "lll"   },
   2828   { "__insn_avgb_u",          TILEPRO_INSN_AVGB_U,      true,  "lll"   },
   2829   { "__insn_avgh",            TILEPRO_INSN_AVGH,        true,  "lll"   },
   2830   { "__insn_bitx",            TILEPRO_INSN_BITX,        true,  "ll"    },
   2831   { "__insn_bytex",           TILEPRO_INSN_BYTEX,       true,  "ll"    },
   2832   { "__insn_clz",             TILEPRO_INSN_CLZ,         true,  "ll"    },
   2833   { "__insn_crc32_32",        TILEPRO_INSN_CRC32_32,    true,  "lll"   },
   2834   { "__insn_crc32_8",         TILEPRO_INSN_CRC32_8,     true,  "lll"   },
   2835   { "__insn_ctz",             TILEPRO_INSN_CTZ,         true,  "ll"    },
   2836   { "__insn_drain",           TILEPRO_INSN_DRAIN,       false, "v"     },
   2837   { "__insn_dtlbpr",          TILEPRO_INSN_DTLBPR,      false, "vl"    },
   2838   { "__insn_dword_align",     TILEPRO_INSN_DWORD_ALIGN, true,  "lllk"  },
   2839   { "__insn_finv",            TILEPRO_INSN_FINV,        false, "vk"    },
   2840   { "__insn_flush",           TILEPRO_INSN_FLUSH,       false, "vk"    },
   2841   { "__insn_fnop",            TILEPRO_INSN_FNOP,        false, "v"     },
   2842   { "__insn_icoh",            TILEPRO_INSN_ICOH,        false, "vk"    },
   2843   { "__insn_ill",             TILEPRO_INSN_ILL,         false, "v"     },
   2844   { "__insn_info",            TILEPRO_INSN_INFO,        false, "vl"    },
   2845   { "__insn_infol",           TILEPRO_INSN_INFOL,       false, "vl"    },
   2846   { "__insn_inthb",           TILEPRO_INSN_INTHB,       true,  "lll"   },
   2847   { "__insn_inthh",           TILEPRO_INSN_INTHH,       true,  "lll"   },
   2848   { "__insn_intlb",           TILEPRO_INSN_INTLB,       true,  "lll"   },
   2849   { "__insn_intlh",           TILEPRO_INSN_INTLH,       true,  "lll"   },
   2850   { "__insn_inv",             TILEPRO_INSN_INV,         false, "vp"    },
   2851   { "__insn_lb",              TILEPRO_INSN_LB,          false, "lk"    },
   2852   { "__insn_lb_u",            TILEPRO_INSN_LB_U,        false, "lk"    },
   2853   { "__insn_lh",              TILEPRO_INSN_LH,          false, "lk"    },
   2854   { "__insn_lh_u",            TILEPRO_INSN_LH_U,        false, "lk"    },
   2855   { "__insn_lnk",             TILEPRO_INSN_LNK,         true,  "l"     },
   2856   { "__insn_lw",              TILEPRO_INSN_LW,          false, "lk"    },
   2857   { "__insn_lw_na",           TILEPRO_INSN_LW_NA,       false, "lk"    },
   2858   { "__insn_lb_L2",           TILEPRO_INSN_LB_L2,       false, "lk"    },
   2859   { "__insn_lb_u_L2",         TILEPRO_INSN_LB_U_L2,     false, "lk"    },
   2860   { "__insn_lh_L2",           TILEPRO_INSN_LH_L2,       false, "lk"    },
   2861   { "__insn_lh_u_L2",         TILEPRO_INSN_LH_U_L2,     false, "lk"    },
   2862   { "__insn_lw_L2",           TILEPRO_INSN_LW_L2,       false, "lk"    },
   2863   { "__insn_lw_na_L2",        TILEPRO_INSN_LW_NA_L2,    false, "lk"    },
   2864   { "__insn_lb_miss",         TILEPRO_INSN_LB_MISS,     false, "lk"    },
   2865   { "__insn_lb_u_miss",       TILEPRO_INSN_LB_U_MISS,   false, "lk"    },
   2866   { "__insn_lh_miss",         TILEPRO_INSN_LH_MISS,     false, "lk"    },
   2867   { "__insn_lh_u_miss",       TILEPRO_INSN_LH_U_MISS,   false, "lk"    },
   2868   { "__insn_lw_miss",         TILEPRO_INSN_LW_MISS,     false, "lk"    },
   2869   { "__insn_lw_na_miss",      TILEPRO_INSN_LW_NA_MISS,  false, "lk"    },
   2870   { "__insn_maxb_u",          TILEPRO_INSN_MAXB_U,      true,  "lll"   },
   2871   { "__insn_maxh",            TILEPRO_INSN_MAXH,        true,  "lll"   },
   2872   { "__insn_maxib_u",         TILEPRO_INSN_MAXIB_U,     true,  "lll"   },
   2873   { "__insn_maxih",           TILEPRO_INSN_MAXIH,       true,  "lll"   },
   2874   { "__insn_mf",              TILEPRO_INSN_MF,          false, "v"     },
   2875   { "__insn_mfspr",           TILEPRO_INSN_MFSPR,       false, "ll"    },
   2876   { "__insn_minb_u",          TILEPRO_INSN_MINB_U,      true,  "lll"   },
   2877   { "__insn_minh",            TILEPRO_INSN_MINH,        true,  "lll"   },
   2878   { "__insn_minib_u",         TILEPRO_INSN_MINIB_U,     true,  "lll"   },
   2879   { "__insn_minih",           TILEPRO_INSN_MINIH,       true,  "lll"   },
   2880   { "__insn_mm",              TILEPRO_INSN_MM,          true,  "lllll" },
   2881   { "__insn_mnz",             TILEPRO_INSN_MNZ,         true,  "lll"   },
   2882   { "__insn_mnzb",            TILEPRO_INSN_MNZB,        true,  "lll"   },
   2883   { "__insn_mnzh",            TILEPRO_INSN_MNZH,        true,  "lll"   },
   2884   { "__insn_move",            TILEPRO_INSN_MOVE,        true,  "ll"    },
   2885   { "__insn_movei",           TILEPRO_INSN_MOVE,        true,  "ll"    },
   2886   { "__insn_moveli",          TILEPRO_INSN_MOVE,        true,  "ll"    },
   2887   { "__insn_movelis",         TILEPRO_INSN_MOVELIS,     false, "ll"    },
   2888   { "__insn_mtspr",           TILEPRO_INSN_MTSPR,       false, "vll"   },
   2889   { "__insn_mulhh_ss",        TILEPRO_INSN_MULHH_SS,    true,  "lll"   },
   2890   { "__insn_mulhh_su",        TILEPRO_INSN_MULHH_SU,    true,  "lll"   },
   2891   { "__insn_mulhh_uu",        TILEPRO_INSN_MULHH_UU,    true,  "lll"   },
   2892   { "__insn_mulhha_ss",       TILEPRO_INSN_MULHHA_SS,   true,  "llll"  },
   2893   { "__insn_mulhha_su",       TILEPRO_INSN_MULHHA_SU,   true,  "llll"  },
   2894   { "__insn_mulhha_uu",       TILEPRO_INSN_MULHHA_UU,   true,  "llll"  },
   2895   { "__insn_mulhhsa_uu",      TILEPRO_INSN_MULHHSA_UU,  true,  "llll"  },
   2896   { "__insn_mulhl_ss",        TILEPRO_INSN_MULHL_SS,    true,  "lll"   },
   2897   { "__insn_mulhl_su",        TILEPRO_INSN_MULHL_SU,    true,  "lll"   },
   2898   { "__insn_mulhl_us",        TILEPRO_INSN_MULHL_US,    true,  "lll"   },
   2899   { "__insn_mulhl_uu",        TILEPRO_INSN_MULHL_UU,    true,  "lll"   },
   2900   { "__insn_mulhla_ss",       TILEPRO_INSN_MULHLA_SS,   true,  "llll"  },
   2901   { "__insn_mulhla_su",       TILEPRO_INSN_MULHLA_SU,   true,  "llll"  },
   2902   { "__insn_mulhla_us",       TILEPRO_INSN_MULHLA_US,   true,  "llll"  },
   2903   { "__insn_mulhla_uu",       TILEPRO_INSN_MULHLA_UU,   true,  "llll"  },
   2904   { "__insn_mulhlsa_uu",      TILEPRO_INSN_MULHLSA_UU,  true,  "llll"  },
   2905   { "__insn_mulll_ss",        TILEPRO_INSN_MULLL_SS,    true,  "lll"   },
   2906   { "__insn_mulll_su",        TILEPRO_INSN_MULLL_SU,    true,  "lll"   },
   2907   { "__insn_mulll_uu",        TILEPRO_INSN_MULLL_UU,    true,  "lll"   },
   2908   { "__insn_mullla_ss",       TILEPRO_INSN_MULLLA_SS,   true,  "llll"  },
   2909   { "__insn_mullla_su",       TILEPRO_INSN_MULLLA_SU,   true,  "llll"  },
   2910   { "__insn_mullla_uu",       TILEPRO_INSN_MULLLA_UU,   true,  "llll"  },
   2911   { "__insn_mulllsa_uu",      TILEPRO_INSN_MULLLSA_UU,  true,  "llll"  },
   2912   { "__insn_mvnz",            TILEPRO_INSN_MVNZ,        true,  "llll"  },
   2913   { "__insn_mvz",             TILEPRO_INSN_MVZ,         true,  "llll"  },
   2914   { "__insn_mz",              TILEPRO_INSN_MZ,          true,  "lll"   },
   2915   { "__insn_mzb",             TILEPRO_INSN_MZB,         true,  "lll"   },
   2916   { "__insn_mzh",             TILEPRO_INSN_MZH,         true,  "lll"   },
   2917   { "__insn_nap",             TILEPRO_INSN_NAP,         false, "v"     },
   2918   { "__insn_nop",             TILEPRO_INSN_NOP,         true,  "v"     },
   2919   { "__insn_nor",             TILEPRO_INSN_NOR,         true,  "lll"   },
   2920   { "__insn_or",              TILEPRO_INSN_OR,          true,  "lll"   },
   2921   { "__insn_ori",             TILEPRO_INSN_OR,          true,  "lll"   },
   2922   { "__insn_packbs_u",        TILEPRO_INSN_PACKBS_U,    false, "lll"   },
   2923   { "__insn_packhb",          TILEPRO_INSN_PACKHB,      true,  "lll"   },
   2924   { "__insn_packhs",          TILEPRO_INSN_PACKHS,      false, "lll"   },
   2925   { "__insn_packlb",          TILEPRO_INSN_PACKLB,      true,  "lll"   },
   2926   { "__insn_pcnt",            TILEPRO_INSN_PCNT,        true,  "ll"    },
   2927   { "__insn_prefetch",        TILEPRO_INSN_PREFETCH,    false, "vk"    },
   2928   { "__insn_prefetch_L1",     TILEPRO_INSN_PREFETCH_L1, false, "vk"    },
   2929   { "__insn_rl",              TILEPRO_INSN_RL,          true,  "lll"   },
   2930   { "__insn_rli",             TILEPRO_INSN_RL,          true,  "lll"   },
   2931   { "__insn_s1a",             TILEPRO_INSN_S1A,         true,  "lll"   },
   2932   { "__insn_s2a",             TILEPRO_INSN_S2A,         true,  "lll"   },
   2933   { "__insn_s3a",             TILEPRO_INSN_S3A,         true,  "lll"   },
   2934   { "__insn_sadab_u",         TILEPRO_INSN_SADAB_U,     true,  "llll"  },
   2935   { "__insn_sadah",           TILEPRO_INSN_SADAH,       true,  "llll"  },
   2936   { "__insn_sadah_u",         TILEPRO_INSN_SADAH_U,     true,  "llll"  },
   2937   { "__insn_sadb_u",          TILEPRO_INSN_SADB_U,      true,  "lll"   },
   2938   { "__insn_sadh",            TILEPRO_INSN_SADH,        true,  "lll"   },
   2939   { "__insn_sadh_u",          TILEPRO_INSN_SADH_U,      true,  "lll"   },
   2940   { "__insn_sb",              TILEPRO_INSN_SB,          false, "vpl"   },
   2941   { "__insn_seq",             TILEPRO_INSN_SEQ,         true,  "lll"   },
   2942   { "__insn_seqb",            TILEPRO_INSN_SEQB,        true,  "lll"   },
   2943   { "__insn_seqh",            TILEPRO_INSN_SEQH,        true,  "lll"   },
   2944   { "__insn_seqi",            TILEPRO_INSN_SEQ,         true,  "lll"   },
   2945   { "__insn_seqib",           TILEPRO_INSN_SEQIB,       true,  "lll"   },
   2946   { "__insn_seqih",           TILEPRO_INSN_SEQIH,       true,  "lll"   },
   2947   { "__insn_sh",              TILEPRO_INSN_SH,          false, "vpl"   },
   2948   { "__insn_shl",             TILEPRO_INSN_SHL,         true,  "lll"   },
   2949   { "__insn_shlb",            TILEPRO_INSN_SHLB,        true,  "lll"   },
   2950   { "__insn_shlh",            TILEPRO_INSN_SHLH,        true,  "lll"   },
   2951   { "__insn_shli",            TILEPRO_INSN_SHL,         true,  "lll"   },
   2952   { "__insn_shlib",           TILEPRO_INSN_SHLIB,       true,  "lll"   },
   2953   { "__insn_shlih",           TILEPRO_INSN_SHLIH,       true,  "lll"   },
   2954   { "__insn_shr",             TILEPRO_INSN_SHR,         true,  "lll"   },
   2955   { "__insn_shrb",            TILEPRO_INSN_SHRB,        true,  "lll"   },
   2956   { "__insn_shrh",            TILEPRO_INSN_SHRH,        true,  "lll"   },
   2957   { "__insn_shri",            TILEPRO_INSN_SHR,         true,  "lll"   },
   2958   { "__insn_shrib",           TILEPRO_INSN_SHRIB,       true,  "lll"   },
   2959   { "__insn_shrih",           TILEPRO_INSN_SHRIH,       true,  "lll"   },
   2960   { "__insn_slt",             TILEPRO_INSN_SLT,         true,  "lll"   },
   2961   { "__insn_slt_u",           TILEPRO_INSN_SLT_U,       true,  "lll"   },
   2962   { "__insn_sltb",            TILEPRO_INSN_SLTB,        true,  "lll"   },
   2963   { "__insn_sltb_u",          TILEPRO_INSN_SLTB_U,      true,  "lll"   },
   2964   { "__insn_slte",            TILEPRO_INSN_SLTE,        true,  "lll"   },
   2965   { "__insn_slte_u",          TILEPRO_INSN_SLTE_U,      true,  "lll"   },
   2966   { "__insn_slteb",           TILEPRO_INSN_SLTEB,       true,  "lll"   },
   2967   { "__insn_slteb_u",         TILEPRO_INSN_SLTEB_U,     true,  "lll"   },
   2968   { "__insn_slteh",           TILEPRO_INSN_SLTEH,       true,  "lll"   },
   2969   { "__insn_slteh_u",         TILEPRO_INSN_SLTEH_U,     true,  "lll"   },
   2970   { "__insn_slth",            TILEPRO_INSN_SLTH,        true,  "lll"   },
   2971   { "__insn_slth_u",          TILEPRO_INSN_SLTH_U,      true,  "lll"   },
   2972   { "__insn_slti",            TILEPRO_INSN_SLT,         true,  "lll"   },
   2973   { "__insn_slti_u",          TILEPRO_INSN_SLT_U,       true,  "lll"   },
   2974   { "__insn_sltib",           TILEPRO_INSN_SLTIB,       true,  "lll"   },
   2975   { "__insn_sltib_u",         TILEPRO_INSN_SLTIB_U,     true,  "lll"   },
   2976   { "__insn_sltih",           TILEPRO_INSN_SLTIH,       true,  "lll"   },
   2977   { "__insn_sltih_u",         TILEPRO_INSN_SLTIH_U,     true,  "lll"   },
   2978   { "__insn_sne",             TILEPRO_INSN_SNE,         true,  "lll"   },
   2979   { "__insn_sneb",            TILEPRO_INSN_SNEB,        true,  "lll"   },
   2980   { "__insn_sneh",            TILEPRO_INSN_SNEH,        true,  "lll"   },
   2981   { "__insn_sra",             TILEPRO_INSN_SRA,         true,  "lll"   },
   2982   { "__insn_srab",            TILEPRO_INSN_SRAB,        true,  "lll"   },
   2983   { "__insn_srah",            TILEPRO_INSN_SRAH,        true,  "lll"   },
   2984   { "__insn_srai",            TILEPRO_INSN_SRA,         true,  "lll"   },
   2985   { "__insn_sraib",           TILEPRO_INSN_SRAIB,       true,  "lll"   },
   2986   { "__insn_sraih",           TILEPRO_INSN_SRAIH,       true,  "lll"   },
   2987   { "__insn_sub",             TILEPRO_INSN_SUB,         true,  "lll"   },
   2988   { "__insn_subb",            TILEPRO_INSN_SUBB,        true,  "lll"   },
   2989   { "__insn_subbs_u",         TILEPRO_INSN_SUBBS_U,     false, "lll"   },
   2990   { "__insn_subh",            TILEPRO_INSN_SUBH,        true,  "lll"   },
   2991   { "__insn_subhs",           TILEPRO_INSN_SUBHS,       false, "lll"   },
   2992   { "__insn_subs",            TILEPRO_INSN_SUBS,        false, "lll"   },
   2993   { "__insn_sw",              TILEPRO_INSN_SW,          false, "vpl"   },
   2994   { "__insn_tblidxb0",        TILEPRO_INSN_TBLIDXB0,    true,  "lll"   },
   2995   { "__insn_tblidxb1",        TILEPRO_INSN_TBLIDXB1,    true,  "lll"   },
   2996   { "__insn_tblidxb2",        TILEPRO_INSN_TBLIDXB2,    true,  "lll"   },
   2997   { "__insn_tblidxb3",        TILEPRO_INSN_TBLIDXB3,    true,  "lll"   },
   2998   { "__insn_tns",             TILEPRO_INSN_TNS,         false, "lp"    },
   2999   { "__insn_wh64",            TILEPRO_INSN_WH64,        false, "vp"    },
   3000   { "__insn_xor",             TILEPRO_INSN_XOR,         true,  "lll"   },
   3001   { "__insn_xori",            TILEPRO_INSN_XOR,         true,  "lll"   },
   3002   { "__tile_network_barrier", TILEPRO_NETWORK_BARRIER,  false, "v"     },
   3003   { "__tile_idn0_receive",    TILEPRO_IDN0_RECEIVE,     false, "l"     },
   3004   { "__tile_idn1_receive",    TILEPRO_IDN1_RECEIVE,     false, "l"     },
   3005   { "__tile_idn_send",        TILEPRO_IDN_SEND,         false, "vl"    },
   3006   { "__tile_sn_receive",      TILEPRO_SN_RECEIVE,       false, "l"     },
   3007   { "__tile_sn_send",         TILEPRO_SN_SEND,          false, "vl"    },
   3008   { "__tile_udn0_receive",    TILEPRO_UDN0_RECEIVE,     false, "l"     },
   3009   { "__tile_udn1_receive",    TILEPRO_UDN1_RECEIVE,     false, "l"     },
   3010   { "__tile_udn2_receive",    TILEPRO_UDN2_RECEIVE,     false, "l"     },
   3011   { "__tile_udn3_receive",    TILEPRO_UDN3_RECEIVE,     false, "l"     },
   3012   { "__tile_udn_send",        TILEPRO_UDN_SEND,         false, "vl"    },
   3013 };
   3014 
   3015 
   3016 /* Convert a character in a builtin type string to a tree type.  */
   3017 static tree
   3018 char_to_type (char c)
   3019 {
   3020   static tree volatile_ptr_type_node = NULL;
   3021   static tree volatile_const_ptr_type_node = NULL;
   3022 
   3023   if (volatile_ptr_type_node == NULL)
   3024     {
   3025       volatile_ptr_type_node =
   3026 	build_pointer_type (build_qualified_type (void_type_node,
   3027 						  TYPE_QUAL_VOLATILE));
   3028       volatile_const_ptr_type_node =
   3029 	build_pointer_type (build_qualified_type (void_type_node,
   3030 						  TYPE_QUAL_CONST
   3031 						  | TYPE_QUAL_VOLATILE));
   3032     }
   3033 
   3034   switch (c)
   3035     {
   3036     case 'v':
   3037       return void_type_node;
   3038     case 'l':
   3039       return long_unsigned_type_node;
   3040     case 'p':
   3041       return volatile_ptr_type_node;
   3042     case 'k':
   3043       return volatile_const_ptr_type_node;
   3044     default:
   3045       gcc_unreachable ();
   3046     }
   3047 }
   3048 
   3049 
   3050 /* Implement TARGET_INIT_BUILTINS.  */
   3051 static void
   3052 tilepro_init_builtins (void)
   3053 {
   3054   size_t i;
   3055 
   3056   for (i = 0; i < ARRAY_SIZE (tilepro_builtins); i++)
   3057     {
   3058       const struct tilepro_builtin_def *p = &tilepro_builtins[i];
   3059       tree ftype, ret_type, arg_type_list = void_list_node;
   3060       tree decl;
   3061       int j;
   3062 
   3063       for (j = strlen (p->type) - 1; j > 0; j--)
   3064 	{
   3065 	  arg_type_list =
   3066 	    tree_cons (NULL_TREE, char_to_type (p->type[j]), arg_type_list);
   3067 	}
   3068 
   3069       ret_type = char_to_type (p->type[0]);
   3070 
   3071       ftype = build_function_type (ret_type, arg_type_list);
   3072 
   3073       decl = add_builtin_function (p->name, ftype, p->code, BUILT_IN_MD,
   3074 				   NULL, NULL);
   3075 
   3076       if (p->is_const)
   3077 	TREE_READONLY (decl) = 1;
   3078       TREE_NOTHROW (decl) = 1;
   3079 
   3080       if (tilepro_builtin_info[p->code].fndecl == NULL)
   3081 	tilepro_builtin_info[p->code].fndecl = decl;
   3082     }
   3083 }
   3084 
   3085 
   3086 /* Implement TARGET_EXPAND_BUILTIN.  */
   3087 static rtx
   3088 tilepro_expand_builtin (tree exp,
   3089 			rtx target,
   3090 			rtx subtarget ATTRIBUTE_UNUSED,
   3091 			machine_mode mode ATTRIBUTE_UNUSED,
   3092 			int ignore ATTRIBUTE_UNUSED)
   3093 {
   3094 #define MAX_BUILTIN_ARGS 4
   3095 
   3096   tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
   3097   unsigned int fcode = DECL_MD_FUNCTION_CODE (fndecl);
   3098   tree arg;
   3099   call_expr_arg_iterator iter;
   3100   enum insn_code icode;
   3101   rtx op[MAX_BUILTIN_ARGS + 1], pat;
   3102   int opnum;
   3103   bool nonvoid;
   3104   insn_gen_fn fn;
   3105 
   3106   if (fcode >= TILEPRO_BUILTIN_max)
   3107     internal_error ("bad builtin fcode");
   3108   icode = tilepro_builtin_info[fcode].icode;
   3109   if (icode == 0)
   3110     internal_error ("bad builtin icode");
   3111 
   3112   nonvoid = TREE_TYPE (TREE_TYPE (fndecl)) != void_type_node;
   3113 
   3114   opnum = nonvoid;
   3115   FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
   3116   {
   3117     const struct insn_operand_data *insn_op;
   3118 
   3119     if (arg == error_mark_node)
   3120       return NULL_RTX;
   3121     if (opnum > MAX_BUILTIN_ARGS)
   3122       return NULL_RTX;
   3123 
   3124     insn_op = &insn_data[icode].operand[opnum];
   3125 
   3126     op[opnum] = expand_expr (arg, NULL_RTX, insn_op->mode, EXPAND_NORMAL);
   3127 
   3128     if (!(*insn_op->predicate) (op[opnum], insn_op->mode))
   3129       op[opnum] = copy_to_mode_reg (insn_op->mode, op[opnum]);
   3130 
   3131     if (!(*insn_op->predicate) (op[opnum], insn_op->mode))
   3132       {
   3133 	/* We still failed to meet the predicate even after moving
   3134 	   into a register. Assume we needed an immediate.  */
   3135 	error_at (EXPR_LOCATION (exp),
   3136 		  "operand must be an immediate of the right size");
   3137 	return const0_rtx;
   3138       }
   3139 
   3140     opnum++;
   3141   }
   3142 
   3143   if (nonvoid)
   3144     {
   3145       machine_mode tmode = insn_data[icode].operand[0].mode;
   3146       if (!target
   3147 	  || GET_MODE (target) != tmode
   3148 	  || !(*insn_data[icode].operand[0].predicate) (target, tmode))
   3149 	target = gen_reg_rtx (tmode);
   3150       op[0] = target;
   3151     }
   3152 
   3153   fn = GEN_FCN (icode);
   3154   switch (opnum)
   3155     {
   3156     case 0:
   3157       pat = fn (NULL_RTX);
   3158       break;
   3159     case 1:
   3160       pat = fn (op[0]);
   3161       break;
   3162     case 2:
   3163       pat = fn (op[0], op[1]);
   3164       break;
   3165     case 3:
   3166       pat = fn (op[0], op[1], op[2]);
   3167       break;
   3168     case 4:
   3169       pat = fn (op[0], op[1], op[2], op[3]);
   3170       break;
   3171     case 5:
   3172       pat = fn (op[0], op[1], op[2], op[3], op[4]);
   3173       break;
   3174     default:
   3175       gcc_unreachable ();
   3176     }
   3177   if (!pat)
   3178     return NULL_RTX;
   3179 
   3180   /* If we are generating a prefetch, tell the scheduler not to move
   3181      it around.  */
   3182   if (GET_CODE (pat) == PREFETCH)
   3183     PREFETCH_SCHEDULE_BARRIER_P (pat) = true;
   3184 
   3185   emit_insn (pat);
   3186 
   3187   if (nonvoid)
   3188     return target;
   3189   else
   3190     return const0_rtx;
   3191 }
   3192 
   3193 
   3194 /* Implement TARGET_BUILTIN_DECL.  */
   3195 static tree
   3196 tilepro_builtin_decl (unsigned code, bool initialize_p ATTRIBUTE_UNUSED)
   3197 {
   3198   if (code >= TILEPRO_BUILTIN_max)
   3199     return error_mark_node;
   3200 
   3201   return tilepro_builtin_info[code].fndecl;
   3202 }
   3203 
   3204 
   3206 
   3207 /* Stack frames  */
   3208 
   3209 /* Return whether REGNO needs to be saved in the stack frame.  */
   3210 static bool
   3211 need_to_save_reg (unsigned int regno)
   3212 {
   3213   if (!call_used_or_fixed_reg_p (regno)
   3214       && df_regs_ever_live_p (regno))
   3215     return true;
   3216 
   3217   if (flag_pic
   3218       && (regno == PIC_OFFSET_TABLE_REGNUM
   3219 	  || regno == TILEPRO_PIC_TEXT_LABEL_REGNUM)
   3220       && (crtl->uses_pic_offset_table || crtl->saves_all_registers))
   3221     return true;
   3222 
   3223   if (crtl->calls_eh_return)
   3224     {
   3225       unsigned i;
   3226       for (i = 0; EH_RETURN_DATA_REGNO (i) != INVALID_REGNUM; i++)
   3227 	{
   3228 	  if (regno == EH_RETURN_DATA_REGNO (i))
   3229 	    return true;
   3230 	}
   3231     }
   3232 
   3233   return false;
   3234 }
   3235 
   3236 
   3237 /* Return the size of the register savev area.  This function is only
   3238    correct starting with local register allocation */
   3239 static int
   3240 tilepro_saved_regs_size (void)
   3241 {
   3242   int reg_save_size = 0;
   3243   int regno;
   3244   int offset_to_frame;
   3245   int align_mask;
   3246 
   3247   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
   3248     if (need_to_save_reg (regno))
   3249       reg_save_size += UNITS_PER_WORD;
   3250 
   3251   /* Pad out the register save area if necessary to make
   3252      frame_pointer_rtx be as aligned as the stack pointer.  */
   3253   offset_to_frame = crtl->args.pretend_args_size + reg_save_size;
   3254   align_mask = (STACK_BOUNDARY / BITS_PER_UNIT) - 1;
   3255   reg_save_size += (-offset_to_frame) & align_mask;
   3256 
   3257   return reg_save_size;
   3258 }
   3259 
   3260 
   3261 /* Round up frame size SIZE.  */
   3262 static int
   3263 round_frame_size (int size)
   3264 {
   3265   return ((size + STACK_BOUNDARY / BITS_PER_UNIT - 1)
   3266 	  & -STACK_BOUNDARY / BITS_PER_UNIT);
   3267 }
   3268 
   3269 
   3270 /* Emit a store in the stack frame to save REGNO at address ADDR, and
   3271    emit the corresponding REG_CFA_OFFSET note described by CFA and
   3272    CFA_OFFSET.  Return the emitted insn.  */
   3273 static rtx
   3274 frame_emit_store (int regno, int regno_note, rtx addr, rtx cfa,
   3275 		  int cfa_offset)
   3276 {
   3277   rtx reg = gen_rtx_REG (Pmode, regno);
   3278   rtx mem = gen_frame_mem (Pmode, addr);
   3279   rtx mov = gen_movsi (mem, reg);
   3280 
   3281   /* Describe what just happened in a way that dwarf understands.  We
   3282      use temporary registers to hold the address to make scheduling
   3283      easier, and use the REG_CFA_OFFSET to describe the address as an
   3284      offset from the CFA.  */
   3285   rtx reg_note = gen_rtx_REG (Pmode, regno_note);
   3286   rtx cfa_relative_addr = gen_rtx_PLUS (Pmode, cfa, gen_int_si (cfa_offset));
   3287   rtx cfa_relative_mem = gen_frame_mem (Pmode, cfa_relative_addr);
   3288   rtx real = gen_rtx_SET (cfa_relative_mem, reg_note);
   3289   add_reg_note (mov, REG_CFA_OFFSET, real);
   3290 
   3291   return emit_insn (mov);
   3292 }
   3293 
   3294 
   3295 /* Emit a load in the stack frame to load REGNO from address ADDR.
   3296    Add a REG_CFA_RESTORE note to CFA_RESTORES if CFA_RESTORES is
   3297    non-null.  Return the emitted insn.  */
   3298 static rtx_insn *
   3299 frame_emit_load (int regno, rtx addr, rtx *cfa_restores)
   3300 {
   3301   rtx reg = gen_rtx_REG (Pmode, regno);
   3302   rtx mem = gen_frame_mem (Pmode, addr);
   3303   if (cfa_restores)
   3304     *cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, *cfa_restores);
   3305   return emit_insn (gen_movsi (reg, mem));
   3306 }
   3307 
   3308 
   3309 /* Helper function to set RTX_FRAME_RELATED_P on instructions,
   3310    including sequences.  */
   3311 static rtx_insn *
   3312 set_frame_related_p (void)
   3313 {
   3314   rtx_insn *seq = get_insns ();
   3315   rtx_insn *insn;
   3316 
   3317   end_sequence ();
   3318 
   3319   if (!seq)
   3320     return NULL;
   3321 
   3322   if (INSN_P (seq))
   3323     {
   3324       insn = seq;
   3325       while (insn != NULL_RTX)
   3326 	{
   3327 	  RTX_FRAME_RELATED_P (insn) = 1;
   3328 	  insn = NEXT_INSN (insn);
   3329 	}
   3330       seq = emit_insn (seq);
   3331     }
   3332   else
   3333     {
   3334       seq = emit_insn (seq);
   3335       RTX_FRAME_RELATED_P (seq) = 1;
   3336     }
   3337   return seq;
   3338 }
   3339 
   3340 
   3341 #define FRP(exp)  (start_sequence (), exp, set_frame_related_p ())
   3342 
   3343 /* This emits code for 'sp += offset'.
   3344 
   3345    The ABI only allows us to modify 'sp' in a single 'addi' or
   3346    'addli', so the backtracer understands it. Larger amounts cannot
   3347    use those instructions, so are added by placing the offset into a
   3348    large register and using 'add'.
   3349 
   3350    This happens after reload, so we need to expand it ourselves.  */
   3351 static rtx_insn *
   3352 emit_sp_adjust (int offset, int *next_scratch_regno, bool frame_related,
   3353 		rtx reg_notes)
   3354 {
   3355   rtx to_add;
   3356   rtx imm_rtx = gen_int_si (offset);
   3357 
   3358   rtx_insn *insn;
   3359   if (satisfies_constraint_J (imm_rtx))
   3360     {
   3361       /* We can add this using a single addi or addli.  */
   3362       to_add = imm_rtx;
   3363     }
   3364   else
   3365     {
   3366       rtx tmp = gen_rtx_REG (Pmode, (*next_scratch_regno)--);
   3367       tilepro_expand_set_const32 (tmp, imm_rtx);
   3368       to_add = tmp;
   3369     }
   3370 
   3371   /* Actually adjust the stack pointer.  */
   3372   insn = emit_insn (gen_sp_adjust (stack_pointer_rtx, stack_pointer_rtx,
   3373 				   to_add));
   3374   REG_NOTES (insn) = reg_notes;
   3375 
   3376   /* Describe what just happened in a way that dwarf understands.  */
   3377   if (frame_related)
   3378     {
   3379       rtx real = gen_rtx_SET (stack_pointer_rtx,
   3380 			      gen_rtx_PLUS (Pmode, stack_pointer_rtx,
   3381 					    imm_rtx));
   3382       RTX_FRAME_RELATED_P (insn) = 1;
   3383       add_reg_note (insn, REG_CFA_ADJUST_CFA, real);
   3384     }
   3385 
   3386   return insn;
   3387 }
   3388 
   3389 
   3390 /* Return whether the current function is leaf.  This takes into
   3391    account whether the function calls tls_get_addr.  */
   3392 static bool
   3393 tilepro_current_function_is_leaf (void)
   3394 {
   3395   return crtl->is_leaf && !cfun->machine->calls_tls_get_addr;
   3396 }
   3397 
   3398 
   3399 /* Return the frame size.  */
   3400 static int
   3401 compute_total_frame_size (void)
   3402 {
   3403   int total_size = (get_frame_size () + tilepro_saved_regs_size ()
   3404 		    + crtl->outgoing_args_size
   3405 		    + crtl->args.pretend_args_size);
   3406 
   3407   if (!tilepro_current_function_is_leaf () || cfun->calls_alloca)
   3408     {
   3409       /* Make room for save area in callee.  */
   3410       total_size += STACK_POINTER_OFFSET;
   3411     }
   3412 
   3413   return round_frame_size (total_size);
   3414 }
   3415 
   3416 
   3417 /* Return nonzero if this function is known to have a null epilogue.
   3418    This allows the optimizer to omit jumps to jumps if no stack was
   3419    created.  */
   3420 bool
   3421 tilepro_can_use_return_insn_p (void)
   3422 {
   3423   return (reload_completed
   3424 	  && cfun->static_chain_decl == 0
   3425 	  && compute_total_frame_size () == 0
   3426 	  && tilepro_current_function_is_leaf ()
   3427 	  && !crtl->profile && !df_regs_ever_live_p (TILEPRO_LINK_REGNUM));
   3428 }
   3429 
   3430 
   3431 /* Returns an rtx for a stack slot at 'FP + offset_from_fp'.  If there
   3432    is a frame pointer, it computes the value relative to
   3433    that. Otherwise it uses the stack pointer.  */
   3434 static rtx
   3435 compute_frame_addr (int offset_from_fp, int *next_scratch_regno)
   3436 {
   3437   rtx base_reg_rtx, tmp_reg_rtx, offset_rtx;
   3438   int offset_from_base;
   3439 
   3440   if (frame_pointer_needed)
   3441     {
   3442       base_reg_rtx = hard_frame_pointer_rtx;
   3443       offset_from_base = offset_from_fp;
   3444     }
   3445   else
   3446     {
   3447       int offset_from_sp = compute_total_frame_size () + offset_from_fp;
   3448       base_reg_rtx = stack_pointer_rtx;
   3449       offset_from_base = offset_from_sp;
   3450     }
   3451 
   3452   if (offset_from_base == 0)
   3453     return base_reg_rtx;
   3454 
   3455   /* Compute the new value of the stack pointer.  */
   3456   tmp_reg_rtx = gen_rtx_REG (Pmode, (*next_scratch_regno)--);
   3457   offset_rtx = gen_int_si (offset_from_base);
   3458 
   3459   if (!tilepro_expand_addsi (tmp_reg_rtx, base_reg_rtx, offset_rtx))
   3460     {
   3461       emit_insn (gen_rtx_SET (tmp_reg_rtx,
   3462 			      gen_rtx_PLUS (Pmode, base_reg_rtx,
   3463 					    offset_rtx)));
   3464     }
   3465 
   3466   return tmp_reg_rtx;
   3467 }
   3468 
   3469 
   3470 /* The stack frame looks like this:
   3471          +-------------+
   3472          |    ...      |
   3473          |  incoming   |
   3474          | stack args  |
   3475    AP -> +-------------+
   3476          | caller's HFP|
   3477          +-------------+
   3478          | lr save     |
   3479   HFP -> +-------------+
   3480          |  var args   |
   3481          |  reg save   | crtl->args.pretend_args_size bytes
   3482          +-------------+
   3483          |    ...      |
   3484          | saved regs  | tilepro_saved_regs_size() bytes
   3485    FP -> +-------------+
   3486          |    ...      |
   3487          |   vars      | get_frame_size() bytes
   3488          +-------------+
   3489          |    ...      |
   3490          |  outgoing   |
   3491          |  stack args | crtl->outgoing_args_size bytes
   3492          +-------------+
   3493          | HFP         | 4 bytes (only here if nonleaf / alloca)
   3494          +-------------+
   3495          | callee lr   | 4 bytes (only here if nonleaf / alloca)
   3496          | save        |
   3497    SP -> +-------------+
   3498 
   3499   HFP == incoming SP.
   3500 
   3501   For functions with a frame larger than 32767 bytes, or which use
   3502   alloca (), r52 is used as a frame pointer.  Otherwise there is no
   3503   frame pointer.
   3504 
   3505   FP is saved at SP+4 before calling a subroutine so the
   3506   callee can chain.  */
   3507 void
   3508 tilepro_expand_prologue (void)
   3509 {
   3510 #define ROUND_ROBIN_SIZE 4
   3511   /* We round-robin through four scratch registers to hold temporary
   3512      addresses for saving registers, to make instruction scheduling
   3513      easier.  */
   3514   rtx reg_save_addr[ROUND_ROBIN_SIZE] = {
   3515     NULL_RTX, NULL_RTX, NULL_RTX, NULL_RTX
   3516   };
   3517   rtx insn, cfa;
   3518   unsigned int which_scratch;
   3519   int offset, start_offset, regno;
   3520 
   3521   /* A register that holds a copy of the incoming fp.  */
   3522   int fp_copy_regno = -1;
   3523 
   3524   /* A register that holds a copy of the incoming sp.  */
   3525   int sp_copy_regno = -1;
   3526 
   3527   /* Next scratch register number to hand out (postdecrementing).  */
   3528   int next_scratch_regno = 29;
   3529 
   3530   int total_size = compute_total_frame_size ();
   3531 
   3532   if (flag_stack_usage_info)
   3533     current_function_static_stack_size = total_size;
   3534 
   3535   /* Save lr first in its special location because code after this
   3536      might use the link register as a scratch register.  */
   3537   if (df_regs_ever_live_p (TILEPRO_LINK_REGNUM) || crtl->calls_eh_return)
   3538     {
   3539       FRP (frame_emit_store (TILEPRO_LINK_REGNUM, TILEPRO_LINK_REGNUM,
   3540 			     stack_pointer_rtx, stack_pointer_rtx, 0));
   3541       emit_insn (gen_blockage ());
   3542     }
   3543 
   3544   if (total_size == 0)
   3545     {
   3546       /* Load the PIC register if needed.  */
   3547       if (flag_pic && crtl->uses_pic_offset_table)
   3548 	load_pic_register (false);
   3549 
   3550       return;
   3551     }
   3552 
   3553   cfa = stack_pointer_rtx;
   3554 
   3555   if (frame_pointer_needed)
   3556     {
   3557       fp_copy_regno = next_scratch_regno--;
   3558 
   3559       /* Copy the old frame pointer aside so we can save it later.  */
   3560       insn = FRP (emit_move_insn (gen_rtx_REG (word_mode, fp_copy_regno),
   3561 				  hard_frame_pointer_rtx));
   3562       add_reg_note (insn, REG_CFA_REGISTER, NULL_RTX);
   3563 
   3564       /* Set up the frame pointer.  */
   3565       insn = FRP (emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx));
   3566       add_reg_note (insn, REG_CFA_DEF_CFA, hard_frame_pointer_rtx);
   3567       cfa = hard_frame_pointer_rtx;
   3568       REGNO_POINTER_ALIGN (HARD_FRAME_POINTER_REGNUM) = STACK_BOUNDARY;
   3569 
   3570       /* fp holds a copy of the incoming sp, in case we need to store
   3571          it.  */
   3572       sp_copy_regno = HARD_FRAME_POINTER_REGNUM;
   3573     }
   3574   else if (!tilepro_current_function_is_leaf ())
   3575     {
   3576       /* Copy the old stack pointer aside so we can save it later.  */
   3577       sp_copy_regno = next_scratch_regno--;
   3578       emit_move_insn (gen_rtx_REG (Pmode, sp_copy_regno),
   3579 		      stack_pointer_rtx);
   3580     }
   3581 
   3582   if (tilepro_current_function_is_leaf ())
   3583     {
   3584       /* No need to store chain pointer to caller's frame.  */
   3585       emit_sp_adjust (-total_size, &next_scratch_regno,
   3586 		      !frame_pointer_needed, NULL_RTX);
   3587     }
   3588   else
   3589     {
   3590       /* Save the frame pointer (incoming sp value) to support
   3591          backtracing.  First we need to create an rtx with the store
   3592          address.  */
   3593       rtx chain_addr = gen_rtx_REG (Pmode, next_scratch_regno--);
   3594       rtx size_rtx = gen_int_si (-(total_size - UNITS_PER_WORD));
   3595 
   3596       if (add_operand (size_rtx, Pmode))
   3597 	{
   3598 	  /* Expose more parallelism by computing this value from the
   3599 	     original stack pointer, not the one after we have pushed
   3600 	     the frame.  */
   3601 	  rtx p = gen_rtx_PLUS (Pmode, stack_pointer_rtx, size_rtx);
   3602 	  emit_insn (gen_rtx_SET (chain_addr, p));
   3603 	  emit_sp_adjust (-total_size, &next_scratch_regno,
   3604 			  !frame_pointer_needed, NULL_RTX);
   3605 	}
   3606       else
   3607 	{
   3608 	  /* The stack frame is large, so just store the incoming sp
   3609 	     value at *(new_sp + UNITS_PER_WORD).  */
   3610 	  rtx p;
   3611 	  emit_sp_adjust (-total_size, &next_scratch_regno,
   3612 			  !frame_pointer_needed, NULL_RTX);
   3613 	  p = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
   3614 			    GEN_INT (UNITS_PER_WORD));
   3615 	  emit_insn (gen_rtx_SET (chain_addr, p));
   3616 	}
   3617 
   3618       /* Save our frame pointer for backtrace chaining.  */
   3619       emit_insn (gen_movsi (gen_frame_mem (SImode, chain_addr),
   3620 			    gen_rtx_REG (SImode, sp_copy_regno)));
   3621     }
   3622 
   3623   /* Compute where to start storing registers we need to save.  */
   3624   start_offset = -crtl->args.pretend_args_size - UNITS_PER_WORD;
   3625   offset = start_offset;
   3626 
   3627   /* Store all registers that need saving.  */
   3628   which_scratch = 0;
   3629   for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--)
   3630     if (need_to_save_reg (regno))
   3631       {
   3632 	rtx r = reg_save_addr[which_scratch];
   3633 	int from_regno;
   3634 	int cfa_offset = frame_pointer_needed ? offset : total_size + offset;
   3635 
   3636 	if (r == NULL_RTX)
   3637 	  {
   3638 	    rtx p = compute_frame_addr (offset, &next_scratch_regno);
   3639 	    r = gen_rtx_REG (word_mode, next_scratch_regno--);
   3640 	    reg_save_addr[which_scratch] = r;
   3641 
   3642 	    emit_insn (gen_rtx_SET (r, p));
   3643 	  }
   3644 	else
   3645 	  {
   3646 	    /* Advance to the next stack slot to store this register.  */
   3647 	    int stride = ROUND_ROBIN_SIZE * -UNITS_PER_WORD;
   3648 	    rtx p = gen_rtx_PLUS (Pmode, r, GEN_INT (stride));
   3649 	    emit_insn (gen_rtx_SET (r, p));
   3650 	  }
   3651 
   3652 	/* Save this register to the stack (but use the old fp value
   3653 	   we copied aside if appropriate).  */
   3654 	from_regno = (fp_copy_regno >= 0
   3655 		      && regno ==
   3656 		      HARD_FRAME_POINTER_REGNUM) ? fp_copy_regno : regno;
   3657 	FRP (frame_emit_store (from_regno, regno, r, cfa, cfa_offset));
   3658 
   3659 	offset -= UNITS_PER_WORD;
   3660 	which_scratch = (which_scratch + 1) % ROUND_ROBIN_SIZE;
   3661       }
   3662 
   3663   /* If profiling, force that to happen after the frame is set up.  */
   3664   if (crtl->profile)
   3665     emit_insn (gen_blockage ());
   3666 
   3667   /* Load the PIC register if needed.  */
   3668   if (flag_pic && crtl->uses_pic_offset_table)
   3669     load_pic_register (false);
   3670 }
   3671 
   3672 
   3673 /* Implement the epilogue and sibcall_epilogue patterns.  SIBCALL_P is
   3674    true for a sibcall_epilogue pattern, and false for an epilogue
   3675    pattern.  */
   3676 void
   3677 tilepro_expand_epilogue (bool sibcall_p)
   3678 {
   3679   /* We round-robin through four scratch registers to hold temporary
   3680      addresses for saving registers, to make instruction scheduling
   3681      easier.  */
   3682   rtx reg_save_addr[ROUND_ROBIN_SIZE] = {
   3683     NULL_RTX, NULL_RTX, NULL_RTX, NULL_RTX
   3684   };
   3685   rtx_insn *last_insn, *insn;
   3686   unsigned int which_scratch;
   3687   int offset, start_offset, regno;
   3688   rtx cfa_restores = NULL_RTX;
   3689 
   3690   /* A register that holds a copy of the incoming fp.  */
   3691   int fp_copy_regno = -1;
   3692 
   3693   /* Next scratch register number to hand out (postdecrementing).  */
   3694   int next_scratch_regno = 29;
   3695 
   3696   int total_size = compute_total_frame_size ();
   3697 
   3698   last_insn = get_last_insn ();
   3699 
   3700   /* Load lr first since we are going to need it first.  */
   3701   insn = NULL;
   3702   if (df_regs_ever_live_p (TILEPRO_LINK_REGNUM))
   3703     {
   3704       insn = frame_emit_load (TILEPRO_LINK_REGNUM,
   3705 			      compute_frame_addr (0, &next_scratch_regno),
   3706 			      &cfa_restores);
   3707     }
   3708 
   3709   if (total_size == 0)
   3710     {
   3711       if (insn)
   3712 	{
   3713 	  RTX_FRAME_RELATED_P (insn) = 1;
   3714 	  REG_NOTES (insn) = cfa_restores;
   3715 	}
   3716       goto done;
   3717     }
   3718 
   3719   /* Compute where to start restoring registers.  */
   3720   start_offset = -crtl->args.pretend_args_size - UNITS_PER_WORD;
   3721   offset = start_offset;
   3722 
   3723   if (frame_pointer_needed)
   3724     fp_copy_regno = next_scratch_regno--;
   3725 
   3726   /* Restore all callee-saved registers.  */
   3727   which_scratch = 0;
   3728   for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--)
   3729     if (need_to_save_reg (regno))
   3730       {
   3731 	rtx r = reg_save_addr[which_scratch];
   3732 	if (r == NULL_RTX)
   3733 	  {
   3734 	    r = compute_frame_addr (offset, &next_scratch_regno);
   3735 	    reg_save_addr[which_scratch] = r;
   3736 	  }
   3737 	else
   3738 	  {
   3739 	    /* Advance to the next stack slot to store this
   3740 	       register.  */
   3741 	    int stride = ROUND_ROBIN_SIZE * -UNITS_PER_WORD;
   3742 	    rtx p = gen_rtx_PLUS (Pmode, r, GEN_INT (stride));
   3743 	    emit_insn (gen_rtx_SET (r, p));
   3744 	  }
   3745 
   3746 	if (fp_copy_regno >= 0 && regno == HARD_FRAME_POINTER_REGNUM)
   3747 	  frame_emit_load (fp_copy_regno, r, NULL);
   3748 	else
   3749 	  frame_emit_load (regno, r, &cfa_restores);
   3750 
   3751 	offset -= UNITS_PER_WORD;
   3752 	which_scratch = (which_scratch + 1) % ROUND_ROBIN_SIZE;
   3753       }
   3754 
   3755   if (!tilepro_current_function_is_leaf ())
   3756     cfa_restores =
   3757       alloc_reg_note (REG_CFA_RESTORE, stack_pointer_rtx, cfa_restores);
   3758 
   3759   emit_insn (gen_blockage ());
   3760 
   3761   if (frame_pointer_needed)
   3762     {
   3763       /* Restore the old stack pointer by copying from the frame
   3764          pointer.  */
   3765       insn = emit_insn (gen_sp_restore (stack_pointer_rtx,
   3766 					hard_frame_pointer_rtx));
   3767       RTX_FRAME_RELATED_P (insn) = 1;
   3768       REG_NOTES (insn) = cfa_restores;
   3769       add_reg_note (insn, REG_CFA_DEF_CFA, stack_pointer_rtx);
   3770     }
   3771   else
   3772     {
   3773       insn = emit_sp_adjust (total_size, &next_scratch_regno, true,
   3774 			     cfa_restores);
   3775     }
   3776 
   3777   if (crtl->calls_eh_return)
   3778     emit_insn (gen_sp_adjust (stack_pointer_rtx, stack_pointer_rtx,
   3779 			      EH_RETURN_STACKADJ_RTX));
   3780 
   3781   /* Restore the old frame pointer.  */
   3782   if (frame_pointer_needed)
   3783     {
   3784       insn = emit_move_insn (hard_frame_pointer_rtx,
   3785 			     gen_rtx_REG (Pmode, fp_copy_regno));
   3786       add_reg_note (insn, REG_CFA_RESTORE, hard_frame_pointer_rtx);
   3787     }
   3788 
   3789   /* Mark the pic registers as live outside of the function.  */
   3790   if (flag_pic)
   3791     {
   3792       emit_use (cfun->machine->text_label_rtx);
   3793       emit_use (cfun->machine->got_rtx);
   3794     }
   3795 
   3796 done:
   3797   if (!sibcall_p)
   3798     {
   3799       /* Emit the actual 'return' instruction.  */
   3800       emit_jump_insn (gen__return ());
   3801     }
   3802   else
   3803     {
   3804       emit_use (gen_rtx_REG (Pmode, TILEPRO_LINK_REGNUM));
   3805     }
   3806 
   3807   /* Mark all insns we just emitted as frame-related.  */
   3808   for (; last_insn != NULL_RTX; last_insn = next_insn (last_insn))
   3809     RTX_FRAME_RELATED_P (last_insn) = 1;
   3810 }
   3811 
   3812 #undef ROUND_ROBIN_SIZE
   3813 
   3814 
   3815 /* Implement INITIAL_ELIMINATION_OFFSET.  */
   3816 int
   3817 tilepro_initial_elimination_offset (int from, int to)
   3818 {
   3819   int total_size = compute_total_frame_size ();
   3820 
   3821   if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
   3822     {
   3823       return (total_size - crtl->args.pretend_args_size
   3824 	      - tilepro_saved_regs_size ());
   3825     }
   3826   else if (from == FRAME_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
   3827     {
   3828       return -(crtl->args.pretend_args_size + tilepro_saved_regs_size ());
   3829     }
   3830   else if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
   3831     {
   3832       return STACK_POINTER_OFFSET + total_size;
   3833     }
   3834   else if (from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
   3835     {
   3836       return STACK_POINTER_OFFSET;
   3837     }
   3838   else
   3839     gcc_unreachable ();
   3840 }
   3841 
   3842 
   3843 /* Return an RTX indicating where the return address to the
   3844    calling function can be found.  */
   3845 rtx
   3846 tilepro_return_addr (int count, rtx frame ATTRIBUTE_UNUSED)
   3847 {
   3848   if (count != 0)
   3849     return const0_rtx;
   3850 
   3851   return get_hard_reg_initial_val (Pmode, TILEPRO_LINK_REGNUM);
   3852 }
   3853 
   3854 
   3855 /* Implement EH_RETURN_HANDLER_RTX.  */
   3856 rtx
   3857 tilepro_eh_return_handler_rtx (void)
   3858 {
   3859   /* The MEM needs to be volatile to prevent it from being
   3860      deleted.  */
   3861   rtx tmp = gen_frame_mem (Pmode, hard_frame_pointer_rtx);
   3862   MEM_VOLATILE_P (tmp) = true;
   3863   return tmp;
   3864 }
   3865 
   3866 
   3868 
   3869 /* Registers  */
   3870 
   3871 /* Implemnet TARGET_CONDITIONAL_REGISTER_USAGE.  */
   3872 static void
   3873 tilepro_conditional_register_usage (void)
   3874 {
   3875   global_regs[TILEPRO_NETORDER_REGNUM] = 1;
   3876   /* TILEPRO_PIC_TEXT_LABEL_REGNUM is conditionally used.  */
   3877   if (TILEPRO_PIC_TEXT_LABEL_REGNUM != INVALID_REGNUM)
   3878     fixed_regs[TILEPRO_PIC_TEXT_LABEL_REGNUM] = 1;
   3879   if (PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM)
   3880     fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
   3881 }
   3882 
   3883 
   3884 /* Implement TARGET_FRAME_POINTER_REQUIRED.  */
   3885 static bool
   3886 tilepro_frame_pointer_required (void)
   3887 {
   3888   return crtl->calls_eh_return || cfun->calls_alloca;
   3889 }
   3890 
   3891 
   3893 
   3894 /* Scheduling and reorg  */
   3895 
   3896 /* Return the length of INSN.  LENGTH is the initial length computed
   3897    by attributes in the machine-description file.  This is where we
   3898    account for bundles.  */
   3899 int
   3900 tilepro_adjust_insn_length (rtx_insn *insn, int length)
   3901 {
   3902   machine_mode mode = GET_MODE (insn);
   3903 
   3904   /* A non-termininating instruction in a bundle has length 0.  */
   3905   if (mode == SImode)
   3906     return 0;
   3907 
   3908   /* By default, there is not length adjustment.  */
   3909   return length;
   3910 }
   3911 
   3912 
   3913 /* Implement TARGET_SCHED_ISSUE_RATE.  */
   3914 static int
   3915 tilepro_issue_rate (void)
   3916 {
   3917   return 3;
   3918 }
   3919 
   3920 
   3921 /* Return the rtx for the jump target.  */
   3922 static rtx
   3923 get_jump_target (rtx branch)
   3924 {
   3925   if (CALL_P (branch))
   3926     {
   3927       rtx call;
   3928       call = PATTERN (branch);
   3929 
   3930       if (GET_CODE (call) == PARALLEL)
   3931 	call = XVECEXP (call, 0, 0);
   3932 
   3933       if (GET_CODE (call) == SET)
   3934 	call = SET_SRC (call);
   3935 
   3936       if (GET_CODE (call) == CALL)
   3937 	return XEXP (XEXP (call, 0), 0);
   3938     }
   3939   return 0;
   3940 }
   3941 
   3942 /* Implement TARGET_SCHED_ADJUST_COST.  */
   3943 static int
   3944 tilepro_sched_adjust_cost (rtx_insn *insn, int dep_type, rtx_insn *dep_insn,
   3945 			   int cost, unsigned int)
   3946 {
   3947   /* If we have a true dependence, INSN is a call, and DEP_INSN
   3948      defines a register that is needed by the call (argument or stack
   3949      pointer), set its latency to 0 so that it can be bundled with
   3950      the call.  Explicitly check for and exclude the case when
   3951      DEP_INSN defines the target of the jump.  */
   3952   if (CALL_P (insn) && dep_type == REG_DEP_TRUE)
   3953     {
   3954       rtx target = get_jump_target (insn);
   3955       if (!REG_P (target) || !set_of (target, dep_insn))
   3956 	return 0;
   3957     }
   3958 
   3959   return cost;
   3960 }
   3961 
   3962 
   3963 /* Skip over irrelevant NOTEs and such and look for the next insn we
   3964    would consider bundling.  */
   3965 static rtx_insn *
   3966 next_insn_to_bundle (rtx_insn *r, rtx_insn *end)
   3967 {
   3968   for (; r != end; r = NEXT_INSN (r))
   3969     {
   3970       if (NONDEBUG_INSN_P (r)
   3971 	  && GET_CODE (PATTERN (r)) != USE
   3972 	  && GET_CODE (PATTERN (r)) != CLOBBER)
   3973 	return r;
   3974     }
   3975 
   3976   return NULL;
   3977 }
   3978 
   3979 
   3980 /* Go through all insns, and use the information generated during
   3981    scheduling to generate SEQUENCEs to represent bundles of
   3982    instructions issued simultaneously.  */
   3983 static void
   3984 tilepro_gen_bundles (void)
   3985 {
   3986   basic_block bb;
   3987   FOR_EACH_BB_FN (bb, cfun)
   3988   {
   3989     rtx_insn *insn, *next;
   3990     rtx_insn *end = NEXT_INSN (BB_END (bb));
   3991 
   3992     for (insn = next_insn_to_bundle (BB_HEAD (bb), end); insn; insn = next)
   3993       {
   3994 	next = next_insn_to_bundle (NEXT_INSN (insn), end);
   3995 
   3996 	/* Never wrap {} around inline asm.  */
   3997 	if (GET_CODE (PATTERN (insn)) != ASM_INPUT)
   3998 	  {
   3999 	    if (next == NULL_RTX || GET_MODE (next) == TImode
   4000 		/* NOTE: The scheduler incorrectly believes a call
   4001 		   insn can execute in the same cycle as the insn
   4002 		   after the call.  This is of course impossible.
   4003 		   Really we need to fix the scheduler somehow, so
   4004 		   the code after the call gets scheduled
   4005 		   optimally.  */
   4006 		|| CALL_P (insn))
   4007 	      {
   4008 		/* Mark current insn as the end of a bundle.  */
   4009 		PUT_MODE (insn, QImode);
   4010 	      }
   4011 	    else
   4012 	      {
   4013 		/* Mark it as part of a bundle.  */
   4014 		PUT_MODE (insn, SImode);
   4015 	      }
   4016 	  }
   4017       }
   4018   }
   4019 }
   4020 
   4021 
   4022 /* Helper function for tilepro_fixup_pcrel_references.  */
   4023 static void
   4024 replace_pc_relative_symbol_ref (rtx_insn *insn, rtx opnds[4], bool first_insn_p)
   4025 {
   4026   rtx_insn *new_insns;
   4027 
   4028   start_sequence ();
   4029 
   4030   if (flag_pic == 1)
   4031     {
   4032       if (!first_insn_p)
   4033 	{
   4034 	  emit_insn (gen_add_got16 (opnds[0], tilepro_got_rtx (),
   4035 				    opnds[2]));
   4036 	  emit_insn (gen_insn_lw (opnds[0], opnds[0]));
   4037 	}
   4038     }
   4039   else
   4040     {
   4041       if (first_insn_p)
   4042 	{
   4043 	  emit_insn (gen_addhi_got32 (opnds[0], tilepro_got_rtx (),
   4044 				      opnds[2]));
   4045 	}
   4046       else
   4047 	{
   4048 	  emit_insn (gen_addlo_got32 (opnds[0], opnds[1], opnds[2]));
   4049 	  emit_insn (gen_insn_lw (opnds[0], opnds[0]));
   4050 	}
   4051     }
   4052 
   4053   new_insns = get_insns ();
   4054   end_sequence ();
   4055 
   4056   if (new_insns)
   4057     emit_insn_before (new_insns, insn);
   4058 
   4059   delete_insn (insn);
   4060 }
   4061 
   4062 
   4063 /* Returns whether INSN is a pc-relative addli insn.   */
   4064 static bool
   4065 match_addli_pcrel (rtx_insn *insn)
   4066 {
   4067   rtx pattern = PATTERN (insn);
   4068   rtx unspec;
   4069 
   4070   if (GET_CODE (pattern) != SET)
   4071     return false;
   4072 
   4073   if (GET_CODE (SET_SRC (pattern)) != LO_SUM)
   4074     return false;
   4075 
   4076   if (GET_CODE (XEXP (SET_SRC (pattern), 1)) != CONST)
   4077     return false;
   4078 
   4079   unspec = XEXP (XEXP (SET_SRC (pattern), 1), 0);
   4080 
   4081   return (GET_CODE (unspec) == UNSPEC
   4082 	  && XINT (unspec, 1) == UNSPEC_PCREL_SYM);
   4083 }
   4084 
   4085 
   4086 /* Helper function for tilepro_fixup_pcrel_references.  */
   4087 static void
   4088 replace_addli_pcrel (rtx_insn *insn)
   4089 {
   4090   rtx pattern = PATTERN (insn);
   4091   rtx set_src;
   4092   rtx unspec;
   4093   rtx opnds[4];
   4094   bool first_insn_p;
   4095 
   4096   gcc_assert (GET_CODE (pattern) == SET);
   4097   opnds[0] = SET_DEST (pattern);
   4098 
   4099   set_src = SET_SRC (pattern);
   4100   gcc_assert (GET_CODE (set_src) == LO_SUM);
   4101   gcc_assert (GET_CODE (XEXP (set_src, 1)) == CONST);
   4102   opnds[1] = XEXP (set_src, 0);
   4103 
   4104   unspec = XEXP (XEXP (set_src, 1), 0);
   4105   gcc_assert (GET_CODE (unspec) == UNSPEC);
   4106   gcc_assert (XINT (unspec, 1) == UNSPEC_PCREL_SYM);
   4107   opnds[2] = XVECEXP (unspec, 0, 0);
   4108   opnds[3] = XVECEXP (unspec, 0, 1);
   4109 
   4110   /* We only need to replace SYMBOL_REFs, not LABEL_REFs.  */
   4111   if (GET_CODE (opnds[2]) != SYMBOL_REF)
   4112     return;
   4113 
   4114   first_insn_p = (opnds[1] == tilepro_text_label_rtx ());
   4115 
   4116   replace_pc_relative_symbol_ref (insn, opnds, first_insn_p);
   4117 }
   4118 
   4119 
   4120 /* Returns whether INSN is a pc-relative auli insn.   */
   4121 static bool
   4122 match_auli_pcrel (rtx_insn *insn)
   4123 {
   4124   rtx pattern = PATTERN (insn);
   4125   rtx high;
   4126   rtx unspec;
   4127 
   4128   if (GET_CODE (pattern) != SET)
   4129     return false;
   4130 
   4131   if (GET_CODE (SET_SRC (pattern)) != PLUS)
   4132     return false;
   4133 
   4134   high = XEXP (SET_SRC (pattern), 1);
   4135 
   4136   if (GET_CODE (high) != HIGH
   4137       || GET_CODE (XEXP (high, 0)) != CONST)
   4138     return false;
   4139 
   4140   unspec = XEXP (XEXP (high, 0), 0);
   4141 
   4142   return (GET_CODE (unspec) == UNSPEC
   4143 	  && XINT (unspec, 1) == UNSPEC_PCREL_SYM);
   4144 }
   4145 
   4146 
   4147 /* Helper function for tilepro_fixup_pcrel_references.  */
   4148 static void
   4149 replace_auli_pcrel (rtx_insn *insn)
   4150 {
   4151   rtx pattern = PATTERN (insn);
   4152   rtx set_src;
   4153   rtx high;
   4154   rtx unspec;
   4155   rtx opnds[4];
   4156   bool first_insn_p;
   4157 
   4158   gcc_assert (GET_CODE (pattern) == SET);
   4159   opnds[0] = SET_DEST (pattern);
   4160 
   4161   set_src = SET_SRC (pattern);
   4162   gcc_assert (GET_CODE (set_src) == PLUS);
   4163   opnds[1] = XEXP (set_src, 0);
   4164 
   4165   high = XEXP (set_src, 1);
   4166   gcc_assert (GET_CODE (high) == HIGH);
   4167   gcc_assert (GET_CODE (XEXP (high, 0)) == CONST);
   4168 
   4169   unspec = XEXP (XEXP (high, 0), 0);
   4170   gcc_assert (GET_CODE (unspec) == UNSPEC);
   4171   gcc_assert (XINT (unspec, 1) == UNSPEC_PCREL_SYM);
   4172   opnds[2] = XVECEXP (unspec, 0, 0);
   4173   opnds[3] = XVECEXP (unspec, 0, 1);
   4174 
   4175   /* We only need to replace SYMBOL_REFs, not LABEL_REFs.  */
   4176   if (GET_CODE (opnds[2]) != SYMBOL_REF)
   4177     return;
   4178 
   4179   first_insn_p = (opnds[1] == tilepro_text_label_rtx ());
   4180 
   4181   replace_pc_relative_symbol_ref (insn, opnds, first_insn_p);
   4182 }
   4183 
   4184 
   4185 /* We generate PC relative SYMBOL_REFs as an optimization, to avoid
   4186    going through the GOT when the symbol is local to the compilation
   4187    unit.  But such a symbol requires that the common text_label that
   4188    we generate at the beginning of the function be in the same section
   4189    as the reference to the SYMBOL_REF.  This may not be true if we
   4190    generate hot/cold sections.  This function looks for such cases and
   4191    replaces such references with the longer sequence going through the
   4192    GOT.
   4193 
   4194    We expect one of the following two instruction sequences:
   4195    addli tmp1, txt_label_reg, lo16(sym - txt_label)
   4196    auli  tmp2,          tmp1, ha16(sym - txt_label)
   4197 
   4198    auli  tmp1, txt_label_reg, ha16(sym - txt_label)
   4199    addli tmp2,          tmp1, lo16(sym - txt_label)
   4200 
   4201    If we're compiling -fpic, we replace the first instruction with
   4202    nothing, and the second instruction with:
   4203 
   4204    addli tmp2, got_rtx, got(sym)
   4205    lw    tmp2,    tmp2
   4206 
   4207    If we're compiling -fPIC, we replace the first instruction with:
   4208 
   4209    auli  tmp1, got_rtx, got_ha16(sym)
   4210 
   4211    and the second instruction with:
   4212 
   4213    addli tmp2,    tmp1, got_lo16(sym)
   4214    lw    tmp2,    tmp2
   4215 
   4216    Note that we're careful to disturb the instruction sequence as
   4217    little as possible, since it's very late in the compilation
   4218    process.
   4219 */
   4220 static void
   4221 tilepro_fixup_pcrel_references (void)
   4222 {
   4223   rtx_insn *insn, *next_insn;
   4224   bool same_section_as_entry = true;
   4225 
   4226   for (insn = get_insns (); insn; insn = next_insn)
   4227     {
   4228       next_insn = NEXT_INSN (insn);
   4229 
   4230       if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_SWITCH_TEXT_SECTIONS)
   4231 	{
   4232 	  same_section_as_entry = !same_section_as_entry;
   4233 	  continue;
   4234 	}
   4235 
   4236       if (same_section_as_entry)
   4237       	continue;
   4238 
   4239       if (!(INSN_P (insn)
   4240 	    && GET_CODE (PATTERN (insn)) != USE
   4241 	    && GET_CODE (PATTERN (insn)) != CLOBBER))
   4242 	continue;
   4243 
   4244       if (match_addli_pcrel (insn))
   4245 	replace_addli_pcrel (insn);
   4246       else if (match_auli_pcrel (insn))
   4247 	replace_auli_pcrel (insn);
   4248     }
   4249 }
   4250 
   4251 
   4252 /* Ensure that no var tracking notes are emitted in the middle of a
   4253    three-instruction bundle.  */
   4254 static void
   4255 reorder_var_tracking_notes (void)
   4256 {
   4257   basic_block bb;
   4258   FOR_EACH_BB_FN (bb, cfun)
   4259   {
   4260     rtx_insn *insn, *next;
   4261     rtx_insn *queue = NULL;
   4262     bool in_bundle = false;
   4263 
   4264     for (insn = BB_HEAD (bb); insn != BB_END (bb); insn = next)
   4265       {
   4266 	next = NEXT_INSN (insn);
   4267 
   4268 	if (INSN_P (insn))
   4269 	  {
   4270 	    /* Emit queued up notes at the last instruction of a bundle.  */
   4271 	    if (GET_MODE (insn) == QImode)
   4272 	      {
   4273 		while (queue)
   4274 		  {
   4275 		    rtx_insn *next_queue = PREV_INSN (queue);
   4276 		    SET_PREV_INSN (NEXT_INSN (insn)) = queue;
   4277 		    SET_NEXT_INSN (queue) = NEXT_INSN (insn);
   4278 		    SET_NEXT_INSN (insn) = queue;
   4279 		    SET_PREV_INSN (queue) = insn;
   4280 		    queue = next_queue;
   4281 		  }
   4282 		in_bundle = false;
   4283 	      }
   4284 	    else if (GET_MODE (insn) == SImode)
   4285 	      in_bundle = true;
   4286 	  }
   4287 	else if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_VAR_LOCATION)
   4288 	  {
   4289 	    if (in_bundle)
   4290 	      {
   4291 		rtx_insn *prev = PREV_INSN (insn);
   4292 		SET_PREV_INSN (next) = prev;
   4293 		SET_NEXT_INSN (prev) = next;
   4294 
   4295 		SET_PREV_INSN (insn) = queue;
   4296 		queue = insn;
   4297 	      }
   4298 	  }
   4299       }
   4300   }
   4301 }
   4302 
   4303 
   4304 /* Perform machine dependent operations on the rtl chain INSNS.  */
   4305 static void
   4306 tilepro_reorg (void)
   4307 {
   4308   /* We are freeing block_for_insn in the toplev to keep compatibility
   4309      with old MDEP_REORGS that are not CFG based.  Recompute it
   4310      now.  */
   4311   compute_bb_for_insn ();
   4312 
   4313   if (flag_reorder_blocks_and_partition)
   4314     {
   4315       tilepro_fixup_pcrel_references ();
   4316     }
   4317 
   4318   if (flag_schedule_insns_after_reload)
   4319     {
   4320       split_all_insns ();
   4321 
   4322       timevar_push (TV_SCHED2);
   4323       schedule_insns ();
   4324       timevar_pop (TV_SCHED2);
   4325 
   4326       /* Examine the schedule to group into bundles.  */
   4327       tilepro_gen_bundles ();
   4328     }
   4329 
   4330   df_analyze ();
   4331 
   4332   if (flag_var_tracking)
   4333     {
   4334       timevar_push (TV_VAR_TRACKING);
   4335       variable_tracking_main ();
   4336       reorder_var_tracking_notes ();
   4337       timevar_pop (TV_VAR_TRACKING);
   4338     }
   4339 
   4340   df_finish_pass (false);
   4341 }
   4342 
   4343 
   4345 
   4346 /* Assembly  */
   4347 
   4348 /* Select a format to encode pointers in exception handling data.
   4349    CODE is 0 for data, 1 for code labels, 2 for function pointers.
   4350    GLOBAL is true if the symbol may be affected by dynamic
   4351    relocations.  */
   4352 int
   4353 tilepro_asm_preferred_eh_data_format (int code ATTRIBUTE_UNUSED, int global)
   4354 {
   4355   return (global ? DW_EH_PE_indirect : 0) | DW_EH_PE_pcrel | DW_EH_PE_sdata4;
   4356 }
   4357 
   4358 
   4359 /* Implement TARGET_ASM_OUTPUT_MI_THUNK.  */
   4360 static void
   4361 tilepro_asm_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
   4362 			     HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
   4363 			     tree function)
   4364 {
   4365   const char *fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk_fndecl));
   4366   rtx this_rtx, funexp;
   4367   rtx_insn *insn;
   4368 
   4369   /* Pretend to be a post-reload pass while generating rtl.  */
   4370   reload_completed = 1;
   4371 
   4372   /* Mark the end of the (empty) prologue.  */
   4373   emit_note (NOTE_INSN_PROLOGUE_END);
   4374 
   4375   /* Find the "this" pointer.  If the function returns a structure,
   4376      the structure return pointer is in $1.  */
   4377   if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))
   4378     this_rtx = gen_rtx_REG (Pmode, 1);
   4379   else
   4380     this_rtx = gen_rtx_REG (Pmode, 0);
   4381 
   4382   /* Add DELTA to THIS_RTX.  */
   4383   emit_insn (gen_addsi3 (this_rtx, this_rtx, GEN_INT (delta)));
   4384 
   4385   /* If needed, add *(*THIS_RTX + VCALL_OFFSET) to THIS_RTX.  */
   4386   if (vcall_offset)
   4387     {
   4388       rtx tmp;
   4389 
   4390       tmp = gen_rtx_REG (Pmode, 29);
   4391       emit_move_insn (tmp, gen_rtx_MEM (Pmode, this_rtx));
   4392 
   4393       emit_insn (gen_addsi3 (tmp, tmp, GEN_INT (vcall_offset)));
   4394 
   4395       emit_move_insn (tmp, gen_rtx_MEM (Pmode, tmp));
   4396 
   4397       emit_insn (gen_addsi3 (this_rtx, this_rtx, tmp));
   4398     }
   4399 
   4400   /* Generate a tail call to the target function.  */
   4401   if (!TREE_USED (function))
   4402     {
   4403       assemble_external (function);
   4404       TREE_USED (function) = 1;
   4405     }
   4406   funexp = XEXP (DECL_RTL (function), 0);
   4407   funexp = gen_rtx_MEM (FUNCTION_MODE, funexp);
   4408   insn = emit_call_insn (gen_sibcall (funexp, const0_rtx));
   4409   SIBLING_CALL_P (insn) = 1;
   4410 
   4411   /* Run just enough of rest_of_compilation to get the insns emitted.
   4412      There's not really enough bulk here to make other passes such as
   4413      instruction scheduling worth while.
   4414 
   4415      We don't currently bundle, but the instruciton sequence is all
   4416      serial except for the tail call, so we're only wasting one cycle.
   4417    */
   4418   insn = get_insns ();
   4419   shorten_branches (insn);
   4420   assemble_start_function (thunk_fndecl, fnname);
   4421   final_start_function (insn, file, 1);
   4422   final (insn, file, 1);
   4423   final_end_function ();
   4424   assemble_end_function (thunk_fndecl, fnname);
   4425 
   4426   /* Stop pretending to be a post-reload pass.  */
   4427   reload_completed = 0;
   4428 }
   4429 
   4430 
   4431 /* Implement TARGET_ASM_TRAMPOLINE_TEMPLATE.  */
   4432 static void
   4433 tilepro_asm_trampoline_template (FILE *file)
   4434 {
   4435   fprintf (file, "\tlnk   r10\n");
   4436   fprintf (file, "\taddi  r10, r10, 32\n");
   4437   fprintf (file, "\tlwadd r11, r10, %d\n", GET_MODE_SIZE (ptr_mode));
   4438   fprintf (file, "\tlw    r10, r10\n");
   4439   fprintf (file, "\tjr    r11\n");
   4440   fprintf (file, "\t.word 0 # <function address>\n");
   4441   fprintf (file, "\t.word 0 # <static chain value>\n");
   4442 }
   4443 
   4444 
   4445 /* Implement TARGET_TRAMPOLINE_INIT.  */
   4446 static void
   4447 tilepro_trampoline_init (rtx m_tramp, tree fndecl, rtx static_chain)
   4448 {
   4449   rtx fnaddr, chaddr;
   4450   rtx mem;
   4451   rtx begin_addr, end_addr;
   4452   int ptr_mode_size = GET_MODE_SIZE (ptr_mode);
   4453 
   4454   fnaddr = copy_to_reg (XEXP (DECL_RTL (fndecl), 0));
   4455   chaddr = copy_to_reg (static_chain);
   4456 
   4457   emit_block_move (m_tramp, assemble_trampoline_template (),
   4458 		   GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
   4459 
   4460   mem = adjust_address (m_tramp, ptr_mode,
   4461 			TRAMPOLINE_SIZE - 2 * ptr_mode_size);
   4462   emit_move_insn (mem, fnaddr);
   4463   mem = adjust_address (m_tramp, ptr_mode,
   4464 			TRAMPOLINE_SIZE - ptr_mode_size);
   4465   emit_move_insn (mem, chaddr);
   4466 
   4467   /* Get pointers to the beginning and end of the code block.  */
   4468   begin_addr = force_reg (Pmode, XEXP (m_tramp, 0));
   4469   end_addr = force_reg (Pmode, plus_constant (Pmode, XEXP (m_tramp, 0),
   4470 					      TRAMPOLINE_SIZE));
   4471 
   4472   maybe_emit_call_builtin___clear_cache (begin_addr, end_addr);
   4473 }
   4474 
   4475 
   4476 /* Implement TARGET_PRINT_OPERAND.  */
   4477 static void
   4478 tilepro_print_operand (FILE *file, rtx x, int code)
   4479 {
   4480   switch (code)
   4481     {
   4482     case 'c':
   4483       /* Print the compare operator opcode for conditional moves. */
   4484       switch (GET_CODE (x))
   4485 	{
   4486 	case EQ:
   4487 	  fputs ("z", file);
   4488 	  break;
   4489 	case NE:
   4490 	  fputs ("nz", file);
   4491 	  break;
   4492 	default:
   4493 	  output_operand_lossage ("invalid %%c operand");
   4494 	}
   4495       return;
   4496 
   4497     case 'C':
   4498       /* Print the compare operator opcode for conditional moves. */
   4499       switch (GET_CODE (x))
   4500 	{
   4501 	case EQ:
   4502 	  fputs ("nz", file);
   4503 	  break;
   4504 	case NE:
   4505 	  fputs ("z", file);
   4506 	  break;
   4507 	default:
   4508 	  output_operand_lossage ("invalid %%C operand");
   4509 	}
   4510       return;
   4511 
   4512     case 'h':
   4513       {
   4514 	/* Print the high 16 bits of a 32-bit constant.  */
   4515 	HOST_WIDE_INT i;
   4516 	if (CONST_INT_P (x))
   4517 	  i = INTVAL (x);
   4518 	else if (GET_CODE (x) == CONST_DOUBLE)
   4519 	  i = CONST_DOUBLE_LOW (x);
   4520 	else
   4521 	  {
   4522 	    output_operand_lossage ("invalid %%h operand");
   4523 	    return;
   4524 	  }
   4525 	i = trunc_int_for_mode (i >> 16, HImode);
   4526 	fprintf (file, HOST_WIDE_INT_PRINT_DEC, i);
   4527 	return;
   4528       }
   4529 
   4530     case 'H':
   4531       {
   4532 	rtx addr = NULL;
   4533 	const char *opstr = NULL;
   4534 	bool pcrel = false;
   4535 	if (GET_CODE (x) == CONST
   4536 	    && GET_CODE (XEXP (x, 0)) == UNSPEC)
   4537 	  {
   4538 	    addr = XVECEXP (XEXP (x, 0), 0, 0);
   4539 	    switch (XINT (XEXP (x, 0), 1))
   4540 	    {
   4541 	    case UNSPEC_GOT32_SYM:
   4542 	      opstr = "got_ha16";
   4543 	      break;
   4544 	    case UNSPEC_PCREL_SYM:
   4545 	      opstr = "ha16";
   4546 	      pcrel = true;
   4547 	      break;
   4548 	    case UNSPEC_TLS_GD:
   4549 	      opstr = "tls_gd_ha16";
   4550 	      break;
   4551 	    case UNSPEC_TLS_IE:
   4552 	      opstr = "tls_ie_ha16";
   4553 	      break;
   4554 	    case UNSPEC_TLS_LE:
   4555 	      opstr = "tls_le_ha16";
   4556 	      break;
   4557 	    default:
   4558 	      output_operand_lossage ("invalid %%H operand");
   4559 	    }
   4560 	  }
   4561 	else
   4562 	  {
   4563 	    addr = x;
   4564 	    opstr = "ha16";
   4565 	  }
   4566 
   4567 	fputs (opstr, file);
   4568 	fputc ('(', file);
   4569 	output_addr_const (file, addr);
   4570 
   4571 	if (pcrel)
   4572 	  {
   4573 	    rtx addr2 = XVECEXP (XEXP (x, 0), 0, 1);
   4574 	    fputs (" - " , file);
   4575 	    output_addr_const (file, addr2);
   4576 	  }
   4577 
   4578 	fputc (')', file);
   4579 	return;
   4580       }
   4581 
   4582     case 'I':
   4583       /* Print an auto-inc memory operand.  */
   4584       if (!MEM_P (x))
   4585 	{
   4586 	  output_operand_lossage ("invalid %%I operand");
   4587 	  return;
   4588 	}
   4589 
   4590       output_memory_autoinc_first = true;
   4591       output_address (GET_MODE (x), XEXP (x, 0));
   4592       return;
   4593 
   4594     case 'i':
   4595       /* Print an auto-inc memory operand.  */
   4596       if (!MEM_P (x))
   4597 	{
   4598 	  output_operand_lossage ("invalid %%i operand");
   4599 	  return;
   4600 	}
   4601 
   4602       output_memory_autoinc_first = false;
   4603       output_address (GET_MODE (x), XEXP (x, 0));
   4604       return;
   4605 
   4606     case 'j':
   4607       {
   4608 	/* Print the low 8 bits of a constant.  */
   4609 	HOST_WIDE_INT i;
   4610 	if (CONST_INT_P (x))
   4611 	  i = INTVAL (x);
   4612 	else if (GET_CODE (x) == CONST_DOUBLE)
   4613 	  i = CONST_DOUBLE_LOW (x);
   4614 	else if (GET_CODE (x) == CONST_VECTOR
   4615 		 && CONST_INT_P (CONST_VECTOR_ELT (x, 0)))
   4616 	  i = INTVAL (CONST_VECTOR_ELT (x, 0));
   4617 	else
   4618 	  {
   4619 	    output_operand_lossage ("invalid %%j operand");
   4620 	    return;
   4621 	  }
   4622 	i = trunc_int_for_mode (i, QImode);
   4623 	fprintf (file, HOST_WIDE_INT_PRINT_DEC, i);
   4624 	return;
   4625       }
   4626 
   4627     case 'L':
   4628       {
   4629 	rtx addr = NULL;
   4630 	const char *opstr = NULL;
   4631 	bool pcrel = false;
   4632 	if (GET_CODE (x) == CONST
   4633 	    && GET_CODE (XEXP (x, 0)) == UNSPEC)
   4634 	  {
   4635 	    addr = XVECEXP (XEXP (x, 0), 0, 0);
   4636 	    switch (XINT (XEXP (x, 0), 1))
   4637 	    {
   4638 	    case UNSPEC_GOT16_SYM:
   4639 	      opstr = "got";
   4640 	      break;
   4641 	    case UNSPEC_GOT32_SYM:
   4642 	      opstr = "got_lo16";
   4643 	      break;
   4644 	    case UNSPEC_PCREL_SYM:
   4645 	      opstr = "lo16";
   4646 	      pcrel = true;
   4647 	      break;
   4648 	    case UNSPEC_TLS_GD:
   4649 	      opstr = "tls_gd_lo16";
   4650 	      break;
   4651 	    case UNSPEC_TLS_IE:
   4652 	      opstr = "tls_ie_lo16";
   4653 	      break;
   4654 	    case UNSPEC_TLS_LE:
   4655 	      opstr = "tls_le_lo16";
   4656 	      break;
   4657 	    default:
   4658 	      output_operand_lossage ("invalid %%L operand");
   4659 	    }
   4660 	  }
   4661 	else
   4662 	  {
   4663 	    addr = x;
   4664 	    opstr = "lo16";
   4665 	  }
   4666 
   4667 	fputs (opstr, file);
   4668 	fputc ('(', file);
   4669 	output_addr_const (file, addr);
   4670 
   4671 	if (pcrel)
   4672 	  {
   4673 	    rtx addr2 = XVECEXP (XEXP (x, 0), 0, 1);
   4674 	    fputs (" - " , file);
   4675 	    output_addr_const (file, addr2);
   4676 	  }
   4677 
   4678 	fputc (')', file);
   4679 	return;
   4680       }
   4681 
   4682     case 'p':
   4683       if (GET_CODE (x) == SYMBOL_REF)
   4684 	{
   4685 	  if (flag_pic && !SYMBOL_REF_LOCAL_P (x))
   4686 	    fprintf (file, "plt(");
   4687 	  output_addr_const (file, x);
   4688 	  if (flag_pic && !SYMBOL_REF_LOCAL_P (x))
   4689 	    fprintf (file, ")");
   4690 	}
   4691       else
   4692 	output_addr_const (file, x);
   4693       return;
   4694 
   4695     case 'P':
   4696       {
   4697 	/* Print a 32-bit constant plus one.  */
   4698 	HOST_WIDE_INT i;
   4699 	if (!CONST_INT_P (x))
   4700 	  {
   4701 	    output_operand_lossage ("invalid %%P operand");
   4702 	    return;
   4703 	  }
   4704 	i = trunc_int_for_mode (INTVAL (x) + 1, SImode);
   4705 	fprintf (file, HOST_WIDE_INT_PRINT_DEC, i);
   4706 	return;
   4707       }
   4708 
   4709     case 'M':
   4710       {
   4711 	/* Print an mm-style bit range.  */
   4712 	int first_bit, last_bit;
   4713 
   4714 	if (!CONST_INT_P (x)
   4715 	    || !tilepro_bitfield_operand_p (INTVAL (x), &first_bit,
   4716 					    &last_bit))
   4717 	  {
   4718 	    output_operand_lossage ("invalid %%M operand");
   4719 	    return;
   4720 	  }
   4721 
   4722 	fprintf (file, "%d, %d", first_bit, last_bit);
   4723 	return;
   4724       }
   4725 
   4726     case 'N':
   4727       {
   4728 	const char *reg = NULL;
   4729 
   4730 	/* Print a network register.  */
   4731 	if (!CONST_INT_P (x))
   4732 	  {
   4733 	    output_operand_lossage ("invalid %%N operand");
   4734 	    return;
   4735 	  }
   4736 
   4737 	switch (INTVAL (x))
   4738 	  {
   4739 	  case TILEPRO_NETREG_IDN0: reg = "idn0"; break;
   4740 	  case TILEPRO_NETREG_IDN1: reg = "idn1"; break;
   4741 	  case TILEPRO_NETREG_SN:   reg = "sn";   break;
   4742 	  case TILEPRO_NETREG_UDN0: reg = "udn0"; break;
   4743 	  case TILEPRO_NETREG_UDN1: reg = "udn1"; break;
   4744 	  case TILEPRO_NETREG_UDN2: reg = "udn2"; break;
   4745 	  case TILEPRO_NETREG_UDN3: reg = "udn3"; break;
   4746 	  default: gcc_unreachable ();
   4747 	  }
   4748 
   4749 	fprintf (file, reg);
   4750 	return;
   4751       }
   4752 
   4753     case 't':
   4754       {
   4755 	/* Log base 2 of a power of two.  */
   4756 	HOST_WIDE_INT i;
   4757 	HOST_WIDE_INT n;
   4758 
   4759 	if (!CONST_INT_P (x))
   4760 	  {
   4761 	    output_operand_lossage ("invalid %%t operand");
   4762 	    return;
   4763 	  }
   4764 	n = trunc_int_for_mode (INTVAL (x), SImode);
   4765 	i = exact_log2 (n);
   4766 	if (i < 0)
   4767 	  {
   4768 	    output_operand_lossage ("invalid %%t operand");
   4769 	    return;
   4770 	  }
   4771 
   4772 	fprintf (file, HOST_WIDE_INT_PRINT_DEC, i);
   4773 	return;
   4774       }
   4775       break;
   4776 
   4777     case 'r':
   4778       /* In this case we need a register.  Use 'zero' if the
   4779          operand is const0_rtx.  */
   4780       if (x == const0_rtx
   4781 	  || (GET_MODE (x) != VOIDmode && x == CONST0_RTX (GET_MODE (x))))
   4782 	{
   4783 	  fputs ("zero", file);
   4784 	  return;
   4785 	}
   4786       else if (!REG_P (x))
   4787 	{
   4788 	  output_operand_lossage ("invalid %%r operand");
   4789 	  return;
   4790 	}
   4791       /* FALLTHRU */
   4792 
   4793     case 0:
   4794       if (REG_P (x))
   4795 	{
   4796 	  fprintf (file, "%s", reg_names[REGNO (x)]);
   4797 	  return;
   4798 	}
   4799       else if (MEM_P (x))
   4800 	{
   4801 	  output_address (VOIDmode, XEXP (x, 0));
   4802 	  return;
   4803 	}
   4804       else
   4805 	{
   4806 	  output_addr_const (file, x);
   4807 	  return;
   4808 	}
   4809       break;
   4810     }
   4811 
   4812   debug_rtx (x);
   4813   output_operand_lossage ("unable to print out operand yet; code == %d (%c)",
   4814 			  code, code);
   4815 }
   4816 
   4817 
   4818 /* Implement TARGET_PRINT_OPERAND_ADDRESS.  */
   4819 static void
   4820 tilepro_print_operand_address (FILE *file, machine_mode mode, rtx addr)
   4821 {
   4822   if (GET_CODE (addr) == POST_DEC
   4823       || GET_CODE (addr) == POST_INC)
   4824     {
   4825       int offset = GET_MODE_SIZE (mode);
   4826 
   4827       gcc_assert (mode != VOIDmode);
   4828 
   4829       if (output_memory_autoinc_first)
   4830 	fprintf (file, "%s", reg_names[REGNO (XEXP (addr, 0))]);
   4831       else
   4832 	fprintf (file, "%d",
   4833 		 GET_CODE (addr) == POST_DEC ? -offset : offset);
   4834     }
   4835   else if (GET_CODE (addr) == POST_MODIFY)
   4836     {
   4837       gcc_assert (mode != VOIDmode);
   4838 
   4839       gcc_assert (GET_CODE (XEXP (addr, 1)) == PLUS);
   4840 
   4841       if (output_memory_autoinc_first)
   4842 	fprintf (file, "%s", reg_names[REGNO (XEXP (addr, 0))]);
   4843       else
   4844 	fprintf (file, HOST_WIDE_INT_PRINT_DEC,
   4845 		 INTVAL (XEXP (XEXP (addr, 1), 1)));
   4846     }
   4847   else
   4848     tilepro_print_operand (file, addr, 'r');
   4849 }
   4850 
   4851 
   4852 /* Machine mode of current insn, for determining curly brace
   4853    placement.  */
   4854 static machine_mode insn_mode;
   4855 
   4856 
   4857 /* Implement FINAL_PRESCAN_INSN.  This is used to emit bundles.  */
   4858 void
   4859 tilepro_final_prescan_insn (rtx_insn *insn)
   4860 {
   4861   /* Record this for tilepro_asm_output_opcode to examine.  */
   4862   insn_mode = GET_MODE (insn);
   4863 }
   4864 
   4865 
   4866 /* While emitting asm, are we currently inside '{' for a bundle? */
   4867 static bool tilepro_in_bundle = false;
   4868 
   4869 /* Implement ASM_OUTPUT_OPCODE.  Prepend/append curly braces as
   4870    appropriate given the bundling information recorded by
   4871    tilepro_gen_bundles.  */
   4872 const char *
   4873 tilepro_asm_output_opcode (FILE *stream, const char *code)
   4874 {
   4875   bool pseudo = !strcmp (code, "pseudo");
   4876 
   4877   if (!tilepro_in_bundle && insn_mode == SImode)
   4878     {
   4879       /* Start a new bundle.  */
   4880       fprintf (stream, "{\n\t");
   4881       tilepro_in_bundle = true;
   4882     }
   4883 
   4884   if (tilepro_in_bundle && insn_mode == QImode)
   4885     {
   4886       /* Close an existing bundle.  */
   4887       static char buf[100];
   4888 
   4889       gcc_assert (strlen (code) + 3 + 1 < sizeof (buf));
   4890 
   4891       strcpy (buf, pseudo ? "" : code);
   4892       strcat (buf, "\n\t}");
   4893       tilepro_in_bundle = false;
   4894 
   4895       return buf;
   4896     }
   4897   else
   4898     {
   4899       return pseudo ? "" : code;
   4900     }
   4901 }
   4902 
   4903 
   4904 /* Output assembler code to FILE to increment profiler label # LABELNO
   4905    for profiling a function entry.  */
   4906 void
   4907 tilepro_function_profiler (FILE *file, int labelno ATTRIBUTE_UNUSED)
   4908 {
   4909   if (tilepro_in_bundle)
   4910     {
   4911       fprintf (file, "\t}\n");
   4912     }
   4913 
   4914   if (flag_pic)
   4915     {
   4916       fprintf (file,
   4917 	       "\t{\n"
   4918 	       "\tmove\tr10, lr\n"
   4919 	       "\tjal\tplt(%s)\n"
   4920 	       "\t}\n", MCOUNT_NAME);
   4921     }
   4922   else
   4923     {
   4924       fprintf (file,
   4925 	       "\t{\n"
   4926 	       "\tmove\tr10, lr\n"
   4927 	       "\tjal\t%s\n"
   4928 	       "\t}\n", MCOUNT_NAME);
   4929     }
   4930 
   4931   tilepro_in_bundle = false;
   4932 }
   4933 
   4934 
   4935 /* Implement TARGET_ASM_FILE_END.  */
   4936 static void
   4937 tilepro_file_end (void)
   4938 {
   4939   if (NEED_INDICATE_EXEC_STACK)
   4940     file_end_indicate_exec_stack ();
   4941 }
   4942 
   4943 
   4944 #undef  TARGET_HAVE_TLS
   4945 #define TARGET_HAVE_TLS HAVE_AS_TLS
   4946 
   4947 #undef  TARGET_OPTION_OVERRIDE
   4948 #define TARGET_OPTION_OVERRIDE tilepro_option_override
   4949 
   4950 #ifdef TARGET_THREAD_SSP_OFFSET
   4951 #undef TARGET_STACK_PROTECT_GUARD
   4952 #define TARGET_STACK_PROTECT_GUARD hook_tree_void_null
   4953 #endif
   4954 
   4955 #undef  TARGET_SCALAR_MODE_SUPPORTED_P
   4956 #define TARGET_SCALAR_MODE_SUPPORTED_P tilepro_scalar_mode_supported_p
   4957 
   4958 #undef  TARGET_VECTOR_MODE_SUPPORTED_P
   4959 #define TARGET_VECTOR_MODE_SUPPORTED_P tile_vector_mode_supported_p
   4960 
   4961 #undef  TARGET_CANNOT_FORCE_CONST_MEM
   4962 #define TARGET_CANNOT_FORCE_CONST_MEM tilepro_cannot_force_const_mem
   4963 
   4964 #undef  TARGET_FUNCTION_OK_FOR_SIBCALL
   4965 #define TARGET_FUNCTION_OK_FOR_SIBCALL tilepro_function_ok_for_sibcall
   4966 
   4967 #undef  TARGET_PASS_BY_REFERENCE
   4968 #define TARGET_PASS_BY_REFERENCE tilepro_pass_by_reference
   4969 
   4970 #undef  TARGET_RETURN_IN_MEMORY
   4971 #define TARGET_RETURN_IN_MEMORY tilepro_return_in_memory
   4972 
   4973 #undef  TARGET_FUNCTION_ARG_BOUNDARY
   4974 #define TARGET_FUNCTION_ARG_BOUNDARY tilepro_function_arg_boundary
   4975 
   4976 #undef  TARGET_FUNCTION_ARG
   4977 #define TARGET_FUNCTION_ARG tilepro_function_arg
   4978 
   4979 #undef  TARGET_FUNCTION_ARG_ADVANCE
   4980 #define TARGET_FUNCTION_ARG_ADVANCE tilepro_function_arg_advance
   4981 
   4982 #undef  TARGET_FUNCTION_VALUE
   4983 #define TARGET_FUNCTION_VALUE tilepro_function_value
   4984 
   4985 #undef  TARGET_LIBCALL_VALUE
   4986 #define TARGET_LIBCALL_VALUE tilepro_libcall_value
   4987 
   4988 #undef  TARGET_FUNCTION_VALUE_REGNO_P
   4989 #define TARGET_FUNCTION_VALUE_REGNO_P tilepro_function_value_regno_p
   4990 
   4991 #undef  TARGET_PROMOTE_FUNCTION_MODE
   4992 #define TARGET_PROMOTE_FUNCTION_MODE \
   4993   default_promote_function_mode_always_promote
   4994 
   4995 #undef  TARGET_PROMOTE_PROTOTYPES
   4996 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_false
   4997 
   4998 #undef  TARGET_BUILD_BUILTIN_VA_LIST
   4999 #define TARGET_BUILD_BUILTIN_VA_LIST tilepro_build_builtin_va_list
   5000 
   5001 #undef  TARGET_EXPAND_BUILTIN_VA_START
   5002 #define TARGET_EXPAND_BUILTIN_VA_START tilepro_va_start
   5003 
   5004 #undef  TARGET_SETUP_INCOMING_VARARGS
   5005 #define TARGET_SETUP_INCOMING_VARARGS tilepro_setup_incoming_varargs
   5006 
   5007 #undef  TARGET_GIMPLIFY_VA_ARG_EXPR
   5008 #define TARGET_GIMPLIFY_VA_ARG_EXPR tilepro_gimplify_va_arg_expr
   5009 
   5010 #undef  TARGET_RTX_COSTS
   5011 #define TARGET_RTX_COSTS tilepro_rtx_costs
   5012 
   5013 /* Limit to what we can reach in one addli.  */
   5014 #undef  TARGET_MIN_ANCHOR_OFFSET
   5015 #define TARGET_MIN_ANCHOR_OFFSET -32768
   5016 #undef  TARGET_MAX_ANCHOR_OFFSET
   5017 #define TARGET_MAX_ANCHOR_OFFSET 32767
   5018 
   5019 #undef  TARGET_LEGITIMATE_CONSTANT_P
   5020 #define TARGET_LEGITIMATE_CONSTANT_P tilepro_legitimate_constant_p
   5021 
   5022 #undef TARGET_LRA_P
   5023 #define TARGET_LRA_P hook_bool_void_false
   5024 
   5025 #undef  TARGET_LEGITIMATE_ADDRESS_P
   5026 #define TARGET_LEGITIMATE_ADDRESS_P tilepro_legitimate_address_p
   5027 
   5028 #undef  TARGET_LEGITIMIZE_ADDRESS
   5029 #define TARGET_LEGITIMIZE_ADDRESS tilepro_legitimize_address
   5030 
   5031 #undef  TARGET_DELEGITIMIZE_ADDRESS
   5032 #define TARGET_DELEGITIMIZE_ADDRESS tilepro_delegitimize_address
   5033 
   5034 #undef  TARGET_INIT_BUILTINS
   5035 #define TARGET_INIT_BUILTINS  tilepro_init_builtins
   5036 
   5037 #undef  TARGET_BUILTIN_DECL
   5038 #define TARGET_BUILTIN_DECL tilepro_builtin_decl
   5039 
   5040 #undef  TARGET_EXPAND_BUILTIN
   5041 #define TARGET_EXPAND_BUILTIN tilepro_expand_builtin
   5042 
   5043 #undef  TARGET_CONDITIONAL_REGISTER_USAGE
   5044 #define TARGET_CONDITIONAL_REGISTER_USAGE tilepro_conditional_register_usage
   5045 
   5046 #undef  TARGET_FRAME_POINTER_REQUIRED
   5047 #define TARGET_FRAME_POINTER_REQUIRED tilepro_frame_pointer_required
   5048 
   5049 #undef  TARGET_DELAY_SCHED2
   5050 #define TARGET_DELAY_SCHED2 true
   5051 
   5052 #undef  TARGET_DELAY_VARTRACK
   5053 #define TARGET_DELAY_VARTRACK true
   5054 
   5055 #undef  TARGET_SCHED_ISSUE_RATE
   5056 #define TARGET_SCHED_ISSUE_RATE tilepro_issue_rate
   5057 
   5058 #undef  TARGET_SCHED_ADJUST_COST
   5059 #define TARGET_SCHED_ADJUST_COST tilepro_sched_adjust_cost
   5060 
   5061 #undef  TARGET_MACHINE_DEPENDENT_REORG
   5062 #define TARGET_MACHINE_DEPENDENT_REORG tilepro_reorg
   5063 
   5064 #undef  TARGET_ASM_CAN_OUTPUT_MI_THUNK
   5065 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK \
   5066   hook_bool_const_tree_hwi_hwi_const_tree_true
   5067 
   5068 #undef  TARGET_ASM_OUTPUT_MI_THUNK
   5069 #define TARGET_ASM_OUTPUT_MI_THUNK tilepro_asm_output_mi_thunk
   5070 
   5071 #undef  TARGET_ASM_TRAMPOLINE_TEMPLATE
   5072 #define TARGET_ASM_TRAMPOLINE_TEMPLATE tilepro_asm_trampoline_template
   5073 
   5074 #undef  TARGET_TRAMPOLINE_INIT
   5075 #define TARGET_TRAMPOLINE_INIT tilepro_trampoline_init
   5076 
   5077 #undef  TARGET_PRINT_OPERAND
   5078 #define TARGET_PRINT_OPERAND tilepro_print_operand
   5079 
   5080 #undef  TARGET_PRINT_OPERAND_ADDRESS
   5081 #define TARGET_PRINT_OPERAND_ADDRESS tilepro_print_operand_address
   5082 
   5083 #undef  TARGET_ASM_FILE_END
   5084 #define TARGET_ASM_FILE_END tilepro_file_end
   5085 
   5086 #undef  TARGET_CAN_USE_DOLOOP_P
   5087 #define TARGET_CAN_USE_DOLOOP_P can_use_doloop_if_innermost
   5088 
   5089 #undef  TARGET_CONSTANT_ALIGNMENT
   5090 #define TARGET_CONSTANT_ALIGNMENT constant_alignment_word_strings
   5091 
   5092 struct gcc_target targetm = TARGET_INITIALIZER;
   5093 
   5094 #include "gt-tilepro.h"
   5095