diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index 69b86416afab0..8efd6b458e9cb 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -778,6 +778,8 @@ macro_rules! options {
             Some(::rustc_back::LinkerFlavor::one_of());
         pub const parse_optimization_fuel: Option<&'static str> =
             Some("crate=integer");
+        pub const parse_unpretty: Option<&'static str> =
+            Some("`string` or `string=string`");
     }
 
     #[allow(dead_code)]
@@ -965,6 +967,17 @@ macro_rules! options {
                 }
             }
         }
+
+        fn parse_unpretty(slot: &mut Option<String>, v: Option<&str>) -> bool {
+            match v {
+                None => false,
+                Some(s) if s.split('=').count() <= 2 => {
+                    *slot = Some(s.to_string());
+                    true
+                }
+                _ => false,
+            }
+        }
     }
 ) }
 
@@ -1102,13 +1115,13 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
         "write syntax and type analysis (in JSON format) information, in \
          addition to normal output"),
     flowgraph_print_loans: bool = (false, parse_bool, [UNTRACKED],
-        "include loan analysis data in --unpretty flowgraph output"),
+        "include loan analysis data in -Z unpretty flowgraph output"),
     flowgraph_print_moves: bool = (false, parse_bool, [UNTRACKED],
-        "include move analysis data in --unpretty flowgraph output"),
+        "include move analysis data in -Z unpretty flowgraph output"),
     flowgraph_print_assigns: bool = (false, parse_bool, [UNTRACKED],
-        "include assignment analysis data in --unpretty flowgraph output"),
+        "include assignment analysis data in -Z unpretty flowgraph output"),
     flowgraph_print_all: bool = (false, parse_bool, [UNTRACKED],
-        "include all dataflow analysis data in --unpretty flowgraph output"),
+        "include all dataflow analysis data in -Z unpretty flowgraph output"),
     print_region_graph: bool = (false, parse_bool, [UNTRACKED],
          "prints region inference graph. \
           Use with RUST_REGION_GRAPH=help for more info"),
@@ -1239,6 +1252,13 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
     dep_info_omit_d_target: bool = (false, parse_bool, [TRACKED],
         "in dep-info output, omit targets for tracking dependencies of the dep-info files \
          themselves"),
+    unpretty: Option<String> = (None, parse_unpretty, [UNTRACKED],
+        "Present the input source, unstable (and less-pretty) variants;
+        valid types are any of the types for `--pretty`, as well as:
+        `flowgraph=<nodeid>` (graphviz formatted flowgraph for node),
+        `everybody_loops` (all function bodies replaced with `loop {}`),
+        `hir` (the HIR), `hir,identified`, or
+        `hir,typed` (HIR with types for each node)."),
 }
 
 pub fn default_lib_output() -> CrateType {
@@ -1512,14 +1532,6 @@ pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
                   `expanded` (crates expanded), or
                   `expanded,identified` (fully parenthesized, AST nodes with IDs).",
                  "TYPE"),
-        opt::opt("", "unpretty",
-                 "Present the input source, unstable (and less-pretty) variants;
-                  valid types are any of the types for `--pretty`, as well as:
-                  `flowgraph=<nodeid>` (graphviz formatted flowgraph for node),
-                  `everybody_loops` (all function bodies replaced with `loop {}`),
-                  `hir` (the HIR), `hir,identified`, or
-                  `hir,typed` (HIR with types for each node).",
-                 "TYPE"),
     ]);
     opts
 }
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index 237656eb43c69..a985fa073ef8c 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -292,8 +292,9 @@ fn parse_pretty(sess: &Session,
     } else {
         None
     };
