Index: doc/tm.texi
===================================================================
--- doc/tm.texi	(revision 241611)
+++ doc/tm.texi	(working copy)
@@ -10618,6 +10618,23 @@ smaller than a word are always performed
 Most RISC machines have this property and most CISC machines do not.
 @end defmac
 
+@deftypefn {Target Hook} {unsigned int} TARGET_MIN_ARITHMETIC_PRECISION (void)
+On some RISC architectures with 64-bit registers, the processor also
+maintains 32-bit condition codes that make it possible to do real 32-bit
+arithmetic, although the operations are performed on the full registers.
+
+On such architectures, defining this hook to 32 tells the compiler to try
+using 32-bit arithmetical operations setting the condition codes instead
+of doing full 64-bit arithmetic.
+
+More generally, define this hook on RISC architectures if you want the
+compiler to try using arithmetical operations setting the condition codes
+with a precision lower than the word precision.
+
+You need not define this hook if @code{WORD_REGISTER_OPERATIONS} is not
+defined to 1.
+@end deftypefn
+
 @defmac LOAD_EXTEND_OP (@var{mem_mode})
 Define this macro to be a C expression indicating when insns that read
 memory in @var{mem_mode}, an integral mode narrower than a word, set the
Index: doc/tm.texi.in
===================================================================
--- doc/tm.texi.in	(revision 241611)
+++ doc/tm.texi.in	(working copy)
@@ -7575,6 +7575,8 @@ smaller than a word are always performed
 Most RISC machines have this property and most CISC machines do not.
 @end defmac
 
+@hook TARGET_MIN_ARITHMETIC_PRECISION
+
 @defmac LOAD_EXTEND_OP (@var{mem_mode})
 Define this macro to be a C expression indicating when insns that read
 memory in @var{mem_mode}, an integral mode narrower than a word, set the
Index: internal-fn.c
===================================================================
--- internal-fn.c	(revision 241611)
+++ internal-fn.c	(working copy)
@@ -1824,12 +1836,11 @@ expand_arith_overflow (enum tree_code co
 	  return;
 	}
 
-      /* For sub-word operations, if target doesn't have them, start
-	 with precres widening right away, otherwise do it only
-	 if the most simple cases can't be used.  */
-      if (WORD_REGISTER_OPERATIONS
-	  && orig_precres == precres
-	  && precres < BITS_PER_WORD)
+      /* For operations with low precision, if target doesn't have them, start
+	 with precres widening right away, otherwise do it only if the most
+	 simple cases can't be used.  */
+      const int min_precision = targetm.min_arithmetic_precision ();
+      if (orig_precres == precres && precres < min_precision)
 	;
       else if ((uns0_p && uns1_p && unsr_p && prec0 <= precres
 		&& prec1 <= precres)
@@ -1864,7 +1875,7 @@ expand_arith_overflow (enum tree_code co
       /* For sub-word operations, retry with a wider type first.  */
       if (orig_precres == precres && precop <= BITS_PER_WORD)
 	{
-	  int p = WORD_REGISTER_OPERATIONS ? BITS_PER_WORD : precop;
+	  int p = MAX (min_precision, precop);
 	  enum machine_mode m = smallest_mode_for_size (p, MODE_INT);
 	  tree optype = build_nonstandard_integer_type (GET_MODE_PRECISION (m),
 							uns0_p && uns1_p
Index: target.def
===================================================================
--- target.def	(revision 241611)
+++ target.def	(working copy)
@@ -5932,6 +5932,24 @@ comparison code or operands.",
  void, (int *code, rtx *op0, rtx *op1, bool op0_preserve_value),
  default_canonicalize_comparison)
 
+DEFHOOK
+(min_arithmetic_precision,
+ "On some RISC architectures with 64-bit registers, the processor also\n\
+maintains 32-bit condition codes that make it possible to do real 32-bit\n\
+arithmetic, although the operations are performed on the full registers.\n\
+\n\
+On such architectures, defining this hook to 32 tells the compiler to try\n\
+using 32-bit arithmetical operations setting the condition codes instead\n\
+of doing full 64-bit arithmetic.\n\
+\n\
+More generally, define this hook on RISC architectures if you want the\n\
+compiler to try using arithmetical operations setting the condition codes\n\
+with a precision lower than the word precision.\n\
+\n\
+You need not define this hook if @code{WORD_REGISTER_OPERATIONS} is not\n\
+defined to 1.",
+ unsigned int, (void), default_min_arithmetic_precision)
+
 DEFHOOKPOD
 (atomic_test_and_set_trueval,
  "This value should be set if the result written by\
Index: targhooks.c
===================================================================
--- targhooks.c	(revision 241611)
+++ targhooks.c	(working copy)
@@ -2127,4 +2127,12 @@ default_max_noce_ifcvt_seq_cost (edge e)
     return BRANCH_COST (true, predictable_p) * COSTS_N_INSNS (3);
 }
 
+/* Default implementation if TARGET_MIN_ARITHMETIC_PRECISION.  */
+
+unsigned int
+default_min_arithmetic_precision (void)
+{
+  return WORD_REGISTER_OPERATIONS ? BITS_PER_WORD : BITS_PER_UNIT;
+}
+
 #include "gt-targhooks.h"
Index: targhooks.h
===================================================================
--- targhooks.h	(revision 241611)
+++ targhooks.h	(working copy)
@@ -260,7 +260,7 @@ extern void default_setup_incoming_varar
 						  int second_time ATTRIBUTE_UNUSED);
 extern bool default_optab_supported_p (int, machine_mode, machine_mode,
 				       optimization_type);
-
 extern unsigned int default_max_noce_ifcvt_seq_cost (edge);
+extern unsigned int default_min_arithmetic_precision (void);
 
 #endif /* GCC_TARGHOOKS_H */
Index: config/sparc/sparc.c
===================================================================
--- config/sparc/sparc.c	(revision 241611)
+++ config/sparc/sparc.c	(working copy)
@@ -648,6 +648,7 @@ static reg_class_t sparc_secondary_reloa
 static machine_mode sparc_cstore_mode (enum insn_code icode);
 static void sparc_atomic_assign_expand_fenv (tree *, tree *, tree *);
 static bool sparc_fixed_condition_code_regs (unsigned int *, unsigned int *);
+static unsigned int sparc_min_arithmetic_precision (void);
 
 #ifdef SUBTARGET_ATTRIBUTE_TABLE
 /* Table of valid machine attributes.  */
@@ -866,6 +867,9 @@ char sparc_hard_reg_printed[8];
 #undef TARGET_FIXED_CONDITION_CODE_REGS
 #define TARGET_FIXED_CONDITION_CODE_REGS sparc_fixed_condition_code_regs
 
+#undef TARGET_MIN_ARITHMETIC_PRECISION
+#define TARGET_MIN_ARITHMETIC_PRECISION sparc_min_arithmetic_precision
+
 #undef TARGET_CUSTOM_FUNCTION_DESCRIPTORS
 #define TARGET_CUSTOM_FUNCTION_DESCRIPTORS 1
 
@@ -2749,6 +2753,14 @@ sparc_fixed_condition_code_regs (unsigne
   return true;
 }
 
+/* Implement TARGET_MIN_ARITHMETIC_PRECISION.  */
+
+static unsigned int
+sparc_min_arithmetic_precision (void)
+{
+  return 32;
+}
+
 /* Given 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,
    CCFP[E]mode is used.  CCNZmode should be used when the first operand
