Skip to content

Commit 28df0a6

Browse files
committed
Compute binary ops between pointers in GVN.
1 parent 304b4ad commit 28df0a6

File tree

3 files changed

+104
-36
lines changed

3 files changed

+104
-36
lines changed

compiler/rustc_mir_transform/src/dataflow_const_prop.rs

+60-6
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
//!
33
//! Currently, this pass only propagates scalar values.
44
5-
use rustc_const_eval::interpret::{ImmTy, Immediate, InterpCx, OpTy, PlaceTy, Projectable};
5+
use rustc_const_eval::interpret::{
6+
ImmTy, Immediate, InterpCx, OpTy, PlaceTy, Pointer, PointerArithmetic, Projectable,
7+
};
68
use rustc_data_structures::fx::FxHashMap;
79
use rustc_hir::def::DefKind;
810
use rustc_middle::mir::interpret::{AllocId, ConstAllocation, InterpResult, Scalar};
@@ -936,12 +938,64 @@ impl<'mir, 'tcx: 'mir> rustc_const_eval::interpret::Machine<'mir, 'tcx> for Dumm
936938
}
937939

938940
fn binary_ptr_op(
939-
_ecx: &InterpCx<'mir, 'tcx, Self>,
940-
_bin_op: BinOp,
941-
_left: &rustc_const_eval::interpret::ImmTy<'tcx, Self::Provenance>,
942-
_right: &rustc_const_eval::interpret::ImmTy<'tcx, Self::Provenance>,
941+
ecx: &InterpCx<'mir, 'tcx, Self>,
942+
bin_op: BinOp,
943+
left: &rustc_const_eval::interpret::ImmTy<'tcx, Self::Provenance>,
944+
right: &rustc_const_eval::interpret::ImmTy<'tcx, Self::Provenance>,
943945
) -> interpret::InterpResult<'tcx, (ImmTy<'tcx, Self::Provenance>, bool)> {
944-
throw_machine_stop_str!("can't do pointer arithmetic");
946+
use rustc_middle::mir::BinOp::*;
947+
Ok(match bin_op {
948+
Eq | Ne | Lt | Le | Gt | Ge => {
949+
assert_eq!(left.layout.abi, right.layout.abi); // types an differ, e.g. fn ptrs with different `for`
950+
let size = ecx.pointer_size();
951+
// Just compare the bits. ScalarPairs are compared lexicographically.
952+
// We thus always compare pairs and simply fill scalars up with 0.
953+
let left = match **left {
954+
Immediate::Scalar(l) => (l.to_bits(size)?, 0),
955+
Immediate::ScalarPair(l1, l2) => (l1.to_bits(size)?, l2.to_bits(size)?),
956+
Immediate::Uninit => panic!("we should never see uninit data here"),
957+
};
958+
let right = match **right {
959+
Immediate::Scalar(r) => (r.to_bits(size)?, 0),
960+
Immediate::ScalarPair(r1, r2) => (r1.to_bits(size)?, r2.to_bits(size)?),
961+
Immediate::Uninit => panic!("we should never see uninit data here"),
962+
};
963+
let res = match bin_op {
964+
Eq => left == right,
965+
Ne => left != right,
966+
Lt => left < right,
967+
Le => left <= right,
968+
Gt => left > right,
969+
Ge => left >= right,
970+
_ => bug!(),
971+
};
972+
(ImmTy::from_bool(res, *ecx.tcx), false)
973+
}
974+
975+
// Some more operations are possible with atomics.
976+
// The return value always has the provenance of the *left* operand.
977+
Add | Sub | BitOr | BitAnd | BitXor => {
978+
assert!(left.layout.ty.is_unsafe_ptr());
979+
assert!(right.layout.ty.is_unsafe_ptr());
980+
let ptr = left.to_scalar().to_pointer(ecx)?;
981+
// We do the actual operation with usize-typed scalars.
982+
let usize_layout = ecx.layout_of(ecx.tcx.types.usize).unwrap();
983+
let left = ImmTy::from_uint(ptr.addr().bytes(), usize_layout);
984+
let right = ImmTy::from_uint(right.to_scalar().to_target_usize(ecx)?, usize_layout);
985+
let (result, overflowing) = ecx.overflowing_binary_op(bin_op, &left, &right)?;
986+
// Construct a new pointer with the provenance of `ptr` (the LHS).
987+
let result_ptr = Pointer::new(
988+
ptr.provenance,
989+
Size::from_bytes(result.to_scalar().to_target_usize(ecx)?),
990+
);
991+
(
992+
ImmTy::from_scalar(Scalar::from_maybe_pointer(result_ptr, ecx), left.layout),
993+
overflowing,
994+
)
995+
}
996+
997+
_ => span_bug!(ecx.cur_span(), "Invalid operator on pointers: {:?}", bin_op),
998+
})
945999
}
9461000