-    if pretty.is_none() && sess.unstable_options() {
-        matches.opt_str("unpretty").map(|a| {
+
+    if pretty.is_none() {
+        sess.opts.debugging_opts.unpretty.as_ref().map(|a| {
             // extended with unstable pretty-print variants
             pretty::parse_pretty(sess, &a, true)
         })
diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs
index 6ce6929af5cab..a771cdad70ff6 100644
--- a/src/librustc_driver/pretty.rs
+++ b/src/librustc_driver/pretty.rs
@@ -66,7 +66,7 @@ pub enum PpSourceMode {
 pub enum PpFlowGraphMode {
     Default,
     /// Drops the labels from the edges in the flowgraph output. This
-    /// is mostly for use in the --unpretty flowgraph run-make tests,
+    /// is mostly for use in the -Z unpretty flowgraph run-make tests,
     /// since the labels are largely uninteresting in those cases and
     /// have become a pain to maintain.
     UnlabelledEdges,
@@ -1006,7 +1006,7 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session,
                                            move |annotation, _| {
                     debug!("pretty printing source code {:?}", s);
                     let sess = annotation.sess();
-                    let hir_map = annotation.hir_map().expect("--unpretty missing HIR map");
+                    let hir_map = annotation.hir_map().expect("-Z unpretty missing HIR map");
                     let mut pp_state = pprust_hir::State::new_from_input(sess.codemap(),
                                                                          &sess.parse_sess,
                                                                          src_name,
@@ -1019,7 +1019,7 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session,
                         pp_state.print_node(node)?;
                         pp_state.s.space()?;
                         let path = annotation.node_path(node_id)
-                            .expect("--unpretty missing node paths");
+                            .expect("-Z unpretty missing node paths");
                         pp_state.synth_comment(path)?;
                         pp_state.s.hardbreak()?;
                     }
@@ -1071,7 +1071,7 @@ fn print_with_analysis<'tcx, 'a: 'tcx>(sess: &'a Session,
                                        ofile: Option<&Path>) {
     let nodeid = if let Some(uii) = uii {
         debug!("pretty printing for {:?}", uii);
-        Some(uii.to_one_node_id("--unpretty", sess, &hir_map))
+        Some(uii.to_one_node_id("-Z unpretty", sess, &hir_map))
     } else {
         debug!("pretty printing for whole crate");
         None
diff --git a/src/test/compile-fail/issue-37665.rs b/src/test/compile-fail/issue-37665.rs
index 98e62965235e7..81ed4375e7793 100644
--- a/src/test/compile-fail/issue-37665.rs
+++ b/src/test/compile-fail/issue-37665.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags: -Z unstable-options --unpretty=mir
+// compile-flags: -Z unpretty=mir
 // ignore-cloudabi no std::path
 
 use std::path::MAIN_SEPARATOR;
diff --git a/src/test/compile-fail/mir-unpretty.rs b/src/test/compile-fail/mir-unpretty.rs
index 8950bef6a4610..fa9365021575f 100644
--- a/src/test/compile-fail/mir-unpretty.rs
+++ b/src/test/compile-fail/mir-unpretty.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags: -Z unstable-options --unpretty=mir
+// compile-flags: -Z unpretty=mir
 
 fn main() {
     let x: () = 0; //~ ERROR: mismatched types
diff --git a/src/test/run-make/hir-tree/Makefile b/src/test/run-make/hir-tree/Makefile
index bedb2b7d6aa50..2e100b269e14b 100644
--- a/src/test/run-make/hir-tree/Makefile
+++ b/src/test/run-make/hir-tree/Makefile
@@ -4,6 +4,5 @@
 # the string constant we would expect to see.
 
 all:
-	$(RUSTC) -o $(TMPDIR)/input.hir -Z unstable-options \
-		--unpretty=hir-tree input.rs
+	$(RUSTC) -o $(TMPDIR)/input.hir -Z unpretty=hir-tree input.rs
 	$(CGREP) '"Hello, Rustaceans!\n"' < $(TMPDIR)/input.hir
diff --git a/src/test/run-make/pretty-print-path-suffix/Makefile b/src/test/run-make/pretty-print-path-suffix/Makefile
index d53005011790b..899457fc7486e 100644
--- a/src/test/run-make/pretty-print-path-suffix/Makefile
+++ b/src/test/run-make/pretty-print-path-suffix/Makefile
@@ -1,9 +1,9 @@
 -include ../tools.mk
 
 all:
-	$(RUSTC) -o $(TMPDIR)/foo.out -Z unstable-options --unpretty hir=foo input.rs
-	$(RUSTC) -o $(TMPDIR)/nest_foo.out -Z unstable-options --unpretty hir=nest::foo input.rs
-	$(RUSTC) -o $(TMPDIR)/foo_method.out -Z unstable-options --unpretty hir=foo_method input.rs
+	$(RUSTC) -o $(TMPDIR)/foo.out -Z unpretty=hir=foo input.rs
+	$(RUSTC) -o $(TMPDIR)/nest_foo.out -Z unpretty=hir=nest::foo input.rs
+	$(RUSTC) -o $(TMPDIR)/foo_method.out -Z unpretty=hir=foo_method input.rs
 	diff -u $(TMPDIR)/foo.out foo.pp
 	diff -u $(TMPDIR)/nest_foo.out nest_foo.pp
 	diff -u $(TMPDIR)/foo_method.out foo_method.pp
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index efbe5e32fcd27..bf5fc00428df2 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -466,8 +466,7 @@ impl<'test> TestCx<'test> {
         let mut rustc = Command::new(&self.config.rustc_path);
         rustc
             .arg("-")
-            .arg("-Zunstable-options")
-            .args(&["--unpretty", &pretty_type])
+            .args(&["-Z", &format!("unpretty={}", pretty_type)])
             .args(&["--target", &self.config.target])
             .arg("-L")
             .arg(&aux_dir)