Я пытаюсь выяснить, как LLVM реализует RVO.Самой простой идеей для меня было иметь указатель в аргументах и memcpy к нему любое значение, которое необходимо вернуть из функции.Затем запустите memcpyopt
pass и получите RVO таким образом, если это возможно.
Похоже, именно так и происходит с -fno-elide-constructors:
define void @_Z3fooic(%struct.X* noalias sret, i32, i8 signext) #0 {
..
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %12, i8* %13, i64 20, i32 4, i1 false)
ret void
, а без этого кажется, что всеоперации непосредственно применяются к %0
.
Это правильное понимание или я здесь упускаю некоторые предостережения?
РЕДАКТИРОВАТЬ
define i8 @make_positive_point_x_I64_y_I64(i64 %x, i64 %y, %Point*) {
entry:
%1 = or i64 %x, %y
%2 = icmp slt i64 %1, 0
br i1 %2, label %exit, label %merge
merge: ; preds = %entry
%3 = alloca %Point, align 8
call void @"Point___new_self_&Point_x_I64_y_I64"(%Point* nonnull %3, i64 %x, i64 %y)
%4 = bitcast %Point* %0 to i8*
%5 = bitcast %Point* %3 to i8*
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %4, i8* %5, i64 zext (%Point* inttoptr (i64 16 to %Point*) to i64), i32 1, i1 false)
br label %exit
exit: ; preds = %entry, %merge
%.0 = phi i8 [ 0, %merge ], [ 1, %entry ]
ret i8 %.0
}
Этокажется, что memcpyopt
недостаточно, поскольку он не распознает, что может использовать %0
вместо %3
.