Skip to content

Commit

Permalink
[DPWBS-1148] feat(InstrInfo): implement storeRegToStackSlot/loadRegFr…
Browse files Browse the repository at this point in the history
…omStackSlot

These functions are used to spill and reload values to / from the stack.
We need to handle all possible register sizes, i.e. 32 and 64 bit.

Tests are added for each case to demonstrate that we choose the correct
instruction for the given register class.
  • Loading branch information
konstantinschwarz committed Dec 4, 2019
1 parent 7565e49 commit 51d6059
Show file tree
Hide file tree
Showing 3 changed files with 249 additions and 0 deletions.
86 changes: 86 additions & 0 deletions llvm/lib/Target/TriCore/TriCoreInstrInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,3 +167,89 @@ void TriCoreInstrInfo::copyPhysReg(MachineBasicBlock &MBB,

llvm_unreachable("unimplemented reg-to-reg copy");
}

static unsigned getLoadStoreOpcode(unsigned SpillSize,
const TargetRegisterClass *RC, bool IsLoad) {

std::pair<unsigned, unsigned> Opc = {0, 0};

switch (SpillSize) {
case 4:
// If the source / destination is a 32-bit D register, choose LDW/STW
// If it is a 32-bit A register, choose LDA, STA
if (TriCore::DataRegsRegClass.hasSubClassEq(RC)) {
Opc = {TriCore::LDW_dalc, TriCore::STW_alcd};
} else if (TriCore::AddrRegsRegClass.hasSubClassEq(RC))
Opc = {TriCore::LDA_aalc, TriCore::STA_alca};
break;
case 8:
// If the source / destination is a 64-bit E register, choose LDD/STD
// If it is a 64-bit P register, choose LDDA/STDA
if (TriCore::ExtDataRegsRegClass.hasSubClassEq(RC)) {
Opc = {TriCore::LDD_eac, TriCore::STD_ace};
} else if (TriCore::ExtAddrRegsRegClass.hasSubClassEq(RC))
Opc = {TriCore::LDDA_pac, TriCore::STDA_acp};
break;
default:
llvm_unreachable("Unhandled register class!");
}

return IsLoad ? Opc.first : Opc.second;
}

void TriCoreInstrInfo::storeRegToStackSlot(
MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, unsigned SrcReg,
bool isKill, int FrameIndex, const TargetRegisterClass *RC,
const TargetRegisterInfo *TRI) const {
MachineFunction &MF = *MBB.getParent();
MachineFrameInfo &MFI = MF.getFrameInfo();
unsigned Align = MFI.getObjectAlignment(FrameIndex);

MachinePointerInfo PtrInfo =
MachinePointerInfo::getFixedStack(MF, FrameIndex);
MachineMemOperand *MMO =
MF.getMachineMemOperand(PtrInfo, MachineMemOperand::MOStore,
MFI.getObjectSize(FrameIndex), Align);

assert(!Register::isVirtualRegister(SrcReg) &&
"expected a physical register");
unsigned Opc =
getLoadStoreOpcode(TRI->getSpillSize(*RC), RC, /*IsLoad*/ false);
assert(Opc && "Unknown register class");

// Create the instruction in the expected form (immediate offset == 0)
// This is asserted in TriCoreRegisterInfo::eliminateFrameIndex
BuildMI(MBB, MI, DebugLoc(), get(Opc))
.addFrameIndex(FrameIndex)
.addImm(0)
.addReg(SrcReg, getKillRegState(isKill))
.addMemOperand(MMO);
}

