Index: lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp
===================================================================
--- lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp
+++ lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp
@@ -9,6 +9,7 @@
 #include "ASTResultSynthesizer.h"
 
 #include "ClangASTImporter.h"
+#include "ClangExpressionSourceCode.h"
 #include "ClangPersistentVariables.h"
 
 #include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
@@ -209,6 +210,14 @@
     return false;
 
   Stmt **last_stmt_ptr = Body->body_end() - 1;
+  // The last statement in the expression is our injected call to
+  // __lldb_use_expr_result. The expression before is the actual user expression
+  // so skip the injected function call.
+  CallExpr *use_call = cast<CallExpr>(*last_stmt_ptr);
+  assert(cast<FunctionDecl>(use_call->getCalleeDecl())->getName() ==
+         ClangExpressionSourceCode::GetUseExprResultFunctionName());
+  --last_stmt_ptr;
+
   Stmt *last_stmt = *last_stmt_ptr;
 
   while (dyn_cast<NullStmt>(last_stmt)) {
@@ -380,6 +389,52 @@
 
   *last_stmt_ptr = static_cast<Stmt *>(result_initialization_stmt_result.get());
 
+  // At this point we created the result variable that stores the result of
+  // the last expression. However, in a situation where we finish on a local
+  // variable, the expression result is just a pointer to something on the stack
+  // and LLVM will optimize that away. E.g., `MyClass c; c` becomes:
+  //
+  //       MyClass c;
+  //       static MyClass *__lldb_expr_result_ptr = &c; // Points to stack.
+  //     } // End of expression function.
+  //
+  // The optimizer will just remove this store. So we add a trailing call to
+  // the undefined function `__lldb_use_expr_result` which will take an address
+  // of `__lldb_expr_result_ptr`. We will manually remove that call later,
+  // but until we remove that function the optimizer can no longer remove
+  // the store to our result variable:
+  //
+  //       MyClass c;
+  //       static MyClass *__lldb_expr_result_ptr = &c; // Points to stack.
+  //       __lldb_expr_result_ptr(__lldb_expr_result_ptr);
+  //     } // End of expression function.
+  //
+  // We already have a call at the end in the form:
+  //     __lldb_expr_result_ptr(nullptr);
+  // which we injected into the wrapping source code. We just need to change
+  // the placeholder `nullptr` argument to the result variable we created above
+  // and do any casting.
+  Expr *ref_result = DeclRefExpr::Create(
+      Ctx, NestedNameSpecifierLoc(), SourceLocation(), result_decl,
+      /*RefersToEnclosingVariableOrCapture=*/false, SourceLocation(),
+      result_decl->getType(), ExprValueKind::VK_LValue);
+  QualType ref_type = ref_result->getType();
+  // __lldb_expr_result isn't a pointer for non-lvalues, so inject an &:
+  // __lldb_expr_result_ptr(&__lldb_expression_result)
+  if (!ref_type->isPointerType())
+    ref_result = UnaryOperator::Create(
+        Ctx, ref_result, UnaryOperator::Opcode::UO_AddrOf,
+        Ctx.getPointerType(ref_type), ExprValueKind::VK_RValue,
+        ExprObjectKind::OK_Ordinary, SourceLocation(), /*CanOverflow=*/false,
+        FPOptionsOverride());
+  // Cast the pointer type we have to void so that the type system is not
+  // complaining.
+  ImplicitCastExpr *c = ImplicitCastExpr::Create(
+      Ctx, Ctx.VoidPtrTy, CastKind::CK_BitCast, ref_result, nullptr,
+      ExprValueKind::VK_RValue, FPOptionsOverride());
+  // Overwrite the placeholder argument.
+  use_call->getArgs()[0] = c;
+
   return true;
 }
 
Index: lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
===================================================================
--- lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
+++ lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
@@ -44,11 +44,13 @@
 
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Module.h"
+#include "llvm/Passes/PassBuilder.h"
 #include "llvm/Support/DynamicLibrary.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/Host.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/Signals.h"
+#include "llvm/Transforms/IPO/PassManagerBuilder.h"
 
 #include "ClangDiagnostic.h"
 #include "ClangExpressionParser.h"
@@ -648,8 +650,18 @@
                                     CodeGenOptions::FramePointerKind::All);
   if (generate_debug_info)
     m_compiler->getCodeGenOpts().setDebugInfo(codegenoptions::FullDebugInfo);
