Skip to content

Commit 00ebb2a

Browse files
committed
Fix linker relaxation problem
1 parent 74ca6ea commit 00ebb2a

File tree

4 files changed

+104
-71
lines changed

4 files changed

+104
-71
lines changed

llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,12 @@ static inline unsigned getVLOpNum(const MCInstrDesc &Desc) {
208208
return Desc.getNumOperands() - Offset;
209209
}
210210

211+
static inline unsigned getTailExpandUseRegNo(const FeatureBitset &FeatureBits) {
212+
// For Zicfilp, PseudoTAIL should be expanded to a software guarded branch.
213+
// It means to use t2(x7) as rs1 of JALR to expand PseudoTAIL.
214+
return FeatureBits[RISCV::FeatureStdExtZicfilp] ? RISCV::X7 : RISCV::X6;
215+
}
216+
211217
static inline unsigned getSEWOpNum(const MCInstrDesc &Desc) {
212218
const uint64_t TSFlags = Desc.TSFlags;
213219
assert(hasSEWOp(TSFlags));

llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -125,11 +125,7 @@ void RISCVMCCodeEmitter::expandFunctionCall(const MCInst &MI,
125125
MCRegister Ra;
126126
if (MI.getOpcode() == RISCV::PseudoTAIL) {
127127
Func = MI.getOperand(0);
128-
Ra = RISCV::X6;
129-
// For Zicfilp, PseudoTAIL should be expanded to a software guarded branch.
130-
// It means to use t2(x7) as rs1 of JALR to expand PseudoTAIL.
131-
if (STI.hasFeature(RISCV::FeatureStdExtZicfilp))
132-
Ra = RISCV::X7;
128+
Ra = RISCVII::getTailExpandUseRegNo(STI.getFeatureBits());
133129
} else if (MI.getOpcode() == RISCV::PseudoCALLReg) {
134130
Func = MI.getOperand(1);
135131
Ra = MI.getOperand(0).getReg();

llvm/lib/Target/RISCV/RISCVInstrInfo.cpp

Lines changed: 88 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
#include "RISCVInstrInfo.h"
14+
#include "MCTargetDesc/RISCVBaseInfo.h"
1415
#include "MCTargetDesc/RISCVMatInt.h"
1516
#include "RISCV.h"
1617
#include "RISCVMachineFunctionInfo.h"
@@ -2938,85 +2939,118 @@ bool RISCVInstrInfo::shouldOutlineFromFunctionByDefault(
29382939
return MF.getFunction().hasMinSize();
29392940
}
29402941

2941-
static bool isCandidatePatchable(const MachineInstr &MI) {
2942-
const MachineBasicBlock *MBB = MI.getParent();
2943-
const MachineFunction *MF = MBB->getParent();
2942+
static bool isCandidatePatchable(const MachineBasicBlock &MBB) {
2943+
const MachineFunction *MF = MBB.getParent();
29442944
const Function &F = MF->getFunction();
29452945
return F.getFnAttribute("fentry-call").getValueAsBool() ||
29462946
F.hasFnAttribute("patchable-function-entry");
29472947
}
29482948

2949-
static bool cannotInsertTailCall(const MachineInstr &MI) {
2950-
if (MI.isTerminator())
2951-
return isCandidatePatchable(MI);
2952-
return true;
2949+
static bool isMIReadsReg(const MachineInstr &MI, const TargetRegisterInfo *TRI,
2950+
unsigned RegNo) {
2951+
return MI.readsRegister(RegNo, TRI) ||
2952+
MI.getDesc().hasImplicitUseOfPhysReg(RegNo);
29532953
}
29542954

2955-
static bool isMIUsesX5(const MachineInstr &MI, const TargetRegisterInfo *TRI) {
2956-
return MI.modifiesRegister(RISCV::X5, TRI) ||
2957-
MI.getDesc().hasImplicitDefOfPhysReg(RISCV::X5);
2955+
static bool isMIModifiesReg(const MachineInstr &MI,
2956+
const TargetRegisterInfo *TRI, unsigned RegNo) {
2957+
return MI.modifiesRegister(RegNo, TRI) ||
2958+
MI.getDesc().hasImplicitDefOfPhysReg(RegNo);
29582959
}
29592960

2960-
std::optional<std::unique_ptr<outliner::OutlinedFunction>>
2961-
RISCVInstrInfo::getOutliningCandidateInfo(
2962-
const MachineModuleInfo &MMI,
2963-
std::vector<outliner::Candidate> &RepeatedSequenceLocs,
2964-
unsigned MinRepeats) const {
2961+
static bool cannotInsertTailCall(const MachineBasicBlock &MBB) {
2962+
if (!MBB.back().isReturn())
2963+
return true;
2964+
if (isCandidatePatchable(MBB))
2965+
return true;
2966+
2967+
// If the candidate reads the pre-set register
2968+
// that can be used for expanding PseudoTAIL instruction,
2969+
// then we cannot insert tail call.
2970+
const TargetSubtargetInfo &STI = MBB.getParent()->getSubtarget();
2971+
unsigned TailExpandUseRegNo =
2972+
RISCVII::getTailExpandUseRegNo(STI.getFeatureBits());
2973+
for (const MachineInstr &MI : MBB) {
2974+
if (isMIReadsReg(MI, STI.getRegisterInfo(), TailExpandUseRegNo))
2975+
return true;
2976+
if (isMIModifiesReg(MI, STI.getRegisterInfo(), TailExpandUseRegNo))
2977+
break;
2978+
}
2979+
return false;
2980+
}
2981+
2982+
static std::optional<MachineOutlinerConstructionID>
2983+
analyzeCandidate(outliner::Candidate &C) {
2984+
// If last instruction is return then we can rely on
2985+
// the verification already performed in the getOutliningTypeImpl.
2986+
if (C.back().isReturn()) {
2987+
assert(!cannotInsertTailCall(*C.getMBB()) &&
2988+
"The candidate who uses return instruction must be outlined "
2989+
"using tail call");
2990+
return MachineOutlinerTailCall;
2991+
}
29652992

29662993
auto CandidateUsesX5 = [](outliner::Candidate &C) {
29672994
const TargetRegisterInfo *TRI = C.getMF()->getSubtarget().getRegisterInfo();
2968-
for (const MachineInstr &MI : C)
2969-
if (isMIUsesX5(MI, TRI))
2970-
return true;
2995+
if (std::any_of(C.begin(), C.end(), [TRI](const MachineInstr &MI) {
2996+
return isMIModifiesReg(MI, TRI, RISCV::X5);
2997+
}))
2998+
return true;
29712999
return !C.isAvailableAcrossAndOutOfSeq(RISCV::X5, *TRI);
29723000
};
29733001

2974-
auto CannotInsertCall = [CandidateUsesX5](outliner::Candidate &C) {
2975-
if (!CandidateUsesX5(C))
2976-
return false;
2977-
if (!cannotInsertTailCall(C.back()))
2978-
return false;
2979-
return true;
2980-
};
3002+
if (!CandidateUsesX5(C))
3003+
return MachineOutlinerDefault;
3004+
3005+
return std::nullopt;
3006+
}
3007+
3008+
std::optional<std::unique_ptr<outliner::OutlinedFunction>>
3009+
RISCVInstrInfo::getOutliningCandidateInfo(
3010+
const MachineModuleInfo &MMI,
3011+
std::vector<outliner::Candidate> &RepeatedSequenceLocs,
3012+
unsigned MinRepeats) const {
29813013

2982-
llvm::erase_if(RepeatedSequenceLocs, CannotInsertCall);
3014+
// Each RepeatedSequenceLoc is identical.
3015+
outliner::Candidate &Candidate = RepeatedSequenceLocs[0];
3016+
auto CandidateInfo = analyzeCandidate(Candidate);
3017+
if (!CandidateInfo)
3018+
RepeatedSequenceLocs.clear();
29833019

29843020
// If the sequence doesn't have enough candidates left, then we're done.
29853021
if (RepeatedSequenceLocs.size() < MinRepeats)
29863022
return std::nullopt;
29873023

2988-
unsigned SequenceSize = 0;
2989-
2990-
for (auto &MI : RepeatedSequenceLocs[0])
2991-
SequenceSize += getInstSizeInBytes(MI);
2992-
2993-
if (!cannotInsertTailCall(RepeatedSequenceLocs[0].back())) {
2994-
// tail function = 8 bytes. Can't be compressed
2995-
for (auto &C : RepeatedSequenceLocs)
2996-
C.setCallInfo(MachineOutlinerTailCall, 8);
2997-
2998-
// Using tail call we move ret instruction from caller to calle.
2999-
// So, FrameOverhead for this is 0
3000-
return std::make_unique<outliner::OutlinedFunction>(
3001-
RepeatedSequenceLocs, SequenceSize, 0, MachineOutlinerTailCall);
3024+
unsigned InstrSizeCExt =
3025+
Candidate.getMF()->getSubtarget<RISCVSubtarget>().hasStdExtCOrZca() ? 2
3026+
: 4;
3027+
unsigned CallOverhead = 0, FrameOverhead = 0;
3028+
3029+
MachineOutlinerConstructionID MOCI = CandidateInfo.value();
3030+
switch (MOCI) {
3031+
case MachineOutlinerDefault:
3032+
// call t0, function = 8 bytes.
3033+
CallOverhead = 8;
3034+
// jr t0 = 4 bytes, 2 bytes if compressed instructions are enabled.
3035+
FrameOverhead = InstrSizeCExt;
3036+
break;
3037+
case MachineOutlinerTailCall:
3038+
// tail call = auipc + jalr in the worst case without linker relaxation.
3039+
CallOverhead = 4 + InstrSizeCExt;
3040+
// Using tail call we move ret instruction from caller to callee.
3041+
FrameOverhead = 0;
3042+
break;
30023043
}
30033044

3004-
// call t0, function = 8 bytes.
3005-
unsigned CallOverhead = 8;
30063045
for (auto &C : RepeatedSequenceLocs)
3007-
C.setCallInfo(MachineOutlinerDefault, CallOverhead);
3046+
C.setCallInfo(MOCI, CallOverhead);
30083047

3009-
// jr t0 = 4 bytes, 2 bytes if compressed instructions are enabled.
3010-
unsigned FrameOverhead = 4;
3011-
if (RepeatedSequenceLocs[0]
3012-
.getMF()
3013-
->getSubtarget<RISCVSubtarget>()
3014-
.hasStdExtCOrZca())
3015-
FrameOverhead = 2;
3048+
unsigned SequenceSize = 0;
3049+
for (auto &MI : Candidate)
3050+
SequenceSize += getInstSizeInBytes(MI);
30163051

30173052
return std::make_unique<outliner::OutlinedFunction>(
3018-
RepeatedSequenceLocs, SequenceSize, FrameOverhead,
3019-
MachineOutlinerDefault);
3053+
RepeatedSequenceLocs, SequenceSize, FrameOverhead, MOCI);
30203054
}
30213055

30223056
outliner::InstrType
@@ -3037,7 +3071,8 @@ RISCVInstrInfo::getOutliningTypeImpl(const MachineModuleInfo &MMI,
30373071
return F.needsUnwindTableEntry() ? outliner::InstrType::Illegal
30383072
: outliner::InstrType::Invisible;
30393073

3040-
if (cannotInsertTailCall(MBB->back()) && isMIUsesX5(MI, TRI))
3074+
if (cannotInsertTailCall(*MBB) &&
3075+
(MI.isReturn() || isMIModifiesReg(MI, TRI, RISCV::X5)))
30413076
return outliner::InstrType::Illegal;
30423077

30433078
// Make sure the operands don't reference something unsafe.

llvm/test/CodeGen/RISCV/machineoutliner-x5.mir

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,53 +6,49 @@
66
# RUN: | FileCheck -check-prefixes=CHECK,RV64I-MO %s
77

88
--- |
9-
define i32 @outline_0(i32 %a, i32 %b) { ret i32 0 }
10-
11-
define i32 @outline_1(i32 %a, i32 %b) { ret i32 0 }
12-
13-
define i32 @outline_2(i32 %a, i32 %b) { ret i32 0 }
9+
define i32 @outline_tail_1(i32 %a, i32 %b) { ret i32 0 }
1410

11+
define i32 @outline_tail_2(i32 %a, i32 %b) { ret i32 0 }
1512
...
1613
---
17-
name: outline_0
14+
name: outline_tail_1
1815
tracksRegLiveness: true
1916
isOutlined: false
2017
body: |
2118
bb.0:
2219
liveins: $x10, $x11, $x5
23-
; RV32I-MO-LABEL: name: outline_0
20+
; RV32I-MO-LABEL: name: outline_tail_1
2421
; RV32I-MO: PseudoTAIL target-flags(riscv-call) @OUTLINED_FUNCTION_0, implicit $x2, implicit-def $x10, implicit-def $x11, implicit-def $x12, implicit $x2, implicit $x5, implicit $x10, implicit $x11
2522
;
26-
; RV64I-MO-LABEL: name: outline_0
23+
; RV64I-MO-LABEL: name: outline_tail_1
2724
; RV64I-MO: PseudoTAIL target-flags(riscv-call) @OUTLINED_FUNCTION_0, implicit $x2, implicit-def $x10, implicit-def $x11, implicit-def $x12, implicit $x2, implicit $x5, implicit $x10, implicit $x11
2825
$x11 = ORI $x11, 1023
2926
$x12 = ADDI $x10, 17
3027
$x10 = ADD $x10, $x5
3128
$x11 = AND $x12, $x11
3229
$x10 = SUB $x10, $x11
3330
PseudoRET implicit $x10
34-
3531
...
3632
---
37-
name: outline_1
33+
name: outline_tail_2
3834
tracksRegLiveness: true
3935
isOutlined: false
4036
body: |
4137
bb.0:
4238
liveins: $x10, $x11, $x5
43-
; RV32I-MO-LABEL: name: outline_1
39+
; RV32I-MO-LABEL: name: outline_tail_2
4440
; RV32I-MO: PseudoTAIL target-flags(riscv-call) @OUTLINED_FUNCTION_0, implicit $x2, implicit-def $x10, implicit-def $x11, implicit-def $x12, implicit $x2, implicit $x5, implicit $x10, implicit $x11
4541
;
46-
; RV64I-MO-LABEL: name: outline_1
42+
; RV64I-MO-LABEL: name: outline_tail_2
4743
; RV64I-MO: PseudoTAIL target-flags(riscv-call) @OUTLINED_FUNCTION_0, implicit $x2, implicit-def $x10, implicit-def $x11, implicit-def $x12, implicit $x2, implicit $x5, implicit $x10, implicit $x11
4844
$x11 = ORI $x11, 1023
4945
$x12 = ADDI $x10, 17
5046
$x10 = ADD $x10, $x5
5147
$x11 = AND $x12, $x11
5248
$x10 = SUB $x10, $x11
5349
PseudoRET implicit $x10
54-
5550
...
5651

52+
5753
# CHECK-LABEL: name: OUTLINED_FUNCTION_0
5854
# CHECK: isOutlined: true

0 commit comments

Comments
 (0)