This revision was automatically updated to reflect the committed changes.
Closed by commit rL290398: Cleanup the handling of noinline function 
attributes, -fno-inline, (authored by chandlerc).

Changed prior to commit:
  https://reviews.llvm.org/D28053?vs=82356&id=82390#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D28053

Files:
  cfe/trunk/include/clang/Frontend/CodeGenOptions.def
  cfe/trunk/include/clang/Frontend/CodeGenOptions.h
  cfe/trunk/lib/CodeGen/BackendUtil.cpp
  cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp
  cfe/trunk/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp
  cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
  cfe/trunk/lib/CodeGen/CodeGenModule.cpp
  cfe/trunk/lib/Frontend/CompilerInvocation.cpp
  cfe/trunk/test/CXX/special/class.dtor/p3-0x.cpp
  cfe/trunk/test/CodeGen/2008-04-08-NoExceptions.c
  cfe/trunk/test/CodeGen/address-safety-attr-kasan.cpp
  cfe/trunk/test/CodeGen/address-safety-attr.cpp
  cfe/trunk/test/CodeGen/address-space-field1.c
  cfe/trunk/test/CodeGen/alias.c
  cfe/trunk/test/CodeGen/attr-minsize.cpp
  cfe/trunk/test/CodeGen/attributes.c
  cfe/trunk/test/CodeGen/incomplete-function-type-2.c
  cfe/trunk/test/CodeGen/inline-optim.c
  cfe/trunk/test/CodeGen/mips16-attr.c
  cfe/trunk/test/CodeGen/mrtd.c
  cfe/trunk/test/CodeGen/ms-declspecs.c
  cfe/trunk/test/CodeGen/ppc64-complex-parms.c
  cfe/trunk/test/CodeGen/ppc64-complex-return.c
  cfe/trunk/test/CodeGen/ppc64-extend.c
  cfe/trunk/test/CodeGen/sanitize-thread-attr.cpp
  cfe/trunk/test/CodeGen/sanitize-thread-no-checking-at-run-time.m
  cfe/trunk/test/CodeGen/unwind-attr.c
  cfe/trunk/test/CodeGenCXX/attr.cpp
  cfe/trunk/test/CodeGenCXX/cxx11-exception-spec.cpp
  cfe/trunk/test/CodeGenCXX/cxx11-noreturn.cpp
  cfe/trunk/test/CodeGenCXX/derived-to-base.cpp
  cfe/trunk/test/CodeGenCXX/global-dtor-no-atexit.cpp
  cfe/trunk/test/CodeGenCXX/global-init.cpp
  cfe/trunk/test/CodeGenCXX/inline-hint.cpp
  cfe/trunk/test/CodeGenCXX/main-norecurse.cpp
  cfe/trunk/test/CodeGenCXX/microsoft-abi-array-cookies.cpp
  cfe/trunk/test/CodeGenCXX/no-exceptions.cpp
  cfe/trunk/test/CodeGenCXX/optnone-class-members.cpp
  cfe/trunk/test/CodeGenCXX/optnone-def-decl.cpp
  cfe/trunk/test/CodeGenCXX/reference-cast.cpp
  cfe/trunk/test/CodeGenCXX/threadsafe-statics.cpp
  cfe/trunk/test/CodeGenCXX/thunks.cpp
  cfe/trunk/test/CodeGenCXX/virtual-base-cast.cpp
  cfe/trunk/test/CodeGenObjC/gnu-exceptions.m
  cfe/trunk/test/CodeGenObjC/objc-literal-tests.m
  cfe/trunk/test/CodeGenObjCXX/lambda-expressions.mm
  cfe/trunk/test/CodeGenOpenCL/amdgpu-attrs.cl
  cfe/trunk/test/Driver/darwin-iphone-defaults.m
  cfe/trunk/test/PCH/objc_container.m

Index: cfe/trunk/include/clang/Frontend/CodeGenOptions.def
===================================================================
--- cfe/trunk/include/clang/Frontend/CodeGenOptions.def
+++ cfe/trunk/include/clang/Frontend/CodeGenOptions.def
@@ -104,8 +104,6 @@
 CODEGENOPT(NoSignedZeros     , 1, 0) ///< Allow ignoring the signedness of FP zero
 CODEGENOPT(ReciprocalMath    , 1, 0) ///< Allow FP divisions to be reassociated.
 CODEGENOPT(NoTrappingMath    , 1, 0) ///< Set when -fno-trapping-math is enabled.
-CODEGENOPT(NoInline          , 1, 0) ///< Set when -fno-inline is enabled.
-                                     ///< Disables use of the inline keyword.
 CODEGENOPT(NoNaNsFPMath      , 1, 0) ///< Assume FP arguments, results not NaN.
 CODEGENOPT(FlushDenorm       , 1, 0) ///< Allow FP denorm numbers to be flushed to zero
 CODEGENOPT(CorrectlyRoundedDivSqrt, 1, 0) ///< -cl-fp32-correctly-rounded-divide-sqrt
@@ -233,7 +231,7 @@
 CODEGENOPT(EmitCodeView, 1, 0)
 
 /// The kind of inlining to perform.
-ENUM_CODEGENOPT(Inlining, InliningMethod, 2, NoInlining)
+ENUM_CODEGENOPT(Inlining, InliningMethod, 2, NormalInlining)
 
 // Vector functions library to use.
 ENUM_CODEGENOPT(VecLib, VectorLibrary, 2, NoLibrary)
Index: cfe/trunk/include/clang/Frontend/CodeGenOptions.h
===================================================================
--- cfe/trunk/include/clang/Frontend/CodeGenOptions.h
+++ cfe/trunk/include/clang/Frontend/CodeGenOptions.h
@@ -44,7 +44,6 @@
 class CodeGenOptions : public CodeGenOptionsBase {
 public:
   enum InliningMethod {
-    NoInlining,         // Perform no inlining whatsoever.
     NormalInlining,     // Use the standard function inlining pass.
     OnlyHintInlining,   // Inline only (implicitly) hinted functions.
     OnlyAlwaysInlining  // Only run the always inlining pass.
Index: cfe/trunk/test/Driver/darwin-iphone-defaults.m
===================================================================
--- cfe/trunk/test/Driver/darwin-iphone-defaults.m
+++ cfe/trunk/test/Driver/darwin-iphone-defaults.m
@@ -26,4 +26,4 @@
   [I1 alloc];
 }
 
-// CHECK: attributes [[F0]] = { ssp{{.*}} }
+// CHECK: attributes [[F0]] = { noinline ssp{{.*}} }
Index: cfe/trunk/test/CodeGenObjCXX/lambda-expressions.mm
===================================================================
--- cfe/trunk/test/CodeGenObjCXX/lambda-expressions.mm
+++ cfe/trunk/test/CodeGenObjCXX/lambda-expressions.mm
@@ -125,5 +125,5 @@
 }
 
 
-// ARC: attributes [[NUW]] = { nounwind{{.*}} }
-// MRC: attributes [[NUW]] = { nounwind{{.*}} }
+// ARC: attributes [[NUW]] = { noinline nounwind{{.*}} }
+// MRC: attributes [[NUW]] = { noinline nounwind{{.*}} }
Index: cfe/trunk/test/CodeGenCXX/microsoft-abi-array-cookies.cpp
===================================================================
--- cfe/trunk/test/CodeGenCXX/microsoft-abi-array-cookies.cpp
+++ cfe/trunk/test/CodeGenCXX/microsoft-abi-array-cookies.cpp
@@ -68,4 +68,4 @@
 void delete_s(S *s) { delete[] s; }
 }
 
