Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions llvm/lib/CodeGen/ReachingDefAnalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
#include "llvm/CodeGen/ReachingDefAnalysis.h"
#include "llvm/ADT/SetOperations.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/CodeGen/LivePhysRegs.h"
#include "llvm/CodeGen/LiveRegUnits.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
Expand Down Expand Up @@ -288,6 +290,16 @@ void ReachingDefInfo::run(MachineFunction &mf) {
TRI = STI.getRegisterInfo();
TII = STI.getInstrInfo();
LLVM_DEBUG(dbgs() << "********** REACHING DEFINITION ANALYSIS **********\n");

MachineFunctionProperties &Props = MF->getProperties();
if (!Props.hasTracksLiveness()) {
Props.setTracksLiveness();

SmallVector<MachineBasicBlock *> AllMBBsInPostOrder;
for (MachineBasicBlock *MBB : post_order(MF))
AllMBBsInPostOrder.push_back(MBB);
fullyRecomputeLiveIns(AllMBBsInPostOrder);
}
init();
traverse();
}
Expand Down
92 changes: 92 additions & 0 deletions llvm/lib/Target/RISCV/RISCVISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25827,3 +25827,95 @@ bool RISCVTargetLowering::isReassocProfitable(SelectionDAG &DAG, SDValue N0,

return true;
}

static MachineInstr *findInstrWhichNeedAllCSRs(MachineBasicBlock &MBB) {
// Some instructions may require (implicitly) all CSRs to be saved.
// For example, call to __cxa_throw is noreturn, but expects that all CSRs are
// taken care of.
// TODO: try to speedup this?
for (MachineInstr &MI : MBB) {
unsigned Opc = MI.getOpcode();
if (Opc != RISCV::PseudoCALL && Opc != RISCV::PseudoTAIL)
continue;
MachineOperand &MO = MI.getOperand(0);
StringRef Name = "";
if (MO.isSymbol()) {
Name = MO.getSymbolName();
} else if (MO.isGlobal()) {
Name = MO.getGlobal()->getName();
} else {
llvm_unreachable("Unexpected operand type.");
}
if (Name == "__cxa_throw" || Name == "__cxa_rethrow" ||
Name == "_Unwind_Resume")
return &MI;
}
return nullptr;
}

void RISCVTargetLowering::finalizeLowering(MachineFunction &MF) const {
if (!Subtarget.savesCSRsEarly()) {
TargetLoweringBase::finalizeLowering(MF);
return;
}

MachineRegisterInfo &MRI = MF.getRegInfo();
const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
const RISCVRegisterInfo &TRI = *Subtarget.getRegisterInfo();
const RISCVFrameLowering &TFI = *Subtarget.getFrameLowering();

SmallVector<MachineInstr *, 4> RestorePoints;
SmallVector<MachineBasicBlock *, 4> SaveMBBs;
SaveMBBs.push_back(&MF.front());
for (MachineBasicBlock &MBB : MF) {
if (MBB.isReturnBlock())
RestorePoints.push_back(&MBB.back());
if (MachineInstr *CallToCxaThrow = findInstrWhichNeedAllCSRs(MBB)) {
MachineBasicBlock::iterator MII = MBB.getFirstTerminator();
MachineInstr *NewRetMI = BuildMI(MBB, MII, CallToCxaThrow->getDebugLoc(),
TII.get(RISCV::UnreachableRET));
RestorePoints.push_back(NewRetMI);
MII = ++NewRetMI->getIterator();
MBB.erase(MII, MBB.end());
}
}

BitVector EarlyCSRs;
TFI.determineEarlyCalleeSaves(MF, EarlyCSRs);

SmallVector<Register, 4> VRegs;
for (MachineBasicBlock *SaveMBB : SaveMBBs) {
for (unsigned Reg = 0; Reg < EarlyCSRs.size(); ++Reg) {
if (!EarlyCSRs[Reg])
continue;
SaveMBB->addLiveIn(Reg);
Register VReg = MRI.createVirtualRegister(
TRI.getLargestLegalSuperClass(TRI.getMinimalPhysRegClass(Reg), MF));
VRegs.push_back(VReg);
BuildMI(*SaveMBB, SaveMBB->begin(),
SaveMBB->findDebugLoc(SaveMBB->begin()),
TII.get(TargetOpcode::COPY), VReg)
.addReg(Reg);
MRI.setSimpleHint(VReg, Reg);
}
}

for (MachineInstr *RestorePoint : RestorePoints) {
auto VRegI = VRegs.begin();
for (unsigned Reg = 0; Reg < EarlyCSRs.size(); ++Reg) {
if (!EarlyCSRs[Reg])
continue;
Register VReg = *VRegI;
BuildMI(*RestorePoint->getParent(), RestorePoint->getIterator(),
RestorePoint->getDebugLoc(), TII.get(TargetOpcode::COPY), Reg)
.addReg(VReg);
RestorePoint->addOperand(MF,
MachineOperand::CreateReg(Reg,
/*isDef=*/false,
/*isImplicit=*/true));
VRegI++;
}
}

TargetLoweringBase::finalizeLowering(MF);
}
2 changes: 2 additions & 0 deletions llvm/lib/Target/RISCV/RISCVISelLowering.h
Original file line number Diff line number Diff line change
Expand Up @@ -652,6 +652,8 @@ class RISCVTargetLowering : public TargetLowering {

std::pair<const TargetRegisterClass *, uint8_t>
findRepresentativeClass(const TargetRegisterInfo *TRI, MVT VT) const override;

void finalizeLowering(MachineFunction &MF) const override;
};

