@@ -242,10 +242,6 @@ void RISCVFrameLowering::determineFrameLayout(MachineFunction &MF) const {
242
242
// Get the alignment.
243
243
Align StackAlign = getStackAlign ();
244
244
245
- // Set Max Call Frame Size
246
- uint64_t MaxCallSize = alignTo (MFI.getMaxCallFrameSize (), StackAlign);
247
- MFI.setMaxCallFrameSize (MaxCallSize);
248
-
249
245
// Make sure the frame is aligned.
250
246
FrameSize = alignTo (FrameSize, StackAlign);
251
247
@@ -293,16 +289,43 @@ static Register getFPReg(const RISCVSubtarget &STI) { return RISCV::X8; }
293
289
static Register getSPReg (const RISCVSubtarget &STI) { return RISCV::X2; }
294
290
295
291
static SmallVector<CalleeSavedInfo, 8 >
296
- getNonLibcallCSI (const std::vector<CalleeSavedInfo> &CSI) {
292
+ getNonLibcallCSI (const MachineFunction &MF,
293
+ const std::vector<CalleeSavedInfo> &CSI) {
294
+ const MachineFrameInfo &MFI = MF.getFrameInfo ();
297
295
SmallVector<CalleeSavedInfo, 8 > NonLibcallCSI;
298
296
299
- for (auto &CS : CSI)
300
- if (CS.getFrameIdx () >= 0 )
297
+ for (auto &CS : CSI) {
298
+ int FI = CS.getFrameIdx ();
299
+ if (FI >= 0 && MFI.getStackID (FI) == TargetStackID::Default)
301
300
NonLibcallCSI.push_back (CS);
301
+ }
302
302
303
303
return NonLibcallCSI;
304
304
}
305
305
306
+ void RISCVFrameLowering::adjustStackForRVV (MachineFunction &MF,
307
+ MachineBasicBlock &MBB,
308
+ MachineBasicBlock::iterator MBBI,
309
+ const DebugLoc &DL,
310
+ int64_t Amount) const {
311
+ assert (Amount != 0 && " Did not need to adjust stack pointer for RVV." );
312
+
313
+ const RISCVInstrInfo *TII = STI.getInstrInfo ();
314
+ Register SPReg = getSPReg (STI);
315
+ unsigned Opc = RISCV::ADD;
316
+ if (Amount < 0 ) {
317
+ Amount = -Amount;
318
+ Opc = RISCV::SUB;
319
+ }
320
+
321
+ // 1. Multiply the number of v-slots to the length of registers
322
+ Register FactorRegister = TII->getVLENFactoredAmount (MF, MBB, MBBI, Amount);
323
+ // 2. SP = SP - RVV stack size
324
+ BuildMI (MBB, MBBI, DL, TII->get (Opc), SPReg)
325
+ .addReg (SPReg)
326
+ .addReg (FactorRegister);
327
+ }
328
+
306
329
void RISCVFrameLowering::emitPrologue (MachineFunction &MF,
307
330
MachineBasicBlock &MBB) const {
308
331
MachineFrameInfo &MFI = MF.getFrameInfo ();
@@ -364,9 +387,10 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF,
364
387
// investigation. Get the number of bytes to allocate from the FrameInfo.
365
388
uint64_t StackSize = MFI.getStackSize ();
366
389
uint64_t RealStackSize = StackSize + RVFI->getLibCallStackSize ();
390
+ uint64_t RVVStackSize = RVFI->getRVVStackSize ();
367
391
368
392
// Early exit if there is no need to allocate on the stack
369
- if (RealStackSize == 0 && !MFI.adjustsStack ())
393
+ if (RealStackSize == 0 && !MFI.adjustsStack () && RVVStackSize == 0 )
370
394
return ;
371
395
372
396
// If the stack pointer has been marked as reserved, then produce an error if
@@ -399,7 +423,7 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF,
399
423
// to the stack, not before.
400
424
// FIXME: assumes exactly one instruction is used to save each callee-saved
401
425
// register.
402
- std::advance (MBBI, getNonLibcallCSI (CSI).size ());
426
+ std::advance (MBBI, getNonLibcallCSI (MF, CSI).size ());
403
427
404
428
// Iterate over list of callee-saved registers and emit .cfi_offset
405
429
// directives.
@@ -489,6 +513,9 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF,
489
513
}
490
514
}
491
515
}
516
+
517
+ if (RVVStackSize)
518
+ adjustStackForRVV (MF, MBB, MBBI, DL, -RVVStackSize);
492
519
}
493
520
494
521
void RISCVFrameLowering::emitEpilogue (MachineFunction &MF,
@@ -526,7 +553,7 @@ void RISCVFrameLowering::emitEpilogue(MachineFunction &MF,
526
553
--MBBI;
527
554
}
528
555
529
- const auto &CSI = getNonLibcallCSI (MFI.getCalleeSavedInfo ());
556
+ const auto &CSI = getNonLibcallCSI (MF, MFI.getCalleeSavedInfo ());
530
557
531
558
// Skip to before the restores of callee-saved registers
532
559
// FIXME: assumes exactly one instruction is used to restore each
@@ -538,6 +565,7 @@ void RISCVFrameLowering::emitEpilogue(MachineFunction &MF,
538
565
uint64_t StackSize = MFI.getStackSize ();
539
566
uint64_t RealStackSize = StackSize + RVFI->getLibCallStackSize ();
540
567
uint64_t FPOffset = RealStackSize - RVFI->getVarArgsSaveSize ();
568
+ uint64_t RVVStackSize = RVFI->getRVVStackSize ();
541
569
542
570
// Restore the stack pointer using the value of the frame pointer. Only
543
571
// necessary if the stack pointer was modified, meaning the stack size is
@@ -546,6 +574,9 @@ void RISCVFrameLowering::emitEpilogue(MachineFunction &MF,
546
574
assert (hasFP (MF) && " frame pointer should not have been eliminated" );
547
575
adjustReg (MBB, LastFrameDestroy, DL, SPReg, FPReg, -FPOffset,
548
576
MachineInstr::FrameDestroy);
577
+ } else {
578
+ if (RVVStackSize)
579
+ adjustStackForRVV (MF, MBB, LastFrameDestroy, DL, RVVStackSize);
549
580
}
550
581
551
582
uint64_t FirstSPAdjustAmount = getFirstSPAdjustAmount (MF);
@@ -578,12 +609,22 @@ RISCVFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI,
578
609
// Callee-saved registers should be referenced relative to the stack
579
610
// pointer (positive offset), otherwise use the frame pointer (negative
580
611
// offset).
581
- const auto &CSI = getNonLibcallCSI (MFI.getCalleeSavedInfo ());
612
+ const auto &CSI = getNonLibcallCSI (MF, MFI.getCalleeSavedInfo ());
582
613
int MinCSFI = 0 ;
583
614
int MaxCSFI = -1 ;
584
-
585
- int Offset = MFI.getObjectOffset (FI) - getOffsetOfLocalArea () +
586
- MFI.getOffsetAdjustment ();
615
+ StackOffset Offset;
616
+ auto StackID = MFI.getStackID (FI);
617
+
618
+ assert ((StackID == TargetStackID::Default ||
619
+ StackID == TargetStackID::ScalableVector) &&
620
+ " Unexpected stack ID for the frame object." );
621
+ if (StackID == TargetStackID::Default) {
622
+ Offset =
623
+ StackOffset::getFixed (MFI.getObjectOffset (FI) - getOffsetOfLocalArea () +
624
+ MFI.getOffsetAdjustment ());
625
+ } else if (StackID == TargetStackID::ScalableVector) {
626
+ Offset = StackOffset::getScalable (MFI.getObjectOffset (FI));
627
+ }
587
628
588
629
uint64_t FirstSPAdjustAmount = getFirstSPAdjustAmount (MF);
589
630
@@ -596,33 +637,86 @@ RISCVFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI,
596
637
FrameReg = RISCV::X2;
597
638
598
639
if (FirstSPAdjustAmount)
599
- Offset += FirstSPAdjustAmount;
640
+ Offset += StackOffset::getFixed ( FirstSPAdjustAmount) ;
600
641
else
601
- Offset += MFI.getStackSize ();
642
+ Offset += StackOffset::getFixed ( MFI.getStackSize () );
602
643
} else if (RI->needsStackRealignment (MF) && !MFI.isFixedObjectIndex (FI)) {
603
644
// If the stack was realigned, the frame pointer is set in order to allow
604
645
// SP to be restored, so we need another base register to record the stack
605
646
// after realignment.
606
- if (hasBP (MF))
647
+ if (hasBP (MF)) {
607
648
FrameReg = RISCVABI::getBPReg ();
608
- else
649
+ // |--------------------------| -- <-- FP
650
+ // | callee-saved registers | |
651
+ // |--------------------------| | MFI.getStackSize()
652
+ // | scalar local variables | |
653
+ // |--------------------------| --
654
+ // | Realignment | |
655
+ // |--------------------------| -- <-- BP
656
+ // | RVV objects | | RVFI->getRVVStackSize()
657
+ // |--------------------------| --
658
+ // | VarSize objects | |
659
+ // |--------------------------| -- <-- SP
660
+ } else {
609
661
FrameReg = RISCV::X2;
610
- Offset += MFI.getStackSize ();
611
- if (FI < 0 )
612
- Offset += RVFI->getLibCallStackSize ();
662
+ // When using SP to access frame objects, we need to add RVV stack size.
663
+ //
664
+ // |--------------------------| -- <-- FP
665
+ // | callee-saved registers | |
666
+ // |--------------------------| | MFI.getStackSize()
667
+ // | scalar local variables | |
668
+ // |--------------------------| --
669
+ // | Realignment | |
670
+ // |--------------------------| --
671
+ // | RVV objects | | RVFI->getRVVStackSize()
672
+ // |--------------------------| -- <-- SP
673
+ Offset += StackOffset::getScalable (RVFI->getRVVStackSize ());
674
+ }
675
+ if (MFI.getStackID (FI) == TargetStackID::Default) {
676
+ Offset += StackOffset::getFixed (MFI.getStackSize ());
677
+ if (FI < 0 )
678
+ Offset += StackOffset::getFixed (RVFI->getLibCallStackSize ());
679
+ }
613
680
} else {
614
681
FrameReg = RI->getFrameRegister (MF);
615
682
if (hasFP (MF)) {
616
- Offset += RVFI->getVarArgsSaveSize ();
683
+ Offset += StackOffset::getFixed ( RVFI->getVarArgsSaveSize () );
617
684
if (FI >= 0 )
618
- Offset -= RVFI->getLibCallStackSize ();
685
+ Offset -= StackOffset::getFixed (RVFI->getLibCallStackSize ());
686
+ // When using FP to access scalable vector objects, we need to minus
687
+ // the frame size.
688
+ //
689
+ // |--------------------------| -- <-- FP
690
+ // | callee-saved registers | |
691
+ // |--------------------------| | MFI.getStackSize()
692
+ // | scalar local variables | |
693
+ // |--------------------------| -- (Offset of RVV objects is from here.)
694
+ // | RVV objects |
695
+ // |--------------------------|
696
+ // | VarSize objects |
697
+ // |--------------------------| <-- SP
698
+ if (MFI.getStackID (FI) == TargetStackID::ScalableVector)
699
+ Offset -= StackOffset::getFixed (MFI.getStackSize ());
619
700
} else {
620
- Offset += MFI.getStackSize ();
621
- if (FI < 0 )
622
- Offset += RVFI->getLibCallStackSize ();
701
+ // When using SP to access frame objects, we need to add RVV stack size.
702
+ //
703
+ // |--------------------------| -- <-- FP
704
+ // | callee-saved registers | |
705
+ // |--------------------------| | MFI.getStackSize()
706
+ // | scalar local variables | |
707
+ // |--------------------------| --
708
+ // | RVV objects | | RVFI->getRVVStackSize()
709
+ // |--------------------------| -- <-- SP
710
+ Offset += StackOffset::getScalable (RVFI->getRVVStackSize ());
711
+ if (MFI.getStackID (FI) == TargetStackID::Default) {
712
+ Offset += StackOffset::getFixed (MFI.getStackSize ());
713
+ if (FI < 0 )
714
+ Offset += StackOffset::getFixed (RVFI->getLibCallStackSize ());
715
+ }
623
716
}
624
717
}
625
- return StackOffset::getFixed (Offset);
718
+
719
+ return Offset;
626
720
}
627
721
628
722
void RISCVFrameLowering::determineCalleeSaves (MachineFunction &MF,
@@ -670,6 +764,37 @@ void RISCVFrameLowering::determineCalleeSaves(MachineFunction &MF,
670
764
}
671
765
}
672
766
767
+ int64_t
768
+ RISCVFrameLowering::assignRVVStackObjectOffsets (MachineFrameInfo &MFI) const {
769
+ int64_t Offset = 0 ;
770
+ // Create a buffer of RVV objects to allocate.
771
+ SmallVector<int , 8 > ObjectsToAllocate;
772
+ for (int I = 0 , E = MFI.getObjectIndexEnd (); I != E; ++I) {
773
+ unsigned StackID = MFI.getStackID (I);
774
+ if (StackID != TargetStackID::ScalableVector)
775
+ continue ;
776
+ if (MFI.isDeadObjectIndex (I))
777
+ continue ;
778
+
779
+ ObjectsToAllocate.push_back (I);
780
+ }
781
+
782
+ // Allocate all RVV locals and spills
783
+ for (int FI : ObjectsToAllocate) {
784
+ // ObjectSize in bytes.
785
+ int64_t ObjectSize = MFI.getObjectSize (FI);
786
+ // If the data type is the fractional vector type, reserve one vector
787
+ // register for it.
788
+ if (ObjectSize < 8 )
789
+ ObjectSize = 8 ;
790
+ // Currently, all scalable vector types are aligned to 8 bytes.
791
+ Offset = alignTo (Offset + ObjectSize, 8 );
792
+ MFI.setObjectOffset (FI, -Offset);
793
+ }
794
+
795
+ return Offset;
796
+ }
797
+
673
798
void RISCVFrameLowering::processFunctionBeforeFrameFinalized (
674
799
MachineFunction &MF, RegScavenger *RS) const {
675
800
const TargetRegisterInfo *RegInfo = MF.getSubtarget ().getRegisterInfo ();
@@ -686,6 +811,10 @@ void RISCVFrameLowering::processFunctionBeforeFrameFinalized(
686
811
RegInfo->getSpillAlign (*RC), false );
687
812
RS->addScavengingFrameIndex (RegScavFI);
688
813
}
814
+
815
+ auto *RVFI = MF.getInfo <RISCVMachineFunctionInfo>();
816
+ int64_t RVVStackSize = assignRVVStackObjectOffsets (MFI);
817
+ RVFI->setRVVStackSize (RVVStackSize);
689
818
}
690
819
691
820
// Not preserve stack space within prologue for outgoing variables when the
@@ -786,7 +915,7 @@ bool RISCVFrameLowering::spillCalleeSavedRegisters(
786
915
}
787
916
788
917
// Manually spill values not spilled by libcall.
789
- const auto &NonLibcallCSI = getNonLibcallCSI (CSI);
918
+ const auto &NonLibcallCSI = getNonLibcallCSI (*MF, CSI);
790
919
for (auto &CS : NonLibcallCSI) {
791
920
// Insert the spill to the stack frame.
792
921
Register Reg = CS.getReg ();
@@ -811,7 +940,7 @@ bool RISCVFrameLowering::restoreCalleeSavedRegisters(
811
940
812
941
// Manually restore values not restored by libcall. Insert in reverse order.
813
942
// loadRegFromStackSlot can insert multiple instructions.
814
- const auto &NonLibcallCSI = getNonLibcallCSI (CSI);
943
+ const auto &NonLibcallCSI = getNonLibcallCSI (*MF, CSI);
815
944
for (auto &CS : reverse (NonLibcallCSI)) {
816
945
Register Reg = CS.getReg ();
817
946
const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass (Reg);
@@ -883,3 +1012,19 @@ bool RISCVFrameLowering::canUseAsEpilogue(const MachineBasicBlock &MBB) const {
883
1012
// replacing the successor with our own tail return at the end of our block.
884
1013
return SuccMBB->isReturnBlock () && SuccMBB->size () == 1 ;
885
1014
}
1015
+
1016
+ bool RISCVFrameLowering::isSupportedStackID (TargetStackID::Value ID) const {
1017
+ switch (ID) {
1018
+ case TargetStackID::Default:
1019
+ case TargetStackID::ScalableVector:
1020
+ return true ;
1021
+ case TargetStackID::NoAlloc:
1022
+ case TargetStackID::SGPRSpill:
1023
+ return false ;
1024
+ }
1025
+ llvm_unreachable (" Invalid TargetStackID::Value" );
1026
+ }
1027
+
1028
+ TargetStackID::Value RISCVFrameLowering::getStackIDForScalableVectors () const {
1029
+ return TargetStackID::ScalableVector;
1030
+ }
0 commit comments