Skip to content

Commit

Permalink
[DPWBS-1149] feat(RegisterInfo): implement eliminateFrameIndex
Browse files Browse the repository at this point in the history
Replace frame index operand with $a14 and immediate if offset does not
exceed 16-bits.

Otherwise, materialize the offset into a register and use an explicit
ADDA_aaa $a14, %offset instruction. Replace the frame index with the
result of this instruction and set the offset immediate to 0.

add tests for eliminateFrameIndex

add XFAIL test until we implement emitProlog/emitEpilogue
  • Loading branch information
gargaroff committed Dec 4, 2019
1 parent 548ac0d commit 7565e49
Show file tree
Hide file tree
Showing 4 changed files with 188 additions and 1 deletion.
82 changes: 81 additions & 1 deletion llvm/lib/Target/TriCore/TriCoreRegisterInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
#include "llvm/CodeGen/TargetInstrInfo.h"
#include "llvm/Support/ErrorHandling.h"

#define DEBUG_TYPE "tricore-reg-info"

#define GET_REGINFO_TARGET_DESC
#include "TriCoreGenRegisterInfo.inc"

Expand Down Expand Up @@ -59,10 +61,88 @@ TriCoreRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
return Reserved;
}

bool TriCoreRegisterInfo::requiresRegisterScavenging(
const MachineFunction &MF) const {
// We might introduce virtual registers and therefore require scavenging
return true;
}

bool TriCoreRegisterInfo::requiresFrameIndexScavenging(
const MachineFunction &MF) const {
// We might introduce virtual registers and therefore require scavenging
return true;
}

void TriCoreRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
int SPAdj, unsigned FIOperandNum,
RegScavenger *RS) const {
report_fatal_error("Subroutines not supported yet");
assert(SPAdj == 0 && "Unexpected SPAdj");

// Common helpers
MachineInstr &MI = *II;
MachineFunction &MF = *MI.getParent()->getParent();
MachineRegisterInfo &MRI = MF.getRegInfo();
const TriCoreInstrInfo *TII =
MF.getSubtarget<TriCoreSubtarget>().getInstrInfo();

// Calculate the offset of the frame index and the frame register
const int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
unsigned FrameReg;

assert(MI.getOperand(FIOperandNum + 1).getImm() == 0 &&
"Unexpected offset operand");

int Offset =
getFrameLowering(MF)->getFrameIndexReference(MF, FrameIndex, FrameReg);

// Make sure that the Offset is within supported bounds
if (!isInt<32>(Offset)) {
LLVM_DEBUG(dbgs() << "Offset not within 32-bits: " << Offset << '\n');
report_fatal_error(
"Frame offsets outside of the signed 32-bit range not supported.");
}

MachineBasicBlock &MBB = *MI.getParent();
bool FrameRegIsKill = false;

// Check if the offset can fit into an 16-bit immediate
if (!isInt<16>(Offset)) {
// Materialize the offset in a register, then use ADD.A with frame register
// Calculation taken from chapter 2.7 Address Arithmetic
const uint64_t OffsetUnsigned = (static_cast<uint64_t>(Offset));
uint64_t Low16 = OffsetUnsigned & 0xFFFFu;
uint64_t High16 = ((OffsetUnsigned + 0x8000u) >> 16u) & 0xFFFFu;

const Register ScratchReg =
MRI.createVirtualRegister(&TriCore::AddrRegsRegClass);

BuildMI(MBB, II, MI.getDebugLoc(), TII->get(TriCore::MOVHA_ac), ScratchReg)
.addImm(High16);

BuildMI(MBB, II, MI.getDebugLoc(), TII->get(TriCore::LEA_aac), ScratchReg)
.addUse(ScratchReg)
.addImm(Low16);

// Build an explicit ADD.A instruction. This might create a situation like
// this:
// %frame_addr = ADD.A %frame_reg, %offset
// %foo = LEA %frame_addr, 0
//
// TODO: delete possibly redundant LEA instruction
BuildMI(MBB, II, MI.getDebugLoc(), TII->get(TriCore::ADDA_aaa), ScratchReg)
.addUse(FrameReg)
.addUse(ScratchReg);

// Update FrameReg, Offset and kill status
FrameReg = ScratchReg;
Offset = 0;
FrameRegIsKill = true;
}

// We can use the instruction directly
MI.getOperand(FIOperandNum)
.ChangeToRegister(FrameReg, false, false, FrameRegIsKill);
MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
}