9471001
fn expose_ptr(

tests/mir-opt/gvn.wide_ptr_ops.GVN.panic-abort.diff

+22-15
Original file line numberDiff line numberDiff line change
@@ -247,13 +247,14 @@
247247
- _45 = _39;
248248
- _43 = Eq(move _44, move _45);
249249
+ _45 = const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8];
250-
+ _43 = Eq(const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8], const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]);
250+
+ _43 = const false;
251251
StorageDead(_45);
252252
StorageDead(_44);
253-
_42 = Not(move _43);
253+
- _42 = Not(move _43);
254+
+ _42 = const true;
254255
StorageDead(_43);
255256
- _41 = opaque::<bool>(move _42) -> [return: bb1, unwind unreachable];
256-
+ _41 = opaque::<bool>(_42) -> [return: bb1, unwind unreachable];
257+
+ _41 = opaque::<bool>(const true) -> [return: bb1, unwind unreachable];
257258
}
258259

259260
bb1: {
@@ -269,11 +270,11 @@
269270
- _49 = _39;
270271
- _47 = Ne(move _48, move _49);
271272
+ _49 = const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8];
272-
+ _47 = _42;
273+
+ _47 = const true;
273274
StorageDead(_49);
274275
StorageDead(_48);
275276
- _46 = opaque::<bool>(move _47) -> [return: bb2, unwind unreachable];
276-
+ _46 = opaque::<bool>(_42) -> [return: bb2, unwind unreachable];
277+
+ _46 = opaque::<bool>(const true) -> [return: bb2, unwind unreachable];
277278
}
278279

279280
bb2: {
@@ -288,10 +289,11 @@
288289
- _53 = _39;
289290
- _51 = Le(move _52, move _53);
290291
+ _53 = const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8];
291-
+ _51 = Le(const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8], const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]);
292+
+ _51 = const true;
292293
StorageDead(_53);
293294
StorageDead(_52);
294-
_50 = opaque::<bool>(move _51) -> [return: bb3, unwind unreachable];
295+
- _50 = opaque::<bool>(move _51) -> [return: bb3, unwind unreachable];
296+
+ _50 = opaque::<bool>(const true) -> [return: bb3, unwind unreachable];
295297
}
296298

297299
bb3: {
@@ -306,10 +308,11 @@
306308
- _57 = _39;
307309
- _55 = Lt(move _56, move _57);
308310
+ _57 = const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8];
309-
+ _55 = Lt(const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8], const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]);
311+
+ _55 = const true;
310312
StorageDead(_57);
311313
StorageDead(_56);
312-
_54 = opaque::<bool>(move _55) -> [return: bb4, unwind unreachable];
314+
- _54 = opaque::<bool>(move _55) -> [return: bb4, unwind unreachable];
315+
+ _54 = opaque::<bool>(const true) -> [return: bb4, unwind unreachable];
313316
}
314317

315318
bb4: {
@@ -325,12 +328,14 @@
325328
- _62 = _39;
326329
- _60 = Ge(move _61, move _62);
327330
+ _62 = const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8];
328-
+ _60 = Ge(const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8], const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]);
331+
+ _60 = const false;
329332
StorageDead(_62);
330333
StorageDead(_61);
331-
_59 = Not(move _60);
334+
- _59 = Not(move _60);
335+
+ _59 = const true;
332336
StorageDead(_60);
333-
_58 = opaque::<bool>(move _59) -> [return: bb5, unwind unreachable];
337+
- _58 = opaque::<bool>(move _59) -> [return: bb5, unwind unreachable];
338+
+ _58 = opaque::<bool>(const true) -> [return: bb5, unwind unreachable];
334339
}
335340

336341
bb5: {
@@ -346,12 +351,14 @@
346351
- _67 = _39;
347352
- _65 = Gt(move _66, move _67);
348353
+ _67 = const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8];
349-
+ _65 = Gt(const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8], const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]);
354+
+ _65 = const false;
350355
StorageDead(_67);
351356
StorageDead(_66);
352-
_64 = Not(move _65);
357+
- _64 = Not(move _65);
358+
+ _64 = const true;
353359
StorageDead(_65);
354-
_63 = opaque::<bool>(move _64) -> [return: bb6, unwind unreachable];
360+
- _63 = opaque::<bool>(move _64) -> [return: bb6, unwind unreachable];
361+
+ _63 = opaque::<bool>(const true) -> [return: bb6, unwind unreachable];
355362
}
356363

