Closed
Description
lib/src.rs
in the foo
crate:
#[inline(never)]
pub fn test(gp1: &mut *const i32, gp2: &mut *const i32, b1: bool, b2: bool) -> (i32, i32) {
let mut g = 0;
let mut b = 0;
let y = 6666;
let mut x = 7777;
let mut p = &mut g as *const _;
{
let mut q = &mut g;
let mut r = &mut 8888;
if b1 {
p = (&y as *const _).wrapping_offset(1);
}
if b2 {
q = &mut x;
}
*gp1 = p.wrapping_offset(1234);
if q as *const _ == p {
b = 1;
*gp2 = (q as *const _).wrapping_offset(1234);
r = q;
}
*r = 42;
}
return (b, x);
}
src/main.rs
in the main crate:
use std::ptr;
extern crate foo;
pub fn main() {
let mut x1 = ptr::null();
let mut x2 = ptr::null();
let mut gp1 = &mut x1;
let mut gp2 = &mut x2;
let (b, x) = foo::test(&mut gp1, &mut gp2, true, true);
println!("b = {}, x = {}", b, x);
}
This prints b = 1, x = 7777
. That is wrong; if b
is 1
, it must be the case that the then-branch in the q as *const _ == p
conditional was taken, so r
is &mut x
(since b2
is true
), so x
cannot still be 7777
.
This is a bug in LLVM's GVN, see https://bugs.llvm.org/show_bug.cgi?id=35229 for the upstream report and some further analysis.
Original C test case by Gil Hur.