From d694e283b3ee045e8c10800a6428332a4fe4e80f Mon Sep 17 00:00:00 2001 From: James Miller Date: Tue, 28 May 2013 11:15:31 +1200 Subject: [PATCH] Refactor optimization pass handling. Refactor the optimization passes to explicitly use the passes. This commit just re-implements the same passes as were already being run. It also adds an option (behind `-Z`) to run the LLVM lint pass on the unoptimized IR. --- Makefile.in | 2 +- mk/rustllvm.mk | 2 +- src/librustc/back/link.rs | 66 +++------- src/librustc/back/passes.rs | 150 ++++++++++++++++++++++ src/librustc/driver/session.rs | 5 + src/librustc/lib/llvm.rs | 221 ++++++++++++++++++++++++++++++++- src/librustc/rustc.rc | 1 + src/rustllvm/PassWrapper.cpp | 160 ++++++++++++++++++++++++ src/rustllvm/RustWrapper.cpp | 48 +------ src/rustllvm/rustllvm.def.in | 102 +++++++++++++++ src/rustllvm/rustllvm.h | 57 +++++++++ 11 files changed, 716 insertions(+), 98 deletions(-) create mode 100644 src/librustc/back/passes.rs create mode 100644 src/rustllvm/PassWrapper.cpp create mode 100644 src/rustllvm/rustllvm.h diff --git a/Makefile.in b/Makefile.in index 3d8133df7a4..f6b50b5491a 100644 --- a/Makefile.in +++ b/Makefile.in @@ -275,7 +275,7 @@ DRIVER_CRATE := $(S)src/driver/driver.rs # FIXME: x86-ism LLVM_COMPONENTS=x86 arm mips ipo bitreader bitwriter linker asmparser jit mcjit \ - interpreter + interpreter instrumentation define DEF_LLVM_VARS # The configure script defines these variables with the target triples diff --git a/mk/rustllvm.mk b/mk/rustllvm.mk index f1ce4445c61..ffe03598e53 100644 --- a/mk/rustllvm.mk +++ b/mk/rustllvm.mk @@ -22,7 +22,7 @@ LLVM_EXTRA_INCDIRS_$(1)= -iquote $(S)src/llvm/include \ -iquote llvm/$(1)/include endif -RUSTLLVM_OBJS_CS_$(1) := $$(addprefix rustllvm/, RustWrapper.cpp) +RUSTLLVM_OBJS_CS_$(1) := $$(addprefix rustllvm/, RustWrapper.cpp PassWrapper.cpp) RUSTLLVM_DEF_$(1) := rustllvm/rustllvm$(CFG_DEF_SUFFIX_$(1)) diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index b7e33d7c68d..41ea44f5f06 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -183,6 +183,8 @@ pub mod write { use lib::llvm::{False, ModuleRef, mk_pass_manager, mk_target_data}; use lib; + use back::passes; + use core::libc::{c_int, c_uint}; use core::path::Path; use core::run; @@ -202,16 +204,12 @@ pub mod write { unsafe { let opts = sess.opts; if sess.time_llvm_passes() { llvm::LLVMRustEnableTimePasses(); } - let mut pm = mk_pass_manager(); let td = mk_target_data(sess.targ_cfg.target_strs.data_layout); + let pm = mk_pass_manager(); llvm::LLVMAddTargetData(td.lltd, pm.llpm); - // FIXME (#2812): run the linter here also, once there are llvm-c - // bindings for it. // Generate a pre-optimization intermediate file if -save-temps // was specified. - - if opts.save_temps { match output_type { output_type_bitcode => { @@ -230,50 +228,22 @@ pub mod write { } } } - if !sess.no_verify() { llvm::LLVMAddVerifierPass(pm.llpm); } - // FIXME (#2396): This is mostly a copy of the bits of opt's -O2 - // that are available in the C api. - // Also: We might want to add optimization levels like -O1, -O2, - // -Os, etc - // Also: Should we expose and use the pass lists used by the opt - // tool? - if opts.optimize != session::No { - let fpm = mk_pass_manager(); - llvm::LLVMAddTargetData(td.lltd, fpm.llpm); + let mut mpm = passes::PassManager::new(td.lltd); - let FPMB = llvm::LLVMPassManagerBuilderCreate(); - llvm::LLVMPassManagerBuilderSetOptLevel(FPMB, 2u as c_uint); - llvm::LLVMPassManagerBuilderPopulateFunctionPassManager( - FPMB, fpm.llpm); - llvm::LLVMPassManagerBuilderDispose(FPMB); - - llvm::LLVMRunPassManager(fpm.llpm, llmod); - let mut threshold = 225; - if opts.optimize == session::Aggressive { threshold = 275; } - - let MPMB = llvm::LLVMPassManagerBuilderCreate(); - llvm::LLVMPassManagerBuilderSetOptLevel(MPMB, - opts.optimize as - c_uint); - llvm::LLVMPassManagerBuilderSetSizeLevel(MPMB, False); - llvm::LLVMPassManagerBuilderSetDisableUnitAtATime(MPMB, - False); - llvm::LLVMPassManagerBuilderSetDisableUnrollLoops(MPMB, - False); - llvm::LLVMPassManagerBuilderSetDisableSimplifyLibCalls(MPMB, - False); - - if threshold != 0u { - llvm::LLVMPassManagerBuilderUseInlinerWithThreshold - (MPMB, threshold as c_uint); - } - llvm::LLVMPassManagerBuilderPopulateModulePassManager( - MPMB, pm.llpm); - - llvm::LLVMPassManagerBuilderDispose(MPMB); + if !sess.no_verify() { + mpm.addPass(llvm::LLVMCreateVerifierPass()); } - if !sess.no_verify() { llvm::LLVMAddVerifierPass(pm.llpm); } + + if sess.lint_llvm() { + mpm.addPass(llvm::LLVMCreateLintPass()); + } + + passes::populatePassManager(&mut mpm, opts.optimize); + + debug!("Running Module Optimization Pass"); + mpm.run(llmod); + if is_object_or_assembly_or_exe(output_type) || opts.jit { let LLVMOptNone = 0 as c_int; // -O0 let LLVMOptLess = 1 as c_int; // -O1 @@ -312,12 +282,9 @@ pub mod write { // Always output the bitcode file with --save-temps let filename = output.with_filetype("opt.bc"); - llvm::LLVMRunPassManager(pm.llpm, llmod); str::as_c_str(filename.to_str(), |buf| { llvm::LLVMWriteBitcodeToFile(llmod, buf) }); - pm = mk_pass_manager(); - // Save the assembly file if -S is used if output_type == output_type_assembly { WriteOutputFile( @@ -377,7 +344,6 @@ pub mod write { } else { // If only a bitcode file is asked for by using the // '--emit-llvm' flag, then output it here - llvm::LLVMRunPassManager(pm.llpm, llmod); str::as_c_str(output.to_str(), |buf| llvm::LLVMWriteBitcodeToFile(llmod, buf) ); } diff --git a/src/librustc/back/passes.rs b/src/librustc/back/passes.rs new file mode 100644 index 00000000000..a9cee275c27 --- /dev/null +++ b/src/librustc/back/passes.rs @@ -0,0 +1,150 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use core::prelude::*; + +use driver::session::{Session, Session_, No, Less, Default}; +use driver::session; +use lib::llvm::{PassRef, ModuleRef,PassManagerRef,ValueRef,TargetDataRef}; +use lib::llvm::llvm; +use lib; + +pub struct PassManager { + priv llpm: PassManagerRef +} + +impl Drop for PassManager { + fn finalize(&self) { + unsafe { + llvm::LLVMDisposePassManager(self.llpm); + } + } +} + +impl PassManager { + pub fn new(td: TargetDataRef) -> PassManager { + unsafe { + let pm = PassManager { + llpm: llvm::LLVMCreatePassManager() + }; + llvm::LLVMAddTargetData(td, pm.llpm); + + return pm; + } + } + + pub fn addPass(&mut self, pass:PassRef) { + unsafe { + llvm::LLVMAddPass(self.llpm, pass); + } + } + + pub fn run(&self, md:ModuleRef) -> bool { + unsafe { + llvm::LLVMRunPassManager(self.llpm, md) == lib::llvm::True + } + } +} + + +pub fn populatePassManager(pm: &mut PassManager, level:session::OptLevel) { + unsafe { + // We add a lot of potentially-unused prototypes, so strip them right at the + // start. We do it again later when we know for certain which ones are used + pm.addPass(llvm::LLVMCreateStripDeadPrototypesPass()); + + if level == session::No { + pm.addPass(llvm::LLVMCreateAlwaysInlinerPass()); + return; + } + + //NOTE: Add library info + + pm.addPass(llvm::LLVMCreateTypeBasedAliasAnalysisPass()); + pm.addPass(llvm::LLVMCreateBasicAliasAnalysisPass()); + + pm.addPass(llvm::LLVMCreateSROAPass()); + pm.addPass(llvm::LLVMCreateEarlyCSEPass()); + pm.addPass(llvm::LLVMCreateLowerExpectIntrinsicPass()); + + pm.addPass(llvm::LLVMCreateGlobalOptimizerPass()); + pm.addPass(llvm::LLVMCreateIPSCCPPass()); + pm.addPass(llvm::LLVMCreateDeadArgEliminationPass()); + pm.addPass(llvm::LLVMCreateInstructionCombiningPass()); + pm.addPass(llvm::LLVMCreateCFGSimplificationPass()); + + pm.addPass(llvm::LLVMCreatePruneEHPass()); + + match level { + session::Less => pm.addPass(llvm::LLVMCreateFunctionInliningPass(200)), + session::Default => pm.addPass(llvm::LLVMCreateFunctionInliningPass(225)), + session::Aggressive => pm.addPass(llvm::LLVMCreateFunctionInliningPass(275)), + session::No => () + } + + pm.addPass(llvm::LLVMCreateFunctionAttrsPass()); + + if level == session::Aggressive { + pm.addPass(llvm::LLVMCreateArgumentPromotionPass()); + } + + pm.addPass(llvm::LLVMCreateSROAPass()); + + pm.addPass(llvm::LLVMCreateEarlyCSEPass()); + pm.addPass(llvm::LLVMCreateSimplifyLibCallsPass()); + pm.addPass(llvm::LLVMCreateJumpThreadingPass()); + pm.addPass(llvm::LLVMCreateCorrelatedValuePropagationPass()); + pm.addPass(llvm::LLVMCreateCFGSimplificationPass()); + pm.addPass(llvm::LLVMCreateInstructionCombiningPass()); + + pm.addPass(llvm::LLVMCreateTailCallEliminationPass()); + pm.addPass(llvm::LLVMCreateCFGSimplificationPass()); + pm.addPass(llvm::LLVMCreateReassociatePass()); + pm.addPass(llvm::LLVMCreateLoopRotatePass()); + pm.addPass(llvm::LLVMCreateLICMPass()); + + pm.addPass(llvm::LLVMCreateLoopUnswitchPass()); + + pm.addPass(llvm::LLVMCreateInstructionCombiningPass()); + pm.addPass(llvm::LLVMCreateIndVarSimplifyPass()); + pm.addPass(llvm::LLVMCreateLoopIdiomPass()); + pm.addPass(llvm::LLVMCreateLoopDeletionPass()); + + if level == session::Aggressive { + pm.addPass(llvm::LLVMCreateLoopUnrollPass()); + } + pm.addPass(llvm::LLVMCreateLoopUnrollPass()); + + if level != session::Less { + pm.addPass(llvm::LLVMCreateGVNPass()); + } + pm.addPass(llvm::LLVMCreateMemCpyOptPass()); + pm.addPass(llvm::LLVMCreateSCCPPass()); + + pm.addPass(llvm::LLVMCreateInstructionCombiningPass()); + pm.addPass(llvm::LLVMCreateJumpThreadingPass()); + pm.addPass(llvm::LLVMCreateCorrelatedValuePropagationPass()); + pm.addPass(llvm::LLVMCreateDeadStoreEliminationPass()); + + pm.addPass(llvm::LLVMCreateBBVectorizePass()); + pm.addPass(llvm::LLVMCreateInstructionCombiningPass()); + if level != session::Less { + pm.addPass(llvm::LLVMCreateGlobalDCEPass()); + pm.addPass(llvm::LLVMCreateConstantMergePass()); + } + + if level == session::Aggressive { + pm.addPass(llvm::LLVMCreateMergeFunctionsPass()); + } + + pm.addPass(llvm::LLVMCreateStripDeadPrototypesPass()); + + } +} diff --git a/src/librustc/driver/session.rs b/src/librustc/driver/session.rs index ae49446c5b3..3f2467948a2 100644 --- a/src/librustc/driver/session.rs +++ b/src/librustc/driver/session.rs @@ -69,6 +69,7 @@ pub static extra_debug_info: uint = 1 << 21; pub static statik: uint = 1 << 22; pub static print_link_args: uint = 1 << 23; pub static no_debug_borrows: uint = 1 << 24; +pub static lint_llvm : uint = 1 << 25; pub fn debugging_opts_map() -> ~[(~str, ~str, uint)] { ~[(~"verbose", ~"in general, enable more debug printouts", verbose), @@ -107,6 +108,9 @@ pub fn debugging_opts_map() -> ~[(~str, ~str, uint)] { (~"no-debug-borrows", ~"do not show where borrow checks fail", no_debug_borrows), + (~"lint-llvm", + ~"Run the LLVM lint pass on the pre-optimization IR", + lint_llvm), ] } @@ -265,6 +269,7 @@ pub impl Session_ { fn meta_stats(@self) -> bool { self.debugging_opt(meta_stats) } fn asm_comments(@self) -> bool { self.debugging_opt(asm_comments) } fn no_verify(@self) -> bool { self.debugging_opt(no_verify) } + fn lint_llvm(@self) -> bool { self.debugging_opt(lint_llvm) } fn trace(@self) -> bool { self.debugging_opt(trace) } fn coherence(@self) -> bool { self.debugging_opt(coherence) } fn borrowck_stats(@self) -> bool { self.debugging_opt(borrowck_stats) } diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs index 7a1a3cf77aa..fc655ed1370 100644 --- a/src/librustc/lib/llvm.rs +++ b/src/librustc/lib/llvm.rs @@ -215,13 +215,15 @@ pub enum ObjectFile_opaque {} pub type ObjectFileRef = *ObjectFile_opaque; pub enum SectionIterator_opaque {} pub type SectionIteratorRef = *SectionIterator_opaque; +pub enum Pass_opaque {} +pub type PassRef = *Pass_opaque; pub mod llvm { use super::{AtomicBinOp, AtomicOrdering, BasicBlockRef}; use super::{Bool, BuilderRef, ContextRef, MemoryBufferRef, ModuleRef}; use super::{ObjectFileRef, Opcode, PassManagerRef, PassManagerBuilderRef}; use super::{SectionIteratorRef, TargetDataRef, TypeKind, TypeRef, UseRef}; - use super::{ValueRef}; + use super::{ValueRef,PassRef}; use core::libc::{c_char, c_int, c_longlong, c_ushort, c_uint, c_ulonglong}; @@ -1654,14 +1656,34 @@ pub mod llvm { /** Creates a pass manager. */ #[fast_ffi] pub unsafe fn LLVMCreatePassManager() -> PassManagerRef; + /** Creates a function-by-function pass manager */ + #[fast_ffi] + pub unsafe fn LLVMCreateFunctionPassManagerForModule(M:ModuleRef) -> PassManagerRef; + /** Disposes a pass manager. */ #[fast_ffi] pub unsafe fn LLVMDisposePassManager(PM: PassManagerRef); + /** Runs a pass manager on a module. */ #[fast_ffi] pub unsafe fn LLVMRunPassManager(PM: PassManagerRef, M: ModuleRef) -> Bool; + /** Runs the function passes on the provided function. */ + #[fast_ffi] + pub unsafe fn LLVMRunFunctionPassManager(FPM:PassManagerRef, F:ValueRef) -> Bool; + + /** Initializes all the function passes scheduled in the manager */ + #[fast_ffi] + pub unsafe fn LLVMInitializeFunctionPassManager(FPM:PassManagerRef) -> Bool; + + /** Finalizes all the function passes scheduled in the manager */ + #[fast_ffi] + pub unsafe fn LLVMFinalizeFunctionPassManager(FPM:PassManagerRef) -> Bool; + + #[fast_ffi] + pub unsafe fn LLVMAddPass(PM:PassManagerRef,P:PassRef); + /** Adds a verification pass. */ #[fast_ffi] pub unsafe fn LLVMAddVerifierPass(PM: PassManagerRef); @@ -1903,6 +1925,203 @@ pub mod llvm { Constraints: *c_char, SideEffects: Bool, AlignStack: Bool, Dialect: c_uint) -> ValueRef; + + // LLVM Passes + + #[fast_ffi] + pub fn LLVMCreateStripSymbolsPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateStripNonDebugSymbolsPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateStripDebugDeclarePass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateStripDeadDebugInfoPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateConstantMergePass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateGlobalOptimizerPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateGlobalDCEPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateAlwaysInlinerPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreatePruneEHPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateInternalizePass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateDeadArgEliminationPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateDeadArgHackingPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateArgumentPromotionPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateIPConstantPropagationPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateIPSCCPPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateLoopExtractorPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateSingleLoopExtractorPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateBlockExtractorPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateStripDeadPrototypesPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateFunctionAttrsPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateMergeFunctionsPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreatePartialInliningPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateMetaRenamerPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateBarrierNoopPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateFunctionInliningPass(Threshold:c_int) -> PassRef; + #[fast_ffi] + pub fn LLVMCreateEdgeProfilerPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateOptimalEdgeProfilerPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreatePathProfilerPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateGCOVProfilerPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateBoundsCheckingPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateConstantPropagationPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateSCCPPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateDeadInstEliminationPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateDeadCodeEliminationPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateDeadStoreEliminationPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateAggressiveDCEPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateSROAPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateScalarReplAggregatesPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateIndVarSimplifyPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateInstructionCombiningPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateLICMPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateLoopStrengthReducePass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateGlobalMergePass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateLoopUnswitchPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateLoopInstSimplifyPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateLoopUnrollPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateLoopRotatePass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateLoopIdiomPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreatePromoteMemoryToRegisterPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateDemoteRegisterToMemoryPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateReassociatePass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateJumpThreadingPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateCFGSimplificationPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateBreakCriticalEdgesPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateLoopSimplifyPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateTailCallEliminationPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateLowerSwitchPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateLowerInvokePass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateBlockPlacementPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateLCSSAPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateEarlyCSEPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateGVNPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateMemCpyOptPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateLoopDeletionPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateSimplifyLibCallsPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateCodeGenPreparePass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateInstructionNamerPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateSinkingPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateLowerAtomicPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateCorrelatedValuePropagationPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateInstructionSimplifierPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateLowerExpectIntrinsicPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateBBVectorizePass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateLoopVectorizePass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateGlobalsModRefPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateAliasAnalysisCounterPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateAAEvalPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateNoAAPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateBasicAliasAnalysisPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateScalarEvolutionAliasAnalysisPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateTypeBasedAliasAnalysisPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateProfileLoaderPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateProfileMetadataLoaderPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateNoProfileInfoPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateProfileEstimatorPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateProfileVerifierPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreatePathProfileLoaderPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateNoPathProfileInfoPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreatePathProfileVerifierPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateLazyValueInfoPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateDependenceAnalysisPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateCostModelAnalysisPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateInstCountPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateRegionInfoPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateModuleDebugInfoPrinterPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateLintPass() -> PassRef; + #[fast_ffi] + pub fn LLVMCreateVerifierPass() -> PassRef; } } diff --git a/src/librustc/rustc.rc b/src/librustc/rustc.rc index 629310b1213..cca194a7773 100644 --- a/src/librustc/rustc.rc +++ b/src/librustc/rustc.rc @@ -128,6 +128,7 @@ pub mod back { pub mod x86_64; pub mod rpath; pub mod target_strs; + pub mod passes; } #[path = "metadata/mod.rs"] diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp new file mode 100644 index 00000000000..fd17dfb4cf8 --- /dev/null +++ b/src/rustllvm/PassWrapper.cpp @@ -0,0 +1,160 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#include "rustllvm.h" + +using namespace llvm; + +// Pass conversion fns +typedef struct LLVMOpaquePass *LLVMPassRef; + +inline Pass *unwrap(LLVMPassRef P) { + return reinterpret_cast(P); +} + +inline LLVMPassRef wrap(const Pass *P) { + return reinterpret_cast(const_cast(P)); +} + +template +inline T *unwrap(LLVMPassRef P) { + T *Q = (T*)unwrap(P); + assert(Q && "Invalid cast!"); + return Q; +} + +#define WRAP_PASS(name) \ + extern "C" LLVMPassRef LLVMCreate##name##Pass() { \ + return wrap(llvm::create##name##Pass()); \ + } + +extern "C" void LLVMAddPass(LLVMPassManagerRef PM, LLVMPassRef P) { + PassManagerBase * pm = unwrap(PM); + Pass * p = unwrap(P); + + pm->add(p); +} + +//////////////// +// Transforms // +// ///////////// + +// IPO Passes +WRAP_PASS(StripSymbols) +WRAP_PASS(StripNonDebugSymbols) +WRAP_PASS(StripDebugDeclare) +WRAP_PASS(StripDeadDebugInfo) +WRAP_PASS(ConstantMerge) +WRAP_PASS(GlobalOptimizer) +WRAP_PASS(GlobalDCE) +WRAP_PASS(AlwaysInliner) +WRAP_PASS(PruneEH) +WRAP_PASS(Internalize) +WRAP_PASS(DeadArgElimination) +WRAP_PASS(DeadArgHacking) +WRAP_PASS(ArgumentPromotion) +WRAP_PASS(IPConstantPropagation) +WRAP_PASS(IPSCCP) +WRAP_PASS(LoopExtractor) +WRAP_PASS(SingleLoopExtractor) +WRAP_PASS(BlockExtractor) +WRAP_PASS(StripDeadPrototypes) +WRAP_PASS(FunctionAttrs) +WRAP_PASS(MergeFunctions) +WRAP_PASS(PartialInlining) +WRAP_PASS(MetaRenamer) +WRAP_PASS(BarrierNoop) + +extern "C" LLVMPassRef LLVMCreateFunctionInliningPass(int Threshold) { + return wrap(llvm::createFunctionInliningPass(Threshold)); +} + +// Instrumentation Passes +WRAP_PASS(EdgeProfiler) +WRAP_PASS(OptimalEdgeProfiler) +WRAP_PASS(PathProfiler) +WRAP_PASS(GCOVProfiler) +WRAP_PASS(BoundsChecking) + +// Scalar Passes +WRAP_PASS(ConstantPropagation) +WRAP_PASS(SCCP) +WRAP_PASS(DeadInstElimination) +WRAP_PASS(DeadCodeElimination) +WRAP_PASS(DeadStoreElimination) +WRAP_PASS(AggressiveDCE) +WRAP_PASS(SROA) +WRAP_PASS(ScalarReplAggregates) +WRAP_PASS(IndVarSimplify) +WRAP_PASS(InstructionCombining) +WRAP_PASS(LICM) +WRAP_PASS(LoopStrengthReduce) +WRAP_PASS(GlobalMerge) +WRAP_PASS(LoopUnswitch) +WRAP_PASS(LoopInstSimplify) +WRAP_PASS(LoopUnroll) +WRAP_PASS(LoopRotate) +WRAP_PASS(LoopIdiom) +WRAP_PASS(PromoteMemoryToRegister) +WRAP_PASS(DemoteRegisterToMemory) +WRAP_PASS(Reassociate) +WRAP_PASS(JumpThreading) +WRAP_PASS(CFGSimplification) +WRAP_PASS(BreakCriticalEdges) +WRAP_PASS(LoopSimplify) +WRAP_PASS(TailCallElimination) +WRAP_PASS(LowerSwitch) +WRAP_PASS(LowerInvoke) +WRAP_PASS(BlockPlacement) +WRAP_PASS(LCSSA) +WRAP_PASS(EarlyCSE) +WRAP_PASS(GVN) +WRAP_PASS(MemCpyOpt) +WRAP_PASS(LoopDeletion) +WRAP_PASS(SimplifyLibCalls) +WRAP_PASS(CodeGenPrepare) +WRAP_PASS(InstructionNamer) +WRAP_PASS(Sinking) +WRAP_PASS(LowerAtomic) +WRAP_PASS(CorrelatedValuePropagation) +WRAP_PASS(InstructionSimplifier) +WRAP_PASS(LowerExpectIntrinsic) + +// Vectorize Passes +WRAP_PASS(BBVectorize) +WRAP_PASS(LoopVectorize) + +////////////// +// Analyses // +////////////// + +WRAP_PASS(GlobalsModRef) +WRAP_PASS(AliasAnalysisCounter) +WRAP_PASS(AAEval) +WRAP_PASS(NoAA) +WRAP_PASS(BasicAliasAnalysis) +WRAP_PASS(ScalarEvolutionAliasAnalysis) +WRAP_PASS(TypeBasedAliasAnalysis) +WRAP_PASS(ProfileLoader) +WRAP_PASS(ProfileMetadataLoader) +WRAP_PASS(NoProfileInfo) +WRAP_PASS(ProfileEstimator) +WRAP_PASS(ProfileVerifier) +WRAP_PASS(PathProfileLoader) +WRAP_PASS(NoPathProfileInfo) +WRAP_PASS(PathProfileVerifier) +WRAP_PASS(LazyValueInfo) +WRAP_PASS(DependenceAnalysis) +WRAP_PASS(CostModelAnalysis) +WRAP_PASS(InstCount) +WRAP_PASS(RegionInfo) +WRAP_PASS(ModuleDebugInfoPrinter) +WRAP_PASS(Lint) +WRAP_PASS(Verifier) diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index cff448b6a1a..4ee5df28d24 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#include "rustllvm.h" + //===----------------------------------------------------------------------=== // // This file defines alternate interfaces to core functions that are more @@ -15,50 +17,6 @@ // //===----------------------------------------------------------------------=== -#include "llvm/IR/InlineAsm.h" -#include "llvm/IR/LLVMContext.h" -#include "llvm/Linker.h" -#include "llvm/PassManager.h" -#include "llvm/IR/InlineAsm.h" -#include "llvm/IR/LLVMContext.h" -#include "llvm/Analysis/Verifier.h" -#include "llvm/Analysis/Passes.h" -#include "llvm/ADT/Triple.h" -#include "llvm/ADT/DenseSet.h" -#include "llvm/Assembly/Parser.h" -#include "llvm/Assembly/PrintModulePass.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/FormattedStream.h" -#include "llvm/Support/Timer.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Support/TargetSelect.h" -#include "llvm/Support/TargetRegistry.h" -#include "llvm/Support/SourceMgr.h" -#include "llvm/Support/Host.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/DynamicLibrary.h" -#include "llvm/Support/Memory.h" -#include "llvm/ExecutionEngine/ExecutionEngine.h" -#include "llvm/ExecutionEngine/JIT.h" -#include "llvm/ExecutionEngine/JITMemoryManager.h" -#include "llvm/ExecutionEngine/MCJIT.h" -#include "llvm/ExecutionEngine/Interpreter.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetOptions.h" -#include "llvm/Transforms/Scalar.h" -#include "llvm/Transforms/IPO.h" -#include "llvm-c/Core.h" -#include "llvm-c/BitReader.h" -#include "llvm-c/Object.h" - -// Used by RustMCJITMemoryManager::getPointerToNamedFunction() -// to get around glibc issues. See the function for more information. -#ifdef __linux__ -#include -#include -#include -#endif - using namespace llvm; using namespace llvm::sys; diff --git a/src/rustllvm/rustllvm.def.in b/src/rustllvm/rustllvm.def.in index dd5dc7102d1..7e3c60cdd5f 100644 --- a/src/rustllvm/rustllvm.def.in +++ b/src/rustllvm/rustllvm.def.in @@ -584,3 +584,105 @@ LLVMConstNamedStruct LLVMStructCreateNamed LLVMStructSetBody LLVMInlineAsm +LLVMAddPass + +LLVMCreateStripSymbolsPass +LLVMCreateStripNonDebugSymbolsPass +LLVMCreateStripDebugDeclarePass +LLVMCreateStripDeadDebugInfoPass +LLVMCreateConstantMergePass +LLVMCreateGlobalOptimizerPass +LLVMCreateGlobalDCEPass +LLVMCreateAlwaysInlinerPass +LLVMCreatePruneEHPass +LLVMCreateInternalizePass +LLVMCreateDeadArgEliminationPass +LLVMCreateDeadArgHackingPass +LLVMCreateArgumentPromotionPass +LLVMCreateIPConstantPropagationPass +LLVMCreateIPSCCPPass +LLVMCreateLoopExtractorPass +LLVMCreateSingleLoopExtractorPass +LLVMCreateBlockExtractorPass +LLVMCreateStripDeadPrototypesPass +LLVMCreateFunctionAttrsPass +LLVMCreateMergeFunctionsPass +LLVMCreatePartialInliningPass +LLVMCreateMetaRenamerPass +LLVMCreateBarrierNoopPass +LLVMCreateFunctionInliningPass +LLVMCreateEdgeProfilerPass +LLVMCreateOptimalEdgeProfilerPass +LLVMCreatePathProfilerPass +LLVMCreateGCOVProfilerPass +LLVMCreateBoundsCheckingPass +LLVMCreateConstantPropagationPass +LLVMCreateSCCPPass +LLVMCreateDeadInstEliminationPass +LLVMCreateDeadCodeEliminationPass +LLVMCreateDeadStoreEliminationPass +LLVMCreateAggressiveDCEPass +LLVMCreateSROAPass +LLVMCreateScalarReplAggregatesPass +LLVMCreateIndVarSimplifyPass +LLVMCreateInstructionCombiningPass +LLVMCreateLICMPass +LLVMCreateLoopStrengthReducePass +LLVMCreateGlobalMergePass +LLVMCreateLoopUnswitchPass +LLVMCreateLoopInstSimplifyPass +LLVMCreateLoopUnrollPass +LLVMCreateLoopRotatePass +LLVMCreateLoopIdiomPass +LLVMCreatePromoteMemoryToRegisterPass +LLVMCreateDemoteRegisterToMemoryPass +LLVMCreateReassociatePass +LLVMCreateJumpThreadingPass +LLVMCreateCFGSimplificationPass +LLVMCreateBreakCriticalEdgesPass +LLVMCreateLoopSimplifyPass +LLVMCreateTailCallEliminationPass +LLVMCreateLowerSwitchPass +LLVMCreateLowerInvokePass +LLVMCreateBlockPlacementPass +LLVMCreateLCSSAPass +LLVMCreateEarlyCSEPass +LLVMCreateGVNPass +LLVMCreateMemCpyOptPass +LLVMCreateLoopDeletionPass +LLVMCreateSimplifyLibCallsPass +LLVMCreateCodeGenPreparePass +LLVMCreateInstructionNamerPass +LLVMCreateSinkingPass +LLVMCreateLowerAtomicPass +LLVMCreateCorrelatedValuePropagationPass +LLVMCreateInstructionSimplifierPass +LLVMCreateLowerExpectIntrinsicPass +LLVMCreateBBVectorizePass +LLVMCreateLoopVectorizePass +LLVMCreateGlobalsModRefPass +LLVMCreateAliasAnalysisCounterPass +LLVMCreateAAEvalPass +LLVMCreateNoAAPass +LLVMCreateBasicAliasAnalysisPass +LLVMCreateScalarEvolutionAliasAnalysisPass +LLVMCreateTypeBasedAliasAnalysisPass +LLVMCreateProfileLoaderPass +LLVMCreateProfileMetadataLoaderPass +LLVMCreateNoProfileInfoPass +LLVMCreateProfileEstimatorPass +LLVMCreateProfileVerifierPass +LLVMCreatePathProfileLoaderPass +LLVMCreateNoPathProfileInfoPass +LLVMCreatePathProfileVerifierPass +LLVMCreateDSAAPass +LLVMCreateDSOptPass +LLVMCreateSteensgaardPass +LLVMCreateLazyValueInfoPass +LLVMCreateDependenceAnalysisPass +LLVMCreateCostModelAnalysisPass +LLVMCreateInstCountPass +LLVMCreateRegionInfoPass +LLVMCreateModuleDebugInfoPrinterPass +LLVMCreateLintPass +LLVMCreateVerifierPass diff --git a/src/rustllvm/rustllvm.h b/src/rustllvm/rustllvm.h new file mode 100644 index 00000000000..1c8842f7b4a --- /dev/null +++ b/src/rustllvm/rustllvm.h @@ -0,0 +1,57 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#include "llvm/IR/InlineAsm.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/Linker.h" +#include "llvm/PassManager.h" +#include "llvm/IR/InlineAsm.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/Analysis/Verifier.h" +#include "llvm/Analysis/Passes.h" +#include "llvm/Analysis/Lint.h" +#include "llvm/ADT/Triple.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/Assembly/Parser.h" +#include "llvm/Assembly/PrintModulePass.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/FormattedStream.h" +#include "llvm/Support/Timer.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/Host.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/DynamicLibrary.h" +#include "llvm/Support/Memory.h" +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/ExecutionEngine/JIT.h" +#include "llvm/ExecutionEngine/JITMemoryManager.h" +#include "llvm/ExecutionEngine/MCJIT.h" +#include "llvm/ExecutionEngine/Interpreter.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/IPO.h" +#include "llvm/Transforms/Instrumentation.h" +#include "llvm/Transforms/Vectorize.h" +#include "llvm-c/Core.h" +#include "llvm-c/BitReader.h" +#include "llvm-c/Object.h" + +// Used by RustMCJITMemoryManager::getPointerToNamedFunction() +// to get around glibc issues. See the function for more information. +#ifdef __linux__ +#include +#include +#include +#endif +