about summary refs log tree commit diff
path: root/src/librustc_mir/transform
AgeCommit message (Collapse)AuthorLines
2019-07-06normalize use of backticks/lowercase in compiler messages for librustc_mirSamy Kacimi-13/+13
https://github.com/rust-lang/rust/issues/60532 r? @alexreg
2019-07-04rename hir::map::local_def_id_from_hir_id to local_def_idljedrz-1/+1
2019-07-04Rollup merge of #62173 - RalfJung:miri-interp, r=oli-obkMazdak Farrokhzad-3/+3
rename InterpretCx -> InterpCx That's more consistent with InterpResult and InterpError. r? @oli-obk
2019-07-03Remove needless lifetimesJeremy Stucki-22/+22
2019-07-02Add a query to get the `promoted`s for a `mir::Body`Wesley Wiser-0/+7
This is a builidng block toward removing a lot of duplicated code between miri and the cosnt-propagator pass. See this thread for more info: https://rust-lang.zulipchat.com/#narrow/stream/189540-t-compiler.2Fwg-mir-opt/topic/Using.20.60InterpCx.60.20more/near/169030661
2019-07-02Auto merge of #61922 - tmandry:moar-generator-optimization, r=matthewjasperbors-30/+40
Don't store locals that have been moved from in generators This avoids reserving storage in generators for locals that are moved out of (and not re-initialized) prior to yield points. Fixes #59123. This adds a new dataflow analysis, `RequiresStorage`, to determine whether the storage of a local can be destroyed without being observed by the program. The rules are: 1. StorageLive(x) => mark x live 2. StorageDead(x) => mark x dead 3. If a local is moved from, _and has never had its address taken_, mark it dead 4. If (any part of) a local is initialized, mark it live' This is used to determine whether to save a local in the generator object at all, as well as which locals can be overlapped in the generator layout. Here's the size in bytes of all testcases included in the change, before and after the change: async fn test |Size before |Size after -----------------|------------|---------- single | 1028 | 1028 single_with_noop | 2056 | 1032 joined | 5132 | 3084 joined_with_noop | 8208 | 3084 generator test |Size before |Size after ----------------------------|------------|---------- move_before_yield | 1028 | 1028 move_before_yield_with_noop | 2056 | 1032 overlap_move_points | 3080 | 2056 ## Future work Note that there is a possible extension to this optimization, which modifies rule 3 to read: "If a local is moved from, _**and either has never had its address taken, or is Freeze and has never been mutably borrowed**_, mark it dead." This was discussed at length in #59123 and then #61849. Because this would cause some behavior to be UB which was not UB before, it's a step that needs to be taken carefully. A more immediate priority for me is inlining `std::mem::size_of_val(&x)` so it becomes apparent that the address of `x` is not taken. This way, using `size_of_val` to look at the size of your inner futures does not affect the size of your outer future. cc @cramertj @eddyb @Matthias247 @nikomatsakis @RalfJung @Zoxc
2019-07-02rustc_mir: treat DropAndReplace as Drop + Assign in qualify_consts.Eduard-Mihai Burtescu-3/+20
2019-07-01Clean up extra lifetime, add assertionsTyler Mandry-11/+8
2019-06-28Use RequiresStorage to determine which locals can overlapTyler Mandry-12/+15
2019-06-28Remove Clone requirementTyler Mandry-1/+2
2019-06-27rename InterpretCx -> InterpCxRalf Jung-3/+3
That's more consistent with InterpResult and InterpError.
2019-06-25Add RequiresStorage pass to decide which locals to save in generatorsTyler Mandry-25/+34
This avoids reserving storage in generators for locals that are moved out of (and not re-initialized) prior to yield points.
2019-06-25Make FlowAtLocation support borrowing flow dataTyler Mandry-3/+3
2019-06-25Rollup merge of #62096 - spastorino:impl-place-from, r=oli-obk,CentrilMazdak Farrokhzad-23/+23
Implement From<Local> for Place and PlaceBase r? @oli-obk More tiny bits of Place 2.0 moved into master
2019-06-25Rollup merge of #62091 - ljedrz:hiridification_almost_there, r=ZoxcMazdak Farrokhzad-2/+2
HirIdification: almost there I'm beginning to run out of stuff to HirIdify :wink:. This time I targeted mainly `hir::map::{find, get_parent_node}`, but a few other bits got changed too. r? @Zoxc
2019-06-25Implement From<Local> for Place and PlaceBaseSantiago Pastorino-23/+23
2019-06-24Auto merge of #61787 - ecstatic-morse:dataflow-split-block-sets, r=pnkfelixbors-19/+13
rustc_mir: Hide initial block state when defining transfer functions This PR addresses [this FIXME](https://github.com/rust-lang/rust/blob/2887008e0ce0824be4e0e9562c22ea397b165c97/src/librustc_mir/dataflow/mod.rs#L594-L596). This makes `sets.on_entry` inaccessible in `{before_,}{statement,terminator}_effect`. This field was meant to allow implementors of `BitDenotation` to access the initial state for each block (optionally with the effect of all previous statements applied via `accumulates_intrablock_state`) while defining transfer functions. However, the ability to set the initial value for the entry set of each basic block (except for START_BLOCK) no longer exists. As a result, this functionality is mostly useless, and when it *was* used it was used erroneously (see #62007). Since `on_entry` is now useless, we can also remove `BlockSets`, which held the `gen`, `kill`, and `on_entry` bitvectors and replace it with a `GenKill` struct. Variables of this type are called `trans` since they represent a transfer function. `GenKill`s are stored contiguously in `AllSets`, which reduces the number of bounds checks and may improve cache performance: one is almost never accessed without the other. Replacing `BlockSets` with `GenKill` allows us to define some new helper functions which streamline dataflow iteration and the dataflow-at-location APIs. Notably, `state_for_location` used a subtle side-effect of the `kill`/`kill_all` setters to apply the transfer function, and could be incorrect if a transfer function depended on effects of previous statements in the block on `gen_set`. Additionally, this PR merges `BitSetOperator` and `InitialFlow` into one trait. Since the value of `InitialFlow` defines the semantics of the `join` operation, there's no reason to have seperate traits for each. We can add a default impl of `join` which branches based on `BOTTOM_VALUE`. This should get optimized away.
2019-06-24HIR: rename find_by_hir_id to findljedrz-1/+1
2019-06-24Auto merge of #62012 - wesleywiser:const_prop_use_ecx, r=oli-obkbors-21/+107
Use ecx for const-prop local storage r? @oli-obk
2019-06-24HIR: rename get_parent_node_by_hir_id to get_parent_nodeljedrz-1/+1
2019-06-22rustc_mir: don't pass `on_entry` when building transfer functions.Dylan MacKenzie-19/+13
This commit makes `sets.on_entry` inaccessible in `{before_,}{statement,terminator}_effect`. This field was meant to allow implementors of `BitDenotation` to access the initial state for each block (optionally with the effect of all previous statements applied via `accumulates_intrablock_state`) while defining transfer functions. However, the ability to set the initial value for the entry set of each basic block (except for START_BLOCK) no longer exists. As a result, this functionality is mostly useless, and when it *was* used it was used erroneously (see #62007). Since `on_entry` is now useless, we can also remove `BlockSets`, which held the `gen`, `kill`, and `on_entry` bitvectors and replace it with a `GenKill` struct. Variables of this type are called `trans` since they represent a transfer function. `GenKill`s are stored contiguously in `AllSets`, which reduces the number of bounds checks and may improve cache performance: one is almost never accessed without the other. Replacing `BlockSets` with `GenKill` allows us to define some new helper functions which streamline dataflow iteration and the dataflow-at-location APIs. Notably, `state_for_location` used a subtle side-effect of the `kill`/`kill_all` setters to apply the transfer function, and could be incorrect if a transfer function depended on effects of previous statements in the block on `gen_set`.
2019-06-21Fix nitsWesley Wiser-17/+35
2019-06-20[const-prop] Move local storage into a `Frame` on `InterpCx`Wesley Wiser-19/+79
This moves us closer to just using `InterpCx` for interpretation.
2019-06-20[const-prop] Introduce getter/setter functionsWesley Wiser-4/+12
2019-06-20rename hir::map::get_by_hir_id to getljedrz-1/+1
2019-06-19Fix rebase falloutOliver Scherer-1/+1
2019-06-19Make interning explicitly care about types and the mutability of memoryOliver Scherer-21/+28
2019-06-18Run `rustfmt --file-lines ...` for changes from previous commits.Eduard-Mihai Burtescu-1/+2
2019-06-18rustc: remove 'x: 'y bounds (except from comments/strings).Eduard-Mihai Burtescu-12/+12
2019-06-17remove _by_hir_id if there is no NodeId counterpartljedrz-7/+7
2019-06-16Auto merge of #60730 - matthewjasper:optimize-false-edges, r=pnkfelixbors-4/+9
Optimize matches Attempt to fix or improve #60571 This is breaking some diagnostics because the MIR for match arms isn't in source order any more. cc @centril
2019-06-14Run `rustfmt --file-lines ...` for changes from previous commits.Eduard-Mihai Burtescu-101/+17
2019-06-14Unify all uses of 'gcx and 'tcx.Eduard-Mihai Burtescu-97/+97
2019-06-13Create fewer basic blocks in match MIR loweringMatthew Jasper-0/+7
2019-06-12Make `FalseEdges` always have two targetsMatthew Jasper-4/+2
We never have more than one imaginary target, so we have no reason for a `Vec`
2019-06-12Run `rustfmt --file-lines ...` for changes from previous commits.Eduard-Mihai Burtescu-242/+249
2019-06-12rustc: remove some unnecessary lifetimes in -> TyCtxt methods.Eduard-Mihai Burtescu-1/+1
2019-06-12rustc: replace `TyCtxt<'tcx, 'gcx, 'tcx>` with `TyCtxt<'gcx, 'tcx>`.Eduard-Mihai Burtescu-92/+92
2019-06-12Fix fallout from `deny(unused_lifetimes)`.Eduard-Mihai Burtescu-61/+61
2019-06-12rustc: replace `TyCtxt<'a, 'gcx, 'tcx>` with `TyCtxt<'tcx, 'gcx, 'tcx>`.Eduard-Mihai Burtescu-112/+112
2019-06-12Auto merge of #60187 - tmandry:generator-optimization, r=eddybbors-43/+226
Generator optimization: Overlap locals that never have storage live at the same time The specific goal of this optimization is to optimize async fns which use `await!`. Notably, `await!` has an enclosing scope around the futures it awaits ([definition](https://github.com/rust-lang/rust/blob/08bfe16129b0621bc90184f8704523d4929695ef/src/libstd/macros.rs#L365-L381)), which we rely on to implement the optimization. More generally, the optimization allows overlapping the storage of some locals which are never storage-live at the same time. **We care about storage-liveness when computing the layout, because knowing a field is `StorageDead` is the only way to prove it will not be accessed, either directly or through a reference.** To determine whether we can overlap two locals in the generator layout, we look at whether they might *both* be `StorageLive` at any point in the MIR. We use the `MaybeStorageLive` dataflow analysis for this. We iterate over every location in the MIR, and build a bitset for each local of the locals it might potentially conflict with. Next, we assign every saved local to one or more variants. The variants correspond to suspension points, and we include the set of locals live across a given suspension point in the variant. (Note that we use liveness instead of storage-liveness here; this ensures that the local has actually been initialized in each variant it has been included in. If the local is not live across a suspension point, then it doesn't need to be included in that variant.). It's important to note that the variants are a "view" into our layout. For the layout computation, we use a simplified approach. 1. Start with the set of locals assigned to only one variant. The rest are disqualified. 2. For each pair of locals which may conflict *and are not assigned to the same variant*, we pick one local to disqualify from overlapping. Disqualified locals go into a non-overlapping "prefix" at the beginning of our layout. This means they always have space reserved for them. All the locals that are allowed to overlap in each variant are then laid out after this prefix, in the "overlap zone". So, if A and B were disqualified, and X, Y, and Z were all eligible for overlap, our generator might look something like this: You can think of a generator as an enum, where some fields are shared between variants. e.g. ```rust enum Generator { Unresumed, Poisoned, Returned, Suspend0(A, B, X), Suspend1(B), Suspend2(A, Y, Z), } ``` where every mention of `A` and `B` refer to the same field, which does not move when changing variants. Note that `A` and `B` would automatically be sent to the prefix in this example. Assuming that `X` is never `StorageLive` at the same time as either `Y` or `Z`, it would be allowed to overlap with them. Note that if two locals (`Y` and `Z` in this case) are assigned to the same variant in our generator, their memory would never overlap in the layout. Thus they can both be eligible for the overlapping section, even if they are storage-live at the same time. --- Depends on: - [x] #59897 Multi-variant layouts for generators - [x] #60840 Preserve local scopes in generator MIR - [x] #61373 Emit StorageDead along unwind paths for generators Before merging: - [x] ~Wrap the types of all generator fields in `MaybeUninitialized` in layout::ty::field~ (opened #60889) - [x] Make PR description more complete (e.g. explain why storage liveness is important and why we have to check every location) - [x] Clean up TODO - [x] Fix the layout code to enforce that the same field never moves around in the generator - [x] Add tests for async/await - [x] ~Reduce # bits we store by half, since the conflict relation is symmetric~ (note: decided not to do this, for simplicity) - [x] Store liveness information for each yield point in our `GeneratorLayout`, that way we can emit more useful debuginfo AND tell miri which fields are definitely initialized for a given variant (see discussion at https://github.com/rust-lang/rust/pull/59897#issuecomment-489468627)
2019-06-11Auto merge of #61741 - Centril:rollup-fgro5kz, r=Centrilbors-1/+1
Rollup of 11 pull requests Successful merges: - #61518 (Add loops to doc list of things not stable in const fn) - #61526 (move some tests into subfolders) - #61550 (Windows 10 SDK is also required now.) - #61606 (Remove some legacy proc macro flavors) - #61652 (Mention slice patterns in array) - #61686 (librustc_errors: Add some more documentation) - #61698 (typeck: Fix const generic in repeat param ICE.) - #61707 (Azure: retry failed awscli installs) - #61715 (make sure make_ascii_lowercase actually leaves upper-case non-ASCII characters alone) - #61724 (core: use memcmp optimization for 128 bit integer slices) - #61726 (Use `for_each` in `Iterator::partition`) Failed merges: r? @ghost
2019-06-11More review fixesTyler Mandry-3/+4
2019-06-11Rollup merge of #61518 - czipperz:const-fn-doc-disallow-loops, r=CentrilMazdak Farrokhzad-1/+1
Add loops to doc list of things not stable in const fn Closes #61508
2019-06-11rustc_mir: deny(unused_lifetimes).Eduard-Mihai Burtescu-4/+4
2019-06-10Use DataflowResultsConsumer and remove dataflow::for_each_locationTyler Mandry-37/+89
2019-06-10Use BitMatrix for storage conflictsTyler Mandry-22/+24
2019-06-10Small review fixesTyler Mandry-30/+48
2019-06-10Only include generator saved locals in the variants that need themTyler Mandry-34/+48
2019-06-10Collect conflict information in GeneratorLayoutTyler Mandry-4/+100