20
20
#include " X86InstrBuilder.h"
21
21
#include " X86InstrInfo.h"
22
22
#include " X86Subtarget.h"
23
+ #include " llvm/CodeGen/LiveRegUnits.h"
23
24
#include " llvm/CodeGen/MachineBasicBlock.h"
24
25
#include " llvm/CodeGen/MachineFrameInfo.h"
25
26
#include " llvm/CodeGen/MachineFunction.h"
@@ -72,10 +73,28 @@ FunctionPass *llvm::createX86LowerTileCopyPass() {
72
73
bool X86LowerTileCopy::runOnMachineFunction (MachineFunction &MF) {
73
74
const X86Subtarget &ST = MF.getSubtarget <X86Subtarget>();
74
75
const X86InstrInfo *TII = ST.getInstrInfo ();
76
+ const TargetRegisterInfo *TRI = ST.getRegisterInfo ();
77
+ BitVector GR64Regs =
78
+ TRI->getAllocatableSet (MF, TRI->getRegClass (X86::GR64RegClassID));
79
+ BitVector TILERegs =
80
+ TRI->getAllocatableSet (MF, TRI->getRegClass (X86::TILERegClassID));
75
81
bool Changed = false ;
76
82
77
83
for (MachineBasicBlock &MBB : MF) {
78
- for (MachineInstr &MI : llvm::make_early_inc_range (MBB)) {
84
+ // There won't be a tile copy if no tile register live in.
85
+ bool HasTileCopy = false ;
86
+ for (const auto &LI : MBB.liveins ()) {
87
+ if (TILERegs.test (LI.PhysReg )) {
88
+ HasTileCopy = true ;
89
+ break ;
90
+ }
91
+ }
92
+ if (!HasTileCopy)
93
+ continue ;
94
+ LiveRegUnits UsedRegs (*TRI);
95
+ UsedRegs.addLiveOuts (MBB);
96
+ for (MachineInstr &MI : llvm::make_early_inc_range (reverse (MBB))) {
97
+ UsedRegs.stepBackward (MI);
79
98
if (!MI.isCopy ())
80
99
continue ;
81
100
MachineOperand &DstMO = MI.getOperand (0 );
@@ -85,27 +104,41 @@ bool X86LowerTileCopy::runOnMachineFunction(MachineFunction &MF) {
85
104
if (!X86::TILERegClass.contains (DstReg, SrcReg))
86
105
continue ;
87
106
88
- const TargetRegisterInfo *TRI = ST.getRegisterInfo ();
89
107
// Allocate stack slot for tile register
90
108
unsigned Size = TRI->getSpillSize (X86::TILERegClass);
91
109
Align Alignment = TRI->getSpillAlign (X86::TILERegClass);
92
110
int TileSS = MF.getFrameInfo ().CreateSpillStackObject (Size , Alignment);
93
- // Allocate stack slot for stride register
94
- Size = TRI->getSpillSize (X86::GR64RegClass);
95
- Alignment = TRI->getSpillAlign (X86::GR64RegClass);
96
- int StrideSS = MF.getFrameInfo ().CreateSpillStackObject (Size , Alignment);
97
111
98
- // TODO: Pick a killed regiter to avoid save/reload. There is problem
99
- // to get live interval in this stage.
100
- Register GR64Cand = X86::RAX;
112
+ int StrideSS = 0 ;
113
+
114
+ // Pick a killed register to avoid a save/reload.
115
+ Register GR64Cand = X86::NoRegister;
116
+ for (auto RegT : GR64Regs.set_bits ()) {
117
+ if (UsedRegs.available (RegT)) {
118
+ GR64Cand = RegT;
119
+ break ;
120
+ }
121
+ }
101
122
102
123
const DebugLoc &DL = MI.getDebugLoc ();
103
- // mov %rax (%sp)
104
- BuildMI (MBB, MI, DL, TII->get (X86::IMPLICIT_DEF), GR64Cand);
105
- addFrameReference (BuildMI (MBB, MI, DL, TII->get (X86::MOV64mr)), StrideSS)
106
- .addReg (GR64Cand);
107
- // mov 64 %rax
108
- BuildMI (MBB, MI, DL, TII->get (X86::MOV64ri), GR64Cand).addImm (64 );
124
+ if (GR64Cand) {
125
+ // mov 64 %reg
126
+ BuildMI (MBB, MI, DL, TII->get (X86::MOV64ri), GR64Cand).addImm (64 );
127
+ } else {
128
+ // No available register? Save RAX and reload it after use.
129
+
130
+ // Allocate stack slot for stride register
131
+ Size = TRI->getSpillSize (X86::GR64RegClass);
132
+ Alignment = TRI->getSpillAlign (X86::GR64RegClass);
133
+ StrideSS = MF.getFrameInfo ().CreateSpillStackObject (Size , Alignment);
134
+
135
+ // mov %reg (%sp)
136
+ addFrameReference (BuildMI (MBB, MI, DL, TII->get (X86::MOV64mr)),
137
+ StrideSS)
138
+ .addReg (X86::RAX);
139
+ // mov 64 %reg
140
+ BuildMI (MBB, MI, DL, TII->get (X86::MOV64ri), X86::RAX).addImm (64 );
141
+ }
109
142
// tilestored %tmm, (%sp, %idx)
110
143
#define GET_EGPR_IF_ENABLED (OPC ) (ST.hasEGPR() ? OPC##_EVEX : OPC)
111
144
unsigned Opc = GET_EGPR_IF_ENABLED (X86::TILESTORED);
@@ -120,10 +153,12 @@ bool X86LowerTileCopy::runOnMachineFunction(MachineFunction &MF) {
120
153
#undef GET_EGPR_IF_ENABLED
121
154
NewMI = addFrameReference (BuildMI (MBB, MI, DL, TII->get (Opc), DstReg),
122
155
TileSS);
123
- // restore %rax
124
- // mov (%sp) %rax
125
- addFrameReference (BuildMI (MBB, MI, DL, TII->get (X86::MOV64rm), GR64Cand),
126
- StrideSS);
156
+ if (!GR64Cand) {
157
+ // restore %rax
158
+ // mov (%sp) %rax
159
+ addFrameReference (
160
+ BuildMI (MBB, MI, DL, TII->get (X86::MOV64rm), GR64Cand), StrideSS);
161
+ }
127
162
MI.eraseFromParent ();
128
163
Changed = true ;
129
164
}
0 commit comments