#include "predict.h"
 #include "memmodel.h"
 #include "tm_p.h"
-#include "expmed.h"
 #include "optabs.h"
+#include "expmed.h"
 #include "regs.h"
 #include "emit-rtl.h"
 #include "diagnostic-core.h"
 
 rtx
 expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
-              rtx op0, rtx op1, rtx target, int unsignedp)
+              rtx op0, rtx op1, rtx target, int unsignedp,
+              enum optab_methods methods)
 {
   machine_mode compute_mode;
   rtx tquotient;
   optab2 = (op1_is_pow2 ? optab1
            : (unsignedp ? udivmod_optab : sdivmod_optab));
 
-  FOR_EACH_MODE_FROM (compute_mode, mode)
-    if (optab_handler (optab1, compute_mode) != CODE_FOR_nothing
-       || optab_handler (optab2, compute_mode) != CODE_FOR_nothing)
-      break;
-
-  if (compute_mode == VOIDmode)
-    FOR_EACH_MODE_FROM (compute_mode, mode)
-      if (optab_libfunc (optab1, compute_mode)
-         || optab_libfunc (optab2, compute_mode))
+  if (methods == OPTAB_WIDEN || methods == OPTAB_LIB_WIDEN)
+    {
+      FOR_EACH_MODE_FROM (compute_mode, mode)
+      if (optab_handler (optab1, compute_mode) != CODE_FOR_nothing
+         || optab_handler (optab2, compute_mode) != CODE_FOR_nothing)
        break;
 
+      if (compute_mode == VOIDmode && methods == OPTAB_LIB_WIDEN)
+       FOR_EACH_MODE_FROM (compute_mode, mode)
+         if (optab_libfunc (optab1, compute_mode)
+             || optab_libfunc (optab2, compute_mode))
+           break;
+    }
+  else
+    compute_mode = mode;
+
   /* If we still couldn't find a mode, use MODE, but expand_binop will
      probably die.  */
   if (compute_mode == VOIDmode)
                        remainder
                          = expand_binop (int_mode, and_optab, op0,
                                          gen_int_mode (mask, int_mode),
-                                         remainder, 1,
-                                         OPTAB_LIB_WIDEN);
+                                         remainder, 1, methods);
                        if (remainder)
                          return gen_lowpart (mode, remainder);
                      }
                        remainder = expand_binop
                          (int_mode, and_optab, op0,
                           gen_int_mode (mask, int_mode),
-                          remainder, 0, OPTAB_LIB_WIDEN);
+                          remainder, 0, methods);
                        if (remainder)
                          return gen_lowpart (mode, remainder);
                      }
          do_cmp_and_jump (op1, const0_rtx, LT, compute_mode, label2);
          do_cmp_and_jump (adjusted_op0, const0_rtx, LT, compute_mode, label1);
          tem = expand_binop (compute_mode, sdiv_optab, adjusted_op0, op1,
-                             quotient, 0, OPTAB_LIB_WIDEN);
+                             quotient, 0, methods);
          if (tem != quotient)
            emit_move_insn (quotient, tem);
          emit_jump_insn (targetm.gen_jump (label5));
          emit_label (label2);
          do_cmp_and_jump (adjusted_op0, const0_rtx, GT, compute_mode, label3);
          tem = expand_binop (compute_mode, sdiv_optab, adjusted_op0, op1,
-                             quotient, 0, OPTAB_LIB_WIDEN);
+                             quotient, 0, methods);
          if (tem != quotient)
            emit_move_insn (quotient, tem);
          emit_jump_insn (targetm.gen_jump (label5));
          expand_dec (adjusted_op0, const1_rtx);
          emit_label (label4);
          tem = expand_binop (compute_mode, sdiv_optab, adjusted_op0, op1,
-                             quotient, 0, OPTAB_LIB_WIDEN);
+                             quotient, 0, methods);
          if (tem != quotient)
            emit_move_insn (quotient, tem);
          expand_dec (quotient, const1_rtx);
                                   floor_log2 (d), tquotient, 1);
                t2 = expand_binop (int_mode, and_optab, op0,
                                   gen_int_mode (d - 1, int_mode),
-                                  NULL_RTX, 1, OPTAB_LIB_WIDEN);
+                                  NULL_RTX, 1, methods);
                t3 = gen_reg_rtx (int_mode);
                t3 = emit_store_flag (t3, NE, t2, const0_rtx, int_mode, 1, 1);
                if (t3 == 0)
              emit_label (label1);
              expand_dec (adjusted_op0, const1_rtx);
              tem = expand_binop (compute_mode, udiv_optab, adjusted_op0, op1,
-                                 quotient, 1, OPTAB_LIB_WIDEN);
+                                 quotient, 1, methods);
              if (tem != quotient)
                emit_move_insn (quotient, tem);
              expand_inc (quotient, const1_rtx);
                                   floor_log2 (d), tquotient, 0);
                t2 = expand_binop (compute_mode, and_optab, op0,
                                   gen_int_mode (d - 1, compute_mode),
-                                  NULL_RTX, 1, OPTAB_LIB_WIDEN);
+                                  NULL_RTX, 1, methods);
                t3 = gen_reg_rtx (compute_mode);
                t3 = emit_store_flag (t3, NE, t2, const0_rtx,
                                      compute_mode, 1, 1);
              do_cmp_and_jump (adjusted_op0, const0_rtx, GT,
                               compute_mode, label1);
              tem = expand_binop (compute_mode, sdiv_optab, adjusted_op0, op1,
-                                 quotient, 0, OPTAB_LIB_WIDEN);
+                                 quotient, 0, methods);
              if (tem != quotient)
                emit_move_insn (quotient, tem);
              emit_jump_insn (targetm.gen_jump (label5));
              do_cmp_and_jump (adjusted_op0, const0_rtx, LT,
                               compute_mode, label3);
              tem = expand_binop (compute_mode, sdiv_optab, adjusted_op0, op1,
-                                 quotient, 0, OPTAB_LIB_WIDEN);
+                                 quotient, 0, methods);
              if (tem != quotient)
                emit_move_insn (quotient, tem);
              emit_jump_insn (targetm.gen_jump (label5));
              expand_inc (adjusted_op0, const1_rtx);
              emit_label (label4);
              tem = expand_binop (compute_mode, sdiv_optab, adjusted_op0, op1,
-                                 quotient, 0, OPTAB_LIB_WIDEN);
+                                 quotient, 0, methods);
              if (tem != quotient)
                emit_move_insn (quotient, tem);
              expand_inc (quotient, const1_rtx);
              {
                rtx tem;
                quotient = expand_binop (int_mode, udiv_optab, op0, op1,
-                                        quotient, 1, OPTAB_LIB_WIDEN);
+                                        quotient, 1, methods);
                tem = expand_mult (int_mode, quotient, op1, NULL_RTX, 1);
                remainder = expand_binop (int_mode, sub_optab, op0, tem,
-                                         remainder, 1, OPTAB_LIB_WIDEN);
+                                         remainder, 1, methods);
              }
            tem = plus_constant (int_mode, op1, -1);
            tem = expand_shift (RSHIFT_EXPR, int_mode, tem, 1, NULL_RTX, 1);
              {
                rtx tem;
                quotient = expand_binop (int_mode, sdiv_optab, op0, op1,
-                                        quotient, 0, OPTAB_LIB_WIDEN);
+                                        quotient, 0, methods);
                tem = expand_mult (int_mode, quotient, op1, NULL_RTX, 0);
                remainder = expand_binop (int_mode, sub_optab, op0, tem,
-                                         remainder, 0, OPTAB_LIB_WIDEN);
+                                         remainder, 0, methods);
              }
            abs_rem = expand_abs (int_mode, remainder, NULL_RTX, 1, 0);
            abs_op1 = expand_abs (int_mode, op1, NULL_RTX, 1, 0);
                quotient = sign_expand_binop (compute_mode,
                                              udiv_optab, sdiv_optab,
                                              op0, op1, target,
-                                             unsignedp, OPTAB_LIB_WIDEN);
+                                             unsignedp, methods);
            }
        }
     }
          /* No divide instruction either.  Use library for remainder.  */
          remainder = sign_expand_binop (compute_mode, umod_optab, smod_optab,
                                         op0, op1, target,
-                                        unsignedp, OPTAB_LIB_WIDEN);
+                                        unsignedp, methods);
          /* No remainder function.  Try a quotient-and-remainder
             function, keeping the remainder.  */
-         if (!remainder)
+         if (!remainder
+             && (methods == OPTAB_LIB || methods == OPTAB_LIB_WIDEN))
            {
              remainder = gen_reg_rtx (compute_mode);
              if (!expand_twoval_binop_libfunc
                                   NULL_RTX, unsignedp);
          remainder = expand_binop (compute_mode, sub_optab, op0,
                                    remainder, target, unsignedp,
-                                   OPTAB_LIB_WIDEN);
+                                   methods);
        }
     }
 
+  if (methods != OPTAB_LIB_WIDEN
+      && (rem_flag ? remainder : quotient) == NULL_RTX)
+    return NULL_RTX;
+
   return gen_lowpart (mode, rem_flag ? remainder : quotient);
 }
 \f