Skip to content

Commit b25820f

Browse files
committed
[LoongArch] Add isSafeToMove hook to prevent unsafe instruction motion
This patch introduces a new virtual method `TargetInstrInfo::isSafeToMove()` to allow backends to control whether a machine instruction can be safely moved by optimization passes. The `BranchFolder` pass now respects this hook when hoisting common code. By default, all instructions are considered safe to to move. For LoongArch, `isSafeToMove()` is overridden to prevent relocation-related instruction sequences (e.g. PC-relative addressing and calls) from being broken by instruction motion. Correspondingly, `isSchedulingBoundary()` is updated to reuse this logic for consistency.
1 parent 705b996 commit b25820f

File tree

5 files changed

+49
-21
lines changed

5 files changed

+49
-21
lines changed

llvm/include/llvm/CodeGen/TargetInstrInfo.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1761,6 +1761,17 @@ class LLVM_ABI TargetInstrInfo : public MCInstrInfo {
17611761
return true;
17621762
}
17631763

1764+
/// Return true if it's safe to move a machine instruction.
1765+
/// This allows the backend to prevent certain special instruction
1766+
/// sequences from being broken by instruction motion in optimization
1767+
/// passes.
1768+
/// By default, this returns true for every instruction.
1769+
virtual bool isSafeToMove(const MachineInstr &MI,
1770+
const MachineBasicBlock *MBB,
1771+
const MachineFunction &MF) const {
1772+
return true;
1773+
}
1774+
17641775
/// Test if the given instruction should be considered a scheduling boundary.
17651776
/// This primarily includes labels and terminators.
17661777
virtual bool isSchedulingBoundary(const MachineInstr &MI,

llvm/lib/CodeGen/BranchFolding.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1818,7 +1818,7 @@ bool BranchFolder::OptimizeBlock(MachineBasicBlock *MBB) {
18181818
bool BranchFolder::HoistCommonCode(MachineFunction &MF) {
18191819
bool MadeChange = false;
18201820
for (MachineBasicBlock &MBB : llvm::make_early_inc_range(MF))
1821-
MadeChange |= HoistCommonCodeInSuccs(&MBB);
1821+
MadeChange |= HoistCommonCodeInSuccs(&MBB, MF);
18221822

18231823
return MadeChange;
18241824
}
@@ -1948,7 +1948,8 @@ MachineBasicBlock::iterator findHoistingInsertPosAndDeps(MachineBasicBlock *MBB,
19481948
return PI;
19491949
}
19501950

1951-
bool BranchFolder::HoistCommonCodeInSuccs(MachineBasicBlock *MBB) {
1951+
bool BranchFolder::HoistCommonCodeInSuccs(MachineBasicBlock *MBB,
1952+
MachineFunction &MF) {
19521953
MachineBasicBlock *TBB = nullptr, *FBB = nullptr;
19531954
SmallVector<MachineOperand, 4> Cond;
19541955
if (TII->analyzeBranch(*MBB, TBB, FBB, Cond, true) || !TBB || Cond.empty())
@@ -1993,6 +1994,10 @@ bool BranchFolder::HoistCommonCodeInSuccs(MachineBasicBlock *MBB) {
19931994
// Hard to reason about register liveness with predicated instruction.
19941995
break;
19951996

1997+
if (!TII->isSafeToMove(*TIB, MBB, MF))
1998+
// Don't hoist the instruction if it isn't safe to move.
1999+
break;
2000+
19962001
bool IsSafe = true;
19972002
for (MachineOperand &MO : TIB->operands()) {
19982003
// Don't attempt to hoist instructions with register masks.

llvm/lib/CodeGen/BranchFolding.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ class TargetRegisterInfo;
196196

197197
/// If the successors of MBB has common instruction sequence at the start of
198198
/// the function, move the instructions before MBB terminator if it's legal.
199-
bool HoistCommonCodeInSuccs(MachineBasicBlock *MBB);
199+
bool HoistCommonCodeInSuccs(MachineBasicBlock *MBB, MachineFunction &MF);
200200
};
201201

202202
} // end namespace llvm

llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -378,12 +378,9 @@ bool LoongArchInstrInfo::isBranchOffsetInRange(unsigned BranchOp,
378378
}
379379
}
380380

381-
bool LoongArchInstrInfo::isSchedulingBoundary(const MachineInstr &MI,
382-
const MachineBasicBlock *MBB,
383-
const MachineFunction &MF) const {
384-
if (TargetInstrInfo::isSchedulingBoundary(MI, MBB, MF))
385-
return true;
386-
381+
bool LoongArchInstrInfo::isSafeToMove(const MachineInstr &MI,
382+
const MachineBasicBlock *MBB,
383+
const MachineFunction &MF) const {
387384
auto MII = MI.getIterator();
388385
auto MIE = MBB->end();
389386

@@ -429,25 +426,25 @@ bool LoongArchInstrInfo::isSchedulingBoundary(const MachineInstr &MI,
429426
auto MO2 = Lu32I->getOperand(2).getTargetFlags();
430427
if (MO0 == LoongArchII::MO_PCREL_HI && MO1 == LoongArchII::MO_PCREL_LO &&
431428
MO2 == LoongArchII::MO_PCREL64_LO)
432-
return true;
429+
return false;
433430
if ((MO0 == LoongArchII::MO_GOT_PC_HI || MO0 == LoongArchII::MO_LD_PC_HI ||
434431
MO0 == LoongArchII::MO_GD_PC_HI) &&
435432
MO1 == LoongArchII::MO_GOT_PC_LO && MO2 == LoongArchII::MO_GOT_PC64_LO)
436-
return true;
433+
return false;
437434
if (MO0 == LoongArchII::MO_IE_PC_HI && MO1 == LoongArchII::MO_IE_PC_LO &&
438435
MO2 == LoongArchII::MO_IE_PC64_LO)
439-
return true;
436+
return false;
440437
if (MO0 == LoongArchII::MO_DESC_PC_HI &&
441438
MO1 == LoongArchII::MO_DESC_PC_LO &&
442439
MO2 == LoongArchII::MO_DESC64_PC_LO)
443-
return true;
440+
return false;
444441
break;
445442
}
446443
case LoongArch::LU52I_D: {
447444
auto MO = MI.getOperand(2).getTargetFlags();
448445
if (MO == LoongArchII::MO_PCREL64_HI || MO == LoongArchII::MO_GOT_PC64_HI ||
449446
MO == LoongArchII::MO_IE_PC64_HI || MO == LoongArchII::MO_DESC64_PC_HI)
450-
return true;
447+
return false;
451448
break;
452449
}
453450
default:
@@ -487,7 +484,7 @@ bool LoongArchInstrInfo::isSchedulingBoundary(const MachineInstr &MI,
487484
auto MO1 = LoongArchII::getDirectFlags(SecondOp->getOperand(2));
488485
auto MO2 = LoongArchII::getDirectFlags(Ld->getOperand(2));
489486
if (MO1 == LoongArchII::MO_DESC_PC_LO && MO2 == LoongArchII::MO_DESC_LD)
490-
return true;
487+
return false;
491488
break;
492489
}
493490
if (SecondOp == MIE ||
@@ -496,41 +493,53 @@ bool LoongArchInstrInfo::isSchedulingBoundary(const MachineInstr &MI,
496493
auto MO1 = LoongArchII::getDirectFlags(SecondOp->getOperand(2));
497494
if (MO0 == LoongArchII::MO_PCREL_HI && SecondOp->getOpcode() == AddiOp &&
498495
MO1 == LoongArchII::MO_PCREL_LO)
499-
return true;
496+
return false;
500497
if (MO0 == LoongArchII::MO_GOT_PC_HI && SecondOp->getOpcode() == LdOp &&
501498
MO1 == LoongArchII::MO_GOT_PC_LO)
502-
return true;
499+
return false;
503500
if ((MO0 == LoongArchII::MO_LD_PC_HI ||
504501
MO0 == LoongArchII::MO_GD_PC_HI) &&
505502
SecondOp->getOpcode() == AddiOp && MO1 == LoongArchII::MO_GOT_PC_LO)
506-
return true;
503+
return false;
507504
break;
508505
}
509506
case LoongArch::ADDI_W:
510507
case LoongArch::ADDI_D: {
511508
auto MO = LoongArchII::getDirectFlags(MI.getOperand(2));
512509
if (MO == LoongArchII::MO_PCREL_LO || MO == LoongArchII::MO_GOT_PC_LO)
513-
return true;
510+
return false;
514511
break;
515512
}
516513
case LoongArch::LD_W:
517514
case LoongArch::LD_D: {
518515
auto MO = LoongArchII::getDirectFlags(MI.getOperand(2));
519516
if (MO == LoongArchII::MO_GOT_PC_LO)
520-
return true;
517+
return false;
521518
break;
522519
}
523520
case LoongArch::PseudoDESC_CALL: {
524521
auto MO = LoongArchII::getDirectFlags(MI.getOperand(2));
525522
if (MO == LoongArchII::MO_DESC_CALL)
526-
return true;
523+
return false;
527524
break;
528525
}
529526
default:
530527
break;
531528
}
532529
}
533530

531+
return true;
532+
}
533+
534+
bool LoongArchInstrInfo::isSchedulingBoundary(const MachineInstr &MI,
535+
const MachineBasicBlock *MBB,
536+
const MachineFunction &MF) const {
537+
if (TargetInstrInfo::isSchedulingBoundary(MI, MBB, MF))
538+
return true;
539+
540+
if (!isSafeToMove(MI, MBB, MF))
541+
return true;
542+
534543
return false;
535544
}
536545

llvm/lib/Target/LoongArch/LoongArchInstrInfo.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ class LoongArchInstrInfo : public LoongArchGenInstrInfo {
6464
bool isBranchOffsetInRange(unsigned BranchOpc,
6565
int64_t BrOffset) const override;
6666

67+
bool isSafeToMove(const MachineInstr &MI, const MachineBasicBlock *MBB,
68+
const MachineFunction &MF) const override;
69+
6770
bool isSchedulingBoundary(const MachineInstr &MI,
6871
const MachineBasicBlock *MBB,
6972
const MachineFunction &MF) const override;

0 commit comments

Comments
 (0)