Skip to content

[llvm][AArch64] Refactor expansion of CALL_BTI and CALL_RVMARKER #80419

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 9, 2024
Merged
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
87 changes: 40 additions & 47 deletions llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -774,6 +774,39 @@ bool AArch64ExpandPseudo::expandSVESpillFill(MachineBasicBlock &MBB,
return true;
}

// Create a call to CallTarget, copying over all the operands from *MBBI,
// starting at the regmask.
static MachineInstr *createCall(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
const AArch64InstrInfo *TII,
MachineOperand &CallTarget,
unsigned RegMaskStartIdx) {
unsigned Opc = CallTarget.isGlobal() ? AArch64::BL : AArch64::BLR;
MachineInstr *Call =
BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII->get(Opc)).getInstr();

assert((CallTarget.isGlobal() || CallTarget.isReg()) &&
"invalid operand for regular call");
Call->addOperand(CallTarget);

// Register arguments are added during ISel, but cannot be added as explicit
// operands of the branch as it expects to be B <target> which is only one
// operand. Instead they are implicit operands used by the branch.
while (!MBBI->getOperand(RegMaskStartIdx).isRegMask()) {
auto MOP = MBBI->getOperand(RegMaskStartIdx);
assert(MOP.isReg() && "can only add register operands");
Call->addOperand(MachineOperand::CreateReg(
MOP.getReg(), /*Def=*/false, /*Implicit=*/true, /*isKill=*/false,
/*isDead=*/false, /*isUndef=*/MOP.isUndef()));
RegMaskStartIdx++;
}
for (const MachineOperand &MO :
llvm::drop_begin(MBBI->operands(), RegMaskStartIdx))
Call->addOperand(MO);

return Call;
}

bool AArch64ExpandPseudo::expandCALL_RVMARKER(
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI) {
// Expand CALL_RVMARKER pseudo to:
Expand All @@ -782,31 +815,12 @@ bool AArch64ExpandPseudo::expandCALL_RVMARKER(
// - another branch, to the runtime function
// Mark the sequence as bundle, to avoid passes moving other code in between.
MachineInstr &MI = *MBBI;

MachineInstr *OriginalCall;
MachineOperand &RVTarget = MI.getOperand(0);
MachineOperand &CallTarget = MI.getOperand(1);
assert((CallTarget.isGlobal() || CallTarget.isReg()) &&
"invalid operand for regular call");
assert(RVTarget.isGlobal() && "invalid operand for attached call");
unsigned Opc = CallTarget.isGlobal() ? AArch64::BL : AArch64::BLR;
OriginalCall = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(Opc)).getInstr();
OriginalCall->addOperand(CallTarget);

unsigned RegMaskStartIdx = 2;
// Skip register arguments. Those are added during ISel, but are not
// needed for the concrete branch.
while (!MI.getOperand(RegMaskStartIdx).isRegMask()) {
auto MOP = MI.getOperand(RegMaskStartIdx);
assert(MOP.isReg() && "can only add register operands");
OriginalCall->addOperand(MachineOperand::CreateReg(
MOP.getReg(), /*Def=*/false, /*Implicit=*/true, /*isKill=*/false,
/*isDead=*/false, /*isUndef=*/MOP.isUndef()));
RegMaskStartIdx++;
}
for (const MachineOperand &MO :
llvm::drop_begin(MI.operands(), RegMaskStartIdx))
OriginalCall->addOperand(MO);
MachineInstr *OriginalCall =
createCall(MBB, MBBI, TII, MI.getOperand(1),
// Regmask starts after the RV and call targets.
/*RegMaskStartIdx=*/2);

BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::ORRXrs))
.addReg(AArch64::FP, RegState::Define)
Expand Down Expand Up @@ -834,31 +848,10 @@ bool AArch64ExpandPseudo::expandCALL_BTI(MachineBasicBlock &MBB,
// - a BTI instruction
// Mark the sequence as a bundle, to avoid passes moving other code in
// between.

MachineInstr &MI = *MBBI;
MachineOperand &CallTarget = MI.getOperand(0);
assert((CallTarget.isGlobal() || CallTarget.isReg()) &&
"invalid operand for regular call");
unsigned Opc = CallTarget.isGlobal() ? AArch64::BL : AArch64::BLR;
MachineInstr *Call =
BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(Opc)).getInstr();
Call->addOperand(CallTarget);

// 1 because we already added the branch target above.
unsigned RegMaskStartIdx = 1;
// The branch is BL <target>, so we cannot attach the arguments of the called
// function to it. Those must be added as implicitly used by the branch.
while (!MI.getOperand(RegMaskStartIdx).isRegMask()) {
auto MOP = MI.getOperand(RegMaskStartIdx);
assert(MOP.isReg() && "can only add register operands");
Call->addOperand(MachineOperand::CreateReg(
MOP.getReg(), /*Def=*/false, /*Implicit=*/true, /*isKill=*/false,
/*isDead=*/false, /*isUndef=*/MOP.isUndef()));
RegMaskStartIdx++;
}
for (const MachineOperand &MO :
llvm::drop_begin(MI.operands(), RegMaskStartIdx))
Call->addOperand(MO);
MachineInstr *Call = createCall(MBB, MBBI, TII, MI.getOperand(0),
// Regmask starts after the call target.
/*RegMaskStartIdx=*/1);

Call->setCFIType(*MBB.getParent(), MI.getCFIType());

Expand Down