diff --git a/IPython/core/interactiveshell.py b/IPython/core/interactiveshell.py
index 24ac215..7067557 100644
--- a/IPython/core/interactiveshell.py
+++ b/IPython/core/interactiveshell.py
@@ -2632,13 +2632,40 @@ class InteractiveShell(SingletonConfigurable):
         if silent:
             store_history = False
 
-        prefilter_failed = False
+        preprocessing_exc_tuple = None
         try:
+            # Static input transformations
             self.input_transformer_manager.push(raw_cell)
+            cell = self.input_transformer_manager.source_reset()
         except SyntaxError:
-            self.showtraceback()
-            prefilter_failed = True
-        cell = self.input_transformer_manager.source_reset()
+            preprocessing_exc_tuple = sys.exc_info()
+            cell = raw_cell  # cell has to exist so it can be stored/logged
+        else:
+            if len(cell.splitlines()) == 1:
+                # Dynamic transformations - only applied for single line commands
+                with self.builtin_trap:
+                    try:
+                        # use prefilter_lines to handle trailing newlines
+                        # restore trailing newline for ast.parse
+                        cell = self.prefilter_manager.prefilter_lines(cell) + '\n'
+                    except Exception:
+                        # don't allow prefilter errors to crash IPython
+                        preprocessing_exc_tuple = sys.exc_info()
+
+        # Store raw and processed history
+        if store_history:
+            self.history_manager.store_inputs(self.execution_count,
+                                              cell, raw_cell)
+        if not silent:
+            self.logger.log(cell, raw_cell)
+
+        # Display the exception if input processing failed.
+        if preprocessing_exc_tuple is not None:
+            self.showtraceback(preprocessing_exc_tuple)
+            del preprocessing_exc_tuple  # Break reference cycle
+            if store_history:
+                self.execution_count += 1
+            return
 
         # Our own compiler remembers the __future__ environment. If we want to
         # run code with a separate __future__ environment, use the default
@@ -2646,72 +2673,53 @@ class InteractiveShell(SingletonConfigurable):
         compiler = self.compile if shell_futures else CachingCompiler()
 
         with self.builtin_trap:
-            if not prefilter_failed and len(cell.splitlines()) == 1:
-                try:
-                    # use prefilter_lines to handle trailing newlines
-                    # restore trailing newline for ast.parse
-                    cell = self.prefilter_manager.prefilter_lines(cell) + '\n'
-                except AliasError as e:
-                    error(e)
-                    prefilter_failed = True
-                except Exception:
-                    # don't allow prefilter errors to crash IPython
-                    self.showtraceback()
-                    prefilter_failed = True
-
-            # Store raw and processed history
-            if store_history:
-                self.history_manager.store_inputs(self.execution_count,
-                                                  cell, raw_cell)
-            if not silent:
-                self.logger.log(cell, raw_cell)
+            cell_name = self.compile.cache(cell, self.execution_count)
 
-            if not prefilter_failed:
-                # don't run if prefilter failed
-                cell_name = self.compile.cache(cell, self.execution_count)
-
-                with self.display_trap:
+            with self.display_trap:
+                # Compile to bytecode
+                try:
+                    code_ast = compiler.ast_parse(cell, filename=cell_name)
+                except IndentationError:
+                    self.showindentationerror()
+                    if store_history:
+                        self.execution_count += 1
+                    return None
+                except (OverflowError, SyntaxError, ValueError, TypeError,
+                        MemoryError):
+                    self.showsyntaxerror()
+                    if store_history:
+                        self.execution_count += 1
+                    return None
+
+                # Apply AST transformations
+                code_ast = self.transform_ast(code_ast)
+
+                # Execute the user code
+                interactivity = "none" if silent else self.ast_node_interactivity
+                self.run_ast_nodes(code_ast.body, cell_name,
+                                   interactivity=interactivity, compiler=compiler)
+
+                # Execute any registered post-execution functions.
+                # unless we are silent
+                post_exec = [] if silent else iteritems(self._post_execute)
+
+                for func, status in post_exec:
+                    if self.disable_failing_post_execute and not status:
+                        continue
                     try:
-                        code_ast = compiler.ast_parse(cell, filename=cell_name)
-                    except IndentationError:
-                        self.showindentationerror()
-                        if store_history:
-                            self.execution_count += 1
-                        return None
-                    except (OverflowError, SyntaxError, ValueError, TypeError,
-                            MemoryError):
-                        self.showsyntaxerror()
-                        if store_history:
-                            self.execution_count += 1
-                        return None
-                    
-                    code_ast = self.transform_ast(code_ast)
-                    
-                    interactivity = "none" if silent else self.ast_node_interactivity
-                    self.run_ast_nodes(code_ast.body, cell_name,
-                                       interactivity=interactivity, compiler=compiler)
-                    
-                    # Execute any registered post-execution functions.
-                    # unless we are silent
-                    post_exec = [] if silent else iteritems(self._post_execute)
-                    
-                    for func, status in post_exec:
-                        if self.disable_failing_post_execute and not status:
-                            continue
-                        try:
-                            func()
-                        except KeyboardInterrupt:
-                            print("\nKeyboardInterrupt", file=io.stderr)
-                        except Exception:
-                            # register as failing:
-                            self._post_execute[func] = False
-                            self.showtraceback()
-                            print('\n'.join([
-                                "post-execution function %r produced an error." % func,
-                                "If this problem persists, you can disable failing post-exec functions with:",
-                                "",
-                                "    get_ipython().disable_failing_post_execute = True"
-                            ]), file=io.stderr)
+                        func()
+                    except KeyboardInterrupt:
+                        print("\nKeyboardInterrupt", file=io.stderr)
+                    except Exception:
+                        # register as failing:
+                        self._post_execute[func] = False
+                        self.showtraceback()
+                        print('\n'.join([
+                            "post-execution function %r produced an error." % func,
+                            "If this problem persists, you can disable failing post-exec functions with:",
+                            "",
+                            "    get_ipython().disable_failing_post_execute = True"
+                        ]), file=io.stderr)
 
         if store_history:
             # Write output to the database. Does nothing unless