Skip to content

Rollup of 5 pull requests #36552

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

Closed
wants to merge 10 commits into from
52 changes: 14 additions & 38 deletions src/libcore/iter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -643,7 +643,9 @@ impl<A, B> FusedIterator for Chain<A, B>
pub struct Zip<A, B> {
a: A,
b: B,
spec: <(A, B) as ZipImplData>::Data,
// index and len are only used by the specialized version of zip
index: usize,
len: usize,
}

#[stable(feature = "rust1", since = "1.0.0")]
Expand Down Expand Up @@ -685,17 +687,6 @@ trait ZipImpl<A, B> {
B: DoubleEndedIterator + ExactSizeIterator;
}

// Zip specialization data members
#[doc(hidden)]
trait ZipImplData {
type Data: 'static + Clone + Default + fmt::Debug;
}

#[doc(hidden)]
impl<T> ZipImplData for T {
default type Data = ();
}

// General Zip impl
#[doc(hidden)]
impl<A, B> ZipImpl<A, B> for Zip<A, B>
Expand All @@ -706,7 +697,8 @@ impl<A, B> ZipImpl<A, B> for Zip<A, B>
Zip {
a: a,
b: b,
spec: Default::default(), // unused
index: 0, // unused
len: 0, // unused
}
}

Expand Down Expand Up @@ -759,20 +751,6 @@ impl<A, B> ZipImpl<A, B> for Zip<A, B>
}
}

#[doc(hidden)]
#[derive(Default, Debug, Clone)]
struct ZipImplFields {
index: usize,
len: usize,
}

#[doc(hidden)]
impl<A, B> ZipImplData for (A, B)
where A: TrustedRandomAccess, B: TrustedRandomAccess
{
type Data = ZipImplFields;
}

#[doc(hidden)]
impl<A, B> ZipImpl<A, B> for Zip<A, B>
where A: TrustedRandomAccess, B: TrustedRandomAccess
Expand All @@ -782,18 +760,16 @@ impl<A, B> ZipImpl<A, B> for Zip<A, B>
Zip {
a: a,
b: b,
spec: ZipImplFields {
index: 0,
len: len,
}
index: 0,
len: len,
}
}

