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 } ````
This commit is contained in:
commit
4af28c98fa
@ -273,7 +273,15 @@ pub fn decl_rust_fn(ccx: &CrateContext, has_env: bool,
|
||||
llvm::LLVMAddAttribute(llarg, lib::llvm::NoAliasAttribute as c_uint);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
_ => {
|
||||
// For non-immediate arguments the callee gets its own copy of
|
||||
// the value on the stack, so there are no aliases
|
||||
if !type_is_immediate(ccx, arg_ty) {
|
||||
unsafe {
|
||||
llvm::LLVMAddAttribute(llarg, lib::llvm::NoAliasAttribute as c_uint);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user