Skip to content

Commit 1f25197

Browse files
committed
Auto merge of #147791 - cuviper:beta-next, r=cuviper
[beta] backports - Change int-to-ptr transmute lowering back to inttoptr #147541 - rewrite outlives placeholder constraints to outlives static when handling opaque types #147566 - GVN: Invalidate derefs at loop headers #147607 r? cuviper
2 parents df8b2e4 + 408e09e commit 1f25197

File tree

22 files changed

+345
-59
lines changed

22 files changed

+345
-59
lines changed

compiler/rustc_borrowck/src/handle_placeholders.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,7 @@ pub(crate) fn compute_sccs_applying_placeholder_outlives_constraints<'tcx>(
348348
}
349349
}
350350

351-
fn rewrite_placeholder_outlives<'tcx>(
351+
pub(crate) fn rewrite_placeholder_outlives<'tcx>(
352352
sccs: &Sccs<RegionVid, ConstraintSccIndex>,
353353
annotations: &SccAnnotations<'_, '_, RegionTracker>,
354354
fr_static: RegionVid,

compiler/rustc_borrowck/src/region_infer/opaque_types/member_constraints.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ pub(super) fn apply_member_constraints<'tcx>(
3939
debug!(?member_constraints);
4040
for scc_a in rcx.constraint_sccs.all_sccs() {
4141
debug!(?scc_a);
42-
// Start by adding the region values required by outlives constraints. This
42+
// Start by adding the region values required by outlives constraints. This
4343
// matches how we compute the final region values in `fn compute_regions`.
4444
//
4545
// We need to do this here to get a lower bound when applying member constraints.
@@ -64,6 +64,7 @@ fn apply_member_constraint<'tcx>(
6464
// If the member region lives in a higher universe, we currently choose
6565
// the most conservative option by leaving it unchanged.
6666
if !rcx.max_placeholder_universe_reached(member).is_root() {
67+
debug!("member region reached non root universe, bailing");
6768
return;
6869
}
6970

compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,10 @@ fn collect_defining_uses<'tcx>(
254254
}
255255
} else {
256256
errors.push(DeferredOpaqueTypeError::InvalidOpaqueTypeArgs(err));
257+
debug!(
258+
"collect_defining_uses: InvalidOpaqueTypeArgs for {:?} := {:?}",
259+
non_nll_opaque_type_key, hidden_type
260+
);
257261
}
258262
continue;
259263
}
@@ -277,6 +281,7 @@ fn collect_defining_uses<'tcx>(
277281
defining_uses
278282
}
279283