#[inline]
fn next(&mut self) -> Option<(A::Item, B::Item)> {
if self.spec.index < self.spec.len {
let i = self.spec.index;
self.spec.index += 1;
if self.index < self.len {
let i = self.index;
self.index += 1;
unsafe {
Some((self.a.get_unchecked(i), self.b.get_unchecked(i)))
}
Expand All @@ -804,7 +780,7 @@ impl<A, B> ZipImpl<A, B> for Zip<A, B>

#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.spec.len - self.spec.index;
let len = self.len - self.index;
(len, Some(len))
}

Expand All @@ -813,9 +789,9 @@ impl<A, B> ZipImpl<A, B> for Zip<A, B>
where A: DoubleEndedIterator + ExactSizeIterator,
B: DoubleEndedIterator + ExactSizeIterator
{
if self.spec.index < self.spec.len {
self.spec.len -= 1;
let i = self.spec.len;
if self.index < self.len {
self.len -= 1;
let i = self.len;
unsafe {
Some((self.a.get_unchecked(i), self.b.get_unchecked(i)))
}
Expand Down
1 change: 0 additions & 1 deletion src/librustc/middle/resolve_lifetime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,6 @@ impl<'a, 'tcx, 'v> Visitor<'v> for LifetimeContext<'a, 'tcx> {

if !self.trait_ref_hack || !trait_ref.bound_lifetimes.is_empty() {
if self.trait_ref_hack {
println!("{:?}", trait_ref.span);
span_err!(self.sess, trait_ref.span, E0316,
"nested quantification of lifetimes");
}
Expand Down
3 changes: 3 additions & 0 deletions src/librustc_driver/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1017,13 +1017,16 @@ pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
passes.push_pass(box mir::transform::no_landing_pads::NoLandingPads);
passes.push_pass(box mir::transform::simplify_cfg::SimplifyCfg::new("no-landing-pads"));

// From here on out, regions are gone.
passes.push_pass(box mir::transform::erase_regions::EraseRegions);

passes.push_pass(box mir::transform::add_call_guards::AddCallGuards);
passes.push_pass(box borrowck::ElaborateDrops);
passes.push_pass(box mir::transform::no_landing_pads::NoLandingPads);
passes.push_pass(box mir::transform::simplify_cfg::SimplifyCfg::new("elaborate-drops"));

// No lifetime analysis based on borrowing can be done from here on out.
passes.push_pass(box mir::transform::instcombine::InstCombine::new());
passes.push_pass(box mir::transform::deaggregator::Deaggregator);

passes.push_pass(box mir::transform::add_call_guards::AddCallGuards);
Expand Down
110 changes: 110 additions & 0 deletions src/librustc_mir/transform/instcombine.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
// 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.

//! Performs various peephole optimizations.

use rustc::mir::repr::{Location, Lvalue, Mir, Operand, ProjectionElem, Rvalue};
use rustc::mir::transform::{MirPass, MirSource, Pass};
use rustc::mir::visit::{MutVisitor, Visitor};
use rustc::ty::TyCtxt;
use rustc::util::nodemap::FnvHashSet;
use std::mem;

pub struct InstCombine {
optimizations: OptimizationList,
}

impl InstCombine {
pub fn new() -> InstCombine {
InstCombine {
optimizations: OptimizationList::default(),
}
}
}

impl Pass for InstCombine {}

impl<'tcx> MirPass<'tcx> for InstCombine {
fn run_pass<'a>(&mut self,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
_: MirSource,
mir: &mut Mir<'tcx>) {
// We only run when optimizing MIR (at any level).
if tcx.sess.opts.debugging_opts.mir_opt_level == Some(0) {
return
}

// First, find optimization opportunities. This is done in a pre-pass to keep the MIR
// read-only so that we can do global analyses on the MIR in the process (e.g.
// `Lvalue::ty()`).
{
let mut optimization_finder = OptimizationFinder::new(mir, tcx);
optimization_finder.visit_mir(mir);
self.optimizations = optimization_finder.optimizations
}

// Then carry out those optimizations.
MutVisitor::visit_mir(&mut *self, mir);
}
}

impl<'tcx> MutVisitor<'tcx> for InstCombine {
fn visit_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>, location: Location) {
if self.optimizations.and_stars.remove(&location) {
debug!("Replacing `&*`: {:?}", rvalue);
let new_lvalue = match *rvalue {
Rvalue::Ref(_, _, Lvalue::Projection(ref mut projection)) => {
mem::replace(&mut projection.base, Lvalue::ReturnPointer)
}
_ => bug!("Detected `&*` but didn't find `&*`!"),
};
*rvalue = Rvalue::Use(Operand::Consume(new_lvalue))
}

self.super_rvalue(rvalue, location)
}
}

/// Finds optimization opportunities on the MIR.
struct OptimizationFinder<'b, 'a, 'tcx:'a+'b> {
mir: &'b Mir<'tcx>,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
optimizations: OptimizationList,
}

impl<'b, 'a, 'tcx:'b> OptimizationFinder<'b, 'a, 'tcx> {
fn new(mir: &'b Mir<'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> OptimizationFinder<'b, 'a, 'tcx> {
OptimizationFinder {
mir: mir,
tcx: tcx,
optimizations: OptimizationList::default(),
}
}
}

impl<'b, 'a, 'tcx> Visitor<'tcx> for OptimizationFinder<'b, 'a, 'tcx> {
fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
if let Rvalue::Ref(_, _, Lvalue::Projection(ref projection)) = *rvalue {
if let ProjectionElem::Deref = projection.elem {
if projection.base.ty(self.mir, self.tcx).to_ty(self.tcx).is_region_ptr() {
self.optimizations.and_stars.insert(location);
}
}
}

self.super_rvalue(rvalue, location)
}
}

#[derive(Default)]
struct OptimizationList {
and_stars: FnvHashSet<Location>,
}

2 changes: 2 additions & 0 deletions src/librustc_mir/transform/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,5 @@ pub mod promote_consts;
pub mod qualify_consts;
pub mod dump_mir;
pub mod deaggregator;
pub mod instcombine;

25 changes: 21 additions & 4 deletions src/librustc_trans/adt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ use syntax::ast;
use syntax::attr;
use syntax::attr::IntType;
use abi::FAT_PTR_ADDR;
use base;
use build::*;
use common::*;
use debuginfo::DebugLoc;
Expand Down Expand Up @@ -963,16 +964,32 @@ pub fn trans_set_discr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>,
Store(bcx, C_null(llptrty), val);
}
}
StructWrappedNullablePointer { nndiscr, ref discrfield, .. } => {
StructWrappedNullablePointer { nndiscr, ref discrfield, ref nonnull, .. } => {
if discr != nndiscr {
let llptrptr = GEPi(bcx, val, &discrfield[..]);
let llptrty = val_ty(llptrptr).element_type();
Store(bcx, C_null(llptrty), llptrptr);
if target_sets_discr_via_memset(bcx) {
// Issue #34427: As workaround for LLVM bug on
// ARM, use memset of 0 on whole struct rather
// than storing null to single target field.
let b = B(bcx);
let llptr = b.pointercast(val, Type::i8(b.ccx).ptr_to());
let fill_byte = C_u8(b.ccx, 0);
let size = C_u64(b.ccx, nonnull.size);
let align = C_u32(b.ccx, nonnull.align);
base::call_memset(&b, llptr, fill_byte, size, align, false);
} else {
let llptrptr = GEPi(bcx, val, &discrfield[..]);
let llptrty = val_ty(llptrptr).element_type();
Store(bcx, C_null(llptrty), llptrptr);
}
}
}
}
}