-// CHECK: attributes [[NUW]] = { nounwind{{.*}} }
+// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} }
Index: cfe/trunk/test/CodeGenCXX/thunks.cpp
===================================================================
--- cfe/trunk/test/CodeGenCXX/thunks.cpp
+++ cfe/trunk/test/CodeGenCXX/thunks.cpp
@@ -1,9 +1,5 @@
-// RUN: %clang_cc1 %s -triple=x86_64-pc-linux-gnu -munwind-tables -emit-llvm -o %t
-// RUN: %clang_cc1 %s -triple=x86_64-pc-linux-gnu -munwind-tables -emit-llvm -o %t.opt -O1 -disable-llvm-passes
-// RUN: FileCheck %s < %t
-// RUN: FileCheck %s < %t.opt
-// RUN: FileCheck --check-prefix=CHECK-NONOPT %s < %t
-// RUN: FileCheck --check-prefix=CHECK-OPT %s < %t.opt
+// RUN: %clang_cc1 %s -triple=x86_64-pc-linux-gnu -munwind-tables -emit-llvm -o - | FileCheck --check-prefix=CHECK --check-prefix=CHECK-NONOPT %s
+// RUN: %clang_cc1 %s -triple=x86_64-pc-linux-gnu -munwind-tables -emit-llvm -o - -O1 -disable-llvm-passes | FileCheck --check-prefix=CHECK --check-prefix=CHECK-OPT %s
 
 namespace Test1 {
 
@@ -405,4 +401,5 @@
 // CHECK-OPT-LABEL: define linkonce_odr void @_ZN6Test101C3fooEv
 // CHECK-OPT-LABEL: define linkonce_odr void @_ZThn8_N6Test101C3fooEv
 
-// CHECK: attributes [[NUW]] = { nounwind uwtable{{.*}} }
+// CHECK-NONOPT: attributes [[NUW]] = { noinline nounwind uwtable{{.*}} }
+// CHECK-OPT: attributes [[NUW]] = { nounwind uwtable{{.*}} }
Index: cfe/trunk/test/CodeGenCXX/no-exceptions.cpp
===================================================================
--- cfe/trunk/test/CodeGenCXX/no-exceptions.cpp
+++ cfe/trunk/test/CodeGenCXX/no-exceptions.cpp
@@ -11,4 +11,4 @@
   // CHECK: ret void
 }
 
-// CHECK: attributes [[NUW]] = { nounwind{{.*}} }
+// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} }
Index: cfe/trunk/test/CodeGenCXX/inline-hint.cpp
===================================================================
--- cfe/trunk/test/CodeGenCXX/inline-hint.cpp
+++ cfe/trunk/test/CodeGenCXX/inline-hint.cpp
@@ -1,6 +1,6 @@
-// RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-linux -finline-functions -emit-llvm -disable-llvm-passes -o - | FileCheck %s --check-prefix=CHECK --check-prefix=SUITABLE
-// RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-linux -finline-hint-functions -emit-llvm -disable-llvm-passes -o - | FileCheck %s --check-prefix=CHECK --check-prefix=HINTED
-// RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-linux -fno-inline -emit-llvm -disable-llvm-passes -o - | FileCheck %s --check-prefix=CHECK --check-prefix=NOINLINE
+// RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-linux -O2 -finline-functions -emit-llvm -disable-llvm-passes -o - | FileCheck %s --check-prefix=CHECK --check-prefix=SUITABLE
+// RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-linux -O2 -finline-hint-functions -emit-llvm -disable-llvm-passes -o - | FileCheck %s --check-prefix=CHECK --check-prefix=HINTED
+// RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-linux -O2 -fno-inline -emit-llvm -disable-llvm-passes -o - | FileCheck %s --check-prefix=CHECK --check-prefix=NOINLINE
 
 // Force non-trivial implicit constructors/destructors/operators for B by having explicit ones for A
 struct A {
Index: cfe/trunk/test/CodeGenCXX/reference-cast.cpp
===================================================================
--- cfe/trunk/test/CodeGenCXX/reference-cast.cpp
+++ cfe/trunk/test/CodeGenCXX/reference-cast.cpp
@@ -193,4 +193,4 @@
   // CHECK: store i64
 }
 
-// CHECK: attributes [[NUW]] = { nounwind{{.*}} }
+// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} }
Index: cfe/trunk/test/CodeGenCXX/optnone-class-members.cpp
===================================================================
--- cfe/trunk/test/CodeGenCXX/optnone-class-members.cpp
+++ cfe/trunk/test/CodeGenCXX/optnone-class-members.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 < %s -triple %itanium_abi_triple -fms-extensions -emit-llvm -x c++ | FileCheck %s
+// RUN: %clang_cc1 < %s -triple %itanium_abi_triple -fms-extensions -O2 -disable-llvm-optzns -emit-llvm -x c++ | FileCheck %s
 
 // Test attribute 'optnone' on methods:
 //  -- member functions;
Index: cfe/trunk/test/CodeGenCXX/main-norecurse.cpp
===================================================================
--- cfe/trunk/test/CodeGenCXX/main-norecurse.cpp
+++ cfe/trunk/test/CodeGenCXX/main-norecurse.cpp
@@ -5,4 +5,4 @@
     return 1;
 }
 
-// CHECK: attributes #0 = { norecurse{{.*}} }
+// CHECK: attributes #0 = { noinline norecurse{{.*}} }
Index: cfe/trunk/test/CodeGenCXX/global-dtor-no-atexit.cpp
===================================================================
--- cfe/trunk/test/CodeGenCXX/global-dtor-no-atexit.cpp
+++ cfe/trunk/test/CodeGenCXX/global-dtor-no-atexit.cpp
@@ -43,4 +43,4 @@
   static A a1, a2;
 }
 
-// CHECK: attributes [[NUW]] = { nounwind{{.*}} }
+// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} }
Index: cfe/trunk/test/CodeGenCXX/derived-to-base.cpp
===================================================================
--- cfe/trunk/test/CodeGenCXX/derived-to-base.cpp
+++ cfe/trunk/test/CodeGenCXX/derived-to-base.cpp
@@ -46,4 +46,4 @@
   }
 }
 
-// CHECK: attributes [[NUW]] = { nounwind{{.*}} }
+// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} }
Index: cfe/trunk/test/CodeGenCXX/cxx11-noreturn.cpp
===================================================================
--- cfe/trunk/test/CodeGenCXX/cxx11-noreturn.cpp
+++ cfe/trunk/test/CodeGenCXX/cxx11-noreturn.cpp
@@ -7,4 +7,4 @@
   while (g()) {}
 }
 
-// CHECK: attributes [[NR]] = { noreturn nounwind{{.*}} }
+// CHECK: attributes [[NR]] = { noinline noreturn nounwind{{.*}} }
Index: cfe/trunk/test/CodeGenCXX/virtual-base-cast.cpp
===================================================================
--- cfe/trunk/test/CodeGenCXX/virtual-base-cast.cpp
+++ cfe/trunk/test/CodeGenCXX/virtual-base-cast.cpp
@@ -82,4 +82,4 @@
 // MSVC:   add nsw i32 4, %[[offset]]
 // MSVC: }
 
