Skip to content

Commit d04b00b

Browse files
heiherllvmbot
authored andcommitted
[LoongArch] Add isSafeToMove hook to prevent unsafe instruction motion (#163725)
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. Fixes #163681 (cherry picked from commit cdc3cb2)
1 parent 4aaab27 commit d04b00b

File tree

4 files changed

+46
-18
lines changed

4 files changed

+46
-18
lines changed

llvm/include/llvm/CodeGen/TargetInstrInfo.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1730,6 +1730,17 @@ class LLVM_ABI TargetInstrInfo : public MCInstrInfo {
17301730
return true;
17311731
}
17321732

1733+
/// Return true if it's safe to move a machine instruction.
1734+
/// This allows the backend to prevent certain special instruction
1735+
/// sequences from being broken by instruction motion in optimization
1736+
/// passes.
1737+
/// By default, this returns true for every instruction.
1738+
virtual bool isSafeToMove(const MachineInstr &MI,
1739+
const MachineBasicBlock *MBB,
1740+
const MachineFunction &MF) const {
1741+
return true;
1742+
}
1743+
17331744
/// Test if the given instruction should be considered a scheduling boundary.
17341745
/// This primarily includes labels and terminators.
17351746
virtual bool isSchedulingBoundary(const MachineInstr &MI,

llvm/lib/CodeGen/BranchFolding.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1971,6 +1971,7 @@ bool BranchFolder::HoistCommonCodeInSuccs(MachineBasicBlock *MBB) {
19711971
MachineBasicBlock::iterator FIB = FBB->begin();
19721972
MachineBasicBlock::iterator TIE = TBB->end();
19731973
MachineBasicBlock::iterator FIE = FBB->end();
1974+
MachineFunction &MF = *MBB->getParent();
19741975
while (TIB != TIE && FIB != FIE) {
19751976
// Skip dbg_value instructions. These do not count.
19761977
TIB = skipDebugInstructionsForward(TIB, TIE, false);
@@ -1985,6 +1986,10 @@ bool BranchFolder::HoistCommonCodeInSuccs(MachineBasicBlock *MBB) {
19851986
// Hard to reason about register liveness with predicated instruction.
19861987
break;
19871988

1989+
if (!TII->isSafeToMove(*TIB, MBB, MF))
1990+
// Don't hoist the instruction if it isn't safe to move.
1991+
break;
1992+
19881993
bool IsSafe = true;
19891994
for (MachineOperand &MO : TIB->operands()) {
19901995
// Don't attempt to hoist instructions with register masks.

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)