void TriCoreInstrInfo::loadRegFromStackSlot(
MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, unsigned DestReg,
int FrameIndex, const TargetRegisterClass *RC,
const TargetRegisterInfo *TRI) const {
MachineFunction &MF = *MBB.getParent();
MachineFrameInfo &MFI = MF.getFrameInfo();
unsigned Align = MFI.getObjectAlignment(FrameIndex);

MachinePointerInfo PtrInfo =
MachinePointerInfo::getFixedStack(MF, FrameIndex);
MachineMemOperand *MMO = MF.getMachineMemOperand(
PtrInfo, MachineMemOperand::MOLoad, MFI.getObjectSize(FrameIndex), Align);

assert(!Register::isVirtualRegister(DestReg) &&
"expected a physical register");
unsigned Opc =
getLoadStoreOpcode(TRI->getSpillSize(*RC), RC, /*IsLoad*/ true);
assert(Opc && "Unknown register class");

// Create the instruction in the expected form (immediate offset == 0)
// This is asserted in TriCoreRegisterInfo::eliminateFrameIndex
BuildMI(MBB, MI, DebugLoc(), get(Opc))
.addDef(DestReg)
.addFrameIndex(FrameIndex)
.addImm(0)
.addMemOperand(MMO);
};
11 changes: 11 additions & 0 deletions llvm/lib/Target/TriCore/TriCoreInstrInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,17 @@ class TriCoreInstrInfo : public TriCoreGenInstrInfo {
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
const DebugLoc &DL, unsigned DestReg, unsigned SrcReg,
bool KillSrc) const override;

void storeRegToStackSlot(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI, unsigned SrcReg,
bool isKill, int FrameIndex,
const TargetRegisterClass *RC,
const TargetRegisterInfo *TRI) const override;

void loadRegFromStackSlot(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI, unsigned DestReg,
int FrameIndex, const TargetRegisterClass *RC,
const TargetRegisterInfo *TRI) const override;
};
} // namespace llvm
#endif // LLVM_LIB_TARGET_TRICORE_TRICOREINSTRINFO_H
152 changes: 152 additions & 0 deletions llvm/test/CodeGen/TriCore/stack-slots.mir
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
# RUN: llc -O0 -mtriple=tricore -run-pass=regallocfast -verify-machineinstrs %s \
# RUN: -o - | FileCheck %s

--- |
declare dso_local void @dummy_s32(i32) local_unnamed_addr
define dso_local i32 @copyDataRegToStackSlot(i32 returned %x) local_unnamed_addr {
entry:
tail call void @dummy_s32(i32 %x)
ret i32 %x
}

declare dso_local void @dummy_s64(i64) local_unnamed_addr
define dso_local i64 @copyExtDataRegToStackSlot(i64 returned %x) local_unnamed_addr {
entry:
tail call void @dummy_s64(i64 %x)
ret i64 %x
}

declare dso_local void @dummy_p0(i32*) local_unnamed_addr
define dso_local i32* @copyAddrRegToStackSlot(i32* returned %x) local_unnamed_addr {
entry:
tail call void @dummy_p0(i32* %x)
ret i32* %x
}

declare dso_local void @dummy_p64(i64) local_unnamed_addr
define dso_local i64 @copyExtAddrRegToStackSlot(i64 returned %x) local_unnamed_addr {
entry:
tail call void @dummy_p64(i64 %x)
ret i64 %x
}

...
---
name: copyDataRegToStackSlot
alignment: 1
legalized: true
regBankSelected: true
selected: true
tracksRegLiveness: true
registers:
- { id: 0, class: dataregs, preferred-register: '' }
liveins:
- { reg: '$d4', virtual-reg: '' }

# CHECK-LABEL: stack:
# CHECK: - { id: [[FRAMEINDEX:[0-9]+]], name: '', type: spill-slot, offset: 0, size: 4, alignment: 4,

body: |
bb.1.entry:
liveins: $d4
; CHECK: STW_alcd %stack.[[FRAMEINDEX]], 0, $d4 :: (store 4 into %stack.[[FRAMEINDEX]])
; CHECK-NEXT: CALL @dummy
; CHECK-NEXT: $d2 = LDW_dalc %stack.[[FRAMEINDEX]], 0 :: (load 4 from %stack.[[FRAMEINDEX]])
%0:dataregs = COPY $d4
$d4 = COPY %0
CALL @dummy_s32, csr_tricore_uppercontext, implicit-def $a11, implicit $psw, implicit $d4
$d2 = COPY %0
RET implicit $a11, implicit $d2
...