-// CHECK: attributes [[NUW]] = { nounwind{{.*}} }
+// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} }
Index: cfe/trunk/test/CodeGenCXX/cxx11-exception-spec.cpp
===================================================================
--- cfe/trunk/test/CodeGenCXX/cxx11-exception-spec.cpp
+++ cfe/trunk/test/CodeGenCXX/cxx11-exception-spec.cpp
@@ -121,7 +121,7 @@
 }
 
 // CHECK: attributes [[NONE]] = { {{.*}} }
-// CHECK: attributes [[NUW]] = { nounwind{{.*}} }
+// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} }
 // CHECK: attributes [[NUW2]] = { nounwind{{.*}} }
 
 
Index: cfe/trunk/test/CodeGenCXX/threadsafe-statics.cpp
===================================================================
--- cfe/trunk/test/CodeGenCXX/threadsafe-statics.cpp
+++ cfe/trunk/test/CodeGenCXX/threadsafe-statics.cpp
@@ -22,6 +22,6 @@
 // NO-TSS-NOT: call void @__cxa_guard_release
 // NO-TSS: ret void
 
-// WITH-TSS: attributes [[NUW]] = { nounwind{{.*}} }
+// WITH-TSS: attributes [[NUW]] = { noinline nounwind{{.*}} }
 
-// NO-TSS: attributes [[NUW]] = { nounwind{{.*}} }
+// NO-TSS: attributes [[NUW]] = { noinline nounwind{{.*}} }
Index: cfe/trunk/test/CodeGenCXX/optnone-def-decl.cpp
===================================================================
--- cfe/trunk/test/CodeGenCXX/optnone-def-decl.cpp
+++ cfe/trunk/test/CodeGenCXX/optnone-def-decl.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -triple %itanium_abi_triple -fms-extensions -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -triple %itanium_abi_triple -fms-extensions -O2 -disable-llvm-optzns -emit-llvm -o - | FileCheck %s
 
 // Test optnone on both function declarations and function definitions.
 // Verify also that we don't generate invalid IR functions with
Index: cfe/trunk/test/CodeGenCXX/attr.cpp
===================================================================
--- cfe/trunk/test/CodeGenCXX/attr.cpp
+++ cfe/trunk/test/CodeGenCXX/attr.cpp
@@ -31,4 +31,4 @@
 // CHECK at top of file
 extern "C" int test2() __attribute__((alias("_Z5test1v")));
 
-// CHECK: attributes [[NUW]] = { nounwind{{.*}} }
+// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} }
Index: cfe/trunk/test/CodeGenCXX/global-init.cpp
===================================================================
--- cfe/trunk/test/CodeGenCXX/global-init.cpp
+++ cfe/trunk/test/CodeGenCXX/global-init.cpp
@@ -204,8 +204,8 @@
 // rdar://problem/8090834: this should be nounwind
 // CHECK-NOEXC: define internal void @_GLOBAL__sub_I_global_init.cpp() [[NUW:#[0-9]+]] section "__TEXT,__StaticInit,regular,pure_instructions" {
 
-// CHECK-NOEXC: attributes [[NUW]] = { nounwind{{.*}} }
+// CHECK-NOEXC: attributes [[NUW]] = { noinline nounwind{{.*}} }
 
 // PR21811: attach the appropriate attribute to the global init function
 // CHECK-FP: define internal void @_GLOBAL__sub_I_global_init.cpp() [[NUX:#[0-9]+]] section "__TEXT,__StaticInit,regular,pure_instructions" {
-// CHECK-FP: attributes [[NUX]] = { nounwind {{.*}}"no-frame-pointer-elim-non-leaf"{{.*}} }
+// CHECK-FP: attributes [[NUX]] = { noinline nounwind {{.*}}"no-frame-pointer-elim-non-leaf"{{.*}} }
Index: cfe/trunk/test/PCH/objc_container.m
===================================================================
--- cfe/trunk/test/PCH/objc_container.m
+++ cfe/trunk/test/PCH/objc_container.m
@@ -21,5 +21,5 @@
 // CHECK-IR: {{call.*objc_msgSend}}
 // CHECK-IR: ret void
 
-// CHECK-IR: attributes #0 = { nounwind {{.*}} }
+// CHECK-IR: attributes #0 = { noinline nounwind {{.*}} }
 // CHECK-IR: attributes #1 = { nonlazybind }
Index: cfe/trunk/test/CodeGenOpenCL/amdgpu-attrs.cl
===================================================================
--- cfe/trunk/test/CodeGenOpenCL/amdgpu-attrs.cl
+++ cfe/trunk/test/CodeGenOpenCL/amdgpu-attrs.cl
@@ -141,26 +141,26 @@
 // CHECK-NOT: "amdgpu-num-sgpr"="0"
 // CHECK-NOT: "amdgpu-num-vgpr"="0"
 
-// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64]] = { nounwind "amdgpu-flat-work-group-size"="32,64"
-// CHECK-DAG: attributes [[WAVES_PER_EU_2]] = { nounwind "amdgpu-waves-per-eu"="2"
-// CHECK-DAG: attributes [[WAVES_PER_EU_2_4]] = { nounwind "amdgpu-waves-per-eu"="2,4"
-// CHECK-DAG: attributes [[NUM_SGPR_32]] = { nounwind "amdgpu-num-sgpr"="32"
-// CHECK-DAG: attributes [[NUM_VGPR_64]] = { nounwind "amdgpu-num-vgpr"="64"
-
-// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2]] = { nounwind "amdgpu-flat-work-group-size"="32,64" "amdgpu-waves-per-eu"="2"
-// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_4]] = { nounwind "amdgpu-flat-work-group-size"="32,64" "amdgpu-waves-per-eu"="2,4"
-// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_NUM_SGPR_32]] = { nounwind "amdgpu-flat-work-group-size"="32,64" "amdgpu-num-sgpr"="32"
-// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_NUM_VGPR_64]] = { nounwind "amdgpu-flat-work-group-size"="32,64" "amdgpu-num-vgpr"="64"
-// CHECK-DAG: attributes [[WAVES_PER_EU_2_NUM_SGPR_32]] = { nounwind "amdgpu-num-sgpr"="32" "amdgpu-waves-per-eu"="2"
-// CHECK-DAG: attributes [[WAVES_PER_EU_2_NUM_VGPR_64]] = { nounwind "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2"
-// CHECK-DAG: attributes [[WAVES_PER_EU_2_4_NUM_SGPR_32]] = { nounwind "amdgpu-num-sgpr"="32" "amdgpu-waves-per-eu"="2,4"
-// CHECK-DAG: attributes [[WAVES_PER_EU_2_4_NUM_VGPR_64]] = { nounwind "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2,4"
-// CHECK-DAG: attributes [[NUM_SGPR_32_NUM_VGPR_64]] = { nounwind "amdgpu-num-sgpr"="32" "amdgpu-num-vgpr"="64"
-
-// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_NUM_SGPR_32]] = { nounwind "amdgpu-flat-work-group-size"="32,64" "amdgpu-num-sgpr"="32" "amdgpu-waves-per-eu"="2"
-// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_NUM_VGPR_64]] = { nounwind "amdgpu-flat-work-group-size"="32,64" "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2"
-// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_4_NUM_SGPR_32]] = { nounwind "amdgpu-flat-work-group-size"="32,64" "amdgpu-num-sgpr"="32" "amdgpu-waves-per-eu"="2,4"
-// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_4_NUM_VGPR_64]] = { nounwind "amdgpu-flat-work-group-size"="32,64" "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2,4"
+// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64]] = { noinline nounwind "amdgpu-flat-work-group-size"="32,64"
+// CHECK-DAG: attributes [[WAVES_PER_EU_2]] = { noinline nounwind "amdgpu-waves-per-eu"="2"
+// CHECK-DAG: attributes [[WAVES_PER_EU_2_4]] = { noinline nounwind "amdgpu-waves-per-eu"="2,4"
+// CHECK-DAG: attributes [[NUM_SGPR_32]] = { noinline nounwind "amdgpu-num-sgpr"="32"
+// CHECK-DAG: attributes [[NUM_VGPR_64]] = { noinline nounwind "amdgpu-num-vgpr"="64"
+
+// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2]] = { noinline nounwind "amdgpu-flat-work-group-size"="32,64" "amdgpu-waves-per-eu"="2"
+// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_4]] = { noinline nounwind "amdgpu-flat-work-group-size"="32,64" "amdgpu-waves-per-eu"="2,4"
+// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_NUM_SGPR_32]] = { noinline nounwind "amdgpu-flat-work-group-size"="32,64" "amdgpu-num-sgpr"="32"
+// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_NUM_VGPR_64]] = { noinline nounwind "amdgpu-flat-work-group-size"="32,64" "amdgpu-num-vgpr"="64"
+// CHECK-DAG: attributes [[WAVES_PER_EU_2_NUM_SGPR_32]] = { noinline nounwind "amdgpu-num-sgpr"="32" "amdgpu-waves-per-eu"="2"
+// CHECK-DAG: attributes [[WAVES_PER_EU_2_NUM_VGPR_64]] = { noinline nounwind "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2"
+// CHECK-DAG: attributes [[WAVES_PER_EU_2_4_NUM_SGPR_32]] = { noinline nounwind "amdgpu-num-sgpr"="32" "amdgpu-waves-per-eu"="2,4"
+// CHECK-DAG: attributes [[WAVES_PER_EU_2_4_NUM_VGPR_64]] = { noinline nounwind "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2,4"
+// CHECK-DAG: attributes [[NUM_SGPR_32_NUM_VGPR_64]] = { noinline nounwind "amdgpu-num-sgpr"="32" "amdgpu-num-vgpr"="64"
+
+// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_NUM_SGPR_32]] = { noinline nounwind "amdgpu-flat-work-group-size"="32,64" "amdgpu-num-sgpr"="32" "amdgpu-waves-per-eu"="2"
+// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_NUM_VGPR_64]] = { noinline nounwind "amdgpu-flat-work-group-size"="32,64" "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2"
+// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_4_NUM_SGPR_32]] = { noinline nounwind "amdgpu-flat-work-group-size"="32,64" "amdgpu-num-sgpr"="32" "amdgpu-waves-per-eu"="2,4"
+// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_4_NUM_VGPR_64]] = { noinline nounwind "amdgpu-flat-work-group-size"="32,64" "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2,4"
 
-// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_NUM_SGPR_32_NUM_VGPR_64]] = { nounwind "amdgpu-flat-work-group-size"="32,64" "amdgpu-num-sgpr"="32" "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2"
-// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_4_NUM_SGPR_32_NUM_VGPR_64]] = { nounwind "amdgpu-flat-work-group-size"="32,64" "amdgpu-num-sgpr"="32" "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2,4"
+// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_NUM_SGPR_32_NUM_VGPR_64]] = { noinline nounwind "amdgpu-flat-work-group-size"="32,64" "amdgpu-num-sgpr"="32" "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2"
+// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_4_NUM_SGPR_32_NUM_VGPR_64]] = { noinline nounwind "amdgpu-flat-work-group-size"="32,64" "amdgpu-num-sgpr"="32" "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2,4"
Index: cfe/trunk/test/CodeGen/incomplete-function-type-2.c
===================================================================
--- cfe/trunk/test/CodeGen/incomplete-function-type-2.c
+++ cfe/trunk/test/CodeGen/incomplete-function-type-2.c
@@ -16,4 +16,4 @@
   p1(0.0);
 }
 
-// CHECK: attributes [[NUW]] = { nounwind{{.*}} }
+// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} }
Index: cfe/trunk/test/CodeGen/alias.c
===================================================================
--- cfe/trunk/test/CodeGen/alias.c
+++ cfe/trunk/test/CodeGen/alias.c
@@ -77,9 +77,9 @@
 // CHECKCC: call arm_aapcs_vfpcc  i32 @inner_weak(i32 %{{.*}})
 // CHECKCC: define internal arm_aapcs_vfpcc i32 @inner_weak(i32 %a) [[NUW]] {
 
-// CHECKBASIC: attributes [[NUW]] = { nounwind{{.*}} }
+// CHECKBASIC: attributes [[NUW]] = { noinline nounwind{{.*}} }
 
-// CHECKCC: attributes [[NUW]] = { nounwind{{.*}} }
+// CHECKCC: attributes [[NUW]] = { noinline nounwind{{.*}} }
 
 void test8_bar() {}
 void test8_foo() __attribute__((weak, alias("test8_bar")));
Index: cfe/trunk/test/CodeGen/sanitize-thread-no-checking-at-run-time.m
===================================================================
--- cfe/trunk/test/CodeGen/sanitize-thread-no-checking-at-run-time.m
+++ cfe/trunk/test/CodeGen/sanitize-thread-no-checking-at-run-time.m
@@ -31,4 +31,4 @@
 // TSAN: initialize{{.*}}) [[ATTR:#[0-9]+]]
 // TSAN: dealloc{{.*}}) [[ATTR:#[0-9]+]]
 // TSAN: cxx_destruct{{.*}}) [[ATTR:#[0-9]+]]
-// TSAN: attributes [[ATTR]] = { nounwind {{.*}} "sanitize_thread_no_checking_at_run_time" {{.*}} }
+// TSAN: attributes [[ATTR]] = { noinline nounwind {{.*}} "sanitize_thread_no_checking_at_run_time" {{.*}} }
Index: cfe/trunk/test/CodeGen/unwind-attr.c
===================================================================
--- cfe/trunk/test/CodeGen/unwind-attr.c
+++ cfe/trunk/test/CodeGen/unwind-attr.c
@@ -23,7 +23,7 @@
   return 0;
 }
 
-// CHECK: attributes [[TF]] = { "{{.*}} }
-// CHECK: attributes [[NUW]] = { nounwind{{.*}} }
+// CHECK: attributes [[TF]] = { noinline "{{.*}} }
+// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} }
 
