Skip to content

Commit cf3ad0e

Browse files
committed
Compute binary ops between pointers in GVN.
1 parent 44c48d7 commit cf3ad0e

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};
@@ -935,12 +937,64 @@ impl<'mir, 'tcx: 'mir> rustc_const_eval::interpret::Machine<'mir, 'tcx> for Dumm
935937
}
936938

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

9461000
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)