Index: gcc/target.def
===================================================================
--- gcc/target.def	2017-09-13 20:12:23.803261934 +0100
+++ gcc/target.def	2017-09-13 20:12:24.499190740 +0100
@@ -3130,6 +3130,20 @@ has an instruction for the division, and
  unsigned int, (machine_mode mode),
  default_min_divisions_for_recip_mul)
 
+DEFHOOK
+(truly_noop_truncation,
+ "This hook returns true if it is safe to ``convert'' a value of\n\
+@var{inprec} bits to one of @var{outprec} bits (where @var{outprec} is\n\
+smaller than @var{inprec}) by merely operating on it as if it had only\n\
+@var{outprec} bits.  The default returns true unconditionally, which\n\
+is correct for most machines.\n\
+\n\
+If @code{TARGET_MODES_TIEABLE_P} returns false for a pair of modes,\n\
+suboptimal code can result if this hook returns true for the corresponding\n\
+mode sizes.  Making this hook return false in such cases may improve things.",
+ bool, (unsigned int outprec, unsigned int inprec),
+ hook_bool_uint_uint_true)
+
 /* If the representation of integral MODE is such that values are
    always sign-extended to a wider mode MODE_REP then return
    SIGN_EXTEND.  Return UNKNOWN otherwise.  */
@@ -3160,7 +3174,7 @@ to define @code{LOAD_EXTEND_OP (mode)} t
 extension.\n\
 \n\
 In order to enforce the representation of @code{mode},\n\
-@code{TRULY_NOOP_TRUNCATION} should return false when truncating to\n\
+@code{TARGET_TRULY_NOOP_TRUNCATION} should return false when truncating to\n\
 @code{mode}.",
  int, (scalar_int_mode mode, scalar_int_mode rep_mode),
  default_mode_rep_extended)
Index: gcc/hooks.h
===================================================================
--- gcc/hooks.h	2017-09-13 20:12:23.803261934 +0100
+++ gcc/hooks.h	2017-09-13 20:12:24.498282217 +0100
@@ -39,6 +39,7 @@ extern bool hook_bool_const_rtx_insn_con
 							  const rtx_insn *);
 extern bool hook_bool_mode_uhwi_false (machine_mode,
 				       unsigned HOST_WIDE_INT);
+extern bool hook_bool_uint_uint_true (unsigned int, unsigned int);
 extern bool hook_bool_uint_mode_false (unsigned int, machine_mode);
 extern bool hook_bool_uint_mode_true (unsigned int, machine_mode);
 extern bool hook_bool_tree_false (tree);
Index: gcc/hooks.c
===================================================================
--- gcc/hooks.c	2017-09-13 20:12:23.803261934 +0100
+++ gcc/hooks.c	2017-09-13 20:12:24.498282217 +0100
@@ -133,6 +133,13 @@ hook_bool_mode_uhwi_false (machine_mode,
   return false;
 }
 
+/* Generic hook that takes (unsigned int, unsigned int) and returns true.  */
+bool
+hook_bool_uint_uint_true (unsigned int, unsigned int)
+{
+  return true;
+}
+
 /* Generic hook that takes (unsigned int, machine_mode) and returns false.  */
 bool
 hook_bool_uint_mode_false (unsigned int, machine_mode)
Index: gcc/doc/tm.texi.in
===================================================================
--- gcc/doc/tm.texi.in	2017-09-13 20:12:23.803261934 +0100
+++ gcc/doc/tm.texi.in	2017-09-13 20:12:24.496465170 +0100
@@ -7482,21 +7482,7 @@ You need not define this macro if it wou
 @anchor{TARGET_SHIFT_TRUNCATION_MASK}
 @hook TARGET_SHIFT_TRUNCATION_MASK
 
-@defmac TRULY_NOOP_TRUNCATION (@var{outprec}, @var{inprec})
-A C expression which is nonzero if on this machine it is safe to
-``convert'' an integer of @var{inprec} bits to one of @var{outprec}
-bits (where @var{outprec} is smaller than @var{inprec}) by merely
-operating on it as if it had only @var{outprec} bits.
-
-On many machines, this expression can be 1.
-
-@c rearranged this, removed the phrase "it is reported that".  this was
-@c to fix an overfull hbox.  --mew 10feb93
-When @code{TRULY_NOOP_TRUNCATION} returns 1 for a pair of sizes for modes
-for which @code{TARGET_MODES_TIEABLE_P} is false, suboptimal code can result.
-If this is the case, making @code{TRULY_NOOP_TRUNCATION} return 0 in
-such cases may improve things.
-@end defmac
+@hook TARGET_TRULY_NOOP_TRUNCATION
 
 @hook TARGET_MODE_REP_EXTENDED
 
Index: gcc/doc/tm.texi
===================================================================
--- gcc/doc/tm.texi	2017-09-13 20:12:23.803261934 +0100
+++ gcc/doc/tm.texi	2017-09-13 20:12:24.496465170 +0100
@@ -10783,21 +10783,17 @@ nevertheless truncate the shift count, y
 by overriding it.
 @end deftypefn
 
-@defmac TRULY_NOOP_TRUNCATION (@var{outprec}, @var{inprec})
-A C expression which is nonzero if on this machine it is safe to
-``convert'' an integer of @var{inprec} bits to one of @var{outprec}
-bits (where @var{outprec} is smaller than @var{inprec}) by merely
-operating on it as if it had only @var{outprec} bits.
-
-On many machines, this expression can be 1.
-
-@c rearranged this, removed the phrase "it is reported that".  this was
-@c to fix an overfull hbox.  --mew 10feb93
-When @code{TRULY_NOOP_TRUNCATION} returns 1 for a pair of sizes for modes
-for which @code{TARGET_MODES_TIEABLE_P} is false, suboptimal code can result.
-If this is the case, making @code{TRULY_NOOP_TRUNCATION} return 0 in
-such cases may improve things.
-@end defmac
+@deftypefn {Target Hook} bool TARGET_TRULY_NOOP_TRUNCATION (unsigned int @var{outprec}, unsigned int @var{inprec})
+This hook returns true if it is safe to ``convert'' a value of
+@var{inprec} bits to one of @var{outprec} bits (where @var{outprec} is
+smaller than @var{inprec}) by merely operating on it as if it had only
+@var{outprec} bits.  The default returns true unconditionally, which
+is correct for most machines.
+
+If @code{TARGET_MODES_TIEABLE_P} returns false for a pair of modes,
+suboptimal code can result if this hook returns true for the corresponding
+mode sizes.  Making this hook return false in such cases may improve things.
+@end deftypefn
 
 @deftypefn {Target Hook} int TARGET_MODE_REP_EXTENDED (scalar_int_mode @var{mode}, scalar_int_mode @var{rep_mode})
 The representation of an integral mode can be such that the values
@@ -10823,7 +10819,7 @@ to define @code{LOAD_EXTEND_OP (mode)} t
 extension.
 
 In order to enforce the representation of @code{mode},
-@code{TRULY_NOOP_TRUNCATION} should return false when truncating to
+@code{TARGET_TRULY_NOOP_TRUNCATION} should return false when truncating to
 @code{mode}.
 @end deftypefn
 