-// CHECK-NOEXC: attributes [[NUW]] = { nounwind{{.*}} }
+// CHECK-NOEXC: attributes [[NUW]] = { noinline nounwind{{.*}} }
Index: cfe/trunk/test/CodeGen/attributes.c
===================================================================
--- cfe/trunk/test/CodeGen/attributes.c
+++ cfe/trunk/test/CodeGen/attributes.c
@@ -90,5 +90,5 @@
 
 // CHECK: define void @t22() [[NUW]] section ".bar"
 
-// CHECK: attributes [[NUW]] = { nounwind{{.*}} }
-// CHECK: attributes [[NR]] = { noreturn nounwind{{.*}} }
+// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} }
+// CHECK: attributes [[NR]] = { noinline noreturn nounwind{{.*}} }
Index: cfe/trunk/test/CodeGen/ms-declspecs.c
===================================================================
--- cfe/trunk/test/CodeGen/ms-declspecs.c
+++ cfe/trunk/test/CodeGen/ms-declspecs.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple i386-pc-win32 %s -emit-llvm -fms-compatibility -o - | FileCheck %s
+// RUN: %clang_cc1 -triple i386-pc-win32 %s -emit-llvm -fms-compatibility -O2 -disable-llvm-optzns -o - | FileCheck %s
 
 __declspec(selectany) int x1 = 1;
 const __declspec(selectany) int x2 = 2;
Index: cfe/trunk/test/CodeGen/ppc64-complex-return.c
===================================================================
--- cfe/trunk/test/CodeGen/ppc64-complex-return.c
+++ cfe/trunk/test/CodeGen/ppc64-complex-return.c
@@ -126,4 +126,4 @@
 // CHECK: extractvalue { i64, i64 } [[VAR8]], 1
 
 
-// CHECK: attributes [[NUW]] = { nounwind{{.*}} }
+// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} }
Index: cfe/trunk/test/CodeGen/address-safety-attr-kasan.cpp
===================================================================
--- cfe/trunk/test/CodeGen/address-safety-attr-kasan.cpp
+++ cfe/trunk/test/CodeGen/address-safety-attr-kasan.cpp
@@ -8,31 +8,31 @@
 int HasSanitizeAddress() {
   return 1;
 }
-// CHECK-NOASAN: {{Function Attrs: nounwind$}}
-// CHECK-ASAN: Function Attrs: nounwind sanitize_address
-// CHECK-KASAN: Function Attrs: nounwind sanitize_address
+// CHECK-NOASAN: {{Function Attrs: noinline nounwind$}}
+// CHECK-ASAN: Function Attrs: noinline nounwind sanitize_address
+// CHECK-KASAN: Function Attrs: noinline nounwind sanitize_address
 
 __attribute__((no_sanitize("address")))
 int NoSanitizeQuoteAddress() {
   return 0;
 }
-// CHECK-NOASAN: {{Function Attrs: nounwind$}}
-// CHECK-ASAN: {{Function Attrs: nounwind$}}
-// CHECK-KASAN: {{Function Attrs: nounwind sanitize_address$}}
+// CHECK-NOASAN: {{Function Attrs: noinline nounwind$}}
+// CHECK-ASAN: {{Function Attrs: noinline nounwind$}}
+// CHECK-KASAN: {{Function Attrs: noinline nounwind sanitize_address$}}
 
 __attribute__((no_sanitize_address))
 int NoSanitizeAddress() {
   return 0;
 }
-// CHECK-NOASAN: {{Function Attrs: nounwind$}}
-// CHECK-ASAN: {{Function Attrs: nounwind$}}
-// CHECK-KASAN: {{Function Attrs: nounwind sanitize_address$}}
+// CHECK-NOASAN: {{Function Attrs: noinline nounwind$}}
+// CHECK-ASAN: {{Function Attrs: noinline nounwind$}}
+// CHECK-KASAN: {{Function Attrs: noinline nounwind sanitize_address$}}
 
 __attribute__((no_sanitize("kernel-address")))
 int NoSanitizeKernelAddress() {
   return 0;
 }
 
-// CHECK-NOASAN: {{Function Attrs: nounwind$}}
-// CHECK-ASAN: {{Function Attrs: nounwind sanitize_address$}}
-// CHECK-KASAN: {{Function Attrs: nounwind$}}
+// CHECK-NOASAN: {{Function Attrs: noinline nounwind$}}
+// CHECK-ASAN: {{Function Attrs: noinline nounwind sanitize_address$}}
+// CHECK-KASAN: {{Function Attrs: noinline nounwind$}}
Index: cfe/trunk/test/CodeGen/ppc64-complex-parms.c
===================================================================
--- cfe/trunk/test/CodeGen/ppc64-complex-parms.c
+++ cfe/trunk/test/CodeGen/ppc64-complex-parms.c
@@ -180,4 +180,4 @@
 // CHECK: %[[VAR77:[A-Za-z0-9.]+]] = load i64, i64* %[[VAR76]], align 8
 // CHECK: %{{[A-Za-z0-9.]+}} = call i64 @foo_long_long(i64 %[[VAR75]], i64 %[[VAR77]])
 
-// CHECK: attributes [[NUW]] = { nounwind{{.*}} }
+// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} }
Index: cfe/trunk/test/CodeGen/address-space-field1.c
===================================================================
--- cfe/trunk/test/CodeGen/address-space-field1.c
+++ cfe/trunk/test/CodeGen/address-space-field1.c
@@ -37,4 +37,4 @@
   p1->b = p2->a;
 }
 
-// CHECK: attributes [[NUW]] = { nounwind{{.*}} }
+// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} }
Index: cfe/trunk/test/CodeGen/mrtd.c
===================================================================
--- cfe/trunk/test/CodeGen/mrtd.c
+++ cfe/trunk/test/CodeGen/mrtd.c
@@ -25,4 +25,4 @@
 // CHECK-LABEL: define x86_stdcallcc void @quux
 // CHECK: call void (i32, ...) @qux
 
-// CHECK: attributes [[NUW]] = { nounwind{{.*}} }
+// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} }
Index: cfe/trunk/test/CodeGen/inline-optim.c
===================================================================
--- cfe/trunk/test/CodeGen/inline-optim.c
+++ cfe/trunk/test/CodeGen/inline-optim.c
@@ -2,8 +2,8 @@
 
 // RUN: %clang_cc1 -triple i686-pc-win32 -emit-llvm %s -o - | FileCheck -check-prefix=NOINLINE %s
 // RUN: %clang_cc1 -triple i686-pc-win32 -O3 -fno-inline-functions -emit-llvm %s -o - | FileCheck -check-prefix=NOINLINE %s
-// RUN: %clang_cc1 -triple i686-pc-win32 -finline-hint-functions -emit-llvm %s -o - | FileCheck -check-prefix=HINT %s
-// RUN: %clang_cc1 -triple i686-pc-win32 -finline-functions -emit-llvm %s -o - | FileCheck -check-prefix=INLINE %s
+// RUN: %clang_cc1 -triple i686-pc-win32 -O3 -finline-hint-functions -emit-llvm %s -o - | FileCheck -check-prefix=HINT %s
+// RUN: %clang_cc1 -triple i686-pc-win32 -O3 -finline-functions -emit-llvm %s -o - | FileCheck -check-prefix=INLINE %s
 
 inline int inline_hint(int a, int b) { return(a+b); }
 
