Skip to content

rustc: Update LLVM #26025

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 17, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion src/librustc_llvm/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -976,6 +976,9 @@ extern {
pub fn LLVMAddDereferenceableAttr(Fn: ValueRef, index: c_uint, bytes: uint64_t);
pub fn LLVMAddFunctionAttribute(Fn: ValueRef, index: c_uint, PA: uint64_t);
pub fn LLVMAddFunctionAttrString(Fn: ValueRef, index: c_uint, Name: *const c_char);
pub fn LLVMAddFunctionAttrStringValue(Fn: ValueRef, index: c_uint,
Name: *const c_char,
Value: *const c_char);
pub fn LLVMRemoveFunctionAttrString(Fn: ValueRef, index: c_uint, Name: *const c_char);
pub fn LLVMGetFunctionAttr(Fn: ValueRef) -> c_ulonglong;
pub fn LLVMRemoveFunctionAttr(Fn: ValueRef, val: c_ulonglong);
Expand Down Expand Up @@ -1920,6 +1923,7 @@ extern {
VarInfo: DIVariable,
AddrOps: *const i64,
AddrOpsCount: c_uint,
DL: ValueRef,
InsertAtEnd: BasicBlockRef)
-> ValueRef;

Expand All @@ -1928,6 +1932,7 @@ extern {
VarInfo: DIVariable,
AddrOps: *const i64,
AddrOpsCount: c_uint,
DL: ValueRef,
InsertBefore: ValueRef)
-> ValueRef;

Expand Down Expand Up @@ -2035,7 +2040,6 @@ extern {
Level: CodeGenOptLevel,
EnableSegstk: bool,
UseSoftFP: bool,
NoFramePointerElim: bool,
PositionIndependentExecutable: bool,
FunctionSections: bool,
DataSections: bool) -> TargetMachineRef;
Expand All @@ -2046,6 +2050,11 @@ extern {
pub fn LLVMRustAddBuilderLibraryInfo(PMB: PassManagerBuilderRef,
M: ModuleRef,
DisableSimplifyLibCalls: bool);
pub fn LLVMRustConfigurePassManagerBuilder(PMB: PassManagerBuilderRef,
OptLevel: CodeGenOptLevel,
MergeFunctions: bool,
SLPVectorize: bool,
LoopVectorize: bool);
pub fn LLVMRustAddLibraryInfo(PM: PassManagerRef, M: ModuleRef,
DisableSimplifyLibCalls: bool);
pub fn LLVMRustRunFunctionPassManager(PM: PassManagerRef, M: ModuleRef);
Expand Down Expand Up @@ -2116,6 +2125,12 @@ extern {
pub fn LLVMWriteSMDiagnosticToString(d: SMDiagnosticRef, s: RustStringRef);
}

// LLVM requires symbols from this library, but apparently they're not printed
// during llvm-config?
#[cfg(windows)]
#[link(name = "ole32")]
extern {}

pub fn SetInstructionCallConv(instr: ValueRef, cc: CallConv) {
unsafe {
LLVMSetInstructionCallConv(instr, cc as c_uint);
Expand Down
91 changes: 47 additions & 44 deletions src/librustc_trans/back/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

use back::lto;
use back::link::{get_cc_prog, remove};
use session::config::{OutputFilenames, NoDebugInfo, Passes, SomePasses, AllPasses};
use session::config::{OutputFilenames, Passes, SomePasses, AllPasses};
use session::Session;
use session::config;
use llvm;
Expand Down Expand Up @@ -188,10 +188,6 @@ fn create_target_machine(sess: &Session) -> TargetMachineRef {
let opt_level = get_llvm_opt_level(sess.opts.optimize);
let use_softfp = sess.opts.cg.soft_float;

// FIXME: #11906: Omitting frame pointers breaks retrieving the value of a parameter.
let no_fp_elim = (sess.opts.debuginfo != NoDebugInfo) ||
!sess.target.target.options.eliminate_frame_pointer;

let any_library = sess.crate_types.borrow().iter().any(|ty| {
*ty != config::CrateTypeExecutable
});
Expand Down Expand Up @@ -237,7 +233,6 @@ fn create_target_machine(sess: &Session) -> TargetMachineRef {
opt_level,
true /* EnableSegstk */,
use_softfp,
no_fp_elim,
!any_library && reloc_model == llvm::RelocPIC,
ffunction_sections,
fdata_sections,
Expand Down Expand Up @@ -279,6 +274,9 @@ struct ModuleConfig {
no_prepopulate_passes: bool,
no_builtins: bool,
time_passes: bool,
vectorize_loop: bool,
vectorize_slp: bool,
merge_functions: bool,
}

unsafe impl Send for ModuleConfig { }
Expand All @@ -301,6 +299,9 @@ impl ModuleConfig {
no_prepopulate_passes: false,
no_builtins: false,
time_passes: false,
vectorize_loop: false,
vectorize_slp: false,
merge_functions: false,
}
}

Expand All @@ -309,6 +310,18 @@ impl ModuleConfig {
self.no_prepopulate_passes = sess.opts.cg.no_prepopulate_passes;
self.no_builtins = trans.no_builtins;
self.time_passes = sess.time_passes();

// Copy what clang does by turning on loop vectorization at O2 and
// slp vectorization at O3. Otherwise configure other optimization aspects
// of this pass manager builder.
self.vectorize_loop = !sess.opts.cg.no_vectorize_loops &&
(sess.opts.optimize == config::Default ||
sess.opts.optimize == config::Aggressive);
self.vectorize_slp = !sess.opts.cg.no_vectorize_slp &&
sess.opts.optimize == config::Aggressive;

self.merge_functions = sess.opts.optimize == config::Default ||
sess.opts.optimize == config::Aggressive;
}
}

Expand Down Expand Up @@ -448,27 +461,26 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
let pass = CString::new(pass).unwrap();
llvm::LLVMRustAddPass(fpm, pass.as_ptr())
};
if !config.no_verify { assert!(addpass("verify")); }

if !config.no_verify { assert!(addpass("verify")); }
if !config.no_prepopulate_passes {
llvm::LLVMRustAddAnalysisPasses(tm, fpm, llmod);
llvm::LLVMRustAddAnalysisPasses(tm, mpm, llmod);
populate_llvm_passes(fpm, mpm, llmod, opt_level,
config.no_builtins);
populate_llvm_passes(fpm, mpm, llmod, opt_level, &config);
}

for pass in &config.passes {
let pass = CString::new(pass.clone()).unwrap();
if !llvm::LLVMRustAddPass(mpm, pass.as_ptr()) {
cgcx.handler.warn(&format!("unknown pass {:?}, ignoring", pass));
if !addpass(pass) {
cgcx.handler.warn(&format!("unknown pass `{}`, ignoring",
pass));
}
}

for pass in &cgcx.plugin_passes {
let pass = CString::new(pass.clone()).unwrap();
if !llvm::LLVMRustAddPass(mpm, pass.as_ptr()) {
cgcx.handler.err(&format!("a plugin asked for LLVM pass {:?} but LLVM \
does not recognize it", pass));
if !addpass(pass) {
cgcx.handler.err(&format!("a plugin asked for LLVM pass \
`{}` but LLVM does not \
recognize it", pass));
}
}

Expand Down Expand Up @@ -520,7 +532,6 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
llvm::LLVMRustAddAnalysisPasses(tm, cpm, llmod);
llvm::LLVMRustAddLibraryInfo(cpm, llmod, no_builtins);
f(cpm);
llvm::LLVMDisposePassManager(cpm);
}

if config.emit_bc {
Expand All @@ -537,13 +548,15 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
let out = path2cstr(&out);
with_codegen(tm, llmod, config.no_builtins, |cpm| {
llvm::LLVMRustPrintModule(cpm, llmod, out.as_ptr());
llvm::LLVMDisposePassManager(cpm);
})
}

if config.emit_asm {
let path = output_names.with_extension(&format!("{}.s", name_extra));
with_codegen(tm, llmod, config.no_builtins, |cpm| {
write_output_file(cgcx.handler, tm, cpm, llmod, &path, llvm::AssemblyFileType);
write_output_file(cgcx.handler, tm, cpm, llmod, &path,
llvm::AssemblyFileType);
});
}

Expand Down Expand Up @@ -1008,25 +1021,16 @@ unsafe fn configure_llvm(sess: &Session) {
use std::sync::Once;
static INIT: Once = Once::new();

// Copy what clang does by turning on loop vectorization at O2 and
// slp vectorization at O3
let vectorize_loop = !sess.opts.cg.no_vectorize_loops &&
(sess.opts.optimize == config::Default ||
sess.opts.optimize == config::Aggressive);
let vectorize_slp = !sess.opts.cg.no_vectorize_slp &&
sess.opts.optimize == config::Aggressive;

let mut llvm_c_strs = Vec::new();
let mut llvm_args = Vec::new();

{
let mut add = |arg: &str| {
let s = CString::new(arg).unwrap();
llvm_args.push(s.as_ptr());
llvm_c_strs.push(s);
};
add("rustc"); // fake program name
if vectorize_loop { add("-vectorize-loops"); }
if vectorize_slp { add("-vectorize-slp"); }
if sess.time_llvm_passes() { add("-time-passes"); }
if sess.print_llvm_passes() { add("-debug-pass=Structure"); }

Expand Down Expand Up @@ -1084,41 +1088,40 @@ unsafe fn populate_llvm_passes(fpm: llvm::PassManagerRef,
mpm: llvm::PassManagerRef,
llmod: ModuleRef,
opt: llvm::CodeGenOptLevel,
no_builtins: bool) {
config: &ModuleConfig) {
// Create the PassManagerBuilder for LLVM. We configure it with
// reasonable defaults and prepare it to actually populate the pass
// manager.
let builder = llvm::LLVMPassManagerBuilderCreate();

llvm::LLVMRustConfigurePassManagerBuilder(builder, opt,
config.merge_functions,
config.vectorize_slp,
config.vectorize_loop);

llvm::LLVMRustAddBuilderLibraryInfo(builder, llmod, config.no_builtins);

// Here we match what clang does (kinda). For O0 we only inline
// always-inline functions (but don't add lifetime intrinsics), at O1 we
// inline with lifetime intrinsics, and O2+ we add an inliner with a
// thresholds copied from clang.
match opt {
llvm::CodeGenLevelNone => {
// Don't add lifetime intrinsics at O0
llvm::LLVMRustAddAlwaysInlinePass(builder, false);
}
llvm::CodeGenLevelLess => {
llvm::LLVMRustAddAlwaysInlinePass(builder, true);
}
// numeric values copied from clang
llvm::CodeGenLevelDefault => {
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder,
225);
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 225);
}
llvm::CodeGenLevelAggressive => {
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder,
275);
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 275);
}
}
llvm::LLVMPassManagerBuilderSetOptLevel(builder, opt as c_uint);
llvm::LLVMRustAddBuilderLibraryInfo(builder, llmod, no_builtins);

// Use the builder to populate the function/module pass managers.
llvm::LLVMPassManagerBuilderPopulateFunctionPassManager(builder, fpm);
llvm::LLVMPassManagerBuilderPopulateModulePassManager(builder, mpm);
llvm::LLVMPassManagerBuilderDispose(builder);

match opt {
llvm::CodeGenLevelDefault | llvm::CodeGenLevelAggressive => {
llvm::LLVMRustAddPass(mpm, "mergefunc\0".as_ptr() as *const _);
}
_ => {}
};
}
21 changes: 18 additions & 3 deletions src/librustc_trans/trans/adt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1029,11 +1029,26 @@ pub fn fold_variants<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
}
General(ity, ref cases, _) => {
let ccx = bcx.ccx();
let unr_cx = fcx.new_temp_block("enum-variant-iter-unr");
Unreachable(unr_cx);

// See the comments in trans/base.rs for more information (inside
// iter_structural_ty), but the gist here is that if the enum's
// discriminant is *not* in the range that we're expecting (in which
// case we'll take the fall-through branch on the switch
// instruction) then we can't just optimize this to an Unreachable
// block.
//
// Currently we still have filling drop, so this means that the drop
// glue for enums may be called when the enum has been paved over
// with the "I've been dropped" value. In this case the default
// branch of the switch instruction will actually be taken at
// runtime, so the basic block isn't actually unreachable, so we
// need to make it do something with defined behavior. In this case
// we just return early from the function.
let ret_void_cx = fcx.new_temp_block("enum-variant-iter-ret-void");
RetVoid(ret_void_cx, DebugLoc::None);

let discr_val = trans_get_discr(bcx, r, value, None);
let llswitch = Switch(bcx, discr_val, unr_cx.llbb, cases.len());
let llswitch = Switch(bcx, discr_val, ret_void_cx.llbb, cases.len());
let bcx_next = fcx.new_temp_block("enum-variant-iter-next");

for (discr, case) in cases.iter().enumerate() {
Expand Down
15 changes: 15 additions & 0 deletions src/librustc_trans/trans/attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use libc::{c_uint, c_ulonglong};
use llvm::{self, ValueRef, AttrHelper};
use middle::ty::{self, ClosureTyper};
use session::config::NoDebugInfo;
use syntax::abi;
use syntax::ast;
pub use syntax::attr::InlineAttr;
Expand Down Expand Up @@ -106,6 +107,20 @@ pub fn from_fn_attrs(ccx: &CrateContext, attrs: &[ast::Attribute], llfn: ValueRe
use syntax::attr::*;
inline(llfn, find_inline_attr(Some(ccx.sess().diagnostic()), attrs));

// FIXME: #11906: Omitting frame pointers breaks retrieving the value of a
// parameter.
let no_fp_elim = (ccx.sess().opts.debuginfo != NoDebugInfo) ||
!ccx.sess().target.target.options.eliminate_frame_pointer;
if no_fp_elim {
unsafe {
let attr = "no-frame-pointer-elim\0".as_ptr() as *const _;
let val = "true\0".as_ptr() as *const _;
llvm::LLVMAddFunctionAttrStringValue(llfn,
llvm::FunctionIndex as c_uint,
attr, val);
}
}

for attr in attrs {
if attr.check_name("no_stack_check") {
split_stack(llfn, false);
Expand Down
20 changes: 17 additions & 3 deletions src/librustc_trans/trans/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -480,9 +480,23 @@ pub fn iter_structural_ty<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>,
}
(_match::Switch, Some(lldiscrim_a)) => {
cx = f(cx, lldiscrim_a, cx.tcx().types.isize);
let unr_cx = fcx.new_temp_block("enum-iter-unr");
Unreachable(unr_cx);
let llswitch = Switch(cx, lldiscrim_a, unr_cx.llbb,

// Create a fall-through basic block for the "else" case of
// the switch instruction we're about to generate. Note that
// we do **not** use an Unreachable instruction here, even
// though most of the time this basic block will never be hit.
//
// When an enum is dropped it's contents are currently
// overwritten to DTOR_DONE, which means the discriminant
// could have changed value to something not within the actual
// range of the discriminant. Currently this function is only
// used for drop glue so in this case we just return quickly
// from the outer function, and any other use case will only
// call this for an already-valid enum in which case the `ret
// void` will never be hit.
let ret_void_cx = fcx.new_temp_block("enum-iter-ret-void");
RetVoid(ret_void_cx, DebugLoc::None);
let llswitch = Switch(cx, lldiscrim_a, ret_void_cx.llbb,
n_variants);
let next_cx = fcx.new_temp_block("enum-iter-next");

Expand Down
2 changes: 1 addition & 1 deletion src/librustc_trans/trans/debuginfo/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1673,7 +1673,7 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
DIB(cx),
containing_scope,
enum_name.as_ptr(),
UNKNOWN_FILE_METADATA,
file_metadata,
UNKNOWN_LINE_NUMBER,
bytes_to_bits(enum_type_size),
bytes_to_bits(enum_type_align),
Expand Down
Loading