#include "clang/AST/TranslationUnit.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/CodeGen/ModuleBuilder.h"
+#include "clang/Driver/CompileOptions.h"
#include "llvm/Module.h"
#include "llvm/ModuleProvider.h"
#include "llvm/PassManager.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/Assembly/PrintModulePass.h"
+#include "llvm/Analysis/CallGraph.h"
+#include "llvm/Analysis/Verifier.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/CodeGen/RegAllocRegistry.h"
#include "llvm/CodeGen/SchedulerRegistry.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetMachineRegistry.h"
+#include "llvm/Transforms/Scalar.h"
+#include "llvm/Transforms/IPO.h"
#include <fstream> // FIXME: Remove
using namespace clang;
namespace {
class VISIBILITY_HIDDEN BackendConsumer : public ASTConsumer {
BackendAction Action;
+ CompileOptions CompileOpts;
const std::string &InputFile;
std::string OutputFile;
llvm::OwningPtr<CodeGenerator> Gen;
public:
BackendConsumer(BackendAction action, Diagnostic &Diags,
- const LangOptions &Features,
+ const LangOptions &Features, const CompileOptions &compopts,
const std::string& infile, const std::string& outfile,
bool GenerateDebugInfo) :
Action(action),
+ CompileOpts(compopts),
InputFile(infile),
OutputFile(outfile),
Gen(CreateLLVMCodeGen(Diags, Features, InputFile, GenerateDebugInfo)),
}
void BackendConsumer::CreatePasses() {
-
+ // In -O0 if checking is disabled, we don't even have per-function passes.
+ if (CompileOpts.VerifyModule)
+ getPerFunctionPasses()->add(createVerifierPass());
+
+ if (CompileOpts.OptimizationLevel > 0) {
+ FunctionPassManager *PM = getPerFunctionPasses();
+ PM->add(createCFGSimplificationPass());
+ if (CompileOpts.OptimizationLevel == 1)
+ PM->add(createPromoteMemoryToRegisterPass());
+ else
+ PM->add(createScalarReplAggregatesPass());
+ PM->add(createInstructionCombiningPass());
+ }
+
+ // For now we always create per module passes.
+ PassManager *PM = getPerModulePasses();
+ if (CompileOpts.OptimizationLevel > 0) {
+ if (CompileOpts.UnitAtATime)
+ PM->add(createRaiseAllocationsPass()); // call %malloc -> malloc inst
+ PM->add(createCFGSimplificationPass()); // Clean up disgusting code
+ PM->add(createPromoteMemoryToRegisterPass()); // Kill useless allocas
+ if (CompileOpts.UnitAtATime) {
+ PM->add(createGlobalOptimizerPass()); // Optimize out global vars
+ PM->add(createGlobalDCEPass()); // Remove unused fns and globs
+ PM->add(createIPConstantPropagationPass()); // IP Constant Propagation
+ PM->add(createDeadArgEliminationPass()); // Dead argument elimination
+ }
+ PM->add(createInstructionCombiningPass()); // Clean up after IPCP & DAE
+ PM->add(createCFGSimplificationPass()); // Clean up after IPCP & DAE
+ if (CompileOpts.UnitAtATime) {
+ PM->add(createPruneEHPass()); // Remove dead EH info
+ PM->add(createAddReadAttrsPass()); // Set readonly/readnone attrs
+ }
+ if (CompileOpts.InlineFunctions)
+ PM->add(createFunctionInliningPass()); // Inline small functions
+ else
+ PM->add(createAlwaysInlinerPass()); // Respect always_inline
+ if (CompileOpts.OptimizationLevel > 2)
+ PM->add(createArgumentPromotionPass()); // Scalarize uninlined fn args
+ if (CompileOpts.SimplifyLibCalls)
+ PM->add(createSimplifyLibCallsPass()); // Library Call Optimizations
+ PM->add(createInstructionCombiningPass()); // Cleanup for scalarrepl.
+ PM->add(createJumpThreadingPass()); // Thread jumps.
+ PM->add(createCFGSimplificationPass()); // Merge & remove BBs
+ PM->add(createScalarReplAggregatesPass()); // Break up aggregate allocas
+ PM->add(createInstructionCombiningPass()); // Combine silly seq's
+ PM->add(createCondPropagationPass()); // Propagate conditionals
+ PM->add(createTailCallEliminationPass()); // Eliminate tail calls
+ PM->add(createCFGSimplificationPass()); // Merge & remove BBs
+ PM->add(createReassociatePass()); // Reassociate expressions
+ PM->add(createLoopRotatePass()); // Rotate Loop
+ PM->add(createLICMPass()); // Hoist loop invariants
+ PM->add(createLoopUnswitchPass(CompileOpts.OptimizeSize ? true : false));
+ PM->add(createLoopIndexSplitPass()); // Split loop index
+ PM->add(createInstructionCombiningPass());
+ PM->add(createIndVarSimplifyPass()); // Canonicalize indvars
+ PM->add(createLoopDeletionPass()); // Delete dead loops
+ if (CompileOpts.UnrollLoops)
+ PM->add(createLoopUnrollPass()); // Unroll small loops
+ PM->add(createInstructionCombiningPass()); // Clean up after the unroller
+ PM->add(createGVNPass()); // Remove redundancies
+ PM->add(createMemCpyOptPass()); // Remove memcpy / form memset
+ PM->add(createSCCPPass()); // Constant prop with SCCP
+
+ // Run instcombine after redundancy elimination to exploit opportunities
+ // opened up by them.
+ PM->add(createInstructionCombiningPass());
+ PM->add(createCondPropagationPass()); // Propagate conditionals
+ PM->add(createDeadStoreEliminationPass()); // Delete dead stores
+ PM->add(createAggressiveDCEPass()); // Delete dead instructions
+ PM->add(createCFGSimplificationPass()); // Merge & remove BBs
+
+ if (CompileOpts.UnitAtATime) {
+ PM->add(createStripDeadPrototypesPass()); // Get rid of dead prototypes
+ PM->add(createDeadTypeEliminationPass()); // Eliminate dead types
+ }
+
+ if (CompileOpts.OptimizationLevel > 1 && CompileOpts.UnitAtATime)
+ PM->add(createConstantMergePass()); // Merge dup global constants
+ } else {
+ PerModulePasses->add(createAlwaysInlinerPass());
+ }
}
/// EmitAssembly - Handle interaction with LLVM backend to generate
ASTConsumer *clang::CreateBackendConsumer(BackendAction Action,
Diagnostic &Diags,
const LangOptions &Features,
+ const CompileOptions &CompileOpts,
const std::string& InFile,
const std::string& OutFile,
bool GenerateDebugInfo) {
- return new BackendConsumer(Action, Diags, Features, InFile, OutFile,
- GenerateDebugInfo);
+ return new BackendConsumer(Action, Diags, Features, CompileOpts,
+ InFile, OutFile, GenerateDebugInfo);
}
#include "clang.h"
#include "ASTConsumers.h"
+#include "clang/Driver/CompileOptions.h"
#include "clang/Driver/HTMLDiagnostics.h"
#include "clang/Driver/InitHeaderSearch.h"
#include "clang/Driver/TextDiagnosticBuffer.h"
delete PA;
}
+//===----------------------------------------------------------------------===//
+// Code generation options
+//===----------------------------------------------------------------------===//
+
+static llvm::cl::opt<bool>
+OptSize("Os",
+ llvm::cl::desc("Optimize for size"));
+
+// It might be nice to add bounds to the CommandLine library directly.
+struct OptLevelParser : public llvm::cl::parser<unsigned> {
+ bool parse(llvm::cl::Option &O, const char *ArgName,
+ const std::string &Arg, unsigned &Val) {
+ if (llvm::cl::parser<unsigned>::parse(O, ArgName, Arg, Val))
+ return true;
+ // FIXME: Support -O4.
+ if (Val > 3)
+ return O.error(": '" + Arg + "' invalid optimization level!");
+ return false;
+ }
+};
+static llvm::cl::opt<unsigned, false, OptLevelParser>
+OptLevel("O", llvm::cl::Prefix,
+ llvm::cl::desc("Optimization level"),
+ llvm::cl::init(0));
+
+static void InitializeCompileOptions(CompileOptions &Opts) {
+ Opts.OptimizationLevel = OptLevel;
+ Opts.OptimizeSize = OptSize;
+ // FIXME: Wire other options.
+}
+
//===----------------------------------------------------------------------===//
// Main driver
//===----------------------------------------------------------------------===//
return CreateSerializationTest(Diag, FileMgr);
case EmitAssembly:
- return CreateBackendConsumer(Backend_EmitAssembly, Diag, LangOpts,
- InFile, OutputFile, GenerateDebugInfo);
case EmitLLVM:
- return CreateBackendConsumer(Backend_EmitLL, Diag, LangOpts,
- InFile, OutputFile, GenerateDebugInfo);
- case EmitBC:
- return CreateBackendConsumer(Backend_EmitBC, Diag, LangOpts,
+ case EmitBC: {
+ BackendAction Act;
+ if (ProgAction == EmitAssembly) {
+ Act = Backend_EmitAssembly;
+ } else if (ProgAction == EmitLLVM) {
+ Act = Backend_EmitLL;
+ } else {
+ Act = Backend_EmitBC;
+ }
+ CompileOptions Opts;
+ InitializeCompileOptions(Opts);
+ return CreateBackendConsumer(Act, Diag, LangOpts, Opts,
InFile, OutputFile, GenerateDebugInfo);
+ }
case SerializeAST:
// FIXME: Allow user to tailor where the file is written.