Index: common/config/avr/avr-common.c
===================================================================
--- common/config/avr/avr-common.c	(revision 244001)
+++ common/config/avr/avr-common.c	(working copy)
@@ -28,9 +28,18 @@
 static const struct default_options avr_option_optimization_table[] =
   {
     { OPT_LEVELS_1_PLUS, OPT_fomit_frame_pointer, NULL, 1 },
+
     // The only effect of -fcaller-saves might be that it triggers
     // a frame without need when it tries to be smart around calls.
     { OPT_LEVELS_ALL, OPT_fcaller_saves, NULL, 0 },
+
+    // Currently, the only purpose of the insn scheduler is to work
+    // around PR78883, i.e. we only need the side effect of defining
+    // INSN_SCHEDULING.  Even with a dummy scheduler we will see reodering
+    // of instructions, which is not wanted if not actually needed.
+    { OPT_LEVELS_ALL, OPT_fschedule_insns, NULL, 0 },
+    { OPT_LEVELS_ALL, OPT_fschedule_insns2, NULL, 0 },
+
     { OPT_LEVELS_NONE, 0, NULL, 0 }
   };
 
Index: config/avr/avr-dfa.md
===================================================================
--- config/avr/avr-dfa.md	(nonexistent)
+++ config/avr/avr-dfa.md	(working copy)
@@ -0,0 +1,48 @@
+;; Copyright (C) 1998-2017 Free Software Foundation, Inc.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+;;
+;; GCC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3.  If not see
+;; <http://www.gnu.org/licenses/>.  */
+
+
+;; FIXME: The only purpose of this dummy scheduler is to work around PR78883
+;; as a less intrusive alternative to implementing CANNOT_CHANGE_MODE_CLASS,
+;; cf. https://gcc.gnu.org/ml/gcc-patches/2017-01/msg00078.html
+;;
+;; Desired side effect is defining INSN_SCHEDULING, which in turn enables the
+;; following chunk of code in recog.c::general_operand, which in turn
+;; defeats the paradoxical subregs of mem which caused PR78883. 
+;;
+;; #ifdef INSN_SCHEDULING
+;;       /* On machines that have insn scheduling, we want all memory
+;;          reference to be explicit, so outlaw paradoxical SUBREGs.
+;;          However, we must allow them after reload so that they can
+;;          get cleaned up by cleanup_subreg_operands.  */
+;;       if (!reload_completed && MEM_P (sub)
+;;           && GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (sub)))
+;;         return 0;
+;; #endif
+;;
+;; Notice that we disable -fschedule-insns and -fschedule-insns2 in
+;; avr-common.c::TARGET_OPTION_OPTIMIZATION_TABLE because some "random"
+;; reordering of instructions is not wanted.
+
+(define_automaton "avr_dfa")
+
+(define_cpu_unit "avr_cpu" "avr_dfa")
+
+(define_insn_reservation "avr_cpu_reserve" 1
+  (const_int 1)
+  "avr_cpu")
Index: config/avr/avr-protos.h
===================================================================
--- config/avr/avr-protos.h	(revision 244001)
+++ config/avr/avr-protos.h	(working copy)
@@ -31,6 +31,7 @@ extern int avr_hard_regno_rename_ok (uns
 extern rtx avr_return_addr_rtx (int count, rtx tem);
 extern void avr_register_target_pragmas (void);
 extern void avr_init_expanders (void);
+extern int avr_hard_regno_call_part_clobbered (unsigned, int);
 
 #ifdef TREE_CODE
 extern void avr_asm_output_aligned_decl_common (FILE*, tree, const char*, unsigned HOST_WIDE_INT, unsigned int, bool);
@@ -46,7 +47,6 @@ extern void avr_init_cumulative_args (CU
 #endif /* TREE_CODE */
 
 #ifdef RTX_CODE
-extern int avr_hard_regno_call_part_clobbered (unsigned, machine_mode);
 extern const char *output_movqi (rtx_insn *insn, rtx operands[], int *l);
 extern const char *output_movhi (rtx_insn *insn, rtx operands[], int *l);
 extern const char *output_movsisf (rtx_insn *insn, rtx operands[], int *l);
Index: config/avr/avr.c
===================================================================
--- config/avr/avr.c	(revision 244001)
+++ config/avr/avr.c	(working copy)
@@ -11873,8 +11873,10 @@ avr_hard_regno_mode_ok (int regno, machi
 /* Implement `HARD_REGNO_CALL_PART_CLOBBERED'.  */
 
 int
-avr_hard_regno_call_part_clobbered (unsigned regno, machine_mode mode)
+avr_hard_regno_call_part_clobbered (unsigned regno, int imode)
 {
+  machine_mode mode = (machine_mode) imode;
+
   /* FIXME: This hook gets called with MODE:REGNO combinations that don't
         represent valid hard registers like, e.g. HI:29.  Returning TRUE
         for such registers can lead to performance degradation as mentioned
Index: config/avr/avr.h
===================================================================
--- config/avr/avr.h	(revision 244001)
+++ config/avr/avr.h	(working copy)
@@ -285,8 +285,11 @@ enum reg_class {
 
 #define REGNO_OK_FOR_INDEX_P(NUM) 0
 
+/* Prototype needed because sched-deps.c does not include tm_p.h.  */
+extern int avr_hard_regno_call_part_clobbered (unsigned, int);
+
 #define HARD_REGNO_CALL_PART_CLOBBERED(REGNO, MODE)     \
-  avr_hard_regno_call_part_clobbered (REGNO, MODE)
+  avr_hard_regno_call_part_clobbered (REGNO, (int) (MODE))
 
 #define TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P hook_bool_mode_true
 
Index: config/avr/avr.md
===================================================================
--- config/avr/avr.md	(revision 244001)
+++ config/avr/avr.md	(working copy)
@@ -6927,3 +6927,6 @@ (define_insn_and_split "*extract.subreg.
 
 ;; Operations on 64-bit registers
 (include "avr-dimode.md")
+
+;; A dummy DFA to cure PR78883
+(include "avr-dfa.md")
Index: testsuite/gcc.c-torture/compile/pr78883.c
===================================================================
--- testsuite/gcc.c-torture/compile/pr78883.c	(nonexistent)
+++ testsuite/gcc.c-torture/compile/pr78883.c	(working copy)
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+
+int foo (int *p)
+{
+  int i;
+  for (i = 0; i < 5; i++)
+    {
+      if (p[i] & 1)
+        return i;
+    }
+  return -1;
+}
