7aa407958b
LLVM recently added a new attribute, dereferenceable: http://reviews.llvm.org/D4449 >This patch adds a dereferencable attribute. In some sense, this is a companion to the nonnull attribute, but specifies that the pointer is known to be dereferencable in the same sense as a pointer generated by alloca is known to be dereferencable. With rust, everywhere that we previously marked `nonnull` we can actually mark as `dereferenceable` (which implies nonnull) since we know the size. That is, except for one case: when generating calls for TyVisitor. It seems like we haven't substituted the self type (so we have `ty_param`) and just treat it as an opaque pointer so I just left that bit as nonnull. With this, LLVM can for example hoist a load out of a loop where it previously couldn't: ```Rust pub fn baz(c: &uint, n: uint) -> uint { let mut res = 0; for i in range(0, n) { if i > 0 { res += *c * i; } } res } ``` Before: ```llvm define i64 @baz(i64* noalias nocapture nonnull readonly, i64) unnamed_addr #0 { entry-block: br label %for_loopback.outer for_loopback.outer: ; preds = %then-block-33-, %entry-block %.ph = phi i64 [ %.lcssa, %then-block-33- ], [ 0, %entry-block ] %res.0.ph = phi i64 [ %8, %then-block-33- ], [ 0, %entry-block ] br label %for_loopback for_exit: ; preds = %for_loopback %res.0.ph.lcssa = phi i64 [ %res.0.ph, %for_loopback ] ret i64 %res.0.ph.lcssa for_loopback: ; preds = %for_loopback.outer, %for_body %2 = phi i64 [ %4, %for_body ], [ %.ph, %for_loopback.outer ] %3 = icmp ult i64 %2, %1 br i1 %3, label %for_body, label %for_exit for_body: ; preds = %for_loopback %4 = add i64 %2, 1 %5 = icmp eq i64 %2, 0 br i1 %5, label %for_loopback, label %then-block-33- then-block-33-: ; preds = %for_body %.lcssa = phi i64 [ %4, %for_body ] %.lcssa15 = phi i64 [ %2, %for_body ] %6 = load i64* %0, align 8 ; <------- this load %7 = mul i64 %6, %.lcssa15 %8 = add i64 %7, %res.0.ph br label %for_loopback.outer } ``` After: ```llvm define i64 @baz(i64* noalias nocapture readonly dereferenceable(8), i64) unnamed_addr #0 { entry-block: %2 = load i64* %0, align 8 ; <------- load once instead br label %for_loopback.outer for_loopback.outer: ; preds = %then-block-33-, %entry-block %.ph = phi i64 [ %.lcssa, %then-block-33- ], [ 0, %entry-block ] %res.0.ph = phi i64 [ %8, %then-block-33- ], [ 0, %entry-block ] br label %for_loopback for_exit: ; preds = %for_loopback %res.0.ph.lcssa = phi i64 [ %res.0.ph, %for_loopback ] ret i64 %res.0.ph.lcssa for_loopback: ; preds = %for_loopback.outer, %for_body %3 = phi i64 [ %5, %for_body ], [ %.ph, %for_loopback.outer ] %4 = icmp ult i64 %3, %1 br i1 %4, label %for_body, label %for_exit for_body: ; preds = %for_loopback %5 = add i64 %3, 1 %6 = icmp eq i64 %3, 0 br i1 %6, label %for_loopback, label %then-block-33- then-block-33-: ; preds = %for_body %.lcssa = phi i64 [ %5, %for_body ] %.lcssa15 = phi i64 [ %3, %for_body ] %7 = mul i64 %2, %.lcssa15 %8 = add i64 %7, %res.0.ph br label %for_loopback.outer } ``` |
||
---|---|---|
.. | ||
_match.rs | ||
adt.rs | ||
asm.rs | ||
base.rs | ||
basic_block.rs | ||
build.rs | ||
builder.rs | ||
cabi_arm.rs | ||
cabi_mips.rs | ||
cabi_x86_64.rs | ||
cabi_x86.rs | ||
cabi.rs | ||
callee.rs | ||
cleanup.rs | ||
closure.rs | ||
common.rs | ||
consts.rs | ||
context.rs | ||
controlflow.rs | ||
datum.rs | ||
debuginfo.rs | ||
doc.rs | ||
expr.rs | ||
foreign.rs | ||
glue.rs | ||
inline.rs | ||
intrinsic.rs | ||
llrepr.rs | ||
machine.rs | ||
macros.rs | ||
meth.rs | ||
mod.rs | ||
monomorphize.rs | ||
reflect.rs | ||
tvec.rs | ||
type_.rs | ||
type_of.rs | ||
value.rs |