namespace RISCVVIntrinsicsTable {
Expand Down
8 changes: 8 additions & 0 deletions llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5127,3 +5127,11 @@ bool RISCVInstrInfo::isHighLatencyDef(int Opc) const {
return true;
}
}

bool RISCVInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
if (MI.getOpcode() == RISCV::UnreachableRET) {
MI.eraseFromParent();
return true;
}
return false;
}
2 changes: 2 additions & 0 deletions llvm/lib/Target/RISCV/RISCVInstrInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,8 @@ class RISCVInstrInfo : public RISCVGenInstrInfo {
static bool isFromLoadImm(const MachineRegisterInfo &MRI,
const MachineOperand &Op, int64_t &Imm);

bool expandPostRAPseudo(MachineInstr &MI) const override;

protected:
const RISCVSubtarget &STI;

Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Target/RISCV/RISCVInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -1836,6 +1836,9 @@ let isBarrier = 1, isReturn = 1, isTerminator = 1 in
def PseudoRET : Pseudo<(outs), (ins), [(riscv_ret_glue)]>,
PseudoInstExpansion<(JALR X0, X1, 0)>;

let isBarrier = 1, isReturn = 1, isTerminator = 1, isMeta = 1, hasSideEffects = 1, mayLoad = 0, mayStore = 0 in
def UnreachableRET : Pseudo<(outs), (ins), []>;

// PseudoTAIL is a pseudo instruction similar to PseudoCALL and will eventually
// expand to auipc and jalr while encoding.
// Define AsmString to print "tail" when compile with -S flag.
Expand Down
4 changes: 4 additions & 0 deletions llvm/test/CodeGen/RISCV/pr53662.mir
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,19 @@ body: |
; CHECK-LABEL: name: b
; CHECK: bb.0:
; CHECK-NEXT: successors: %bb.1(0x80000000)
; CHECK-NEXT: liveins: $x10
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: PseudoBR %bb.1
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: bb.1:
; CHECK-NEXT: successors: %bb.2(0x80000000)
; CHECK-NEXT: liveins: $x10
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: DBG_VALUE $noreg
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: bb.2:
; CHECK-NEXT: liveins: $x10
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: PseudoRET implicit killed $x10
bb.0 :
PseudoBR %bb.1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ body: |

SD $x10, %stack.0, 0
SD $x10, %stack.2, 0
dead renamable $x15 = PseudoVSETIVLI 1, 72, implicit-def $vl, implicit-def $vtype
renamable $x15 = PseudoVSETIVLI 1, 72, implicit-def $vl, implicit-def $vtype
VS1R_V killed renamable $v25, %stack.1 :: (store (<vscale x 1 x s64>) into %stack.1, align 8)
; This is here just to make all the eligible registers live at this point.
; This way when we replace the frame index %stack.1 with its actual address
Expand Down
113 changes: 113 additions & 0 deletions llvm/test/CodeGen/RISCV/save-csr-early.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5
; RUN: llc %s -mtriple=riscv64 -riscv-save-csrs-early=true \
; RUN: -stop-after=finalize-isel -o - | FileCheck %s

define void @test0() {
; CHECK-LABEL: name: test0
; CHECK: bb.0 (%ir-block.0):
; CHECK-NEXT: liveins: $x1, $x8, $x9, $x18, $x19, $x20, $x21, $x22, $x23, $x24, $x25, $x26, $x27
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[COPY:%[0-9]+]]:gprjalrnonx7_and_gprnox31 = COPY $x27
; CHECK-NEXT: [[COPY1:%[0-9]+]]:gprjalrnonx7_and_gprnox31 = COPY $x26
; CHECK-NEXT: [[COPY2:%[0-9]+]]:gprjalrnonx7_and_gprnox31 = COPY $x25
; CHECK-NEXT: [[COPY3:%[0-9]+]]:gprjalrnonx7_and_gprnox31 = COPY $x24
; CHECK-NEXT: [[COPY4:%[0-9]+]]:sr07 = COPY $x23
; CHECK-NEXT: [[COPY5:%[0-9]+]]:sr07 = COPY $x22
; CHECK-NEXT: [[COPY6:%[0-9]+]]:sr07 = COPY $x21
; CHECK-NEXT: [[COPY7:%[0-9]+]]:sr07 = COPY $x20
; CHECK-NEXT: [[COPY8:%[0-9]+]]:sr07 = COPY $x19
; CHECK-NEXT: [[COPY9:%[0-9]+]]:sr07 = COPY $x18
; CHECK-NEXT: [[COPY10:%[0-9]+]]:gprc_and_sr07 = COPY $x9
; CHECK-NEXT: [[COPY11:%[0-9]+]]:gprc_and_sr07 = COPY $x8
; CHECK-NEXT: [[COPY12:%[0-9]+]]:gprx1 = COPY $x1
; CHECK-NEXT: $x1 = COPY [[COPY12]]
; CHECK-NEXT: $x8 = COPY [[COPY11]]
; CHECK-NEXT: $x9 = COPY [[COPY10]]
; CHECK-NEXT: $x18 = COPY [[COPY9]]
; CHECK-NEXT: $x19 = COPY [[COPY8]]
; CHECK-NEXT: $x20 = COPY [[COPY7]]
; CHECK-NEXT: $x21 = COPY [[COPY6]]
; CHECK-NEXT: $x22 = COPY [[COPY5]]
; CHECK-NEXT: $x23 = COPY [[COPY4]]
; CHECK-NEXT: $x24 = COPY [[COPY3]]
; CHECK-NEXT: $x25 = COPY [[COPY2]]
; CHECK-NEXT: $x26 = COPY [[COPY1]]
; CHECK-NEXT: $x27 = COPY [[COPY]]
; CHECK-NEXT: PseudoRET implicit $x1, implicit $x8, implicit $x9, implicit $x18, implicit $x19, implicit $x20, implicit $x21, implicit $x22, implicit $x23, implicit $x24, implicit $x25, implicit $x26, implicit $x27
ret void
}

