if (CalleeCC != CallingConv::Fast && CalleeCC != CallingConv::C)
return false;
- // Functions containing by val parameters are not supported.
+ // Caller contains any byval parameter is not supported.
if (any_of(Ins, [](const ISD::InputArg &IA) { return IA.Flags.isByVal(); }))
return false;
+ // Callee contains any byval parameter is not supported, too.
+ // Note: This is a quick work around, because in some cases, e.g.
+ // caller's stack size > callee's stack size, we are still able to apply
+ // sibling call optimization. See: https://reviews.llvm.org/D23441#513574
+ if (any_of(Outs, [](const ISD::OutputArg& OA) { return OA.Flags.isByVal(); }))
+ return false;
+
// No TCO/SCO on indirect call because Caller have to restore its TOC
if (!isFunctionGlobalAddress(Callee) &&
!isa<ExternalSymbolSDNode>(Callee))
; CHECK-SCO-LABEL: w_caller:
; CHECK-SCO: bl w_callee
}
+
+%struct.byvalTest = type { [8 x i8] }
+@byval = common global %struct.byvalTest zeroinitializer
+
+define void @byval_callee(%struct.byvalTest* byval %ptr) { ret void }
+define void @byval_caller() {
+ tail call void @byval_callee(%struct.byvalTest* byval @byval)
+ ret void
+
+; CHECK-SCO-LABEL: bl byval_callee
+; CHECK-SCO: bl byval_callee
+}