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"
@@ -90,22 +91,52 @@ bool X86LowerTileCopy::runOnMachineFunction(MachineFunction &MF) {
90
91
unsigned Size = TRI->getSpillSize (X86::TILERegClass);
91
92
Align Alignment = TRI->getSpillAlign (X86::TILERegClass);
92
93
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
94
98
- // TODO: Pick a killed regiter to avoid save/reload. There is problem
95
+ int StrideSS = 0 ;
96
+
97
+ LiveRegUnits UsedRegs (*TRI);
98
+ UsedRegs.addLiveOuts (MBB);
99
+
100
+ auto InstUpToMI = MBB.end ();
101
+ while (InstUpToMI != MI)
102
+ // The pre-decrement is on purpose here.
103
+ // We want to have the liveness right before I.
104
+ UsedRegs.stepBackward (*--InstUpToMI);
105
+
106
+ // Look for a temporary register to use.
107
+ BitVector GR64Regs =
108
+ TRI->getAllocatableSet (MF, TRI->getRegClass (X86::GR64RegClassID));
109
+ // Pick a killed regiter to avoid save/reload. There is problem
99
110
// to get live interval in this stage.
100
111
Register GR64Cand = X86::RAX;
101
112
113
+ // Find the first available-register that is available
114
+ bool found = false ;
115
+ for (auto RegT : GR64Regs.set_bits ()) {
116
+ if (UsedRegs.available (RegT)) {
117
+ GR64Cand = RegT;
118
+ break ;
119
+ }
120
+ }
121
+
102
122
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 );
123
+ if (found) {
124
+ // mov 64 %reg
125
+ BuildMI (MBB, MI, DL, TII->get (X86::MOV64ri), GR64Cand).addImm (64 );
126
+ } else {
127
+ // Allocate stack slot for stride register
128
+ Size = TRI->getSpillSize (X86::GR64RegClass);
129
+ Alignment = TRI->getSpillAlign (X86::GR64RegClass);
130
+ StrideSS = MF.getFrameInfo ().CreateSpillStackObject (Size, Alignment);
131
+
132
+ // mov %reg (%sp)
133
+ BuildMI (MBB, MI, DL, TII->get (X86::IMPLICIT_DEF), GR64Cand);
134
+ addFrameReference (BuildMI (MBB, MI, DL, TII->get (X86::MOV64mr)),
135
+ StrideSS)
136
+ .addReg (GR64Cand);
137
+ // mov 64 %reg
138
+ BuildMI (MBB, MI, DL, TII->get (X86::MOV64ri), GR64Cand).addImm (64 );
139
+ }
109
140
// tilestored %tmm, (%sp, %idx)
110
141
#define GET_EGPR_IF_ENABLED (OPC ) (ST.hasEGPR() ? OPC##_EVEX : OPC)
111
142
unsigned Opc = GET_EGPR_IF_ENABLED (X86::TILESTORED);
@@ -120,10 +151,12 @@ bool X86LowerTileCopy::runOnMachineFunction(MachineFunction &MF) {
120
151
#undef GET_EGPR_IF_ENABLED
121
152
NewMI = addFrameReference (BuildMI (MBB, MI, DL, TII->get (Opc), DstReg),
122
153
TileSS);
123
- // restore %rax
124
- // mov (%sp) %rax
125
- addFrameReference (BuildMI (MBB, MI, DL, TII->get (X86::MOV64rm), GR64Cand),
126
- StrideSS);
154
+ if (!found) {
155
+ // restore %rax
156
+ // mov (%sp) %rax
157
+ addFrameReference (
158
+ BuildMI (MBB, MI, DL, TII->get (X86::MOV64rm), GR64Cand), StrideSS);
159
+ }
127
160
MI.eraseFromParent ();
128
161
Changed = true ;
129
162
}
0 commit comments