357364
bb6: {

tests/mir-opt/gvn.wide_ptr_ops.GVN.panic-unwind.diff

+22-15
Original file line numberDiff line numberDiff line change
@@ -247,13 +247,14 @@
247247
- _45 = _39;
248248
- _43 = Eq(move _44, move _45);
249249
+ _45 = const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8];
250-
+ _43 = Eq(const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8], const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]);
250+
+ _43 = const false;
251251
StorageDead(_45);
252252
StorageDead(_44);
253-
_42 = Not(move _43);
253+
- _42 = Not(move _43);
254+
+ _42 = const true;
254255
StorageDead(_43);
255256
- _41 = opaque::<bool>(move _42) -> [return: bb1, unwind continue];
256-
+ _41 = opaque::<bool>(_42) -> [return: bb1, unwind continue];
257+
+ _41 = opaque::<bool>(const true) -> [return: bb1, unwind continue];
257258
}
258259

259260
bb1: {
@@ -269,11 +270,11 @@
269270
- _49 = _39;
270271
- _47 = Ne(move _48, move _49);
271272
+ _49 = const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8];
272-
+ _47 = _42;
273+
+ _47 = const true;
273274
StorageDead(_49);
274275
StorageDead(_48);
275276
- _46 = opaque::<bool>(move _47) -> [return: bb2, unwind continue];
276-
+ _46 = opaque::<bool>(_42) -> [return: bb2, unwind continue];
277+
+ _46 = opaque::<bool>(const true) -> [return: bb2, unwind continue];
277278
}
278279

279280
bb2: {
@@ -288,10 +289,11 @@
288289
- _53 = _39;
289290
- _51 = Le(move _52, move _53);
290291
+ _53 = const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8];
291-
+ _51 = Le(const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8], const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]);
292+
+ _51 = const true;
292293
StorageDead(_53);
293294
StorageDead(_52);
294-
_50 = opaque::<bool>(move _51) -> [return: bb3, unwind continue];
295+
- _50 = opaque::<bool>(move _51) -> [return: bb3, unwind continue];
296+
+ _50 = opaque::<bool>(const true) -> [return: bb3, unwind continue];
295297
}
296298

297299
bb3: {
@@ -306,10 +308,11 @@
306308
- _57 = _39;
307309
- _55 = Lt(move _56, move _57);
308310
+ _57 = const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8];
309-
+ _55 = Lt(const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8], const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]);
311+
+ _55 = const true;
310312
StorageDead(_57);
311313
StorageDead(_56);
312-
_54 = opaque::<bool>(move _55) -> [return: bb4, unwind continue];
314+
- _54 = opaque::<bool>(move _55) -> [return: bb4, unwind continue];
315+
+ _54 = opaque::<bool>(const true) -> [return: bb4, unwind continue];
313316
}
314317

315318
bb4: {
@@ -325,12 +328,14 @@
325328
- _62 = _39;
326329
- _60 = Ge(move _61, move _62);
327330
+ _62 = const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8];
328-
+ _60 = Ge(const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8], const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]);
331+
+ _60 = const false;
329332
StorageDead(_62);
330333
StorageDead(_61);
331-
_59 = Not(move _60);
334+
- _59 = Not(move _60);
335+
+ _59 = const true;
332336
StorageDead(_60);
333-
_58 = opaque::<bool>(move _59) -> [return: bb5, unwind continue];
337+
- _58 = opaque::<bool>(move _59) -> [return: bb5, unwind continue];
338+
+ _58 = opaque::<bool>(const true) -> [return: bb5, unwind continue];
334339
}
335340

336341
bb5: {
@@ -346,12 +351,14 @@
346351
- _67 = _39;
347352
- _65 = Gt(move _66, move _67);
348353
+ _67 = const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8];
349-
+ _65 = Gt(const Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [u8], const Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [u8]);
354+
+ _65 = const false;
350355
StorageDead(_67);
351356
StorageDead(_66);
352-
_64 = Not(move _65);
357+
- _64 = Not(move _65);
358+
+ _64 = const true;
353359
StorageDead(_65);
354-
_63 = opaque::<bool>(move _64) -> [return: bb6, unwind continue];
360+
- _63 = opaque::<bool>(move _64) -> [return: bb6, unwind continue];
361+
+ _63 = opaque::<bool>(const true) -> [return: bb6, unwind continue];
355362
}
356363

357364
bb6: {

0 commit comments

Comments
 (0)