Skip to content

Commit

Permalink
Auto merge of rust-lang#74533 - nikic:issue-74425, r=eddyb
Browse files Browse the repository at this point in the history
Emit == null instead of <= null for niche check

When the niche maximum is zero, emit a "== zero" check instead of a "<= zero" check. In particular, this avoids the awkward case of "<= null". While LLVM does canonicalize this to "== null", this apparently doesn't happen for constant expressions, leading to the issue in rust-lang#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 rust-lang#74425.
  • Loading branch information
bors committed Aug 8, 2020
2 parents c989ac1 + 7e5c7cf commit 2bac92b
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 8 deletions.
15 changes: 7 additions & 8 deletions src/librustc_codegen_ssa/mir/place.rs
Expand Up @@ -253,14 +253,13 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
bx.sub(tag, bx.cx().const_uint_big(niche_llty, niche_start))
};
let relative_max = niche_variants.end().as_u32() - niche_variants.start().as_u32();
let is_niche = {
let relative_max = if relative_max == 0 {
// Avoid calling `const_uint`, which wouldn't work for pointers.
// FIXME(eddyb) check the actual primitive type here.
bx.cx().const_null(niche_llty)
} else {
bx.cx().const_uint(niche_llty, relative_max as u64)
};
let is_niche = if relative_max == 0 {
// Avoid calling `const_uint`, which wouldn't work for pointers.
// Also use canonical == 0 instead of non-canonical u<= 0.
// FIXME(eddyb) check the actual primitive type here.
bx.icmp(IntPredicate::IntEQ, relative_discr, bx.cx().const_null(niche_llty))
} else {
let relative_max = bx.cx().const_uint(niche_llty, relative_max as u64);
bx.icmp(IntPredicate::IntULE, relative_discr, relative_max)
};

Expand Down
25 changes: 25 additions & 0 deletions src/test/codegen/some-global-nonnull.rs
@@ -0,0 +1,25 @@
// compile-flags: -O

#![crate_type = "lib"]

// CHECK-LABEL: @test
// CHECK-NEXT: start:
// CHECK-NEXT: tail call void @ext_fn0()
#[no_mangle]
pub fn test() {
test_inner(Some(inner0));
}

fn test_inner(f_maybe: Option<fn()>) {
if let Some(f) = f_maybe {
f();
}
}

fn inner0() {
unsafe { ext_fn0() };
}

extern "C" {
fn ext_fn0();
}

0 comments on commit 2bac92b

Please sign in to comment.