declare void @__cxa_throw(ptr, ptr, ptr)

define void @test1(i1 %x, ptr %p0, ptr %p1, ptr %p2) {
; CHECK-LABEL: name: test1
; CHECK: bb.0.entry:
; CHECK-NEXT: successors: %bb.1(0x00000000), %bb.2(0x80000000)
; CHECK-NEXT: liveins: $x10, $x11, $x12, $x13, $x1, $x8, $x9, $x18, $x19, $x20, $x21, $x22, $x23, $x24, $x25, $x26, $x27
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[COPY:%[0-9]+]]:gprjalrnonx7_and_gprnox31 = COPY $x27
; CHECK-NEXT: [[COPY1:%[0-9]+]]:gprjalrnonx7_and_gprnox31 = COPY $x26
; CHECK-NEXT: [[COPY2:%[0-9]+]]:gprjalrnonx7_and_gprnox31 = COPY $x25
; CHECK-NEXT: [[COPY3:%[0-9]+]]:gprjalrnonx7_and_gprnox31 = COPY $x24
; CHECK-NEXT: [[COPY4:%[0-9]+]]:sr07 = COPY $x23
; CHECK-NEXT: [[COPY5:%[0-9]+]]:sr07 = COPY $x22
; CHECK-NEXT: [[COPY6:%[0-9]+]]:sr07 = COPY $x21
; CHECK-NEXT: [[COPY7:%[0-9]+]]:sr07 = COPY $x20
; CHECK-NEXT: [[COPY8:%[0-9]+]]:sr07 = COPY $x19
; CHECK-NEXT: [[COPY9:%[0-9]+]]:sr07 = COPY $x18
; CHECK-NEXT: [[COPY10:%[0-9]+]]:gprc_and_sr07 = COPY $x9
; CHECK-NEXT: [[COPY11:%[0-9]+]]:gprc_and_sr07 = COPY $x8
; CHECK-NEXT: [[COPY12:%[0-9]+]]:gprx1 = COPY $x1
; CHECK-NEXT: [[COPY13:%[0-9]+]]:gpr = COPY $x13
; CHECK-NEXT: [[COPY14:%[0-9]+]]:gpr = COPY $x12
; CHECK-NEXT: [[COPY15:%[0-9]+]]:gpr = COPY $x11
; CHECK-NEXT: [[COPY16:%[0-9]+]]:gpr = COPY $x10
; CHECK-NEXT: [[ANDI:%[0-9]+]]:gpr = ANDI [[COPY16]], 1
; CHECK-NEXT: BEQ killed [[ANDI]], $x0, %bb.2
; CHECK-NEXT: PseudoBR %bb.1
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: bb.1.throw:
; CHECK-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def dead $x2, implicit $x2
; CHECK-NEXT: $x10 = COPY [[COPY15]]
; CHECK-NEXT: $x11 = COPY [[COPY14]]
; CHECK-NEXT: $x12 = COPY [[COPY13]]
; CHECK-NEXT: PseudoCALL target-flags(riscv-call) @__cxa_throw, csr_ilp32_lp64, implicit-def dead $x1, implicit $x10, implicit $x11, implicit $x12, implicit-def $x2
; CHECK-NEXT: ADJCALLSTACKUP 0, 0, implicit-def dead $x2, implicit $x2
; CHECK-NEXT: $x1 = COPY [[COPY12]]
; CHECK-NEXT: $x8 = COPY [[COPY11]]
; CHECK-NEXT: $x9 = COPY [[COPY10]]
; CHECK-NEXT: $x18 = COPY [[COPY9]]
; CHECK-NEXT: $x19 = COPY [[COPY8]]
; CHECK-NEXT: $x20 = COPY [[COPY7]]
; CHECK-NEXT: $x21 = COPY [[COPY6]]
; CHECK-NEXT: $x22 = COPY [[COPY5]]
; CHECK-NEXT: $x23 = COPY [[COPY4]]
; CHECK-NEXT: $x24 = COPY [[COPY3]]
; CHECK-NEXT: $x25 = COPY [[COPY2]]
; CHECK-NEXT: $x26 = COPY [[COPY1]]
; CHECK-NEXT: $x27 = COPY [[COPY]]
; CHECK-NEXT: UnreachableRET implicit $x1, implicit $x8, implicit $x9, implicit $x18, implicit $x19, implicit $x20, implicit $x21, implicit $x22, implicit $x23, implicit $x24, implicit $x25, implicit $x26, implicit $x27
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: bb.2.return:
; CHECK-NEXT: $x1 = COPY [[COPY12]]
; CHECK-NEXT: $x8 = COPY [[COPY11]]
; CHECK-NEXT: $x9 = COPY [[COPY10]]
; CHECK-NEXT: $x18 = COPY [[COPY9]]
; CHECK-NEXT: $x19 = COPY [[COPY8]]
; CHECK-NEXT: $x20 = COPY [[COPY7]]
; CHECK-NEXT: $x21 = COPY [[COPY6]]
; CHECK-NEXT: $x22 = COPY [[COPY5]]
; CHECK-NEXT: $x23 = COPY [[COPY4]]
; CHECK-NEXT: $x24 = COPY [[COPY3]]
; CHECK-NEXT: $x25 = COPY [[COPY2]]
; CHECK-NEXT: $x26 = COPY [[COPY1]]
; CHECK-NEXT: $x27 = COPY [[COPY]]
; CHECK-NEXT: PseudoRET implicit $x1, implicit $x8, implicit $x9, implicit $x18, implicit $x19, implicit $x20, implicit $x21, implicit $x22, implicit $x23, implicit $x24, implicit $x25, implicit $x26, implicit $x27
entry:
br i1 %x, label %throw, label %return
throw:
call void @__cxa_throw(ptr %p0, ptr %p1, ptr %p2)
unreachable
return:
ret void
}
Loading