284+
#[instrument(level = "debug", skip(rcx, concrete_opaque_types, defining_uses, errors))]
280285
fn compute_concrete_types_from_defining_uses<'tcx>(
281286
rcx: &RegionCtxt<'_, 'tcx>,
282287
concrete_opaque_types: &mut ConcreteOpaqueTypes<'tcx>,
@@ -288,13 +293,15 @@ fn compute_concrete_types_from_defining_uses<'tcx>(
288293
let mut decls_modulo_regions: FxIndexMap<OpaqueTypeKey<'tcx>, (OpaqueTypeKey<'tcx>, Span)> =
289294
FxIndexMap::default();
290295
for &DefiningUse { opaque_type_key, ref arg_regions, hidden_type } in defining_uses {
296+
debug!(?opaque_type_key, ?arg_regions, ?hidden_type);
291297
// After applying member constraints, we now map all regions in the hidden type
292298
// to the `arg_regions` of this defining use. In case a region in the hidden type
293299
// ended up not being equal to any such region, we error.
294300
let hidden_type =
295301
match hidden_type.try_fold_with(&mut ToArgRegionsFolder::new(rcx, arg_regions)) {
296302
Ok(hidden_type) => hidden_type,
297303
Err(r) => {
304+
debug!("UnexpectedHiddenRegion: {:?}", r);
298305
errors.push(DeferredOpaqueTypeError::UnexpectedHiddenRegion {
299306
hidden_type,
300307
opaque_type_key,

compiler/rustc_borrowck/src/region_infer/opaque_types/region_ctxt.rs

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ use crate::constraints::ConstraintSccIndex;
1111
use crate::handle_placeholders::{SccAnnotations, region_definitions};
1212
use crate::region_infer::reverse_sccs::ReverseSccGraph;
1313
use crate::region_infer::values::RegionValues;
14-
use crate::region_infer::{ConstraintSccs, RegionDefinition, RegionTracker, Representative};
14+
use crate::region_infer::{
15+
ConstraintSccs, OutlivesConstraintSet, RegionDefinition, RegionTracker, Representative,
16+
};
1517
use crate::type_check::MirTypeckRegionConstraints;
1618
use crate::type_check::free_region_relations::UniversalRegionRelations;
1719
use crate::universal_regions::UniversalRegions;
@@ -39,16 +41,36 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> {
3941
location_map: Rc<DenseLocationMap>,
4042
constraints: &MirTypeckRegionConstraints<'tcx>,
4143
) -> RegionCtxt<'a, 'tcx> {
44+
let mut outlives_constraints = constraints.outlives_constraints.clone();
4245
let universal_regions = &universal_region_relations.universal_regions;
4346
let (definitions, _has_placeholders) = region_definitions(infcx, universal_regions);
47+
48+
let compute_sccs =
49+
|outlives_constraints: &OutlivesConstraintSet<'tcx>,
50+
annotations: &mut SccAnnotations<'_, 'tcx, RegionTracker>| {
51+
ConstraintSccs::new_with_annotation(
52+
&outlives_constraints
53+
.graph(definitions.len())
54+
.region_graph(outlives_constraints, universal_regions.fr_static),
55+
annotations,
56+
)
57+
};
58+
4459
let mut scc_annotations = SccAnnotations::init(&definitions);
45-
let constraint_sccs = ConstraintSccs::new_with_annotation(
46-
&constraints
47-
.outlives_constraints
48-
.graph(definitions.len())
49-
.region_graph(&constraints.outlives_constraints, universal_regions.fr_static),
50-
&mut scc_annotations,
60+
let mut constraint_sccs = compute_sccs(&outlives_constraints, &mut scc_annotations);
61+
62+
let added_constraints = crate::handle_placeholders::rewrite_placeholder_outlives(
63+
&constraint_sccs,
64+
&scc_annotations,
65+
universal_regions.fr_static,
66+
&mut outlives_constraints,
5167
);
68+
69+
if added_constraints {
70+
scc_annotations = SccAnnotations::init(&definitions);
71+
constraint_sccs = compute_sccs(&outlives_constraints, &mut scc_annotations);
72+
}
73+
5274
let scc_annotations = scc_annotations.scc_to_annotation;
5375

5476
// Unlike the `RegionInferenceContext`, we only care about free regions

compiler/rustc_codegen_ssa/src/mir/rvalue.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1048,14 +1048,14 @@ pub(super) fn transmute_scalar<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
10481048
imm = match (from_scalar.primitive(), to_scalar.primitive()) {
10491049
(Int(..) | Float(_), Int(..) | Float(_)) => bx.bitcast(imm, to_backend_ty),
10501050
(Pointer(..), Pointer(..)) => bx.pointercast(imm, to_backend_ty),
1051-
(Int(..), Pointer(..)) => bx.ptradd(bx.const_null(bx.type_ptr()), imm),
1051+
(Int(..), Pointer(..)) => bx.inttoptr(imm, to_backend_ty),
10521052
(Pointer(..), Int(..)) => {
10531053
// FIXME: this exposes the provenance, which shouldn't be necessary.
10541054
bx.ptrtoint(imm, to_backend_ty)
10551055
}
10561056
(Float(_), Pointer(..)) => {
10571057
let int_imm = bx.bitcast(imm, bx.cx().type_isize());
1058-
bx.ptradd(bx.const_null(bx.type_ptr()), int_imm)
1058+
bx.inttoptr(int_imm, to_backend_ty)
10591059
}
10601060
(Pointer(..), Float(_)) => {
10611061
// FIXME: this exposes the provenance, which shouldn't be necessary.
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
use rustc_index::bit_set::DenseBitSet;
2+
3+
use super::*;
4+
5+
/// Compute the set of loop headers in the given body. A loop header is usually defined as a block
6+
/// which dominates one of its predecessors. This definition is only correct for reducible CFGs.
7+
/// However, computing dominators is expensive, so we approximate according to the post-order
8+
/// traversal order. A loop header for us is a block which is visited after its predecessor in
9+
/// post-order. This is ok as we mostly need a heuristic.
10+
pub fn maybe_loop_headers(body: &Body<'_>) -> DenseBitSet<BasicBlock> {
11+
let mut maybe_loop_headers = DenseBitSet::new_empty(body.basic_blocks.len());
12+
let mut visited = DenseBitSet::new_empty(body.basic_blocks.len());
13+
for (bb, bbdata) in traversal::postorder(body) {
14+
// Post-order means we visit successors before the block for acyclic CFGs.
15+
// If the successor is not visited yet, consider it a loop header.
16+
for succ in bbdata.terminator().successors() {
17+
if !visited.contains(succ) {
18+
maybe_loop_headers.insert(succ);
19+
}
20+
}
21+
22+
// Only mark `bb` as visited after we checked the successors, in case we have a self-loop.
23+
// bb1: goto -> bb1;
24+
let _new = visited.insert(bb);
25+
debug_assert!(_new);
26+
}
27+
28+
maybe_loop_headers
29+
}

compiler/rustc_middle/src/mir/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ mod statement;
5151
mod syntax;
5252
mod terminator;
5353

54+
pub mod loops;
5455
pub mod traversal;
5556
pub mod visit;
5657

compiler/rustc_mir_transform/src/gvn.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ impl<'tcx> crate::MirPass<'tcx> for GVN {
126126
let ssa = SsaLocals::new(tcx, body, typing_env);
127127
// Clone dominators because we need them while mutating the body.
128128
let dominators = body.basic_blocks.dominators().clone();
129+
let maybe_loop_headers = loops::maybe_loop_headers(body);
129130

130131
let mut state = VnState::new(tcx, body, typing_env, &ssa, dominators, &body.local_decls);
131132

@@ -136,6 +137,11 @@ impl<'tcx> crate::MirPass<'tcx> for GVN {
136137

137138
let reverse_postorder = body.basic_blocks.reverse_postorder().to_vec();
138139
for bb in reverse_postorder {
140+
// N.B. With loops, reverse postorder cannot produce a valid topological order.
141+
// A statement or terminator from inside the loop, that is not processed yet, may have performed an indirect write.
142+
if maybe_loop_headers.contains(bb) {
143+
state.invalidate_derefs();
144+
}
139145
let data = &mut body.basic_blocks.as_mut_preserves_cfg()[bb];
140146
state.visit_basic_block_data(bb, data);
141147
}

compiler/rustc_mir_transform/src/jump_threading.rs

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ impl<'tcx> crate::MirPass<'tcx> for JumpThreading {
8484
body,
8585
arena,
8686
map: Map::new(tcx, body, Some(MAX_PLACES)),
87-
loop_headers: loop_headers(body),
87+
loop_headers: loops::maybe_loop_headers(body),
8888
opportunities: Vec::new(),
8989
};
9090

@@ -832,21 +832,3 @@ enum Update {
832832
Incr,
833833
Decr,
834834
}
835-
836-
/// Compute the set of loop headers in the given body. We define a loop header as a block which has
837-
/// at least a predecessor which it dominates. This definition is only correct for reducible CFGs.
838-
/// But if the CFG is already irreducible, there is no point in trying much harder.
839-
/// is already irreducible.
840-
fn loop_headers(body: &Body<'_>) -> DenseBitSet<BasicBlock> {
841-
let mut loop_headers = DenseBitSet::new_empty(body.basic_blocks.len());
842-
let dominators = body.basic_blocks.dominators();
843-
// Only visit reachable blocks.
844-
for (bb, bbdata) in traversal::preorder(body) {
845-
for succ in bbdata.terminator().successors() {
846-
if dominators.dominates(succ, bb) {
847-
loop_headers.insert(succ);
848-
}
849-
}
850-
}
851-
loop_headers
852-
}

tests/codegen-llvm/common_prim_int_ptr.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
#[no_mangle]
1212
pub fn insert_int(x: usize) -> Result<usize, Box<()>> {
1313
// CHECK: start:
14-
// CHECK-NEXT: %[[WO_PROV:.+]] = getelementptr i8, ptr null, [[USIZE:i[0-9]+]] %x
14+
// CHECK-NEXT: %[[WO_PROV:.+]] = inttoptr [[USIZE:i[0-9]+]] %x to ptr
1515
// CHECK-NEXT: %[[R:.+]] = insertvalue { [[USIZE]], ptr } { [[USIZE]] 0, ptr poison }, ptr %[[WO_PROV]], 1
1616
// CHECK-NEXT: ret { [[USIZE]], ptr } %[[R]]
1717
Ok(x)

0 commit comments

Comments
 (0)