Index: include/clang/Basic/Attr.td =================================================================== --- include/clang/Basic/Attr.td +++ include/clang/Basic/Attr.td @@ -1651,6 +1651,24 @@ let Documentation = [OptnoneDocs]; } +def OptimizeLess : InheritableAttr { + let Spellings = [Clang<"optless">]; + let Subjects = SubjectList<[Function, ObjCMethod]>; + let Documentation = [Undocumented]; +} + +def OptimizeDefault : InheritableAttr { + let Spellings = [Clang<"optdefault">]; + let Subjects = SubjectList<[Function, ObjCMethod]>; + let Documentation = [Undocumented]; +} + +def OptimizeAggressive : InheritableAttr { + let Spellings = [Clang<"optaggr">]; + let Subjects = SubjectList<[Function, ObjCMethod]>; + let Documentation = [Undocumented]; +} + def Overloadable : Attr { let Spellings = [Clang<"overloadable">]; let Subjects = SubjectList<[Function], ErrorDiag>; Index: lib/CodeGen/CGCall.cpp =================================================================== --- lib/CodeGen/CGCall.cpp +++ lib/CodeGen/CGCall.cpp @@ -1694,6 +1694,20 @@ FuncAttrs.addAttribute(llvm::Attribute::OptimizeForSize); if (CodeGenOpts.OptimizeSize == 2) FuncAttrs.addAttribute(llvm::Attribute::MinSize); + switch (CodeGenOpts.OptimizationLevel) { + case 0: + FuncAttrs.addAttribute(llvm::Attribute::OptimizeNone); + break; + case 1: + FuncAttrs.addAttribute(llvm::Attribute::OptimizeLess); + break; + case 2: + FuncAttrs.addAttribute(llvm::Attribute::OptimizeDefault); + break; + case 3: + FuncAttrs.addAttribute(llvm::Attribute::OptimizeAggressive); + break; + } } if (CodeGenOpts.DisableRedZone) Index: lib/CodeGen/CodeGenModule.cpp =================================================================== --- lib/CodeGen/CodeGenModule.cpp +++ lib/CodeGen/CodeGenModule.cpp @@ -1161,6 +1161,8 @@ ShouldAddOptNone &= !F->hasFnAttribute(llvm::Attribute::AlwaysInline); ShouldAddOptNone &= !D->hasAttr(); + if (!ShouldAddOptNone) + F->removeFnAttr(llvm::Attribute::OptimizeNone); if (ShouldAddOptNone || D->hasAttr()) { B.addAttribute(llvm::Attribute::OptimizeNone); @@ -1174,9 +1176,13 @@ if (D->hasAttr()) B.addAttribute(llvm::Attribute::Naked); - // OptimizeNone wins over OptimizeForSize and MinSize. + // OptimizeNone wins over all optimization levels including OptimizeForSize + // and MinSizesize. F->removeFnAttr(llvm::Attribute::OptimizeForSize); F->removeFnAttr(llvm::Attribute::MinSize); + F->removeFnAttr(llvm::Attribute::OptimizeLess); + F->removeFnAttr(llvm::Attribute::OptimizeDefault); + F->removeFnAttr(llvm::Attribute::OptimizeAggressive); } else if (D->hasAttr()) { // Naked implies noinline: we should not be inlining such functions. B.addAttribute(llvm::Attribute::Naked); Index: test/CodeGen/aarch64-neon-2velem.c =================================================================== --- test/CodeGen/aarch64-neon-2velem.c +++ test/CodeGen/aarch64-neon-2velem.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple arm64-none-linux-gnu -target-feature +neon -disable-O0-optnone -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s +// RUN: %clang_cc1 -triple arm64-none-linux-gnu -target-feature +neon -O2 -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s // Test new aarch64 intrinsics and types Index: test/CodeGen/function-attributes-opt-level.c =================================================================== --- /dev/null +++ test/CodeGen/function-attributes-opt-level.c @@ -0,0 +1,42 @@ +// RUN: %clang_cc1 -triple arm64-unknown-unknown -emit-llvm -disable-llvm-passes -std=c99 -o - %s | FileCheck %s --check-prefixes=CHECK,NONE +// RUN: %clang_cc1 -triple arm64-unknown-unknown -emit-llvm -disable-llvm-passes -O0 -std=c99 -o - %s | FileCheck %s --check-prefixes=CHECK,NONE +// RUN: %clang_cc1 -triple arm64-unknown-unknown -emit-llvm -disable-llvm-passes -O1 -std=c99 -o - %s | FileCheck %s --check-prefixes=CHECK,LESS +// RUN: %clang_cc1 -triple arm64-unknown-unknown -emit-llvm -disable-llvm-passes -O2 -std=c99 -o - %s | FileCheck %s --check-prefixes=CHECK,DEFAULT +// RUN: %clang_cc1 -triple arm64-unknown-unknown -emit-llvm -disable-llvm-passes -O3 -std=c99 -o - %s | FileCheck %s --check-prefixes=CHECK,AGGR +// RUN: %clang_cc1 -triple arm64-unknown-unknown -emit-llvm -disable-llvm-passes -Os -std=c99 -o - %s | FileCheck %s --check-prefixes=CHECK,SIZE +// RUN: %clang_cc1 -triple arm64-unknown-unknown -emit-llvm -disable-llvm-passes -Oz -std=c99 -o - %s | FileCheck %s --check-prefixes=CHECK,MINSIZE + +void f0(void) { } +// CHECK-LABEL: define void @f0() +// CHECK: [[ATTR0:#[0-9]+]] + +// We can't add optnone if minsize is present. +void __attribute__((minsize)) f1(void) { } +// CHECK-LABEL: define void @f1() +// CHECK: [[MS:#[0-9]+]] + +// We can't add optnone if alwaysinline is present. +void __attribute__((always_inline)) f2(void) { } +// CHECK-LABEL: define void @f2() +// CHECK: [[AI:#[0-9]+]] + +// NONE: attributes [[ATTR0]] = { noinline nounwind optnone +// LESS: attributes [[ATTR0]] = { nounwind optless +// DEFAULT: attributes [[ATTR0]] = { nounwind optdefault +// AGGR: attributes [[ATTR0]] = { nounwind optaggr +// SIZE: attributes [[ATTR0]] = { nounwind optdefault optsize +// MINSIZE: attributes [[ATTR0]] = { minsize nounwind optdefault optsize + +// NONE: attributes [[MS]] = { minsize noinline nounwind +// LESS: attributes [[MS]] = { minsize nounwind optless +// DEFAULT: attributes [[MS]] = { minsize nounwind optdefault +// AGGR: attributes [[MS]] = { minsize nounwind optaggr +// SIZE: attributes [[MS]] = { minsize nounwind optdefault optsize +// No check for MINSIZE because the attributes for f1 match those for f0. + +// NONE: attributes [[AI]] = { alwaysinline nounwind +// LESS: attributes [[AI]] = { alwaysinline nounwind optless +// DEFAULT: attributes [[AI]] = { alwaysinline nounwind optdefault +// AGGR: attributes [[AI]] = { alwaysinline nounwind optaggr +// SIZE: attributes [[AI]] = { alwaysinline nounwind optdefault optsize +// MINSIZE: attributes [[AI]] = { alwaysinline minsize nounwind optdefault optsize Index: test/CodeGen/function-attributes.c =================================================================== --- test/CodeGen/function-attributes.c +++ test/CodeGen/function-attributes.c @@ -1,6 +1,12 @@ // RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm -disable-llvm-passes -Os -o - %s | FileCheck %s // RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm -disable-llvm-passes -Os -std=c99 -o - %s | FileCheck %s // RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -disable-llvm-passes -Os -std=c99 -o - %s | FileCheck %s + +// RUN: %clang_cc1 -triple arm64-unknown-unknown -emit-llvm -disable-llvm-passes -O0 -std=c99 -o - %s | FileCheck %s --check-prefix:NONE +// RUN: %clang_cc1 -triple arm64-unknown-unknown -emit-llvm -disable-llvm-passes -O1 -std=c99 -o - %s | FileCheck %s --check-prefix:LESS +// RUN: %clang_cc1 -triple arm64-unknown-unknown -emit-llvm -disable-llvm-passes -O2 -std=c99 -o - %s | FileCheck %s --check-prefix:DEFAULT +// RUN: %clang_cc1 -triple arm64-unknown-unknown -emit-llvm -disable-llvm-passes -O3 -std=c99 -o - %s | FileCheck %s --check-prefix:AGGR + // CHECK: define signext i8 @f0(i32 %x) [[NUW:#[0-9]+]] // CHECK: define zeroext i8 @f1(i32 %x) [[NUW]] // CHECK: define void @f2(i8 signext %x) [[NUW]] @@ -109,11 +115,11 @@ _setjmp(0); } -// CHECK: attributes [[NUW]] = { nounwind optsize{{.*}} } -// CHECK: attributes [[AI]] = { alwaysinline nounwind optsize{{.*}} } -// CHECK: attributes [[NUW_OS_RN]] = { nounwind optsize readnone{{.*}} } -// CHECK: attributes [[ALIGN]] = { nounwind optsize alignstack=16{{.*}} } -// CHECK: attributes [[RT]] = { nounwind optsize returns_twice{{.*}} } -// CHECK: attributes [[NR]] = { noreturn optsize } -// CHECK: attributes [[NUW_RN]] = { nounwind optsize readnone } -// CHECK: attributes [[RT_CALL]] = { optsize returns_twice } +// CHECK: attributes [[NUW]] = { nounwind optdefault optsize{{.*}} } +// CHECK: attributes [[AI]] = { alwaysinline nounwind optdefault optsize{{.*}} } +// CHECK: attributes [[NUW_OS_RN]] = { nounwind optdefault optsize readnone{{.*}} } +// CHECK: attributes [[ALIGN]] = { nounwind optdefault optsize alignstack=16{{.*}} } +// CHECK: attributes [[RT]] = { nounwind optdefault optsize returns_twice{{.*}} } +// CHECK: attributes [[NR]] = { noreturn optdefault optsize } +// CHECK: attributes [[NUW_RN]] = { nounwind optdefault optsize readnone } +// CHECK: attributes [[RT_CALL]] = { optdefault optsize returns_twice } Index: test/CodeGen/ms-declspecs.c =================================================================== --- test/CodeGen/ms-declspecs.c +++ test/CodeGen/ms-declspecs.c @@ -37,8 +37,8 @@ // CHECK: call void @noalias_callee({{.*}}) [[NA:#[0-9]+]] void noalias_caller(int *x) { noalias_callee(x); } -// CHECK: attributes [[NAKED]] = { naked noinline nounwind{{.*}} } -// CHECK: attributes [[NUW]] = { nounwind{{.*}} } -// CHECK: attributes [[NI]] = { noinline nounwind{{.*}} } -// CHECK: attributes [[NR]] = { noreturn } -// CHECK: attributes [[NA]] = { argmemonly nounwind{{.*}} } +// CHECK: attributes [[NAKED]] = { naked noinline nounwind optdefault{{.*}} } +// CHECK: attributes [[NUW]] = { nounwind optdefault{{.*}} } +// CHECK: attributes [[NI]] = { noinline nounwind optdefault{{.*}} } +// CHECK: attributes [[NR]] = { noreturn optdefault } +// CHECK: attributes [[NA]] = { argmemonly nounwind optdefault{{.*}} } Index: test/CodeGenCXX/thunks.cpp =================================================================== --- test/CodeGenCXX/thunks.cpp +++ test/CodeGenCXX/thunks.cpp @@ -402,4 +402,4 @@ // CHECK-OPT-LABEL: define linkonce_odr void @_ZThn8_N6Test101C3fooEv // CHECK-NONOPT: attributes [[NUW]] = { noinline nounwind optnone uwtable{{.*}} } -// CHECK-OPT: attributes [[NUW]] = { nounwind uwtable{{.*}} } +// CHECK-OPT: attributes [[NUW]] = { nounwind optless uwtable{{.*}} } Index: test/CodeGenObjC/arc-no-arc-exceptions.m =================================================================== --- test/CodeGenObjC/arc-no-arc-exceptions.m +++ test/CodeGenObjC/arc-no-arc-exceptions.m @@ -9,7 +9,7 @@ void not(void) __attribute__((nothrow)); // CHECK-LABEL: define void @test0( -// CHECK: call void @thrower(), !clang.arc.no_objc_arc_exceptions ! +// CHECK: call void @thrower() {{#[0-9]}}, !clang.arc.no_objc_arc_exceptions ! // CHECK: call void @not() [[NUW:#[0-9]+]], !clang.arc.no_objc_arc_exceptions ! // NO-METADATA-LABEL: define void @test0( // NO-METADATA-NOT: !clang.arc.no_objc_arc_exceptions @@ -20,7 +20,7 @@ } // CHECK-LABEL: define void @test1( -// CHECK: call void @thrower(), !clang.arc.no_objc_arc_exceptions ! +// CHECK: call void @thrower() {{#[0-9]}}, !clang.arc.no_objc_arc_exceptions ! // CHECK: call void @not() [[NUW]], !clang.arc.no_objc_arc_exceptions ! // NO-METADATA-LABEL: define void @test1( // NO-METADATA-NOT: !clang.arc.no_objc_arc_exceptions @@ -77,4 +77,4 @@ } } -// CHECK: attributes [[NUW]] = { nounwind } +// CHECK: attributes [[NUW]] = { nounwind optdefault } Index: test/CodeGenOpenCL/convergent.cl =================================================================== --- test/CodeGenOpenCL/convergent.cl +++ test/CodeGenOpenCL/convergent.cl @@ -127,16 +127,18 @@ // CHECK: declare spir_func void @nodupfun(){{[^#]*}} #[[attr3:[0-9]+]] // CHECK-LABEL: @assume_convergent_asm -// CHECK: tail call void asm sideeffect "s_barrier", ""() #5 +// CHECK: tail call void asm sideeffect "s_barrier", ""() #8 kernel void assume_convergent_asm() { __asm__ volatile("s_barrier"); } -// CHECK: attributes #0 = { noinline norecurse nounwind " +// CHECK: attributes #0 = { noinline norecurse nounwind // CHECK: attributes #1 = { {{[^}]*}}convergent{{[^}]*}} } // CHECK: attributes #2 = { {{[^}]*}}convergent{{[^}]*}} } // CHECK: attributes #3 = { {{[^}]*}}convergent noduplicate{{[^}]*}} } // CHECK: attributes #4 = { {{[^}]*}}convergent{{[^}]*}} } // CHECK: attributes #5 = { {{[^}]*}}convergent{{[^}]*}} } -// CHECK: attributes #6 = { {{[^}]*}}convergent noduplicate{{[^}]*}} } +// CHECK: attributes #6 = { optdefault } +// CHECK: attributes #7 = { {{[^}]*}}convergent noduplicate{{[^}]*}} } +// CHECK: attributes #8 = { {{[^}]*}}convergent{{[^}]*}} }