Index: cfe/trunk/test/CodeGen/attr-minsize.cpp
===================================================================
--- cfe/trunk/test/CodeGen/attr-minsize.cpp
+++ cfe/trunk/test/CodeGen/attr-minsize.cpp
@@ -76,4 +76,4 @@
 
 // Oz: attributes [[MINSIZE]] = { minsize{{.*}} }
 
-// OTHER: attributes [[MS]] = { minsize nounwind{{.*}} }
+// OTHER: attributes [[MS]] = { minsize{{.*}} }
Index: cfe/trunk/test/CodeGen/sanitize-thread-attr.cpp
===================================================================
--- cfe/trunk/test/CodeGen/sanitize-thread-attr.cpp
+++ cfe/trunk/test/CodeGen/sanitize-thread-attr.cpp
@@ -54,9 +54,9 @@
 // BL: @__cxx_global_var_init{{.*}}[[NOATTR:#[0-9]+]]
 // TSAN: @__cxx_global_var_init{{.*}}[[WITH:#[0-9]+]]
 
-// WITHOUT: attributes [[NOATTR]] = { nounwind{{.*}} }
+// WITHOUT: attributes [[NOATTR]] = { noinline nounwind{{.*}} }
 
-// BL: attributes [[NOATTR]] = { nounwind{{.*}} }
+// BL: attributes [[NOATTR]] = { noinline nounwind{{.*}} }
 
-// TSAN: attributes [[NOATTR]] = { nounwind{{.*}} }
-// TSAN: attributes [[WITH]] = { nounwind sanitize_thread{{.*}} }
+// TSAN: attributes [[NOATTR]] = { noinline nounwind{{.*}} }
+// TSAN: attributes [[WITH]] = { noinline nounwind sanitize_thread{{.*}} }
Index: cfe/trunk/test/CodeGen/ppc64-extend.c
===================================================================
--- cfe/trunk/test/CodeGen/ppc64-extend.c
+++ cfe/trunk/test/CodeGen/ppc64-extend.c
@@ -13,4 +13,4 @@
 unsigned int f4(void) { return 0; }
 // CHECK: define zeroext i32 @f4() [[NUW]]
 
-// CHECK: attributes [[NUW]] = { nounwind{{.*}} }
+// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} }
Index: cfe/trunk/test/CodeGen/address-safety-attr.cpp
===================================================================
--- cfe/trunk/test/CodeGen/address-safety-attr.cpp
+++ cfe/trunk/test/CodeGen/address-safety-attr.cpp
@@ -143,13 +143,13 @@
 // BLFUNC: @__cxx_global_var_init{{.*}}[[WITH]]
 // ASAN: @__cxx_global_var_init{{.*}}[[WITH]]
 
-// WITHOUT: attributes [[NOATTR]] = { nounwind{{.*}} }
+// WITHOUT: attributes [[NOATTR]] = { noinline nounwind{{.*}} }
 
-// BLFILE: attributes [[WITH]] = { nounwind sanitize_address{{.*}} }
-// BLFILE: attributes [[NOATTR]] = { nounwind{{.*}} }
+// BLFILE: attributes [[WITH]] = { noinline nounwind sanitize_address{{.*}} }
+// BLFILE: attributes [[NOATTR]] = { noinline nounwind{{.*}} }
 
-// BLFUNC: attributes [[WITH]] = { nounwind sanitize_address{{.*}} }
-// BLFUNC: attributes [[NOATTR]] = { nounwind{{.*}} }
+// BLFUNC: attributes [[WITH]] = { noinline nounwind sanitize_address{{.*}} }
+// BLFUNC: attributes [[NOATTR]] = { noinline nounwind{{.*}} }
 
-// ASAN: attributes [[WITH]] = { nounwind sanitize_address{{.*}} }
-// ASAN: attributes [[NOATTR]] = { nounwind{{.*}} }
+// ASAN: attributes [[WITH]] = { noinline nounwind sanitize_address{{.*}} }
+// ASAN: attributes [[NOATTR]] = { noinline nounwind{{.*}} }
Index: cfe/trunk/test/CodeGen/2008-04-08-NoExceptions.c
===================================================================
--- cfe/trunk/test/CodeGen/2008-04-08-NoExceptions.c
+++ cfe/trunk/test/CodeGen/2008-04-08-NoExceptions.c
@@ -9,4 +9,4 @@
 
 // CHECK-NOT: declare void @f() [[NUW]]
 
-// CHECK: attributes [[NUW]] = { nounwind{{.*}} }
+// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} }
Index: cfe/trunk/test/CodeGen/mips16-attr.c
===================================================================
--- cfe/trunk/test/CodeGen/mips16-attr.c
+++ cfe/trunk/test/CodeGen/mips16-attr.c
@@ -11,7 +11,7 @@
 
 // CHECK: define void @nofoo() [[NOMIPS16:#[0-9]+]]
 
-// CHECK: attributes [[MIPS16]] = { nounwind {{.*}} "mips16" {{.*}} }
+// CHECK: attributes [[MIPS16]] = { noinline nounwind {{.*}} "mips16" {{.*}} }
 
-// CHECK: attributes [[NOMIPS16]]  = { nounwind {{.*}} "nomips16" {{.*}} }
+// CHECK: attributes [[NOMIPS16]]  = { noinline nounwind {{.*}} "nomips16" {{.*}} }
 
Index: cfe/trunk/test/CodeGenObjC/objc-literal-tests.m
===================================================================
--- cfe/trunk/test/CodeGenObjC/objc-literal-tests.m
+++ cfe/trunk/test/CodeGenObjC/objc-literal-tests.m
@@ -94,4 +94,4 @@
   bar(^(void) { return YES; });
 }
 
-// CHECK: attributes [[NUW]] = { {{(norecurse )?}}nounwind{{.*}} }
+// CHECK: attributes [[NUW]] = { noinline {{(norecurse )?}}nounwind{{.*}} }
Index: cfe/trunk/test/CodeGenObjC/gnu-exceptions.m
===================================================================
--- cfe/trunk/test/CodeGenObjC/gnu-exceptions.m
+++ cfe/trunk/test/CodeGenObjC/gnu-exceptions.m
@@ -32,4 +32,4 @@
   log(1);
 }
 
-// CHECK: attributes [[TF]] = { "{{.*}} }
+// CHECK: attributes [[TF]] = { noinline "{{.*}} }
Index: cfe/trunk/test/CXX/special/class.dtor/p3-0x.cpp
===================================================================
--- cfe/trunk/test/CXX/special/class.dtor/p3-0x.cpp
+++ cfe/trunk/test/CXX/special/class.dtor/p3-0x.cpp
@@ -176,4 +176,4 @@
 template <typename T>
 TVC<T>::~TVC() {}
 
-// CHECK: attributes [[ATTRGRP]] = { nounwind{{.*}} }
+// CHECK: attributes [[ATTRGRP]] = { noinline nounwind{{.*}} }
Index: cfe/trunk/lib/Frontend/CompilerInvocation.cpp
===================================================================
--- cfe/trunk/lib/Frontend/CompilerInvocation.cpp
+++ cfe/trunk/lib/Frontend/CompilerInvocation.cpp
@@ -441,22 +441,25 @@
   }
   Opts.OptimizationLevel = OptimizationLevel;
 