-  else
+  else {
     m_compiler->getCodeGenOpts().setDebugInfo(codegenoptions::NoDebugInfo);
+    // If the user doesn't want to debug the expression we can optimize it.
+    // This makes it run a bit faster in case it's a long-running expression
+    // and it makes the life of the IRInterpreter easier as all the verbose
+    // IR nodes generated by Clang are simplified.
+    // The level set here gets propagated to the pass manager.
+    m_compiler->getCodeGenOpts().OptimizationLevel = 2;
+    // LLVM's lifetime markers aren't supported by the IRInterpreter so avoid
+    // generating them.
+    m_compiler->getCodeGenOpts().DisableLifetimeMarkers = true;
+  }
 
   // Disable some warnings.
   SetupDefaultClangDiagnostics(*m_compiler);
@@ -1319,6 +1331,45 @@
   return false;
 }
 
+static void RunOptimizationPipeline(llvm::Module &module,
+                                      clang::CodeGenOptions &opts) {
+  // Build a fitting target machine for our triple.
+  llvm::Triple triple(module.getTargetTriple());
+  std::unique_ptr<llvm::TargetMachine> target_machine;
+  llvm::SmallVector<std::string, 0> mAttrs;
+  target_machine.reset(llvm::EngineBuilder().selectTarget(triple,
+                                                          /*MArch=*/"",
+                                                          /*MCPU=*/"", mAttrs));
+
+  // Build the default analysis managers.
+  LoopAnalysisManager LAM;
+  FunctionAnalysisManager FAM;
+  CGSCCAnalysisManager CGAM;
+  ModuleAnalysisManager MAM;
+
+  PassInstrumentationCallbacks PIC;
+  Optional<PGOOptions> P;
+  PipelineTuningOptions PTO;
+  PassBuilder PB(target_machine.get(), PTO, P, &PIC);
+
+  // Register all passes.
+  PB.registerModuleAnalyses(MAM);
+  PB.registerCGSCCAnalyses(CGAM);
+  PB.registerFunctionAnalyses(FAM);
+  PB.registerLoopAnalyses(LAM);
+  PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
+
+  ModulePassManager MPM;
+  // Pick a pipeline that fits to our CodeGenOpts optimization level and add
+  // the respective passes.
+  std::string pipelineString =
+      "default<O" + std::to_string(opts.OptimizationLevel) + ">";
+  if (auto Err = PB.parsePassPipeline(MPM, pipelineString))
+    llvm_unreachable("Failed to parse pipeline");
+
+  MPM.run(module, MAM);
+}
+
 lldb_private::Status ClangExpressionParser::PrepareForExecution(
     lldb::addr_t &func_addr, lldb::addr_t &func_end,
     lldb::IRExecutionUnitSP &execution_unit_sp, ExecutionContext &exe_ctx,
@@ -1407,6 +1458,17 @@
       return err;
     }
 
+    // Run the default LLVM optimization passes over the generated module unless
+    // this is an expression that the user wants to debug (in which case the
+    // optimizations would degrade the debug experience).
+    if (!GetGenerateDebugInfo())
+      RunOptimizationPipeline(*execution_unit_sp->GetModule(),
+                                m_compiler->getCodeGenOpts());
+    // Remove the injected function call that prevents the optimizer from
+    // removing the seemingly dead store of the expression result.
+    ir_for_target.RemoveAllCallsToFunction(
+        ClangExpressionSourceCode::GetUseExprResultFunctionName());
+
     Process *process = exe_ctx.GetProcessPtr();
 
     if (execution_policy != eExecutionPolicyAlways &&
Index: lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h
===================================================================
--- lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h
+++ lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h
@@ -73,6 +73,10 @@
   bool GetOriginalBodyBounds(std::string transformed_text,
                              size_t &start_loc, size_t &end_loc);
 
+  /// Returns the name of the function that is injected in the source code
+  /// to make sure the expression result is considered used by the optimizer.
+  static llvm::StringRef GetUseExprResultFunctionName();
+
 protected:
   ClangExpressionSourceCode(llvm::StringRef filename, llvm::StringRef name,
                             llvm::StringRef prefix, llvm::StringRef body,
Index: lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp
===================================================================
--- lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp
+++ lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp
@@ -32,6 +32,8 @@
 
 #define PREFIX_NAME "<lldb wrapper prefix>"
 #define SUFFIX_NAME "<lldb wrapper suffix>"
+/// \see ClangExpressionSourceCode::GetUseExprResultFunctionName
+#define LLDB_USE_EXPR_RESULT "__lldb_use_expr_result"
 
 const llvm::StringRef ClangExpressionSourceCode::g_prefix_file_name = PREFIX_NAME;
 
@@ -71,6 +73,7 @@
 extern "C"
 {
     int printf(const char * __restrict, ...);
+    void )" LLDB_USE_EXPR_RESULT R"((void *);
 }
 )";
 
@@ -415,6 +418,7 @@
                          "{                              \n"
                          "    %s;                        \n"
                          "%s"
+                         "    " LLDB_USE_EXPR_RESULT "(0);\n"
                          "}                              \n",
                          module_imports.c_str(), m_name.c_str(),
                          lldb_local_var_decls.GetData(), tagged_body.c_str());
