@@ -431,13 +431,44 @@ static bool mayTailCallThisCC(CallingConv::ID CC) {
431
431
}
432
432
}
433
433
434
+ bool AArch64CallLowering::doCallerAndCalleePassArgsTheSameWay (
435
+ CallLoweringInfo &Info, MachineFunction &MF,
436
+ SmallVectorImpl<ArgInfo> &InArgs) const {
437
+ const Function &CallerF = MF.getFunction ();
438
+ CallingConv::ID CalleeCC = Info.CallConv ;
439
+ CallingConv::ID CallerCC = CallerF.getCallingConv ();
440
+
441
+ // If the calling conventions match, then everything must be the same.
442
+ if (CalleeCC == CallerCC)
443
+ return true ;
444
+
445
+ // Check if the caller and callee will handle arguments in the same way.
446
+ const AArch64TargetLowering &TLI = *getTLI<AArch64TargetLowering>();
447
+ CCAssignFn *CalleeAssignFn = TLI.CCAssignFnForCall (CalleeCC, Info.IsVarArg );
448
+ CCAssignFn *CallerAssignFn =
449
+ TLI.CCAssignFnForCall (CallerCC, CallerF.isVarArg ());
450
+
451
+ if (!resultsCompatible (Info, MF, InArgs, *CalleeAssignFn, *CallerAssignFn))
452
+ return false ;
453
+
454
+ // Make sure that the caller and callee preserve all of the same registers.
455
+ auto TRI = MF.getSubtarget <AArch64Subtarget>().getRegisterInfo ();
456
+ const uint32_t *CallerPreserved = TRI->getCallPreservedMask (MF, CallerCC);
457
+ const uint32_t *CalleePreserved = TRI->getCallPreservedMask (MF, CalleeCC);
458
+ if (MF.getSubtarget <AArch64Subtarget>().hasCustomCallingConv ()) {
459
+ TRI->UpdateCustomCallPreservedMask (MF, &CallerPreserved);
460
+ TRI->UpdateCustomCallPreservedMask (MF, &CalleePreserved);
461
+ }
462
+
463
+ return TRI->regmaskSubsetEqual (CallerPreserved, CalleePreserved);
464
+ }
465
+
434
466
bool AArch64CallLowering::isEligibleForTailCallOptimization (
435
- MachineIRBuilder &MIRBuilder, CallLoweringInfo &Info) const {
467
+ MachineIRBuilder &MIRBuilder, CallLoweringInfo &Info,
468
+ SmallVectorImpl<ArgInfo> &InArgs) const {
436
469
CallingConv::ID CalleeCC = Info.CallConv ;
437
470
MachineFunction &MF = MIRBuilder.getMF ();
438
471
const Function &CallerF = MF.getFunction ();
439
- CallingConv::ID CallerCC = CallerF.getCallingConv ();
440
- bool CCMatch = CallerCC == CalleeCC;
441
472
442
473
LLVM_DEBUG (dbgs () << " Attempting to lower call as tail call\n " );
443
474
@@ -509,11 +540,11 @@ bool AArch64CallLowering::isEligibleForTailCallOptimization(
509
540
assert ((!Info.IsVarArg || CalleeCC == CallingConv::C) &&
510
541
" Unexpected variadic calling convention" );
511
542
512
- // For now, only support the case where the calling conventions match .
513
- if (!CCMatch ) {
543
+ // Look at the incoming values .
544
+ if (!doCallerAndCalleePassArgsTheSameWay (Info, MF, InArgs) ) {
514
545
LLVM_DEBUG (
515
546
dbgs ()
516
- << " ... Cannot tail call with mismatched calling conventions yet .\n " );
547
+ << " ... Caller and callee have incompatible calling conventions.\n " );
517
548
return false ;
518
549
}
519
550
@@ -552,6 +583,7 @@ bool AArch64CallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
552
583
const Function &F = MF.getFunction ();
553
584
MachineRegisterInfo &MRI = MF.getRegInfo ();
554
585
auto &DL = F.getParent ()->getDataLayout ();
586
+ const AArch64TargetLowering &TLI = *getTLI<AArch64TargetLowering>();
555
587
556
588
if (Info.IsMustTailCall ) {
557
589
// TODO: Until we lower all tail calls, we should fall back on this.
@@ -573,13 +605,16 @@ bool AArch64CallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
573
605
SplitArgs.back ().Flags [0 ].setZExt ();
574
606
}
575
607
576
- bool IsSibCall =
577
- Info.IsTailCall && isEligibleForTailCallOptimization (MIRBuilder, Info);
608
+ SmallVector<ArgInfo, 8 > InArgs;
609
+ if (!Info.OrigRet .Ty ->isVoidTy ())
610
+ splitToValueTypes (Info.OrigRet , InArgs, DL, MRI, F.getCallingConv ());
611
+
612
+ bool IsSibCall = Info.IsTailCall &&
613
+ isEligibleForTailCallOptimization (MIRBuilder, Info, InArgs);
578
614
if (IsSibCall)
579
615
MF.getFrameInfo ().setHasTailCall ();
580
616
581
617
// Find out which ABI gets to decide where things go.
582
- const AArch64TargetLowering &TLI = *getTLI<AArch64TargetLowering>();
583
618
CCAssignFn *AssignFnFixed =
584
619
TLI.CCAssignFnForCall (Info.CallConv , /* IsVarArg=*/ false );
585
620
CCAssignFn *AssignFnVarArg =
@@ -649,14 +684,10 @@ bool AArch64CallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
649
684
// Finally we can copy the returned value back into its virtual-register. In
650
685
// symmetry with the arugments, the physical register must be an
651
686
// implicit-define of the call instruction.
652
- CCAssignFn *RetAssignFn = TLI.CCAssignFnForReturn (F.getCallingConv ());
653
687
if (!Info.OrigRet .Ty ->isVoidTy ()) {
654
- SplitArgs.clear ();
655
-
656
- splitToValueTypes (Info.OrigRet , SplitArgs, DL, MRI, F.getCallingConv ());
657
-
688
+ CCAssignFn *RetAssignFn = TLI.CCAssignFnForReturn (F.getCallingConv ());
658
689
CallReturnHandler Handler (MIRBuilder, MRI, MIB, RetAssignFn);
659
- if (!handleAssignments (MIRBuilder, SplitArgs , Handler))
690
+ if (!handleAssignments (MIRBuilder, InArgs , Handler))
660
691
return false ;
661
692
}
662
693
0 commit comments