Skip to content

Commit 7e5c7cf

Browse files
committed
Emit == null instead of <= null
When the niche maximum is zero, emit a "== zero" check instead of a "<= zero" check. In particular, this avoid the awkward case of "<= null". While LLVM does canonicalize this to "!= null", this appently doesn't happen for constant expressions, leading to the issue in #74425. While that can be addressed on the LLVM side, it still seems prudent to emit sensible IR here, because this will allow null checks to be optimized earlier in the pipeline. Fixes #74425.
1 parent 4803680 commit 7e5c7cf

File tree

2 files changed

+32
-8
lines changed

2 files changed

+32
-8
lines changed

src/librustc_codegen_ssa/mir/place.rs

+7-8
Original file line numberDiff line numberDiff line change
@@ -253,14 +253,13 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
253253
bx.sub(tag, bx.cx().const_uint_big(niche_llty, niche_start))
254254
};
255255
let relative_max = niche_variants.end().as_u32() - niche_variants.start().as_u32();
256-
let is_niche = {
257-
let relative_max = if relative_max == 0 {
258-
// Avoid calling `const_uint`, which wouldn't work for pointers.
259-
// FIXME(eddyb) check the actual primitive type here.
260-
bx.cx().const_null(niche_llty)
261-
} else {
262-
bx.cx().const_uint(niche_llty, relative_max as u64)
263-
};
256+
let is_niche = if relative_max == 0 {
257+
// Avoid calling `const_uint`, which wouldn't work for pointers.
258+
// Also use canonical == 0 instead of non-canonical u<= 0.
259+
// FIXME(eddyb) check the actual primitive type here.
260+
bx.icmp(IntPredicate::IntEQ, relative_discr, bx.cx().const_null(niche_llty))
261+
} else {
262+
let relative_max = bx.cx().const_uint(niche_llty, relative_max as u64);
264263
bx.icmp(IntPredicate::IntULE, relative_discr, relative_max)
265264
};
266265

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// compile-flags: -O
2+
3+
#![crate_type = "lib"]
4+
5+
// CHECK-LABEL: @test
6+
// CHECK-NEXT: start:
7+
// CHECK-NEXT: tail call void @ext_fn0()
8+
#[no_mangle]
9+
pub fn test() {
10+
test_inner(Some(inner0));
11+
}
12+
13+
fn test_inner(f_maybe: Option<fn()>) {
14+
if let Some(f) = f_maybe {
15+
f();
16+
}
17+
}
18+
19+
fn inner0() {
20+
unsafe { ext_fn0() };
21+
}
22+
23+
extern "C" {
24+
fn ext_fn0();
25+
}

0 commit comments

Comments
 (0)