diff options
| author | bors <bors@rust-lang.org> | 2014-07-26 15:46:18 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2014-07-26 15:46:18 +0000 |
| commit | 7aa407958b8ab2aec16b0182f0103ad92380b5dc (patch) | |
| tree | 59dd1c3707de288a8b9584ca859a9bfdd3b7b9f3 /src/rustllvm/RustWrapper.cpp | |
| parent | 50c62b466723077ba725c1d7ea8093928613c311 (diff) | |
| parent | a78c0f1019a4a023de60ae1228ad47fafc96e423 (diff) | |
| download | rust-7aa407958b8ab2aec16b0182f0103ad92380b5dc.tar.gz rust-7aa407958b8ab2aec16b0182f0103ad92380b5dc.zip | |
auto merge of #15998 : luqmana/rust/nmnnbd, r=thestinger
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
}
```
Diffstat (limited to 'src/rustllvm/RustWrapper.cpp')
| -rw-r--r-- | src/rustllvm/RustWrapper.cpp | 26 |
1 files changed, 26 insertions, 0 deletions
diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index e28a78b1ee7..8a3e06aabc6 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -113,6 +113,21 @@ extern "C" void LLVMAddCallSiteAttribute(LLVMValueRef Instr, unsigned index, uin index, B))); } + +#if LLVM_VERSION_MINOR >= 5 +extern "C" void LLVMAddDereferenceableCallSiteAttr(LLVMValueRef Instr, unsigned idx, uint64_t b) { + CallSite Call = CallSite(unwrap<Instruction>(Instr)); + AttrBuilder B; + B.addDereferenceableAttr(b); + Call.setAttributes( + Call.getAttributes().addAttributes(Call->getContext(), idx, + AttributeSet::get(Call->getContext(), + idx, B))); +} +#else +extern "C" void LLVMAddDereferenceableCallSiteAttr(LLVMValueRef, unsigned, uint64_t) {} +#endif + extern "C" void LLVMAddFunctionAttribute(LLVMValueRef Fn, unsigned index, uint64_t Val) { Function *A = unwrap<Function>(Fn); AttrBuilder B; @@ -120,6 +135,17 @@ extern "C" void LLVMAddFunctionAttribute(LLVMValueRef Fn, unsigned index, uint64 A->addAttributes(index, AttributeSet::get(A->getContext(), index, B)); } +#if LLVM_VERSION_MINOR >= 5 +extern "C" void LLVMAddDereferenceableAttr(LLVMValueRef Fn, unsigned index, uint64_t bytes) { + Function *A = unwrap<Function>(Fn); + AttrBuilder B; + B.addDereferenceableAttr(bytes); + A->addAttributes(index, AttributeSet::get(A->getContext(), index, B)); +} +#else +extern "C" void LLVMAddDereferenceableAttr(LLVMValueRef, unsigned, uint64_t) {} +#endif + extern "C" void LLVMAddFunctionAttrString(LLVMValueRef Fn, unsigned index, const char *Name) { Function *F = unwrap<Function>(Fn); AttrBuilder B; |
