llvm.org GIT mirror llvm / 6ee0857
[Sparc] Implement spill and load for long double(f128) registers. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@189768 91177308-0d34-0410-b5e6-96231b3b80d8 Venkatraman Govindaraju 6 years ago
3 changed file(s) with 138 addition(s) and 36 deletion(s). Raw diff Collapse all Expand all
4343 if (MI->getOpcode() == SP::LDri ||
4444 MI->getOpcode() == SP::LDXri ||
4545 MI->getOpcode() == SP::LDFri ||
46 MI->getOpcode() == SP::LDDFri) {
46 MI->getOpcode() == SP::LDDFri ||
47 MI->getOpcode() == SP::LDQFri) {
4748 if (MI->getOperand(1).isFI() && MI->getOperand(2).isImm() &&
4849 MI->getOperand(2).getImm() == 0) {
4950 FrameIndex = MI->getOperand(1).getIndex();
6364 if (MI->getOpcode() == SP::STri ||
6465 MI->getOpcode() == SP::STXri ||
6566 MI->getOpcode() == SP::STFri ||
66 MI->getOpcode() == SP::STDFri) {
67 MI->getOpcode() == SP::STDFri ||
68 MI->getOpcode() == SP::STQFri) {
6769 if (MI->getOperand(0).isFI() && MI->getOperand(1).isImm() &&
6870 MI->getOperand(1).getImm() == 0) {
6971 FrameIndex = MI->getOperand(0).getIndex();
272274 MachineBasicBlock::iterator I, DebugLoc DL,
273275 unsigned DestReg, unsigned SrcReg,
274276 bool KillSrc) const {
277 unsigned numSubRegs = 0;
278 unsigned movOpc = 0;
279 const unsigned *subRegIdx = 0;
280
281 const unsigned DFP_FP_SubRegsIdx[] = { SP::sub_even, SP::sub_odd };
282 const unsigned QFP_DFP_SubRegsIdx[] = { SP::sub_even64, SP::sub_odd64 };
283 const unsigned QFP_FP_SubRegsIdx[] = { SP::sub_even, SP::sub_odd,
284 SP::sub_odd64_then_sub_even,
285 SP::sub_odd64_then_sub_odd };
286
275287 if (SP::IntRegsRegClass.contains(DestReg, SrcReg))
276288 BuildMI(MBB, I, DL, get(SP::ORrr), DestReg).addReg(SP::G0)
277289 .addReg(SrcReg, getKillRegState(KillSrc));
284296 .addReg(SrcReg, getKillRegState(KillSrc));
285297 } else {
286298 // Use two FMOVS instructions.
287 const TargetRegisterInfo *TRI = &getRegisterInfo();
288 MachineInstr *MovMI = 0;
289 unsigned subRegIdx[] = {SP::sub_even, SP::sub_odd};
290 for (unsigned i = 0; i != 2; ++i) {
291 unsigned Dst = TRI->getSubReg(DestReg, subRegIdx[i]);
292 unsigned Src = TRI->getSubReg(SrcReg, subRegIdx[i]);
293 assert(Dst && Src && "Bad sub-register");
294
295 MovMI = BuildMI(MBB, I, DL, get(SP::FMOVS), Dst).addReg(Src);
299 subRegIdx = DFP_FP_SubRegsIdx;
300 numSubRegs = 2;
301 movOpc = SP::FMOVS;
302 }
303 } else if (SP::QFPRegsRegClass.contains(DestReg, SrcReg)) {
304 if (Subtarget.isV9()) {
305 if (Subtarget.hasHardQuad()) {
306 BuildMI(MBB, I, DL, get(SP::FMOVQ), DestReg)
307 .addReg(SrcReg, getKillRegState(KillSrc));
308 } else {
309 // Use two FMOVD instructions.
310 subRegIdx = QFP_DFP_SubRegsIdx;
311 numSubRegs = 2;
312 movOpc = SP::FMOVD;
296313 }
297 // Add implicit super-register defs and kills to the last MovMI.
298 MovMI->addRegisterDefined(DestReg, TRI);
299 if (KillSrc)
300 MovMI->addRegisterKilled(SrcReg, TRI);
314 } else {
315 // Use four FMOVS instructions.
316 subRegIdx = QFP_FP_SubRegsIdx;
317 numSubRegs = 4;
318 movOpc = SP::FMOVS;
301319 }
302320 } else
303321 llvm_unreachable("Impossible reg-to-reg copy");
322
323 if (numSubRegs == 0 || subRegIdx == 0 || movOpc == 0)
324 return;
325
326 const TargetRegisterInfo *TRI = &getRegisterInfo();
327 MachineInstr *MovMI = 0;
328
329 for (unsigned i = 0; i != numSubRegs; ++i) {
330 unsigned Dst = TRI->getSubReg(DestReg, subRegIdx[i]);
331 unsigned Src = TRI->getSubReg(SrcReg, subRegIdx[i]);
332 assert(Dst && Src && "Bad sub-register");
333
334 MovMI = BuildMI(MBB, I, DL, get(movOpc), Dst).addReg(Src);
335 }
336 // Add implicit super-register defs and kills to the last MovMI.
337 MovMI->addRegisterDefined(DestReg, TRI);
338 if (KillSrc)
339 MovMI->addRegisterKilled(SrcReg, TRI);
304340 }
305341
306342 void SparcInstrInfo::
320356 MFI.getObjectAlignment(FI));
321357
322358 // On the order of operands here: think "[FrameIdx + 0] = SrcReg".
323 if (RC == &SP::I64RegsRegClass)
359 if (RC == &SP::I64RegsRegClass)
324360 BuildMI(MBB, I, DL, get(SP::STXri)).addFrameIndex(FI).addImm(0)
325361 .addReg(SrcReg, getKillRegState(isKill)).addMemOperand(MMO);
326362 else if (RC == &SP::IntRegsRegClass)
329365 else if (RC == &SP::FPRegsRegClass)
330366 BuildMI(MBB, I, DL, get(SP::STFri)).addFrameIndex(FI).addImm(0)
331367 .addReg(SrcReg, getKillRegState(isKill)).addMemOperand(MMO);
332 else if (RC == &SP::DFPRegsRegClass)
368 else if (SP::DFPRegsRegClass.hasSubClassEq(RC))
333369 BuildMI(MBB, I, DL, get(SP::STDFri)).addFrameIndex(FI).addImm(0)
370 .addReg(SrcReg, getKillRegState(isKill)).addMemOperand(MMO);
371 else if (SP::QFPRegsRegClass.hasSubClassEq(RC))
372 // Use STQFri irrespective of its legality. If STQ is not legal, it will be
373 // lowered into two STDs in eliminateFrameIndex.
374 BuildMI(MBB, I, DL, get(SP::STQFri)).addFrameIndex(FI).addImm(0)
334375 .addReg(SrcReg, getKillRegState(isKill)).addMemOperand(MMO);
335376 else
336377 llvm_unreachable("Can't store this register to stack slot");
361402 else if (RC == &SP::FPRegsRegClass)
362403 BuildMI(MBB, I, DL, get(SP::LDFri), DestReg).addFrameIndex(FI).addImm(0)
363404 .addMemOperand(MMO);
364 else if (RC == &SP::DFPRegsRegClass)
405 else if (SP::DFPRegsRegClass.hasSubClassEq(RC))
365406 BuildMI(MBB, I, DL, get(SP::LDDFri), DestReg).addFrameIndex(FI).addImm(0)
407 .addMemOperand(MMO);
408 else if (SP::QFPRegsRegClass.hasSubClassEq(RC))
409 // Use LDQFri irrespective of its legality. If LDQ is not legal, it will be
410 // lowered into two LDDs in eliminateFrameIndex.
411 BuildMI(MBB, I, DL, get(SP::LDQFri), DestReg).addFrameIndex(FI).addImm(0)
366412 .addMemOperand(MMO);
367413 else
368414 llvm_unreachable("Can't load this register from stack slot");
8686 return Subtarget.is64Bit() ? &SP::I64RegsRegClass : &SP::IntRegsRegClass;
8787 }
8888
89 static void replaceFI(MachineFunction &MF,
90 MachineBasicBlock::iterator II,
91 MachineInstr &MI,
92 DebugLoc dl,
93 unsigned FIOperandNum, int Offset,
94 unsigned FramePtr)
95 {
96 // Replace frame index with a frame pointer reference.
97 if (Offset >= -4096 && Offset <= 4095) {
98 // If the offset is small enough to fit in the immediate field, directly
99 // encode it.
100 MI.getOperand(FIOperandNum).ChangeToRegister(FramePtr, false);
101 MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
102 } else {
103 // Otherwise, emit a G1 = SETHI %hi(offset). FIXME: it would be better to
104 // scavenge a register here instead of reserving G1 all of the time.
105 const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
106 unsigned OffHi = (unsigned)Offset >> 10U;
107 BuildMI(*MI.getParent(), II, dl, TII.get(SP::SETHIi), SP::G1).addImm(OffHi);
108 // Emit G1 = G1 + I6
109 BuildMI(*MI.getParent(), II, dl, TII.get(SP::ADDrr), SP::G1).addReg(SP::G1)
110 .addReg(FramePtr);
111 // Insert: G1+%lo(offset) into the user.
112 MI.getOperand(FIOperandNum).ChangeToRegister(SP::G1, false);
113 MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset & ((1 << 10)-1));
114 }
115 }
116
117
89118 void
90119 SparcRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
91120 int SPAdj, unsigned FIOperandNum,
110139 Offset += (stackSize) ? Subtarget.getAdjustedFrameSize(stackSize) : 0 ;
111140 }
112141
113 // Replace frame index with a frame pointer reference.
114 if (Offset >= -4096 && Offset <= 4095) {
115 // If the offset is small enough to fit in the immediate field, directly
116 // encode it.
117 MI.getOperand(FIOperandNum).ChangeToRegister(FramePtr, false);
118 MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
119 } else {
120 // Otherwise, emit a G1 = SETHI %hi(offset). FIXME: it would be better to
121 // scavenge a register here instead of reserving G1 all of the time.
122 const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
123 unsigned OffHi = (unsigned)Offset >> 10U;
124 BuildMI(*MI.getParent(), II, dl, TII.get(SP::SETHIi), SP::G1).addImm(OffHi);
125 // Emit G1 = G1 + I6
126 BuildMI(*MI.getParent(), II, dl, TII.get(SP::ADDrr), SP::G1).addReg(SP::G1)
127 .addReg(FramePtr);
128 // Insert: G1+%lo(offset) into the user.
129 MI.getOperand(FIOperandNum).ChangeToRegister(SP::G1, false);
130 MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset & ((1 << 10)-1));
142 if (!Subtarget.isV9() || !Subtarget.hasHardQuad()) {
143 if (MI.getOpcode() == SP::STQFri) {
144 const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
145 unsigned SrcReg = MI.getOperand(2).getReg();
146 unsigned SrcEvenReg = getSubReg(SrcReg, SP::sub_even64);
147 unsigned SrcOddReg = getSubReg(SrcReg, SP::sub_odd64);
148 MachineInstr *StMI =
149 BuildMI(*MI.getParent(), II, dl, TII.get(SP::STDFri))
150 .addReg(FramePtr).addImm(0).addReg(SrcEvenReg);
151 replaceFI(MF, II, *StMI, dl, 0, Offset, FramePtr);
152 MI.setDesc(TII.get(SP::STDFri));
153 MI.getOperand(2).setReg(SrcOddReg);
154 Offset += 8;
155 } else if (MI.getOpcode() == SP::LDQFri) {
156 const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
157 unsigned DestReg = MI.getOperand(0).getReg();
158 unsigned DestEvenReg = getSubReg(DestReg, SP::sub_even64);
159 unsigned DestOddReg = getSubReg(DestReg, SP::sub_odd64);
160 MachineInstr *StMI =
161 BuildMI(*MI.getParent(), II, dl, TII.get(SP::LDDFri), DestEvenReg)
162 .addReg(FramePtr).addImm(0);
163 replaceFI(MF, II, *StMI, dl, 1, Offset, FramePtr);
164
165 MI.setDesc(TII.get(SP::LDDFri));
166 MI.getOperand(0).setReg(DestOddReg);
167 Offset += 8;
168 }
131169 }
170
171 replaceFI(MF, II, MI, dl, FIOperandNum, Offset, FramePtr);
172
132173 }
133174
134175 unsigned SparcRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
2424 store fp128 %7, fp128* %scalar.result, align 8
2525 ret void
2626 }
27
28 ; CHECK-LABEL: f128_spill
29 ; CHECK: std %f{{.+}}, [%[[S0:.+]]]
30 ; CHECK: std %f{{.+}}, [%[[S1:.+]]]
31 ; CHECK-DAG: ldd [%[[S0]]], %f{{.+}}
32 ; CHECK-DAG: ldd [%[[S1]]], %f{{.+}}
33 ; CHECK: jmp
34
35 define void @f128_spill(fp128* noalias sret %scalar.result, fp128* byval %a) {
36 entry:
37 %0 = load fp128* %a, align 8
38 call void asm sideeffect "", "~{f0},~{f1},~{f2},~{f3},~{f4},~{f5},~{f6},~{f7},~{f8},~{f9},~{f10},~{f11},~{f12},~{f13},~{f14},~{f15},~{f16},~{f17},~{f18},~{f19},~{f20},~{f21},~{f22},~{f23},~{f24},~{f25},~{f26},~{f27},~{f28},~{f29},~{f30},~{f31}"()
39 store fp128 %0, fp128* %scalar.result, align 8
40 ret void
41 }