fn target_sets_discr_via_memset<'blk, 'tcx>(bcx: Block<'blk, 'tcx>) -> bool {
bcx.sess().target.target.arch == "arm" || bcx.sess().target.target.arch == "aarch64"
}

fn assert_discr_in_range(ity: IntType, min: Disr, max: Disr, discr: Disr) {
match ity {
attr::UnsignedInt(_) => {
Expand Down
2 changes: 1 addition & 1 deletion src/libsyntax/parse/attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,8 @@ impl<'a> Parser<'a> {

self.expect(&token::OpenDelim(token::Bracket))?;
let meta_item = self.parse_meta_item()?;
let hi = self.last_span.hi;
self.expect(&token::CloseDelim(token::Bracket))?;
let hi = self.last_span.hi;

(mk_sp(lo, hi), meta_item, style)
}
Expand Down
26 changes: 26 additions & 0 deletions src/test/run-pass/issue-34427.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// 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.

// Issue #34427: On ARM, the code in `foo` at one time was generating
// a machine code instruction of the form: `str r0, [r0, rN]!` (for
// some N), which is not legal because the source register and base
// register cannot be identical in the preindexed form signalled by
// the `!`.
//
// See LLVM bug: https://llvm.org/bugs/show_bug.cgi?id=28809

#[inline(never)]
fn foo(n: usize) -> Vec<Option<(*mut (), &'static ())>> {
(0..n).map(|_| None).collect()
}

fn main() {
let _ = (foo(10), foo(32));
}
17 changes: 17 additions & 0 deletions src/test/run-pass/variance-iterators-in-libcore.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright 2015 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.

#![allow(warnings)]

use std::iter::Zip;

fn zip_covariant<'a, A, B>(iter: Zip<&'static A, &'static B>) -> Zip<&'a A, &'a B> { iter }

fn main() { }
14 changes: 14 additions & 0 deletions src/test/ui/span/issue-36530.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright 2014 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.

#[foo]
mod foo {
#![foo]
}
18 changes: 18 additions & 0 deletions src/test/ui/span/issue-36530.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
error: The attribute `foo` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
--> $DIR/issue-36530.rs:11:1
|
11 | #[foo]
| ^^^^^^
|
= help: add #![feature(custom_attribute)] to the crate attributes to enable

error: The attribute `foo` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
--> $DIR/issue-36530.rs:13:5
|
13 | #![foo]
| ^^^^^^^
|
= help: add #![feature(custom_attribute)] to the crate attributes to enable

error: aborting due to 2 previous errors