about summary refs log tree commit diff
path: root/src/rustllvm/PassWrapper.cpp
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-02-15 12:46:23 -0800
committerbors <bors@rust-lang.org>2014-02-15 12:46:23 -0800
commit4af28c98fac5bc36a93527b79c77081eedfb554b (patch)
treecdc91ef488c6f37b0920fd878ab386d8b2df8bf4 /src/rustllvm/PassWrapper.cpp
parentadea48abb730bfcfdc7008f6bc5964ed5b1e7ca6 (diff)
parent500d29b589a608357c1b82e4203dc1b77454c78c (diff)
downloadrust-4af28c98fac5bc36a93527b79c77081eedfb554b.tar.gz
rust-4af28c98fac5bc36a93527b79c77081eedfb554b.zip
auto merge of #12296 : dotdash/rust/byval_noalias, r=cmr
Function parameters that are to be passed by value but don't fit into a
single register are currently passed by creating a copy on the stack and
passing a pointer to that copy to the callee. Since the copy is made
just for the function call, there are no aliases.

For example, this sometimes allows LLVM to eliminate unnecessary calls
to drop glue. Given

````rust
struct Foo {
    a: int,
    b: Option<~str>,
}

extern {
    fn eat(eat: Option<~str>);
}

pub fn foo(v: Foo) {
    match v {
        Foo { a: _, b } => unsafe { eat(b) }
    }
}
````

LLVM currently can't eliminate the drop call for the string, because it
only sees a _pointer_ to Foo, for which it has to expect an alias. So we
get:

````llvm
; Function Attrs: uwtable
define void @_ZN3foo20h9f32c90ae7201edbxaa4v0.0E(%struct.Foo* nocapture) unnamed_addr #0 {
"_ZN34std..option..Option$LT$$UP$str$GT$9glue_drop17hc39b3015f3b9c69dE.exit":
  %1 = getelementptr inbounds %struct.Foo* %0, i64 0, i32 1, i32 0
  %2 = load { i64, i64, [0 x i8] }** %1, align 8
  store { i64, i64, [0 x i8] }* null, { i64, i64, [0 x i8] }** %1, align 8
  %3 = ptrtoint { i64, i64, [0 x i8] }* %2 to i64
  %.fca.0.insert = insertvalue { i64 } undef, i64 %3, 0
  tail call void @eat({ i64 } %.fca.0.insert)
  %4 = load { i64, i64, [0 x i8] }** %1, align 8
  %5 = icmp eq { i64, i64, [0 x i8] }* %4, null
  br i1 %5, label %_ZN3Foo9glue_drop17hf611996539d3036fE.exit, label %"_ZN8_$UP$str9glue_drop17h15dbdbe2b8897a98E.exit.i.i"

"_ZN8_$UP$str9glue_drop17h15dbdbe2b8897a98E.exit.i.i": ; preds = %"_ZN34std..option..Option$LT$$UP$str$GT$9glue_drop17hc39b3015f3b9c69dE.exit"
  %6 = bitcast { i64, i64, [0 x i8] }* %4 to i8*
  tail call void @free(i8* %6) #1
  br label %_ZN3Foo9glue_drop17hf611996539d3036fE.exit

_ZN3Foo9glue_drop17hf611996539d3036fE.exit:       ; preds = %"_ZN34std..option..Option$LT$$UP$str$GT$9glue_drop17hc39b3015f3b9c69dE.exit", %"_ZN8_$UP$str9glue_drop17h15dbdbe2b8897a98E.exit.i.i"
  ret void
}
````

But with the `noalias` attribute, it can safely optimize that to:

````llvm
define void @_ZN3foo20hd28431f929f0d6c4xaa4v0.0E(%struct.Foo* noalias nocapture) unnamed_addr #0 {
_ZN3Foo9glue_drop17he9afbc09d4e9c851E.exit:
  %1 = getelementptr inbounds %struct.Foo* %0, i64 0, i32 1, i32 0
  %2 = load { i64, i64, [0 x i8] }** %1, align 8
  store { i64, i64, [0 x i8] }* null, { i64, i64, [0 x i8] }** %1, align 8
  %3 = ptrtoint { i64, i64, [0 x i8] }* %2 to i64
  %.fca.0.insert = insertvalue { i64 } undef, i64 %3, 0
  tail call void @eat({ i64 } %.fca.0.insert)
  ret void
}
````
Diffstat (limited to 'src/rustllvm/PassWrapper.cpp')
0 files changed, 0 insertions, 0 deletions