Index: lib/Transforms/IPO/PassManagerBuilder.cpp =================================================================== --- lib/Transforms/IPO/PassManagerBuilder.cpp +++ lib/Transforms/IPO/PassManagerBuilder.cpp @@ -176,6 +176,7 @@ // if enabled, the function merging pass. if (OptLevel == 0) { if (Inliner) { + MPM.add(createGlobalDCEPass()); // Remove dead fns and globals. MPM.add(Inliner); Inliner = nullptr; } @@ -217,6 +218,7 @@ if (!DisableUnitAtATime) MPM.add(createPruneEHPass()); // Remove dead EH info if (Inliner) { + MPM.add(createGlobalDCEPass()); // Remove dead fns and globals. MPM.add(Inliner); Inliner = nullptr; } @@ -453,6 +455,7 @@ // Inline small functions bool RunInliner = Inliner; if (RunInliner) { + PM.add(createGlobalDCEPass()); // Remove dead fns and globals. PM.add(Inliner); Inliner = nullptr; } Index: test/Transforms/Inline/always-inline-O0.ll =================================================================== --- test/Transforms/Inline/always-inline-O0.ll +++ test/Transforms/Inline/always-inline-O0.ll @@ -0,0 +1,19 @@ +; RUN: opt < %s -O0 -S | FileCheck %s +; CHECK-NOT: call{{.*}}AAA +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-linux-gnu" + +define void @AAA() alwaysinline { + ret void +} + +define internal void @BBB() { + call void @CCC() + call void @AAA() + ret void +} + +define internal void @CCC() { + call void @AAA() + ret void +} Index: test/Transforms/Inline/always-inline-O1.ll =================================================================== --- test/Transforms/Inline/always-inline-O1.ll +++ test/Transforms/Inline/always-inline-O1.ll @@ -0,0 +1,40 @@ +; RUN: opt < %s -O1 -S | FileCheck %s +; RUN: opt < %s -O2 -S | FileCheck %s +; RUN: opt < %s -O3 -S | FileCheck %s +; CHECK-NOT: call{{.*}}BBB + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +declare void @AAA() + +define void @BBB() alwaysinline { +entry: + call void @AAA() + ret void +} + +define internal void @CCC() { +entry: + call void @BBB() + ret void +} + +define void @DDD(i8* %x) { +entry: + %a = load i8, i8* %x, align 4 + %cmpa = icmp ne i8 %a, 1 + br i1 %cmpa, label %return, label %if.end + +if.end: + %b = load i8, i8* %x, align 4 + %cmpb = icmp eq i8 %b, 1 + br i1 %cmpb, label %return, label %if.end.2 + +if.end.2: + call void @CCC() + br label %return + +return: + ret void +} Index: tools/opt/opt.cpp =================================================================== --- tools/opt/opt.cpp +++ tools/opt/opt.cpp @@ -116,6 +116,10 @@ cl::desc("Include the standard link time optimizations")); static cl::opt +OptLevelO0("O0", + cl::desc("Optimization level 0. Similar to clang -O0")); + +static cl::opt OptLevelO1("O1", cl::desc("Optimization level 1. Similar to clang -O1")); @@ -453,7 +457,7 @@ : TargetIRAnalysis())); std::unique_ptr FPasses; - if (OptLevelO1 || OptLevelO2 || OptLevelOs || OptLevelOz || OptLevelO3) { + if (OptLevelO0 || OptLevelO1 || OptLevelO2 || OptLevelOs || OptLevelOz || OptLevelO3) { FPasses.reset(new legacy::FunctionPassManager(M.get())); FPasses->add(createTargetTransformInfoWrapperPass( TM ? TM->getTargetIRAnalysis() : TargetIRAnalysis())); @@ -485,6 +489,11 @@ StandardLinkOpts = false; } + if (OptLevelO0 && OptLevelO0.getPosition() < PassList.getPosition(i)) { + AddOptimizationPasses(Passes, *FPasses, 0, 0); + OptLevelO0 = false; + } + if (OptLevelO1 && OptLevelO1.getPosition() < PassList.getPosition(i)) { AddOptimizationPasses(Passes, *FPasses, 1, 0); OptLevelO1 = false; @@ -557,6 +566,9 @@ StandardLinkOpts = false; } + if (OptLevelO0) + AddOptimizationPasses(Passes, *FPasses, 0, 0); + if (OptLevelO1) AddOptimizationPasses(Passes, *FPasses, 1, 0); @@ -572,7 +584,7 @@ if (OptLevelO3) AddOptimizationPasses(Passes, *FPasses, 3, 0); - if (OptLevelO1 || OptLevelO2 || OptLevelOs || OptLevelOz || OptLevelO3) { + if (OptLevelO0 || OptLevelO1 || OptLevelO2 || OptLevelOs || OptLevelOz || OptLevelO3) { FPasses->doInitialization(); for (Function &F : *M) FPasses->run(F);