Change:
I've spent the past few hours looking through documentation for how to build rustc with a patched LLVM without success. Currently, the best I'm at is: And then build with: But even that doesn't rebuild anything unless I . Which completely loses incremental compilation results. Is there any way to make this development workflow better? Rebuilding from scratch at every change is… painful.
You need to modify to rebuild LLVM. (tagging this issue as a documentation problem.)
Thanks! Leaving open for the documentation problem :)

Discussion:
} } <del> let rebuild_trigger = builder.src.join("src/rustllvm/llvm-rebuild-trigger"); let rebuild_trigger_contents = t!(fs::read_to_string(&rebuild_trigger)); let (out_dir, llvm_config_ret_dir) = if emscripten { </del> <ins> let (submodule, root, out_dir, llvm_config_ret_dir) = if emscripten { </ins> let dir = builder.emscripten_llvm_out(target); let config_dir = dir.join("bin"); <del> (dir, config_dir) </del> <ins> ("src/llvm-emscripten", "src/llvm-emscripten", dir, config_dir) </ins> } else { let mut dir = builder.llvm_out(builder.config.build); if !builder.config.build.contains("msvc") || builder.config.ninja { dir.push("build"); } <del> (builder.llvm_out(target), dir.join("bin")) </del> <ins> ("src/llvm-project", "src/llvm-project/llvm", builder.llvm_out(target), dir.join("bin")) </ins> }; <del> let done_stamp = out_dir.join("llvm-finished-building"); </del> <ins> let git_output = t!(Command::new("git") .args(&["rev-parse", "--verify", &format!("@:./{}", submodule)]) .current_dir(&builder.src) .output()); let llvm_commit = if git_output.status.success() { Some(git_output.stdout) } else { println!( "git could not determine the LLVM submodule commit hash ({}).  Assuming that an LLVM build is necessary.", String::from_utf8_lossy(&git_output.stderr), ); None }; </ins> let build_llvm_config = llvm_config_ret_dir .join(exe("llvm-config", &*builder.config.build)); <del> if done_stamp.exists() { let done_contents = t!(fs::read_to_string(&done_stamp)); </del> <ins> let done_stamp = out_dir.join("llvm-finished-building"); </ins> <del> // If LLVM was already built previously and contents of the rebuild-trigger file // didn't change from the previous build, then no action is required. if done_contents == rebuild_trigger_contents { return build_llvm_config </del> <ins> if let Some(llvm_commit) = &llvm_commit { if done_stamp.exists() { let done_contents = t!(fs::read(&done_stamp)); // If LLVM was already built previously and the submodule's commit didn't change // from the previous build, then no action is required. if done_contents == llvm_commit.as_slice() { return build_llvm_config } </ins> } }

t!(fs::create_dir_all(&out_dir)); // http://llvm.org/docs/CMake.html <del> let root = if self.emscripten { "src/llvm-emscripten" } else { "src/llvm-project/llvm" }; </del> let mut cfg = cmake::Config::new(builder.src.join(root)); let profile = match (builder.config.llvm_optimize, builder.config.llvm_release_debuginfo) {

cfg.build(); <del> t!(fs::write(&done_stamp, &rebuild_trigger_contents)); </del> <ins> if let Some(llvm_commit) = llvm_commit { t!(fs::write(&done_stamp, &llvm_commit)); } </ins> build_llvm_config }

<del> # If this file is modified, then llvm will be (optionally) cleaned and then rebuilt. # The actual contents of this file do not matter, but to trigger a change on the # build bots then the contents should be changed so git updates the mtime. 2019-03-18 </del>