-  // We must always run at least the always inlining pass.
-  Opts.setInlining(
-    (Opts.OptimizationLevel > 1) ? CodeGenOptions::NormalInlining
-                                 : CodeGenOptions::OnlyAlwaysInlining);
-  // -fno-inline-functions overrides OptimizationLevel > 1.
-  Opts.NoInline = Args.hasArg(OPT_fno_inline);
-  if (Arg* InlineArg = Args.getLastArg(options::OPT_finline_functions,
-                                       options::OPT_finline_hint_functions,
-                                       options::OPT_fno_inline_functions)) {
-    const Option& InlineOpt = InlineArg->getOption();
-    if (InlineOpt.matches(options::OPT_finline_functions))
-      Opts.setInlining(CodeGenOptions::NormalInlining);
-    else if (InlineOpt.matches(options::OPT_finline_hint_functions))
-      Opts.setInlining(CodeGenOptions::OnlyHintInlining);
-    else
-      Opts.setInlining(CodeGenOptions::OnlyAlwaysInlining);
+  // At O0 we want to fully disable inlining outside of cases marked with
+  // 'alwaysinline' that are required for correctness.
+  Opts.setInlining((Opts.OptimizationLevel == 0)
+                       ? CodeGenOptions::OnlyAlwaysInlining
+                       : CodeGenOptions::NormalInlining);
+  // Explicit inlining flags can disable some or all inlining even at
+  // optimization levels above zero.
+  if (Arg *InlineArg = Args.getLastArg(
+          options::OPT_finline_functions, options::OPT_finline_hint_functions,
+          options::OPT_fno_inline_functions, options::OPT_fno_inline)) {
+    if (Opts.OptimizationLevel > 0) {
+      const Option &InlineOpt = InlineArg->getOption();
+      if (InlineOpt.matches(options::OPT_finline_functions))
+        Opts.setInlining(CodeGenOptions::NormalInlining);
+      else if (InlineOpt.matches(options::OPT_finline_hint_functions))
+        Opts.setInlining(CodeGenOptions::OnlyHintInlining);
+      else
+        Opts.setInlining(CodeGenOptions::OnlyAlwaysInlining);
+    }
   }
 
   if (Arg *A = Args.getLastArg(OPT_fveclib)) {
@@ -2188,7 +2191,12 @@
   // This is the __NO_INLINE__ define, which just depends on things like the
   // optimization level and -fno-inline, not actually whether the backend has
   // inlining enabled.
-  Opts.NoInlineDefine = !Opt || Args.hasArg(OPT_fno_inline);
+  Opts.NoInlineDefine = !Opts.Optimize;
+  if (Arg *InlineArg = Args.getLastArg(
+          options::OPT_finline_functions, options::OPT_finline_hint_functions,
+          options::OPT_fno_inline_functions, options::OPT_fno_inline))
+    if (InlineArg->getOption().matches(options::OPT_fno_inline))
+      Opts.NoInlineDefine = true;
 
   Opts.FastMath = Args.hasArg(OPT_ffast_math) ||
       Args.hasArg(OPT_cl_fast_relaxed_math);
Index: cfe/trunk/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp
===================================================================
--- cfe/trunk/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp
+++ cfe/trunk/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp
@@ -372,6 +372,7 @@
         CGOpenMPRuntime::emitParallelOrTeamsOutlinedFunction(
             D, ThreadIDVar, InnermostKind, CodeGen);
     OutlinedFun = cast<llvm::Function>(OutlinedFunVal);
+    OutlinedFun->removeFnAttr(llvm::Attribute::NoInline);
     OutlinedFun->addFnAttr(llvm::Attribute::AlwaysInline);
   } else
     llvm_unreachable("parallel directive is not yet supported for nvptx "
Index: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
===================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
@@ -775,27 +775,9 @@
     }
   }
 
-  // Pass inline keyword to optimizer if it appears explicitly on any
-  // declaration. Also, in the case of -fno-inline attach NoInline
-  // attribute to all functions that are not marked AlwaysInline, or
-  // to all functions that are not marked inline or implicitly inline
-  // in the case of -finline-hint-functions.
-  if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) {
-    const CodeGenOptions& CodeGenOpts = CGM.getCodeGenOpts();
-    if (!CodeGenOpts.NoInline) {
-      for (auto RI : FD->redecls())
-        if (RI->isInlineSpecified()) {
-          Fn->addFnAttr(llvm::Attribute::InlineHint);
-          break;
-        }
-      if (CodeGenOpts.getInlining() == CodeGenOptions::OnlyHintInlining &&
-          !FD->isInlined() && !Fn->hasFnAttribute(llvm::Attribute::InlineHint))
-        Fn->addFnAttr(llvm::Attribute::NoInline);
-    } else if (!FD->hasAttr<AlwaysInlineAttr>())
-      Fn->addFnAttr(llvm::Attribute::NoInline);
+  if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D))
     if (CGM.getLangOpts().OpenMP && FD->hasAttr<OMPDeclareSimdDeclAttr>())
       CGM.getOpenMPRuntime().emitDeclareSimdFunction(FD, Fn);
-  }
 
   // Add no-jump-tables value.
   Fn->addFnAttr("no-jump-tables",
Index: cfe/trunk/lib/CodeGen/BackendUtil.cpp
===================================================================
--- cfe/trunk/lib/CodeGen/BackendUtil.cpp
+++ cfe/trunk/lib/CodeGen/BackendUtil.cpp
@@ -289,9 +289,6 @@
   if (CodeGenOpts.DisableLLVMPasses)
     return;
 
-  unsigned OptLevel = CodeGenOpts.OptimizationLevel;
-  CodeGenOptions::InliningMethod Inlining = CodeGenOpts.getInlining();
-
   PassManagerBuilderWrapper PMBuilder(CodeGenOpts, LangOpts);
 
   // Figure out TargetLibraryInfo.  This needs to be added to MPM and FPM
@@ -302,26 +299,17 @@
   std::unique_ptr<TargetLibraryInfoImpl> TLII(
       createTLII(TargetTriple, CodeGenOpts));
 
-  switch (Inlining) {
-  case CodeGenOptions::NoInlining:
-    break;
-  case CodeGenOptions::NormalInlining:
-  case CodeGenOptions::OnlyHintInlining: {
-    PMBuilder.Inliner =
-        createFunctionInliningPass(OptLevel, CodeGenOpts.OptimizeSize);
-    break;
-  }
-  case CodeGenOptions::OnlyAlwaysInlining:
-    // Respect always_inline.
-    if (OptLevel == 0)
-      // Do not insert lifetime intrinsics at -O0.
-      PMBuilder.Inliner = createAlwaysInlinerLegacyPass(false);
-    else
-      PMBuilder.Inliner = createAlwaysInlinerLegacyPass();
-    break;
+  // At O0 and O1 we only run the always inliner which is more efficient. At
+  // higher optimization levels we run the normal inliner.
+  if (CodeGenOpts.OptimizationLevel <= 1) {
+    bool InsertLifetimeIntrinsics = CodeGenOpts.OptimizationLevel != 0;
+    PMBuilder.Inliner = createAlwaysInlinerLegacyPass(InsertLifetimeIntrinsics);
+  } else {
+    PMBuilder.Inliner = createFunctionInliningPass(
+        CodeGenOpts.OptimizationLevel, CodeGenOpts.OptimizeSize);
   }
 
-  PMBuilder.OptLevel = OptLevel;
+  PMBuilder.OptLevel = CodeGenOpts.OptimizationLevel;
   PMBuilder.SizeLevel = CodeGenOpts.OptimizeSize;
   PMBuilder.BBVectorize = CodeGenOpts.VectorizeBB;
   PMBuilder.SLPVectorize = CodeGenOpts.VectorizeSLP;
Index: cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp
===================================================================
--- cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp
+++ cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -757,6 +757,7 @@
       FnTy, llvm::GlobalValue::InternalLinkage,
       IsCombiner ? ".omp_combiner." : ".omp_initializer.", &CGM.getModule());
   CGM.SetInternalFunctionAttributes(/*D=*/nullptr, Fn, FnInfo);
+  Fn->removeFnAttr(llvm::Attribute::NoInline);
   Fn->addFnAttr(llvm::Attribute::AlwaysInline);
   CodeGenFunction CGF(CGM);
   // Map "T omp_in;" variable to "*omp_in_parm" value in all expressions.
@@ -3472,6 +3473,7 @@
       ".omp_task_privates_map.", &CGM.getModule());
   CGM.SetInternalFunctionAttributes(/*D=*/nullptr, TaskPrivatesMap,
                                     TaskPrivatesMapFnInfo);