@@ -427,6 +431,7 @@
                          "{                                      \n"
                          "    %s;                                \n"
                          "%s"
+                         "    " LLDB_USE_EXPR_RESULT "(nullptr); \n"
                          "}                                      \n",
                          module_imports.c_str(), m_name.c_str(),
                          lldb_local_var_decls.GetData(), tagged_body.c_str());
@@ -442,6 +447,7 @@
           "{                                                      \n"
           "    %s;                                                \n"
           "%s"
+          "    " LLDB_USE_EXPR_RESULT "(0);                       \n"
           "}                                                      \n"
           "@end                                                   \n",
           module_imports.c_str(), m_name.c_str(), m_name.c_str(),
@@ -459,6 +465,7 @@
           "{                                                       \n"
           "    %s;                                                 \n"
           "%s"
+          "    " LLDB_USE_EXPR_RESULT "(0);                        \n"
           "}                                                       \n"
           "@end                                                    \n",
           module_imports.c_str(), m_name.c_str(), m_name.c_str(),
@@ -483,3 +490,7 @@
   end_loc = transformed_text.find(m_end_marker);
   return end_loc != std::string::npos;
 }
+
+llvm::StringRef ClangExpressionSourceCode::GetUseExprResultFunctionName() {
+  return LLDB_USE_EXPR_RESULT;
+}
Index: lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.h
===================================================================
--- lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.h
+++ lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.h
@@ -103,6 +103,11 @@
   ///     True on success; false otherwise
   bool runOnModule(llvm::Module &llvm_module) override;
 
+  /// Removes all calls to the function with the given name in the module.
+  ///
+  /// All calls found by this function must be safe to remove.
+  void RemoveAllCallsToFunction(llvm::StringRef function_name);
+
   /// Interface stub
   ///
   /// Implementation of the llvm::ModulePass::assignPassManager() function.
Index: lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp
===================================================================
--- lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp
+++ lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp
@@ -364,7 +364,9 @@
   LLDB_LOG(log, "Replacing \"{0}\" with \"{1}\"", PrintValue(result_global),
            PrintValue(new_result_global));
 
-  if (result_global->use_empty()) {
+  // If the old global had an initializer, create a store that initializes
+  // the new global with the same value.
+  if (result_global->hasInitializer()) {
     // We need to synthesize a store for this variable, because otherwise
     // there's nothing to put into its equivalent persistent variable.
 
@@ -374,16 +376,6 @@
     if (!first_entry_instruction)
       return false;
 
-    if (!result_global->hasInitializer()) {
-      LLDB_LOG(log, "Couldn't find initializer for unused variable");
-
-      m_error_stream.Format("Internal error [IRForTarget]: Result variable "
-                            "({0}) has no writes and no initializer\n",
-                            result_name);
-
-      return false;
-    }
-
     Constant *initializer = result_global->getInitializer();
 
     StoreInst *synthesized_store =
@@ -391,9 +383,9 @@
 
     LLDB_LOG(log, "Synthesized result store \"{0}\"\n",
              PrintValue(synthesized_store));
-  } else {
-    result_global->replaceAllUsesWith(new_result_global);
   }
+  // About to remove the old result global, so RAUW the new global.
+  result_global->replaceAllUsesWith(new_result_global);
 
   if (!m_decl_map->AddPersistentVariable(
           result_decl, m_result_name, m_result_type, true, m_result_is_pointer))
@@ -2023,6 +2015,24 @@
   return true;
 }
 
+void IRForTarget::RemoveAllCallsToFunction(llvm::StringRef function_name) {
+  for (llvm::Function &function : *m_module) {
+    for (BasicBlock &bb : function) {
+      for (BasicBlock::iterator i = bb.begin(), end = bb.end(); i != end;) {
+        if (CallInst *call = dyn_cast<CallInst>(&(*i))) {
+          if (llvm::Function *func = call->getCalledFunction()) {
+            if (func->getName() == function_name) {
+              i = call->eraseFromParent();
+              continue;
+            }
+          }
+        }
+        ++i;
+      }
+    }
+  }
+}
+
 void IRForTarget::assignPassManager(PMStack &pass_mgr_stack,
                                     PassManagerType pass_mgr_type) {}