---
name: copyExtDataRegToStackSlot
alignment: 1
legalized: true
regBankSelected: true
selected: true
tracksRegLiveness: true
registers:
- { id: 0, class: extdataregs, preferred-register: '' }
liveins:
- { reg: '$e4', virtual-reg: '' }

# CHECK-LABEL: stack:
# CHECK: - { id: [[FRAMEINDEX:[0-9]+]], name: '', type: spill-slot, offset: 0, size: 8, alignment: 4,

body: |
bb.1.entry:
liveins: $e4
; CHECK: STD_ace %stack.[[FRAMEINDEX]], 0, $e4 :: (store 8 into %stack.[[FRAMEINDEX]], align 4)
; CHECK-NEXT: CALL @dummy
; CHECK-NEXT: $e2 = LDD_eac %stack.[[FRAMEINDEX]], 0 :: (load 8 from %stack.[[FRAMEINDEX]], align 4)
%0:extdataregs = COPY $e4
$e4 = COPY %0
CALL @dummy_s64, csr_tricore_uppercontext, implicit-def $a11, implicit $psw, implicit $e4
$e2 = COPY %0
RET implicit $a11, implicit $e2
...

---
name: copyAddrRegToStackSlot
alignment: 1
legalized: true
regBankSelected: true
selected: true
tracksRegLiveness: true
registers:
- { id: 0, class: addrregs, preferred-register: '' }
liveins:
- { reg: '$a4', virtual-reg: '' }

# CHECK-LABEL: stack:
# CHECK: - { id: [[FRAMEINDEX:[0-9]+]], name: '', type: spill-slot, offset: 0, size: 4, alignment: 4,

body: |
bb.1.entry:
liveins: $a4
; CHECK: STA_alca %stack.[[FRAMEINDEX]], 0, $a4 :: (store 4 into %stack.[[FRAMEINDEX]])
; CHECK-NEXT: CALL @dummy
; CHECK-NEXT: $a2 = LDA_aalc %stack.[[FRAMEINDEX]], 0 :: (load 4 from %stack.[[FRAMEINDEX]])
%0:addrregs = COPY $a4
$a4 = COPY %0
CALL @dummy_p0, csr_tricore_uppercontext, implicit-def $a11, implicit $psw, implicit $a4
$a2 = COPY %0
RET implicit $a11, implicit $a2
...

---
name: copyExtAddrRegToStackSlot
alignment: 1
legalized: true
regBankSelected: true
selected: true
tracksRegLiveness: true
registers:
- { id: 0, class: extaddrregs, preferred-register: '' }
liveins:
- { reg: '$e4', virtual-reg: '' }

# CHECK-LABEL: stack:
# CHECK: - { id: [[FRAMEINDEX:[0-9]+]], name: '', type: spill-slot, offset: 0, size: 8, alignment: 4,

body: |
bb.1.entry:
liveins: $p4
; CHECK: STDA_acp %stack.[[FRAMEINDEX]], 0, $p4 :: (store 8 into %stack.[[FRAMEINDEX]], align 4)
; CHECK-NEXT: CALL @dummy
; CHECK-NEXT: $p2 = LDDA_pac %stack.[[FRAMEINDEX]], 0 :: (load 8 from %stack.[[FRAMEINDEX]], align 4)
%0:extaddrregs = COPY $p4
$p4 = COPY %0
CALL @dummy_p64, csr_tricore_uppercontext, implicit-def $a11, implicit $psw, implicit $p4
$p2 = COPY %0
RET implicit $a11, implicit $p2
...

0 comments on commit 51d6059

Please sign in to comment.