-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Implement optimization fuel and re-enable struct field reordering #40377
Changes from 8 commits
63ebf08
4db9c7a
9125999
8b00837
98eb121
0931e20
d821e98
a384f13
e18c59f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -123,6 +123,20 @@ pub struct Session { | |
pub code_stats: RefCell<CodeStats>, | ||
|
||
next_node_id: Cell<ast::NodeId>, | ||
|
||
/// If -zfuel=crate=n is specified, Some(crate). | ||
optimization_fuel_crate: Option<String>, | ||
/// If -zfuel=crate=n is specified, initially set to n. Otherwise 0. | ||
optimization_fuel_limit: Cell<u64>, | ||
/// We're rejecting all further optimizations. | ||
out_of_fuel: Cell<bool>, | ||
|
||
// The next two are public because the driver needs to read them. | ||
|
||
/// If -zprint-fuel=crate, Some(crate). | ||
pub print_fuel_crate: Option<String>, | ||
/// Always set to zero and incremented so that we can print fuel expended by a crate. | ||
pub print_fuel: Cell<u64>, | ||
} | ||
|
||
pub struct PerfStats { | ||
|
@@ -507,6 +521,33 @@ impl Session { | |
println!("Total time spent decoding DefPath tables: {}", | ||
duration_to_secs_str(self.perf_stats.decode_def_path_tables_time.get())); | ||
} | ||
|
||
/// We want to know if we're allowed to do an optimization for crate foo from -z fuel=foo=n. | ||
/// This expends fuel if applicable, and records fuel if applicable. | ||
pub fn consider_optimizing<T: Fn() -> String>(&self, crate_name: &str, msg: T) -> bool { | ||
let mut ret = true; | ||
match self.optimization_fuel_crate { | ||
Some(ref c) if c == crate_name => { | ||
let fuel = self.optimization_fuel_limit.get(); | ||
ret = fuel != 0; | ||
if fuel == 0 && !self.out_of_fuel.get(){ | ||
println!("optimization-fuel-exhausted: {}", msg()); | ||
self.out_of_fuel.set(true); | ||
} | ||
else if fuel > 0{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should be on the previous line and have a space before |
||
self.optimization_fuel_limit.set(fuel-1); | ||
} | ||
} | ||
_ => {} | ||
} | ||
match self.print_fuel_crate { | ||
Some(ref c) if c == crate_name=> { | ||
self.print_fuel.set(self.print_fuel.get()+1); | ||
}, | ||
_ => {} | ||
} | ||
ret | ||
} | ||
} | ||
|
||
pub fn build_session(sopts: config::Options, | ||
|
@@ -602,6 +643,12 @@ pub fn build_session_(sopts: config::Options, | |
} | ||
); | ||
|
||
let optimization_fuel_crate = sopts.debugging_opts.fuel.as_ref().map(|i| i.0.clone()); | ||
let optimization_fuel_limit = Cell::new(sopts.debugging_opts.fuel.as_ref() | ||
.map(|i| i.1).unwrap_or(0)); | ||
let print_fuel_crate = sopts.debugging_opts.print_fuel.clone(); | ||
let print_fuel = Cell::new(0); | ||
|
||
let sess = Session { | ||
dep_graph: dep_graph.clone(), | ||
target: target_cfg, | ||
|
@@ -643,6 +690,11 @@ pub fn build_session_(sopts: config::Options, | |
decode_def_path_tables_time: Cell::new(Duration::from_secs(0)), | ||
}, | ||
code_stats: RefCell::new(CodeStats::new()), | ||
optimization_fuel_crate: optimization_fuel_crate, | ||
optimization_fuel_limit: optimization_fuel_limit, | ||
print_fuel_crate: print_fuel_crate, | ||
print_fuel: print_fuel, | ||
out_of_fuel: Cell::new(false), | ||
}; | ||
|
||
init_llvm(&sess); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -517,6 +517,14 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls { | |
control.make_glob_map = resolve::MakeGlobMap::Yes; | ||
} | ||
|
||
if sess.print_fuel_crate.is_some() { | ||
control.compilation_done.callback = box |state| { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This may be a bad idea, because it could override something else. Not sure though. |
||
let sess = state.session; | ||
println!("Fuel used by {}: {}", | ||
sess.print_fuel_crate.as_ref().unwrap(), | ||
sess.print_fuel.get()); | ||
} | ||
} | ||
control | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,7 +16,7 @@ use llvm; | |
use llvm::{ValueRef}; | ||
use abi::{Abi, FnType}; | ||
use adt; | ||
use mir::lvalue::LvalueRef; | ||
use mir::lvalue::{LvalueRef, Alignment}; | ||
use base::*; | ||
use common::*; | ||
use declare; | ||
|
@@ -36,8 +36,6 @@ use syntax_pos::Span; | |
use std::cmp::Ordering; | ||
use std::iter; | ||
|
||
use mir::lvalue::Alignment; | ||
|
||
fn get_simple_intrinsic(ccx: &CrateContext, name: &str) -> Option<ValueRef> { | ||
let llvm_name = match name { | ||
"sqrtf32" => "llvm.sqrt.f32", | ||
|
@@ -622,7 +620,10 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, | |
|
||
for i in 0..elems.len() { | ||
let val = bcx.extract_value(val, i); | ||
bcx.store(val, bcx.struct_gep(llresult, i), None); | ||
let lval = LvalueRef::new_sized_ty(llresult, ret_ty, | ||
Alignment::AbiAligned); | ||
let (dest, _) = lval.trans_field_ptr(bcx, i); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think you're supposed to pass the second value to |
||
bcx.store(val, dest, None); | ||
} | ||
C_nil(ccx) | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -386,7 +386,7 @@ fn arg_local_refs<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, | |
|
||
let lvalue = LvalueRef::alloca(bcx, arg_ty, &format!("arg{}", arg_index)); | ||
for (i, &tupled_arg_ty) in tupled_arg_tys.iter().enumerate() { | ||
let dst = bcx.struct_gep(lvalue.llval, i); | ||
let (dst, _) = lvalue.trans_field_ptr(bcx, i); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same but here it's less worrying because we know it can't be anything other than a tuple, and those don't get packed or anything like that, and |
||
let arg = &mircx.fn_ty.args[idx]; | ||
idx += 1; | ||
if common::type_is_fat_ptr(bcx.ccx, tupled_arg_ty) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
// 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 <LICENSE-APACHE or | ||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | ||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | ||
// option. This file may not be copied, modified, or distributed | ||
// except according to those terms. | ||
|
||
#![crate_name="foo"] | ||
|
||
use std::mem::size_of; | ||
|
||
// compile-flags: -Z fuel=foo=0 | ||
|
||
struct S1(u8, u16, u8); | ||
struct S2(u8, u16, u8); | ||
|
||
fn main() { | ||
assert_eq!(size_of::<S1>(), 6); | ||
assert_eq!(size_of::<S2>(), 6); | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
// 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 <LICENSE-APACHE or | ||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | ||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | ||
// option. This file may not be copied, modified, or distributed | ||
// except according to those terms. | ||
|
||
#![crate_name="foo"] | ||
|
||
use std::mem::size_of; | ||
|
||
// compile-flags: -Z fuel=foo=1 | ||
|
||
struct S1(u8, u16, u8); | ||
struct S2(u8, u16, u8); | ||
|
||
fn main() { | ||
let optimized = (size_of::<S1>() == 4) as usize | ||
+(size_of::<S2>() == 4) as usize; | ||
assert_eq!(optimized, 1); | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
// Copyright 2016 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 <LICENSE-APACHE or | ||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | ||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | ||
// option. This file may not be copied, modified, or distributed | ||
// except according to those terms. | ||
|
||
#![crate_name="foo"] | ||
#![allow(dead_code)] | ||
|
||
// compile-flags: -Z print-fuel=foo | ||
|
||
struct S1(u8, u16, u8); | ||
struct S2(u8, u16, u8); | ||
struct S3(u8, u16, u8); | ||
|
||
fn main() { | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Fuel used by foo: 3 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing space before
{
.