blob: c53a7e10d54877a024ddd9bef6044c2c4d097f9a [file] [log] [blame]
Tom Stellard75aadc22012-12-11 21:25:42 +00001//===-- SIMachineFunctionInfo.cpp - SI Machine Function Info -------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8/// \file
9//===----------------------------------------------------------------------===//
10
11
12#include "SIMachineFunctionInfo.h"
Tom Stellardeba61072014-05-02 15:41:42 +000013#include "SIInstrInfo.h"
Tom Stellardc149dc02013-11-27 21:23:35 +000014#include "SIRegisterInfo.h"
15#include "llvm/CodeGen/MachineRegisterInfo.h"
Tom Stellardeba61072014-05-02 15:41:42 +000016#include "llvm/IR/Function.h"
17#include "llvm/IR/LLVMContext.h"
Tom Stellardc149dc02013-11-27 21:23:35 +000018
19#define MAX_LANES 64
Tom Stellard75aadc22012-12-11 21:25:42 +000020
21using namespace llvm;
22
Juergen Ributzkad12ccbd2013-11-19 00:57:56 +000023
24// Pin the vtable to this file.
25void SIMachineFunctionInfo::anchor() {}
26
Tom Stellard75aadc22012-12-11 21:25:42 +000027SIMachineFunctionInfo::SIMachineFunctionInfo(const MachineFunction &MF)
Vincent Lejeuneace6f732013-04-01 21:47:53 +000028 : AMDGPUMachineFunction(MF),
Tom Stellardc149dc02013-11-27 21:23:35 +000029 PSInputAddr(0),
Tom Stellardb02094e2014-07-21 15:45:01 +000030 SpillTracker(),
31 NumUserSGPRs(0) { }
Tom Stellardc149dc02013-11-27 21:23:35 +000032
Tom Stellardeba61072014-05-02 15:41:42 +000033static unsigned createLaneVGPR(MachineRegisterInfo &MRI, MachineFunction *MF) {
34 unsigned VGPR = MRI.createVirtualRegister(&AMDGPU::VReg_32RegClass);
Tom Stellardc149dc02013-11-27 21:23:35 +000035
Tom Stellardeba61072014-05-02 15:41:42 +000036 // We need to add this register as live out for the function, in order to
37 // have the live range calculated directly.
38 //
39 // When register spilling begins, we have already calculated the live
40 // live intervals for all the registers. Since we are spilling SGPRs to
41 // VGPRs, we need to update the Lane VGPR's live interval every time we
42 // spill or restore a register.
43 //
44 // Unfortunately, there is no good way to update the live interval as
45 // the TargetInstrInfo callbacks for spilling and restoring don't give
46 // us access to the live interval information.
47 //
48 // We are lucky, though, because the InlineSpiller calls
49 // LiveRangeEdit::calculateRegClassAndHint() which iterates through
50 // all the new register that have been created when restoring a register
51 // and calls LiveIntervals::getInterval(), which creates and computes
52 // the live interval for the newly created register. However, once this
53 // live intervals is created, it doesn't change and since we usually reuse
54 // the Lane VGPR multiple times, this means any uses after the first aren't
55 // added to the live interval.
56 //
57 // To work around this, we add Lane VGPRs to the functions live out list,
58 // so that we can guarantee its live range will cover all of its uses.
59
60 for (MachineBasicBlock &MBB : *MF) {
61 if (MBB.back().getOpcode() == AMDGPU::S_ENDPGM) {
62 MBB.back().addOperand(*MF, MachineOperand::CreateReg(VGPR, false, true));
63 return VGPR;
Tom Stellardc149dc02013-11-27 21:23:35 +000064 }
65 }
Matt Arsenaultfda9dad2014-07-07 18:34:42 +000066
67 LLVMContext &Ctx = MF->getFunction()->getContext();
68 Ctx.emitError("Could not find S_ENDPGM instruction.");
69
Tom Stellardeba61072014-05-02 15:41:42 +000070 return VGPR;
71}
72
73unsigned SIMachineFunctionInfo::RegSpillTracker::reserveLanes(
74 MachineRegisterInfo &MRI, MachineFunction *MF, unsigned NumRegs) {
75 unsigned StartLane = CurrentLane;
76 CurrentLane += NumRegs;
77 if (!LaneVGPR) {
78 LaneVGPR = createLaneVGPR(MRI, MF);
79 } else {
80 if (CurrentLane >= MAX_LANES) {
81 StartLane = CurrentLane = 0;
82 LaneVGPR = createLaneVGPR(MRI, MF);
83 }
84 }
85 return StartLane;
Tom Stellardc149dc02013-11-27 21:23:35 +000086}
87
88void SIMachineFunctionInfo::RegSpillTracker::addSpilledReg(unsigned FrameIndex,
89 unsigned Reg,
90 int Lane) {
91 SpilledRegisters[FrameIndex] = SpilledReg(Reg, Lane);
92}
93
94const SIMachineFunctionInfo::SpilledReg&
95SIMachineFunctionInfo::RegSpillTracker::getSpilledReg(unsigned FrameIndex) {
96 return SpilledRegisters[FrameIndex];
97}