Add clang-cc support for -disable-llvm-optzns.
 - Avoids running any LLVM optimizations, even at -O2, etc., while still keeping
   any language changes these optimizations imply.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@72742 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/Frontend/CompileOptions.h b/include/clang/Frontend/CompileOptions.h
index 1af5e48..34815c8 100644
--- a/include/clang/Frontend/CompileOptions.h
+++ b/include/clang/Frontend/CompileOptions.h
@@ -23,12 +23,17 @@
 /// is optimized and passed to the backend.
 class CompileOptions {
 public:
+  enum InliningMethod {
+    NoInlining,         // Perform no inlining whatsoever.
+    NormalInlining,     // Use the standard function inlining pass.
+    OnlyAlwaysInlining  // Only run the always inlining pass.
+  };
+
   unsigned OptimizationLevel : 3; /// The -O[0-4] option specified.
   unsigned OptimizeSize      : 1; /// If -Os is specified.
   unsigned DebugInfo         : 1; /// Should generate deubg info (-g).
   unsigned UnitAtATime       : 1; /// Unused. For mirroring GCC
                                   /// optimization selection.
-  unsigned InlineFunctions   : 1; /// Should functions be inlined?
   unsigned SimplifyLibCalls  : 1; /// Should standard library calls be
                                   /// treated specially.
   unsigned UnrollLoops       : 1; /// Control whether loops are unrolled.
@@ -37,6 +42,9 @@
   unsigned TimePasses        : 1; /// Set when -ftime-report is enabled.
   unsigned NoCommon          : 1; /// Set when -fno-common or C++ is enabled.
 
+  /// Inlining - The kind of inlining to perform.
+  InliningMethod Inlining;
+
   /// CPU - An optional CPU to target.
   std::string CPU;
 
@@ -50,10 +58,11 @@
     OptimizeSize = 0;
     DebugInfo = 0;
     UnitAtATime = 1;
-    InlineFunctions = SimplifyLibCalls = UnrollLoops = 0;
+    SimplifyLibCalls = UnrollLoops = 0;
     VerifyModule = 1;
     TimePasses = 0;
     NoCommon = 0;
+    Inlining = NoInlining;
   }  
 };
 
diff --git a/lib/Frontend/Backend.cpp b/lib/Frontend/Backend.cpp
index 44aa3a8..697ba94 100644
--- a/lib/Frontend/Backend.cpp
+++ b/lib/Frontend/Backend.cpp
@@ -294,10 +294,16 @@
       PM->add(createPruneEHPass());               // Remove dead EH info
       PM->add(createFunctionAttrsPass());         // Set readonly/readnone attrs
     }
-    if (CompileOpts.InlineFunctions)
+    switch (CompileOpts.Inlining) {
+    case CompileOptions::NoInlining:
+      break;
+    case CompileOptions::NormalInlining:
       PM->add(createFunctionInliningPass());      // Inline small functions
-    else 
+      break;
+    case CompileOptions::OnlyAlwaysInlining:
       PM->add(createAlwaysInlinerPass());         // Respect always_inline
+      break;
+    }
     if (CompileOpts.OptimizationLevel > 2)
       PM->add(createArgumentPromotionPass());     // Scalarize uninlined fn args
     if (CompileOpts.SimplifyLibCalls)
@@ -341,7 +347,16 @@
     if (CompileOpts.OptimizationLevel > 1 && CompileOpts.UnitAtATime)
       PM->add(createConstantMergePass());         // Merge dup global constants 
   } else {
-    PM->add(createAlwaysInlinerPass());  
+    switch (CompileOpts.Inlining) {
+    case CompileOptions::NoInlining:
+      break;
+    case CompileOptions::NormalInlining:
+      PM->add(createFunctionInliningPass());      // Inline small functions
+      break;
+    case CompileOptions::OnlyAlwaysInlining:
+      PM->add(createAlwaysInlinerPass());         // Respect always_inline
+      break;
+    }
   }
 }
 
diff --git a/test/CodeGen/always_inline.c b/test/CodeGen/always_inline.c
new file mode 100644
index 0000000..d159bd2
--- /dev/null
+++ b/test/CodeGen/always_inline.c
@@ -0,0 +1,13 @@
+// RUN: clang-cc -emit-llvm -o %t %s &&
+// RUN: grep '@f0' %t | count 0 &&
+// RUN: clang-cc -disable-llvm-optzns -emit-llvm -o %t %s &&
+// RUN: grep '@f0' %t | count 2
+
+//static int f0() { 
+static int __attribute__((always_inline)) f0() { 
+  return 1;
+}
+
+int f1() {
+  return f0();
+}
diff --git a/tools/clang-cc/clang-cc.cpp b/tools/clang-cc/clang-cc.cpp
index a0ccafa..0e0a072 100644
--- a/tools/clang-cc/clang-cc.cpp
+++ b/tools/clang-cc/clang-cc.cpp
@@ -667,6 +667,10 @@
 OptSize("Os", llvm::cl::desc("Optimize for size"));
 
 static llvm::cl::opt<bool>
+DisableLLVMOptimizations("disable-llvm-optzns", 
+                         llvm::cl::desc("Don't run LLVM optimization passes"));
+
+static llvm::cl::opt<bool>
 NoCommon("fno-common",
          llvm::cl::desc("Compile common globals like normal definitions"),
          llvm::cl::ValueDisallowed);
@@ -1420,16 +1424,26 @@
                                      const llvm::StringMap<bool> &Features) {
   Opts.OptimizeSize = OptSize;
   Opts.DebugInfo = GenerateDebugInfo;
-  if (OptSize) {
-    // -Os implies -O2
-    // FIXME: Diagnose conflicting options.
-    Opts.OptimizationLevel = 2;
+
+  if (DisableLLVMOptimizations) {
+    Opts.OptimizationLevel = 0;
+    Opts.Inlining = CompileOptions::NoInlining;
   } else {
-    Opts.OptimizationLevel = OptLevel;
+    if (OptSize) {
+      // -Os implies -O2
+      Opts.OptimizationLevel = 2;
+    } else {
+      Opts.OptimizationLevel = OptLevel;
+    }
+
+    // We must always run at least the always inlining pass.
+    if (Opts.OptimizationLevel > 1)
+      Opts.Inlining = CompileOptions::NormalInlining;
+    else
+      Opts.Inlining = CompileOptions::OnlyAlwaysInlining;
   }
 
   // FIXME: There are llvm-gcc options to control these selectively.
-  Opts.InlineFunctions = (Opts.OptimizationLevel > 1);
   Opts.UnrollLoops = (Opts.OptimizationLevel > 1 && !OptSize);
   Opts.SimplifyLibCalls = !LangOpts.NoBuiltin;