Index: gcc/combine.c
===================================================================
--- gcc/combine.c	2017-09-13 20:12:23.803261934 +0100
+++ gcc/combine.c	2017-09-13 20:12:24.482837321 +0100
@@ -7721,7 +7721,7 @@ make_extraction (machine_mode mode, rtx
   else if (!MEM_P (inner))
     {
       /* On the LHS, don't create paradoxical subregs implicitely truncating
-	 the register unless TRULY_NOOP_TRUNCATION.  */
+	 the register unless TARGET_TRULY_NOOP_TRUNCATION.  */
       if (in_dest
 	  && !TRULY_NOOP_TRUNCATION_MODES_P (GET_MODE (inner),
 					     wanted_inner_mode))
@@ -12496,7 +12496,7 @@ simplify_comparison (enum rtx_code code,
 	     (ne:DI (and:DI (reg:DI 4) (const_int 0xffffffff)) (const_int 0))
 	     -> (ne:DI (reg:SI 4) (const_int 0))
 
-	     unless TRULY_NOOP_TRUNCATION allows it or the register is
+	     unless TARGET_TRULY_NOOP_TRUNCATION allows it or the register is
 	     known to hold a value of the required mode the
 	     transformation is invalid.  */
 	  if ((equality_comparison_p || unsigned_comparison_p)
@@ -13336,8 +13336,8 @@ reg_truncated_to_mode (machine_mode mode
 }
 
 /* If X is a hard reg or a subreg record the mode that the register is
-   accessed in.  For non-TRULY_NOOP_TRUNCATION targets we might be able
-   to turn a truncate into a subreg using this information.  Return true
+   accessed in.  For non-TARGET_TRULY_NOOP_TRUNCATION targets we might be
+   able to turn a truncate into a subreg using this information.  Return true
    if traversing X is complete.  */
 
 static bool
Index: gcc/expmed.c
===================================================================
--- gcc/expmed.c	2017-09-13 20:12:23.803261934 +0100
+++ gcc/expmed.c	2017-09-13 20:12:24.497373693 +0100
@@ -1854,7 +1854,7 @@ extract_bit_field_1 (rtx str_rtx, unsign
       && !reverse
       /* ??? We could limit the structure size to the part of OP0 that
 	 contains the field, with appropriate checks for endianness
-	 and TRULY_NOOP_TRUNCATION.  */
+	 and TARGET_TRULY_NOOP_TRUNCATION.  */
       && get_best_reg_extraction_insn (&extv, pattern,
 				       GET_MODE_BITSIZE (op0_mode.require ()),
 				       tmode))
@@ -2233,7 +2233,7 @@ extract_split_bit_field (rtx op0, opt_sc
        a zero extension
 
      - when MODE is smaller than SRC_MODE, the extraction involves
-       a truncation (and is thus subject to TRULY_NOOP_TRUNCATION).
+       a truncation (and is thus subject to TARGET_TRULY_NOOP_TRUNCATION).
 
    In other words, this routine performs a computation, whereas the
    gen_lowpart* routines are conceptually lvalue or rvalue subreg
Index: gcc/convert.c
===================================================================
--- gcc/convert.c	2017-09-13 20:12:23.803261934 +0100
+++ gcc/convert.c	2017-09-13 20:12:24.495556647 +0100
@@ -873,7 +873,7 @@ convert_to_integer_1 (tree type, tree ex
 		break;
 
 	      if (outprec >= BITS_PER_WORD
-		  || TRULY_NOOP_TRUNCATION (outprec, inprec)
+		  || targetm.truly_noop_truncation (outprec, inprec)
 		  || inprec > TYPE_PRECISION (TREE_TYPE (arg0))
 		  || inprec > TYPE_PRECISION (TREE_TYPE (arg1)))
 		{
Index: gcc/function.c
===================================================================
--- gcc/function.c	2017-09-13 20:12:23.803261934 +0100
+++ gcc/function.c	2017-09-13 20:12:24.498282217 +0100
@@ -2997,7 +2997,8 @@ assign_parm_setup_block (struct assign_p
 		 to the value directly in mode MODE, otherwise we must
 		 start with the register in word_mode and explicitly
 		 convert it.  */
-	      if (TRULY_NOOP_TRUNCATION (size * BITS_PER_UNIT, BITS_PER_WORD))
+	      if (targetm.truly_noop_truncation (size * BITS_PER_UNIT,
+						 BITS_PER_WORD))
 		reg = gen_rtx_REG (mode, REGNO (entry_parm));
 	      else
 		{
Index: gcc/machmode.h
===================================================================
--- gcc/machmode.h	2017-09-13 20:12:23.803261934 +0100
+++ gcc/machmode.h	2017-09-13 20:12:24.498282217 +0100
@@ -781,8 +781,8 @@ get_narrowest_mode (T mode)
 extern void init_adjust_machine_modes (void);
 
 #define TRULY_NOOP_TRUNCATION_MODES_P(MODE1, MODE2) \
-  TRULY_NOOP_TRUNCATION (GET_MODE_PRECISION (MODE1), \
-			 GET_MODE_PRECISION (MODE2))
+  (targetm.truly_noop_truncation (GET_MODE_PRECISION (MODE1), \
+				  GET_MODE_PRECISION (MODE2)))
 
 #define HWI_COMPUTABLE_MODE_P(MODE) \
   (SCALAR_INT_MODE_P (MODE) \
Index: gcc/rtlhooks.c
===================================================================
--- gcc/rtlhooks.c	2017-09-13 20:12:23.803261934 +0100
+++ gcc/rtlhooks.c	2017-09-13 20:12:24.498282217 +0100
@@ -30,6 +30,7 @@ Software Foundation; either version 3, o
 #include "recog.h"
 #include "rtlhooks-def.h"
 #include "explow.h"
+#include "target.h"
 
 
 /* For speed, we will copy the RTX hooks struct member-by-member
Index: gcc/config/aarch64/aarch64.h
===================================================================
--- gcc/config/aarch64/aarch64.h	2017-09-13 20:12:23.803261934 +0100
+++ gcc/config/aarch64/aarch64.h	2017-09-13 20:12:24.482837321 +0100
@@ -773,8 +773,6 @@ #define STRICT_ALIGNMENT		TARGET_STRICT_
    if we don't have to, for power-saving reasons.  */
 #define SLOW_BYTE_ACCESS		0
 
-#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
-
 #define NO_FUNCTION_CSE	1
 
 /* Specify the machine mode that the hardware addresses have.
Index: gcc/config/alpha/alpha.h
===================================================================
--- gcc/config/alpha/alpha.h	2017-09-13 20:12:23.803261934 +0100
+++ gcc/config/alpha/alpha.h	2017-09-13 20:12:24.482837321 +0100
@@ -800,10 +800,6 @@ #define LOAD_EXTEND_OP(MODE) ((MODE) ==
 /* Define if loading short immediate values into registers sign extends.  */
 #define SHORT_IMMEDIATES_SIGN_EXTEND 1
 
-/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
-   is done just by pretending it is already truncated.  */
-#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
-
 /* The CIX ctlz and cttz instructions return 64 for zero.  */
 #define CLZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE)  ((VALUE) = 64, \
   TARGET_CIX ? 1 : 0)
Index: gcc/config/arc/arc.h
===================================================================
--- gcc/config/arc/arc.h	2017-09-13 20:12:23.803261934 +0100
+++ gcc/config/arc/arc.h	2017-09-13 20:12:24.482837321 +0100
@@ -1449,10 +1449,6 @@ #define MOVE_RATIO(SPEED) ((SPEED) ? 15
 */
 #define SHIFT_COUNT_TRUNCATED 1
 
-/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
-   is done just by pretending it is already truncated.  */
-#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
-
 /* We assume that the store-condition-codes instructions store 0 for false
    and some other value for true.  This is the value stored for true.  */
 #define STORE_FLAG_VALUE 1
Index: gcc/config/arm/arm.h
===================================================================
--- gcc/config/arm/arm.h	2017-09-13 20:12:23.803261934 +0100
+++ gcc/config/arm/arm.h	2017-09-13 20:12:24.483745845 +0100
@@ -1897,9 +1897,6 @@ #define SLOW_BYTE_ACCESS 0
    rotates is modulo 32 used.  */
 /* #define SHIFT_COUNT_TRUNCATED 1 */
 
-/* All integers have the same format so truncation is easy.  */
-#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC)  1
-
 /* Calling from registers is a massive pain.  */
 #define NO_FUNCTION_CSE 1
 
Index: gcc/config/avr/avr.h
===================================================================
--- gcc/config/avr/avr.h	2017-09-13 20:12:23.803261934 +0100
+++ gcc/config/avr/avr.h	2017-09-13 20:12:24.483745845 +0100
@@ -471,8 +471,6 @@ #define MOVE_MAX_PIECES 2
 
 #define MOVE_RATIO(speed) ((speed) ? 3 : 2)
 
-#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
-
 #define Pmode HImode
 
 #define FUNCTION_MODE HImode
Index: gcc/config/bfin/bfin.h
===================================================================
--- gcc/config/bfin/bfin.h	2017-09-13 20:12:23.803261934 +0100
+++ gcc/config/bfin/bfin.h	2017-09-13 20:12:24.483745845 +0100
@@ -799,10 +799,6 @@ #define SYMBOLIC_CONST(X)	\
 
 #define NOTICE_UPDATE_CC(EXPR, INSN) 0
 
-/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
-   is done just by pretending it is already truncated.  */
-#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
-
 /* Max number of bytes we can move from memory to memory
    in one reasonably fast instruction.  */
 #define MOVE_MAX UNITS_PER_WORD
Index: gcc/config/c6x/c6x.h
===================================================================
--- gcc/config/c6x/c6x.h	2017-09-13 20:12:23.803261934 +0100
+++ gcc/config/c6x/c6x.h	2017-09-13 20:12:24.483745845 +0100
@@ -596,7 +596,6 @@ #define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, B
 #define CASE_VECTOR_MODE SImode
 #define MOVE_MAX 4
 #define MOVE_RATIO(SPEED) 4
-#define TRULY_NOOP_TRUNCATION(outprec, inprec) 1
 #define CLZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) ((VALUE) = 32, 1)
 #define Pmode SImode
 #define FUNCTION_MODE QImode
Index: gcc/config/cr16/cr16.h
===================================================================
--- gcc/config/cr16/cr16.h	2017-09-13 20:12:23.803261934 +0100
+++ gcc/config/cr16/cr16.h	2017-09-13 20:12:24.483745845 +0100
@@ -551,8 +551,6 @@ #define CASE_VECTOR_MODE  Pmode
 
 #define MOVE_MAX 4
 
-#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC)  1
-
 #define STORE_FLAG_VALUE  1
 
 #define Pmode SImode
Index: gcc/config/cris/cris.h
===================================================================
--- gcc/config/cris/cris.h	2017-09-13 20:12:23.803261934 +0100
+++ gcc/config/cris/cris.h	2017-09-13 20:12:24.484654368 +0100
@@ -1038,8 +1038,6 @@ #define MOVE_MAX 4
 
 /* Maybe SHIFT_COUNT_TRUNCATED is safe to define?  FIXME: Check later.  */
 
-#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
-
 #define CLZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) ((VALUE) = 32, 1)
 #define CTZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) ((VALUE) = 32, 1)
 
Index: gcc/config/epiphany/epiphany.h
===================================================================
--- gcc/config/epiphany/epiphany.h	2017-09-13 20:12:23.803261934 +0100
+++ gcc/config/epiphany/epiphany.h	2017-09-13 20:12:24.484654368 +0100
@@ -840,10 +840,6 @@ #define MOVE_MAX 8
    few bits.  */
 #define SHIFT_COUNT_TRUNCATED 1
 
-/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
-   is done just by pretending it is already truncated.  */
-#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
-
 /* Specify the machine mode that pointers have.
    After generation of rtl, the compiler makes no further distinction
    between pointers and any other objects of this machine mode.  */
Index: gcc/config/fr30/fr30.h
===================================================================
--- gcc/config/fr30/fr30.h	2017-09-13 20:12:23.803261934 +0100
+++ gcc/config/fr30/fr30.h	2017-09-13 20:12:24.484654368 +0100
@@ -776,18 +776,6 @@ #define CASE_VECTOR_MODE SImode
    memory to memory.  */
 #define MOVE_MAX 8
 
-/* A C expression which is nonzero if on this machine it is safe to "convert"
-   an integer of INPREC bits to one of OUTPREC bits (where OUTPREC is smaller
-   than INPREC) by merely operating on it as if it had only OUTPREC bits.
-
-   On many machines, this expression can be 1.
-
-   When `TRULY_NOOP_TRUNCATION' returns 1 for a pair of sizes for modes for
-   which `TARGET_MODES_TIEABLE_P' is 0, suboptimal code can result.
-   If this is the case, making `TRULY_NOOP_TRUNCATION' return 0 in such
-   cases may improve things.  */
-#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
-
 /* An alias for the machine mode for pointers.  On most machines, define this
    to be the integer mode corresponding to the width of a hardware pointer;
    `SImode' on 32-bit machine or `DImode' on 64-bit machines.  On some machines
Index: gcc/config/frv/frv.h
===================================================================
--- gcc/config/frv/frv.h	2017-09-13 20:12:23.803261934 +0100
+++ gcc/config/frv/frv.h	2017-09-13 20:12:24.484654368 +0100
@@ -1813,18 +1813,6 @@ #define SHORT_IMMEDIATES_SIGN_EXTEND 1
    memory to memory.  */
 #define MOVE_MAX 8
 
-/* A C expression which is nonzero if on this machine it is safe to "convert"
-   an integer of INPREC bits to one of OUTPREC bits (where OUTPREC is smaller
-   than INPREC) by merely operating on it as if it had only OUTPREC bits.
-
-   On many machines, this expression can be 1.
-
-   When `TRULY_NOOP_TRUNCATION' returns 1 for a pair of sizes for modes
-   for which `TARGET_MODES_TIEABLE_P' is 0, suboptimal code can result.
-   If this is the case, making `TRULY_NOOP_TRUNCATION' return 0 in such
-   cases may improve things.  */
-#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
-
 /* An alias for the machine mode for pointers.  On most machines, define this
    to be the integer mode corresponding to the width of a hardware pointer;
    `SImode' on 32-bit machine or `DImode' on 64-bit machines.  On some machines
Index: gcc/config/ft32/ft32.h
===================================================================
--- gcc/config/ft32/ft32.h	2017-09-13 20:12:23.803261934 +0100
+++ gcc/config/ft32/ft32.h	2017-09-13 20:12:24.484654368 +0100
@@ -449,7 +449,6 @@ #define REGNO_OK_FOR_INDEX_P(NUM) FT32_F
    quickly between memory and registers or between two memory
    locations.  */
 #define MOVE_MAX 4
-#define TRULY_NOOP_TRUNCATION(op,ip) 1
 
 /* Define this to be nonzero if shift instructions ignore all but the low-order
    few bits.  */
Index: gcc/config/h8300/h8300.h
===================================================================
--- gcc/config/h8300/h8300.h	2017-09-13 20:12:23.803261934 +0100
+++ gcc/config/h8300/h8300.h	2017-09-13 20:12:24.484654368 +0100
@@ -561,10 +561,6 @@ #define SLOW_BYTE_ACCESS TARGET_SLOWBYTE
    of a shift count.  */
 /* #define SHIFT_COUNT_TRUNCATED */
 
-/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
-   is done just by pretending it is already truncated.  */
-#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
-
 /* Specify the machine mode that pointers have.
    After generation of rtl, the compiler makes no further distinction
    between pointers and any other objects of this machine mode.  */
Index: gcc/config/i386/i386.h
===================================================================
--- gcc/config/i386/i386.h	2017-09-13 20:12:23.803261934 +0100
+++ gcc/config/i386/i386.h	2017-09-13 20:12:24.485562891 +0100
@@ -1911,10 +1911,6 @@ #define CLEAR_RATIO(speed) ((speed) ? MI
 
 /* #define SHIFT_COUNT_TRUNCATED */
 
-/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
-   is done just by pretending it is already truncated.  */
-#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
-
 /* A macro to update M and UNSIGNEDP when an object whose type is
    TYPE and which has the specified mode and signedness is to be
    stored in a register.  This macro is only called when TYPE is a
Index: gcc/config/ia64/ia64.h
===================================================================
--- gcc/config/ia64/ia64.h	2017-09-13 20:12:23.803261934 +0100
+++ gcc/config/ia64/ia64.h	2017-09-13 20:12:24.485562891 +0100
@@ -1567,12 +1567,6 @@ #define LOAD_EXTEND_OP(MODE) ZERO_EXTEND
    memory to memory.  */
 #define MOVE_MAX 8
 
-/* A C expression which is nonzero if on this machine it is safe to "convert"
-   an integer of INPREC bits to one of OUTPREC bits (where OUTPREC is smaller
-   than INPREC) by merely operating on it as if it had only OUTPREC bits.  */
-
-#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
-
 /* A C expression describing the value returned by a comparison operator with
    an integral mode and stored by a store-flag instruction (`sCOND') when the
    condition is true.  */
Index: gcc/config/iq2000/iq2000.h
===================================================================
--- gcc/config/iq2000/iq2000.h	2017-09-13 20:12:23.803261934 +0100
+++ gcc/config/iq2000/iq2000.h	2017-09-13 20:12:24.485562891 +0100
@@ -526,8 +526,6 @@ #define MAX_MOVE_MAX 8
 
 #define SHIFT_COUNT_TRUNCATED 1
 
-#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
-
 #define STORE_FLAG_VALUE 1
 
 #define Pmode SImode
Index: gcc/config/lm32/lm32.h
===================================================================
--- gcc/config/lm32/lm32.h	2017-09-13 20:12:23.803261934 +0100
+++ gcc/config/lm32/lm32.h	2017-09-13 20:12:24.485562891 +0100
@@ -519,8 +519,6 @@ #define MAX_MOVE_MAX    4
 
 #define SHIFT_COUNT_TRUNCATED 1
 
-#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
-
 #define Pmode SImode
 
 #define FUNCTION_MODE SImode
Index: gcc/config/m32c/m32c.h
===================================================================
--- gcc/config/m32c/m32c.h	2017-09-13 20:12:23.803261934 +0100
+++ gcc/config/m32c/m32c.h	2017-09-13 20:12:24.485562891 +0100
@@ -629,7 +629,6 @@ #define CASE_VECTOR_MODE SImode
 #define LOAD_EXTEND_OP(MEM) ZERO_EXTEND
 
 #define MOVE_MAX 4
-#define TRULY_NOOP_TRUNCATION(op,ip) 1
 
 #define STORE_FLAG_VALUE 1
 
Index: gcc/config/m32r/m32r.h
===================================================================
--- gcc/config/m32r/m32r.h	2017-09-13 20:12:23.803261934 +0100
+++ gcc/config/m32r/m32r.h	2017-09-13 20:12:24.486471414 +0100
@@ -981,10 +981,6 @@ #define MOVE_MAX 4
    few bits.  */
 #define SHIFT_COUNT_TRUNCATED 1
 
-/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
-   is done just by pretending it is already truncated.  */
-#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
-
 /* Specify the machine mode that pointers have.
    After generation of rtl, the compiler makes no further distinction
    between pointers and any other objects of this machine mode.  */
Index: gcc/config/m68k/m68k.h
===================================================================
--- gcc/config/m68k/m68k.h	2017-09-13 20:12:23.803261934 +0100
+++ gcc/config/m68k/m68k.h	2017-09-13 20:12:24.486471414 +0100
@@ -665,8 +665,6 @@ #define DEFAULT_SIGNED_CHAR 1
 #define MOVE_MAX 4
 #define SLOW_BYTE_ACCESS 0
 
-#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
-
 /* The 68020 BFFFO and ColdFire FF1 instructions return 32 for zero. */
 #define CLZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) ((VALUE) = 32, 1)
 
Index: gcc/config/mcore/mcore.h
===================================================================
--- gcc/config/mcore/mcore.h	2017-09-13 20:12:23.803261934 +0100
+++ gcc/config/mcore/mcore.h	2017-09-13 20:12:24.486471414 +0100
@@ -549,9 +549,6 @@ #define SLOW_BYTE_ACCESS TARGET_SLOW_BYT
    target.  */
 #define SHIFT_COUNT_TRUNCATED 0
 
-/* All integers have the same format so truncation is easy.  */
-#define TRULY_NOOP_TRUNCATION(OUTPREC,INPREC)  1
-
 /* Define this if addresses of constant functions
    shouldn't be put through pseudo regs where they can be cse'd.
    Desirable on machines where ordinary constants are expensive
Index: gcc/config/microblaze/microblaze.h
===================================================================
--- gcc/config/microblaze/microblaze.h	2017-09-13 20:12:23.803261934 +0100
+++ gcc/config/microblaze/microblaze.h	2017-09-13 20:12:24.486471414 +0100
@@ -554,11 +554,6 @@ #define STORE_FLAG_VALUE			1
 
 #define SHIFT_COUNT_TRUNCATED			1
 
-/* This results in inefficient code for 64 bit to 32 conversions.
-   Something needs to be done about this.  Perhaps not use any 32 bit
-   instructions?  Perhaps use PROMOTE_MODE?  */
-#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC)  1
-
 #define Pmode SImode
 
 #define FUNCTION_MODE   SImode
Index: gcc/config/mips/mips.h
===================================================================
--- gcc/config/mips/mips.h	2017-09-13 20:12:23.803261934 +0100
+++ gcc/config/mips/mips.h	2017-09-13 20:12:24.488288461 +0100
@@ -2658,11 +2658,6 @@ #define SLOW_BYTE_ACCESS (!TARGET_MIPS16
    do not truncate the shift amount at all.  */
 #define SHIFT_COUNT_TRUNCATED (!TARGET_LOONGSON_VECTORS)
 
-/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
-   is done just by pretending it is already truncated.  */
-#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) \
-  (TARGET_64BIT ? ((INPREC) <= 32 || (OUTPREC) > 32) : 1)
-
 
 /* Specify the machine mode that pointers have.
    After generation of rtl, the compiler makes no further distinction
Index: gcc/config/mips/mips.c
===================================================================
--- gcc/config/mips/mips.c	2017-09-13 20:12:23.803261934 +0100
+++ gcc/config/mips/mips.c	2017-09-13 20:12:24.488288461 +0100
@@ -22328,6 +22328,14 @@ mips_promote_function_mode (const_tree t
   *punsignedp = unsignedp;
   return mode;
 }
+
+/* Implement TARGET_TRULY_NOOP_TRUNCATION.  */
+
+static bool
+mips_truly_noop_truncation (unsigned int outprec, unsigned int inprec)
+{
+  return !TARGET_64BIT || inprec <= 32 || outprec > 32;
+}
 
 /* Initialize the GCC target structure.  */
 #undef TARGET_ASM_ALIGNED_HI_OP
@@ -22623,6 +22631,9 @@ #define TARGET_SECONDARY_MEMORY_NEEDED m
 #undef TARGET_CAN_CHANGE_MODE_CLASS
 #define TARGET_CAN_CHANGE_MODE_CLASS mips_can_change_mode_class
 
+#undef TARGET_TRULY_NOOP_TRUNCATION
+#define TARGET_TRULY_NOOP_TRUNCATION mips_truly_noop_truncation
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 #include "gt-mips.h"
Index: gcc/config/mips/mips.md
===================================================================
--- gcc/config/mips/mips.md	2017-09-13 20:12:23.803261934 +0100
+++ gcc/config/mips/mips.md	2017-09-13 20:12:24.489196984 +0100
@@ -3242,9 +3242,9 @@ (define_expand "and<mode>3"
 		 (match_operand:GPR 2 "and_reg_operand")))])
 
 ;; The middle-end is not allowed to convert ANDing with 0xffff_ffff into a
-;; zero_extendsidi2 because of TRULY_NOOP_TRUNCATION, so handle these here.
-;; Note that this variant does not trigger for SI mode because we require
-;; a 64-bit HOST_WIDE_INT and 0xffff_ffff wouldn't be a canonical
+;; zero_extendsidi2 because of TARGET_TRULY_NOOP_TRUNCATION, so handle these
+;; here.  Note that this variant does not trigger for SI mode because we
+;; require a 64-bit HOST_WIDE_INT and 0xffff_ffff wouldn't be a canonical
 ;; sign-extended SImode value.
 ;;
 ;; These are possible combinations for operand 1 and 2.  The table
@@ -3426,7 +3426,7 @@ (define_insn "truncdfsf2"
 ;; modes is a no-op, as it is for most other GCC ports.  Truncating
 ;; DImode values to SImode is not a no-op for TARGET_64BIT since we
 ;; need to make sure that the lower 32 bits are properly sign-extended
-;; (see TRULY_NOOP_TRUNCATION).  Truncating DImode values into modes
+;; (see TARGET_TRULY_NOOP_TRUNCATION).  Truncating DImode values into modes
 ;; smaller than SImode is equivalent to two separate truncations:
 ;;
 ;;                        A       B
@@ -3644,7 +3644,7 @@ (define_insn "*zero_extendhi_truncqi"
 ;; Those for integer source operand are ordered widest source type first.
 
 ;; When TARGET_64BIT, all SImode integer and accumulator registers
-;; should already be in sign-extended form (see TRULY_NOOP_TRUNCATION
+;; should already be in sign-extended form (see TARGET_TRULY_NOOP_TRUNCATION
 ;; and truncdisi2).  We can therefore get rid of register->register
 ;; instructions if we constrain the source to be in the same register as
 ;; the destination.
Index: gcc/config/mmix/mmix.h
===================================================================
--- gcc/config/mmix/mmix.h	2017-09-13 20:12:23.803261934 +0100
+++ gcc/config/mmix/mmix.h	2017-09-13 20:12:24.489196984 +0100
@@ -788,8 +788,6 @@ #define LOAD_EXTEND_OP(MODE) (TARGET_ZER
 
 #define MOVE_MAX 8
 
-#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
-
 /* ??? MMIX allows a choice of STORE_FLAG_VALUE.  Revisit later,
    we don't have scc expanders yet.  */
 
Index: gcc/config/mn10300/mn10300.h
===================================================================
--- gcc/config/mn10300/mn10300.h	2017-09-13 20:12:23.803261934 +0100
+++ gcc/config/mn10300/mn10300.h	2017-09-13 20:12:24.489196984 +0100
@@ -691,10 +691,6 @@ #define MOVE_MAX	4
    of a shift count.  */
 #define SHIFT_COUNT_TRUNCATED 1
 
-/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
-   is done just by pretending it is already truncated.  */
-#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
-
 /* Specify the machine mode that pointers have.
    After generation of rtl, the compiler makes no further distinction
    between pointers and any other objects of this machine mode.  */
Index: gcc/config/moxie/moxie.h
===================================================================
--- gcc/config/moxie/moxie.h	2017-09-13 20:12:23.803261934 +0100
+++ gcc/config/moxie/moxie.h	2017-09-13 20:12:24.489196984 +0100
@@ -409,7 +409,6 @@ #define REGNO_OK_FOR_INDEX_P(NUM) MOXIE_
    quickly between memory and registers or between two memory
    locations.  */
 #define MOVE_MAX 4
-#define TRULY_NOOP_TRUNCATION(op,ip) 1
 
 /* All load operations zero extend.  */
 #define LOAD_EXTEND_OP(MEM) ZERO_EXTEND
@@ -418,8 +417,6 @@ #define LOAD_EXTEND_OP(MEM) ZERO_EXTEND
    valid memory address.  */
 #define MAX_REGS_PER_ADDRESS 1
 
-#define TRULY_NOOP_TRUNCATION(op,ip) 1
-
 /* An alias for a machine mode name.  This is the machine mode that
    elements of a jump-table should have.  */
 #define CASE_VECTOR_MODE SImode
Index: gcc/config/msp430/msp430.h
===================================================================
--- gcc/config/msp430/msp430.h	2017-09-13 20:12:23.803261934 +0100
+++ gcc/config/msp430/msp430.h	2017-09-13 20:12:24.489196984 +0100
@@ -204,8 +204,6 @@ #define INCOMING_RETURN_ADDR_RTX \
 #define RETURN_ADDR_RTX(COUNT, FA)		\
   msp430_return_addr_rtx (COUNT)
 
-#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC)   1
-
 #define SLOW_BYTE_ACCESS		0
 
 
Index: gcc/config/nds32/nds32.h
===================================================================
--- gcc/config/nds32/nds32.h	2017-09-13 20:12:23.803261934 +0100
+++ gcc/config/nds32/nds32.h	2017-09-13 20:12:24.490105507 +0100
@@ -998,11 +998,6 @@ #define MOVE_MAX 4
    of bits needed to represent the size of the object being shifted.  */
 #define SHIFT_COUNT_TRUNCATED 1
 
-/* A C expression which is nonzero if on this machine it is safe to "convert"
-   an integer of 'inprec' bits to one of 'outprec' bits by merely operating
-   on it as if it had only 'outprec' bits.  */
-#define TRULY_NOOP_TRUNCATION(outprec, inprec) 1
-
 /* A C expression describing the value returned by a comparison operator with
    an integral mode and stored by a store-flag instruction ('cstoremode4')
    when the condition is true.  */
Index: gcc/config/nios2/nios2.h
===================================================================
--- gcc/config/nios2/nios2.h	2017-09-13 20:12:23.803261934 +0100
+++ gcc/config/nios2/nios2.h	2017-09-13 20:12:24.490105507 +0100
@@ -515,8 +515,6 @@ #define FUNCTION_MODE QImode
 
 #define CASE_VECTOR_MODE Pmode
 
-#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
-
 #define LOAD_EXTEND_OP(MODE) (ZERO_EXTEND)
 
 #define WORD_REGISTER_OPERATIONS 1
Index: gcc/config/nvptx/nvptx.h
===================================================================
--- gcc/config/nvptx/nvptx.h	2017-09-13 20:12:23.803261934 +0100
+++ gcc/config/nvptx/nvptx.h	2017-09-13 20:12:24.490105507 +0100
@@ -310,7 +310,6 @@ #define FLOAT_STORE_FLAG_VALUE(MODE) REA
 #define CASE_VECTOR_MODE SImode
 #define MOVE_MAX 8
 #define MOVE_RATIO(SPEED) 4
-#define TRULY_NOOP_TRUNCATION(outprec, inprec) 1
 #define FUNCTION_MODE QImode
 #define HAS_INIT_SECTION 1
 
Index: gcc/config/pa/pa.h
===================================================================
--- gcc/config/pa/pa.h	2017-09-13 20:12:23.803261934 +0100
+++ gcc/config/pa/pa.h	2017-09-13 20:12:24.490105507 +0100
@@ -1019,10 +1019,6 @@ #define LOAD_EXTEND_OP(MODE) ZERO_EXTEND
 /* Nonzero if access to memory by bytes is slow and undesirable.  */
 #define SLOW_BYTE_ACCESS 1
 
-/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
-   is done just by pretending it is already truncated.  */
-#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
-
 /* Specify the machine mode that pointers have.
    After generation of rtl, the compiler makes no further distinction
    between pointers and any other objects of this machine mode.  */
Index: gcc/config/pdp11/pdp11.h
===================================================================
--- gcc/config/pdp11/pdp11.h	2017-09-13 20:12:23.803261934 +0100
+++ gcc/config/pdp11/pdp11.h	2017-09-13 20:12:24.490105507 +0100
@@ -432,10 +432,6 @@ #define SLOW_BYTE_ACCESS 0
 /* Do not break .stabs pseudos into continuations.  */
 #define DBX_CONTIN_LENGTH 0
 
-/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
-   is done just by pretending it is already truncated.  */
-#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
-
 /* Give a comparison code (EQ, NE etc) and the first operand of a COMPARE,
    return the mode to be used for the comparison.  For floating-point, CCFPmode
    should be used.  */
Index: gcc/config/powerpcspe/powerpcspe.h
===================================================================
--- gcc/config/powerpcspe/powerpcspe.h	2017-09-13 20:12:23.803261934 +0100
+++ gcc/config/powerpcspe/powerpcspe.h	2017-09-13 20:12:24.490105507 +0100
@@ -2108,10 +2108,6 @@ #define LOAD_EXTEND_OP(MODE) ZERO_EXTEND
 /* Define if loading short immediate values into registers sign extends.  */
 #define SHORT_IMMEDIATES_SIGN_EXTEND 1
 
-/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
-   is done just by pretending it is already truncated.  */
-#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
-
 /* The cntlzw and cntlzd instructions return 32 and 64 for input of zero.  */
 #define CLZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) \
   ((VALUE) = GET_MODE_BITSIZE (MODE), 2)
Index: gcc/config/riscv/riscv.h
===================================================================
--- gcc/config/riscv/riscv.h	2017-09-13 20:12:23.803261934 +0100
+++ gcc/config/riscv/riscv.h	2017-09-13 20:12:24.491922554 +0100
@@ -637,8 +637,6 @@ #define SLOW_BYTE_ACCESS 0
 
 #define SHIFT_COUNT_TRUNCATED 1
 
-#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
-
 /* Specify the machine mode that pointers have.
    After generation of rtl, the compiler makes no further distinction
    between pointers and any other objects of this machine mode.  */
Index: gcc/config/riscv/riscv.md
===================================================================
--- gcc/config/riscv/riscv.md	2017-09-13 20:12:23.803261934 +0100
+++ gcc/config/riscv/riscv.md	2017-09-13 20:12:24.491922554 +0100
@@ -1307,7 +1307,8 @@ (define_insn "*movhi_internal"
    (set_attr "mode" "HI")])
 
 ;; HImode constant generation; see riscv_move_integer for details.
-;; si+si->hi without truncation is legal because of TRULY_NOOP_TRUNCATION.
+;; si+si->hi without truncation is legal because of
+;; TARGET_TRULY_NOOP_TRUNCATION.
 
 (define_insn "*add<mode>hi3"
   [(set (match_operand:HI            0 "register_operand" "=r,r")
Index: gcc/config/rl78/rl78.h
===================================================================
--- gcc/config/rl78/rl78.h	2017-09-13 20:12:23.803261934 +0100
+++ gcc/config/rl78/rl78.h	2017-09-13 20:12:24.491922554 +0100
@@ -151,8 +151,6 @@ #define HAS_LONG_UNCOND_BRANCH		0
 #define MOVE_MAX 			2
 #define STARTING_FRAME_OFFSET		0
 
-#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC)   1
-
 #define ADDR_SPACE_NEAR			1
 #define ADDR_SPACE_FAR			2
 
Index: gcc/config/rs6000/rs6000.h
===================================================================
--- gcc/config/rs6000/rs6000.h	2017-09-13 20:12:23.803261934 +0100
+++ gcc/config/rs6000/rs6000.h	2017-09-13 20:12:24.491922554 +0100
@@ -2005,10 +2005,6 @@ #define LOAD_EXTEND_OP(MODE) ZERO_EXTEND
 /* Define if loading short immediate values into registers sign extends.  */
 #define SHORT_IMMEDIATES_SIGN_EXTEND 1
 
-/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
-   is done just by pretending it is already truncated.  */
-#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
-
 /* The cntlzw and cntlzd instructions return 32 and 64 for input of zero.  */
 #define CLZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) \
   ((VALUE) = GET_MODE_BITSIZE (MODE), 2)
Index: gcc/config/rx/rx.h
===================================================================
--- gcc/config/rx/rx.h	2017-09-13 20:12:23.803261934 +0100
+++ gcc/config/rx/rx.h	2017-09-13 20:12:24.491922554 +0100
@@ -171,8 +171,6 @@ #define HAS_LONG_UNCOND_BRANCH		0
 #define MOVE_MAX 			4
 #define STARTING_FRAME_OFFSET		0
 
-#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC)   1
-
 #define HAVE_PRE_DECREMENT		1
 #define HAVE_POST_INCREMENT		1
 
Index: gcc/config/s390/s390.h
===================================================================
--- gcc/config/s390/s390.h	2017-09-13 20:12:23.803261934 +0100
+++ gcc/config/s390/s390.h	2017-09-13 20:12:24.492831077 +0100
@@ -963,10 +963,6 @@ #define ASM_DECLARE_FUNCTION_SIZE s390_a
    tablejump instruction.  */
 #define CASE_VECTOR_MODE (TARGET_64BIT ? DImode : SImode)
 
-/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
-   is done just by pretending it is already truncated.  */
-#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC)  1
-
 /* Specify the machine mode that pointers have.
    After generation of rtl, the compiler makes no further distinction
    between pointers and any other objects of this machine mode.  */
Index: gcc/config/sh/sh.h
===================================================================
--- gcc/config/sh/sh.h	2017-09-13 20:12:23.803261934 +0100
+++ gcc/config/sh/sh.h	2017-09-13 20:12:24.492831077 +0100
@@ -1430,8 +1430,6 @@ #define PIC_REFERENCE_P(OP) \
 #define MAYBE_BASE_REGISTER_RTX_P(X, STRICT)			\
   ((REG_P (X) && REG_OK_FOR_BASE_P (X, STRICT))	\
    || (GET_CODE (X) == SUBREG					\
-       && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (GET_MODE ((X))),	\
-				 GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (X)))) \
        && REG_P (SUBREG_REG (X))			\
        && REG_OK_FOR_BASE_P (SUBREG_REG (X), STRICT)))
 
@@ -1441,8 +1439,6 @@ #define MAYBE_BASE_REGISTER_RTX_P(X, STR
 #define MAYBE_INDEX_REGISTER_RTX_P(X, STRICT)				\
   ((REG_P (X) && REG_OK_FOR_INDEX_P (X, STRICT))	\
    || (GET_CODE (X) == SUBREG					\
-       && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (GET_MODE ((X))), \
-				 GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (X)))) \
        && REG_P (SUBREG_REG (X))		\
        && SUBREG_OK_FOR_INDEX_P (SUBREG_REG (X), SUBREG_BYTE (X), STRICT)))
 
@@ -1557,9 +1553,6 @@ #define SH_DYNAMIC_SHIFT_COST (TARGET_DY
    more compact code.  */
 #define SHIFT_COUNT_TRUNCATED (0)
 
-/* All integers have the same format so truncation is easy.  */
-#define TRULY_NOOP_TRUNCATION(OUTPREC,INPREC) (true)
-
 /* Define this if addresses of constant functions
    shouldn't be put through pseudo regs where they can be cse'd.
    Desirable on machines where ordinary constants are expensive
Index: gcc/config/sparc/sparc.h
===================================================================
--- gcc/config/sparc/sparc.h	2017-09-13 20:12:23.803261934 +0100
+++ gcc/config/sparc/sparc.h	2017-09-13 20:12:24.492831077 +0100
@@ -1447,10 +1447,6 @@ #define SLOW_BYTE_ACCESS 1
    few bits.  */
 #define SHIFT_COUNT_TRUNCATED 1
 
-/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
-   is done just by pretending it is already truncated.  */
-#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
-
 /* For SImode, we make sure the top 32-bits of the register are clear and
    then we subtract 32 from the lzd instruction result.  */
 #define CLZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) \
Index: gcc/config/spu/spu.h
===================================================================
--- gcc/config/spu/spu.h	2017-09-13 20:12:23.803261934 +0100
+++ gcc/config/spu/spu.h	2017-09-13 20:12:24.493739600 +0100
@@ -487,8 +487,6 @@ #define CASE_VECTOR_MODE SImode
 
 #define MOVE_MAX 16 
 
-#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) ((INPREC) <= 32 && (OUTPREC) <= (INPREC))
-
 #define STORE_FLAG_VALUE -1
 
 #define Pmode SImode
Index: gcc/config/spu/spu.c
===================================================================
--- gcc/config/spu/spu.c	2017-09-13 20:12:23.803261934 +0100
+++ gcc/config/spu/spu.c	2017-09-13 20:12:24.493739600 +0100
@@ -7173,6 +7173,14 @@ spu_can_change_mode_class (machine_mode
 	  || (GET_MODE_SIZE (from) <= 4 && GET_MODE_SIZE (to) <= 4)
 	  || (GET_MODE_SIZE (from) >= 16 && GET_MODE_SIZE (to) >= 16));
 }
+
+/* Implement TARGET_TRULY_NOOP_TRUNCATION.  */
+
+static bool
+spu_truly_noop_truncation (unsigned int outprec, unsigned int inprec)
+{
+  return inprec <= 32 && outprec <= inprec;
+}
 
 /*  Table of machine attributes.  */
 static const struct attribute_spec spu_attribute_table[] =
@@ -7407,6 +7415,9 @@ #define TARGET_HARD_REGNO_NREGS spu_hard
 #undef TARGET_CAN_CHANGE_MODE_CLASS
 #define TARGET_CAN_CHANGE_MODE_CLASS spu_can_change_mode_class
 
+#undef TARGET_TRULY_NOOP_TRUNCATION
+#define TARGET_TRULY_NOOP_TRUNCATION spu_truly_noop_truncation
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 #include "gt-spu.h"
Index: gcc/config/stormy16/stormy16.h
===================================================================
--- gcc/config/stormy16/stormy16.h	2017-09-13 20:12:23.803261934 +0100
+++ gcc/config/stormy16/stormy16.h	2017-09-13 20:12:24.493739600 +0100
@@ -478,8 +478,6 @@ #define MOVE_MAX 2
 
 #define SHIFT_COUNT_TRUNCATED 1
 
-#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
-
 #define Pmode HImode
 
 #define FUNCTION_MODE HImode
Index: gcc/config/tilegx/tilegx.h
===================================================================
--- gcc/config/tilegx/tilegx.h	2017-09-13 20:12:23.803261934 +0100
+++ gcc/config/tilegx/tilegx.h	2017-09-13 20:12:24.493739600 +0100
@@ -378,11 +378,6 @@ #define SHIFT_COUNT_TRUNCATED 0
 
 #define SHORT_IMMEDIATES_SIGN_EXTEND 1
 
-/* We represent all SI values as sign-extended DI values in
-   registers.  */
-#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) \
-  ((INPREC) <= 32 || (OUTPREC) > 32)
-
 #define CLZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) ((VALUE) = 64, 1)
 #define CTZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) ((VALUE) = 64, 1)
 
Index: gcc/config/tilegx/tilegx.c
===================================================================
--- gcc/config/tilegx/tilegx.c	2017-09-13 20:12:23.803261934 +0100
+++ gcc/config/tilegx/tilegx.c	2017-09-13 20:12:24.493739600 +0100
@@ -5560,7 +5560,14 @@ tilegx_file_end (void)
     file_end_indicate_exec_stack ();
 }
 
+/* Implement TARGET_TRULY_NOOP_TRUNCATION.  We represent all SI values
+   as sign-extended DI values in registers.  */
 
+static bool
+tilegx_truly_noop_truncation (unsigned int outprec, unsigned int inprec)
+{
+  return inprec <= 32 || outprec > 32;
+}
 
 #undef  TARGET_HAVE_TLS
 #define TARGET_HAVE_TLS HAVE_AS_TLS
@@ -5724,6 +5731,9 @@ #define TARGET_ASM_ALIGNED_DI_OP "\t.qua
 #undef  TARGET_CAN_USE_DOLOOP_P
 #define TARGET_CAN_USE_DOLOOP_P can_use_doloop_if_innermost
 
+#undef  TARGET_TRULY_NOOP_TRUNCATION
+#define TARGET_TRULY_NOOP_TRUNCATION tilegx_truly_noop_truncation
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 #include "gt-tilegx.h"
Index: gcc/config/tilegx/tilegx.md
===================================================================
--- gcc/config/tilegx/tilegx.md	2017-09-13 20:12:23.803261934 +0100
+++ gcc/config/tilegx/tilegx.md	2017-09-13 20:12:24.494648124 +0100
@@ -2004,8 +2004,8 @@ (define_insn "extendhi<mode>2"
    ld2s_add\t%0, %I1, %i1"
   [(set_attr "type" "X0,Y2_2cycle,X1_2cycle")])
 
-;; All SImode integer registers should already be in sign-extended
-;; form (see TRULY_NOOP_TRUNCATION and truncdisi2).  We can therefore
+;; All SImode integer registers should already be in sign-extended form
+;; (see TARGET_TRULY_NOOP_TRUNCATION and truncdisi2).  We can therefore
 ;; get rid of register->register instructions if we constrain the
 ;; source to be in the same register as the destination.
 (define_insn_and_split "extendsidi2"
@@ -2028,7 +2028,7 @@ (define_insn_and_split "extendsidi2"
 ;; modes is a no-op, as it is for most other GCC ports.  Truncating
 ;; DImode values to SImode is not a no-op since we
 ;; need to make sure that the lower 32 bits are properly sign-extended
-;; (see TRULY_NOOP_TRUNCATION).  Truncating DImode values into modes
+;; (see TARGET_TRULY_NOOP_TRUNCATION).  Truncating DImode values into modes
 ;; smaller than SImode is equivalent to two separate truncations:
 ;;
 ;;                        A       B
Index: gcc/config/tilepro/tilepro.h
===================================================================
--- gcc/config/tilepro/tilepro.h	2017-09-13 20:12:23.803261934 +0100
+++ gcc/config/tilepro/tilepro.h	2017-09-13 20:12:24.494648124 +0100
@@ -337,8 +337,6 @@ #define SHIFT_COUNT_TRUNCATED 1
 
 #define SHORT_IMMEDIATES_SIGN_EXTEND 1
 
-#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
-
 #define CLZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) ((VALUE) = 32, 1)
 #define CTZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) ((VALUE) = 32, 1)
 
Index: gcc/config/v850/v850.h
===================================================================
--- gcc/config/v850/v850.h	2017-09-13 20:12:23.803261934 +0100
+++ gcc/config/v850/v850.h	2017-09-13 20:12:24.494648124 +0100
@@ -766,10 +766,6 @@ #define MOVE_MAX	4
    of a shift count.  */
 #define SHIFT_COUNT_TRUNCATED 1
 
-/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
-   is done just by pretending it is already truncated.  */
-#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
-
 /* Specify the machine mode that pointers have.
    After generation of rtl, the compiler makes no further distinction
    between pointers and any other objects of this machine mode.  */
Index: gcc/config/vax/vax.h
===================================================================
--- gcc/config/vax/vax.h	2017-09-13 20:12:23.803261934 +0100
+++ gcc/config/vax/vax.h	2017-09-13 20:12:24.494648124 +0100
@@ -448,10 +448,6 @@ #define SLOW_BYTE_ACCESS 0
    of a shift count.  */
 /* #define SHIFT_COUNT_TRUNCATED */
 
-/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
-   is done just by pretending it is already truncated.  */
-#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
-
 /* Specify the machine mode that pointers have.
    After generation of rtl, the compiler makes no further distinction
    between pointers and any other objects of this machine mode.  */
Index: gcc/config/visium/visium.h
===================================================================
--- gcc/config/visium/visium.h	2017-09-13 20:12:23.803261934 +0100
+++ gcc/config/visium/visium.h	2017-09-13 20:12:24.494648124 +0100
@@ -1202,21 +1202,6 @@ #define MAX_MOVE_MAX 4
    bitfield instructions. */
 #define SHIFT_COUNT_TRUNCATED 0
 
-/* `TRULY_NOOP_TRUNCATION (OUTPREC, INPREC)'
-
-   A C expression which is nonzero if on this machine it is safe to
-   "convert" an integer of INPREC bits to one of OUTPREC bits (where
-   OUTPREC is smaller than INPREC) by merely operating on it as if it
-   had only OUTPREC bits.
-
-   On many machines, this expression can be 1.
-
-   When `TRULY_NOOP_TRUNCATION' returns 1 for a pair of sizes for
-   modes for which `TARGET_MODES_TIEABLE_P' is 0, suboptimal code can result.
-   If this is the case, making `TRULY_NOOP_TRUNCATION' return 0 in
-   such cases may improve things. */
-#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
-
 /* `STORE_FLAG_VALUE'
 
    A C expression describing the value returned by a comparison
Index: gcc/config/xtensa/xtensa.h
===================================================================
--- gcc/config/xtensa/xtensa.h	2017-09-13 20:12:23.803261934 +0100
+++ gcc/config/xtensa/xtensa.h	2017-09-13 20:12:24.495556647 +0100
@@ -669,10 +669,6 @@ #define SLOW_BYTE_ACCESS 1
 /* Shift instructions ignore all but the low-order few bits.  */
 #define SHIFT_COUNT_TRUNCATED 1
 
-/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
-   is done just by pretending it is already truncated.  */
-#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
-
 #define CLZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE)  ((VALUE) = 32, 1)
 #define CTZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE)  ((VALUE) = -1, 1)
 
Index: gcc/system.h
===================================================================
--- gcc/system.h	2017-09-13 20:12:03.827824030 +0100
+++ gcc/system.h	2017-09-13 20:12:24.498282217 +0100
@@ -914,7 +914,8 @@ #define realloc xrealloc
 	HARD_REGNO_CALL_PART_CLOBBERED HARD_REGNO_MODE_OK		\
 	MODES_TIEABLE_P FUNCTION_ARG_PADDING SLOW_UNALIGNED_ACCESS	\
 	HARD_REGNO_NREGS SECONDARY_MEMORY_NEEDED_MODE			\
-	SECONDARY_MEMORY_NEEDED CANNOT_CHANGE_MODE_CLASS
+	SECONDARY_MEMORY_NEEDED CANNOT_CHANGE_MODE_CLASS		\
+	TRULY_NOOP_TRUNCATION
 
 /* Target macros only used for code built for the target, that have
    moved to libgcc-tm.h or have never been present elsewhere.  */