Register
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Target/TriCore/TriCoreRegisterInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ struct TriCoreRegisterInfo : public TriCoreGenRegisterInfo {

BitVector getReservedRegs(const MachineFunction &MF) const override;

bool requiresFrameIndexScavenging(const MachineFunction &MF) const override;
bool requiresRegisterScavenging(const MachineFunction &MF) const override;

void eliminateFrameIndex(MachineBasicBlock::iterator MI, int SPAdj,
unsigned FIOperandNum,
RegScavenger *RS = nullptr) const override;
Expand Down
42 changes: 42 additions & 0 deletions llvm/test/CodeGen/TriCore/elim-frame-index-xfail.mir
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# RUN: llc -mtriple=tricore -run-pass=prologepilog -verify-machineinstrs %s -o -
# XFAIL: *

# This will fail as long we as we don't implement emitProlog/Epilogue because
# $a14 is not defined / declared as a live-in

--- |
%struct.bar = type { i32, i32 }

define dso_local void @test_frame_index_elimination() {
entry:
%ptr0 = alloca [65536 x i32], align 4
%ptr1 = alloca [65536 x i32], align 4
%ptr2 = alloca %struct.bar, align 4
ret void
}

...
---
name: test_frame_index_elimination
legalized: true
regBankSelected: true
selected: true
tracksRegLiveness: true
stack:
- { id: 0, name: ptr0, type: default, offset: 0, size: 262144, alignment: 4 }
- { id: 1, name: ptr1, type: default, offset: 0, size: 262144, alignment: 4 }
- { id: 2, name: ptr2, type: default, offset: 0, size: 8, alignment: 4 }
body: |
bb.0.entry:
liveins: $d4
$a2 = LEA_aac %stack.0.ptr0, 0
$a3 = LEA_aac %stack.1.ptr1, 0
$a4 = LEA_aac %stack.2.ptr2, 0
STW_alcd %stack.0.ptr0, 0, $d4
STW_alcd %stack.1.ptr1, 0, $d4
STW_alcd %stack.2.ptr2, 0, killed $d4
$d2 = LDW_dalc %stack.0.ptr0, 0
$d3 = LDW_dalc %stack.1.ptr1, 0
$d4 = LDW_dalc %stack.2.ptr2, 0
...
62 changes: 62 additions & 0 deletions llvm/test/CodeGen/TriCore/elim-frame-index.mir
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
# RUN: llc -mtriple=tricore -run-pass=prologepilog -verify-machineinstrs %s -o - | FileCheck %s

--- |
%struct.bar = type { i32, i32 }

define dso_local void @test_frame_index_elimination() {
entry:
%ptr0 = alloca [65536 x i32], align 4
%ptr1 = alloca [65536 x i32], align 4
%ptr2 = alloca %struct.bar, align 4
ret void
}

...
---
name: test_frame_index_elimination
legalized: true
regBankSelected: true
selected: true
tracksRegLiveness: true
stack:
- { id: 0, name: ptr0, type: default, offset: 0, size: 262144, alignment: 4 }
- { id: 1, name: ptr1, type: default, offset: 0, size: 262144, alignment: 4 }
- { id: 2, name: ptr2, type: default, offset: 0, size: 8, alignment: 4 }
body: |
bb.0.entry:
; $a14 is needed as we are not implementing emitProlog/Epilogue yet.
liveins: $a14, $d4
; CHECK-LABEL: name: test_frame_index_elimination
; CHECK: id: 0, name: ptr0, type: default, offset: -262144, size: 262144
; CHECK: id: 1, name: ptr1, type: default, offset: -524288, size: 262144
; CHECK: id: 2, name: ptr2, type: default, offset: -524296, size: 8
; CHECK: liveins: $a14, $d4
; CHECK: $a15 = MOVHA_ac 4
; CHECK-NEXT: $a15 = LEA_aac $a15, 8
; CHECK-NEXT: $a15 = ADDA_aaa $a14, $a15
; CHECK-NEXT: $a2 = LEA_aac killed $a15, 0
; CHECK: $a3 = LEA_aac $a14, 8
; CHECK: $a4 = LEA_aac $a14, 0
; CHECK: $a15 = MOVHA_ac 4
; CHECK-NEXT: $a15 = LEA_aac $a15, 8
; CHECK-NEXT: $a15 = ADDA_aaa $a14, $a15
; CHECK-NEXT: STW_alcd killed $a15, 0, $d4 :: (store 4)
; CHECK: STW_alcd $a14, 8, $d4 :: (store 4)
; CHECK: STW_alcd $a14, 0, killed $d4 :: (store 4)
; CHECK: $a15 = MOVHA_ac 4
; CHECK-NEXT: $a15 = LEA_aac $a15, 8
; CHECK-NEXT: $a15 = ADDA_aaa $a14, $a15
; CHECK-NEXT: $d2 = LDW_dalc killed $a15, 0 :: (load 4)
; CHECK: $d3 = LDW_dalc $a14, 8 :: (load 4)
; CHECK: $d4 = LDW_dalc $a14, 0 :: (load 4)
$a2 = LEA_aac %stack.0.ptr0, 0
$a3 = LEA_aac %stack.1.ptr1, 0
$a4 = LEA_aac %stack.2.ptr2, 0
STW_alcd %stack.0.ptr0, 0, $d4 :: (store 4)
STW_alcd %stack.1.ptr1, 0, $d4 :: (store 4)
STW_alcd %stack.2.ptr2, 0, killed $d4 :: (store 4)
$d2 = LDW_dalc %stack.0.ptr0, 0 :: (load 4)
$d3 = LDW_dalc %stack.1.ptr1, 0 :: (load 4)
$d4 = LDW_dalc %stack.2.ptr2, 0 :: (load 4)
...

0 comments on commit 7565e49

Please sign in to comment.