+  TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline);
   TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline);
   CodeGenFunction CGF(CGM);
   CGF.disableDebugInfo();
Index: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
===================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp
@@ -875,57 +875,86 @@
     B.addAttribute(llvm::Attribute::StackProtectReq);
 
   if (!D) {
+    // If we don't have a declaration to control inlining, the function isn't
+    // explicitly marked as alwaysinline for semantic reasons, and inlining is
+    // disabled, mark the function as noinline.
+    if (!F->hasFnAttribute(llvm::Attribute::AlwaysInline) &&
+        CodeGenOpts.getInlining() == CodeGenOptions::OnlyAlwaysInlining)
+      B.addAttribute(llvm::Attribute::NoInline);
+
     F->addAttributes(llvm::AttributeSet::FunctionIndex,
                      llvm::AttributeSet::get(
                          F->getContext(),
                          llvm::AttributeSet::FunctionIndex, B));
     return;
   }
 
-  if (D->hasAttr<NakedAttr>()) {
+  if (D->hasAttr<OptimizeNoneAttr>()) {
+    B.addAttribute(llvm::Attribute::OptimizeNone);
+
+    // OptimizeNone implies noinline; we should not be inlining such functions.
+    B.addAttribute(llvm::Attribute::NoInline);
+    assert(!F->hasFnAttribute(llvm::Attribute::AlwaysInline) &&
+           "OptimizeNone and AlwaysInline on same function!");
+
+    // We still need to handle naked functions even though optnone subsumes
+    // much of their semantics.
+    if (D->hasAttr<NakedAttr>())
+      B.addAttribute(llvm::Attribute::Naked);
+
+    // OptimizeNone wins over OptimizeForSize and MinSize.
+    F->removeFnAttr(llvm::Attribute::OptimizeForSize);
+    F->removeFnAttr(llvm::Attribute::MinSize);
+  } else if (D->hasAttr<NakedAttr>()) {
     // Naked implies noinline: we should not be inlining such functions.
     B.addAttribute(llvm::Attribute::Naked);
     B.addAttribute(llvm::Attribute::NoInline);
   } else if (D->hasAttr<NoDuplicateAttr>()) {
     B.addAttribute(llvm::Attribute::NoDuplicate);
   } else if (D->hasAttr<NoInlineAttr>()) {
     B.addAttribute(llvm::Attribute::NoInline);
   } else if (D->hasAttr<AlwaysInlineAttr>() &&
-             !F->getAttributes().hasAttribute(llvm::AttributeSet::FunctionIndex,
-                                              llvm::Attribute::NoInline)) {
+             !F->hasFnAttribute(llvm::Attribute::NoInline)) {
     // (noinline wins over always_inline, and we can't specify both in IR)
     B.addAttribute(llvm::Attribute::AlwaysInline);
+  } else if (CodeGenOpts.getInlining() == CodeGenOptions::OnlyAlwaysInlining) {
+    // If we're not inlining, then force everything that isn't always_inline to
+    // carry an explicit noinline attribute.
+    if (!F->hasFnAttribute(llvm::Attribute::AlwaysInline))
+      B.addAttribute(llvm::Attribute::NoInline);
+  } else {
+    // Otherwise, propagate the inline hint attribute and potentially use its
+    // absence to mark things as noinline.
+    if (auto *FD = dyn_cast<FunctionDecl>(D)) {
+      if (any_of(FD->redecls(), [&](const FunctionDecl *Redecl) {
+            return Redecl->isInlineSpecified();
+          })) {
+        B.addAttribute(llvm::Attribute::InlineHint);
+      } else if (CodeGenOpts.getInlining() ==
+                     CodeGenOptions::OnlyHintInlining &&
+                 !FD->isInlined() &&
+                 !F->hasFnAttribute(llvm::Attribute::AlwaysInline)) {
+        B.addAttribute(llvm::Attribute::NoInline);
+      }
+    }
   }
 
-  if (D->hasAttr<ColdAttr>()) {
-    if (!D->hasAttr<OptimizeNoneAttr>())
+  // Add other optimization related attributes if we are optimizing this
+  // function.
+  if (!D->hasAttr<OptimizeNoneAttr>()) {
+    if (D->hasAttr<ColdAttr>()) {
       B.addAttribute(llvm::Attribute::OptimizeForSize);
-    B.addAttribute(llvm::Attribute::Cold);
-  }
+      B.addAttribute(llvm::Attribute::Cold);
+    }
 
-  if (D->hasAttr<MinSizeAttr>())
-    B.addAttribute(llvm::Attribute::MinSize);
+    if (D->hasAttr<MinSizeAttr>())
+      B.addAttribute(llvm::Attribute::MinSize);
+  }
 
   F->addAttributes(llvm::AttributeSet::FunctionIndex,
                    llvm::AttributeSet::get(
                        F->getContext(), llvm::AttributeSet::FunctionIndex, B));
 
-  if (D->hasAttr<OptimizeNoneAttr>()) {
-    // OptimizeNone implies noinline; we should not be inlining such functions.
-    F->addFnAttr(llvm::Attribute::OptimizeNone);
-    F->addFnAttr(llvm::Attribute::NoInline);
-
-    // OptimizeNone wins over OptimizeForSize, MinSize, AlwaysInline.
-    F->removeFnAttr(llvm::Attribute::OptimizeForSize);
-    F->removeFnAttr(llvm::Attribute::MinSize);
-    assert(!F->hasFnAttribute(llvm::Attribute::AlwaysInline) &&
-           "OptimizeNone and AlwaysInline on same function!");
-
-    // Attribute 'inlinehint' has no effect on 'optnone' functions.
-    // Explicitly remove it from the set of function attributes.
-    F->removeFnAttr(llvm::Attribute::InlineHint);
-  }
-
   unsigned alignment = D->getMaxAlignment() / Context.getCharWidth();
   if (alignment)
     F->setAlignment(alignment);
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to