Skip to content

Commit 5cd8d53

Browse files
authored
[RISCV] Teach RISCVMergeBaseOffset to handle inline asm (#78945)
For inline asm with memory operands, we can merge the offset into the second operand of memory constraint operands. Differential Revision: https://reviews.llvm.org/D158062
1 parent ac296b6 commit 5cd8d53

File tree

5 files changed

+193
-171
lines changed

5 files changed

+193
-171
lines changed

llvm/include/llvm/CodeGen/MachineOperand.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -782,6 +782,10 @@ class MachineOperand {
782782
void ChangeToGA(const GlobalValue *GV, int64_t Offset,
783783
unsigned TargetFlags = 0);
784784

785+
/// ChangeToBA - Replace this operand with a new block address operand.
786+
void ChangeToBA(const BlockAddress *BA, int64_t Offset,
787+
unsigned TargetFlags = 0);
788+
785789
/// ChangeToMCSymbol - Replace this operand with a new MC symbol operand.
786790
void ChangeToMCSymbol(MCSymbol *Sym, unsigned TargetFlags = 0);
787791

llvm/lib/CodeGen/MachineOperand.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,19 @@ void MachineOperand::ChangeToGA(const GlobalValue *GV, int64_t Offset,
206206
setTargetFlags(TargetFlags);
207207
}
208208

209+
void MachineOperand::ChangeToBA(const BlockAddress *BA, int64_t Offset,
210+
unsigned TargetFlags) {
211+
assert((!isReg() || !isTied()) &&
212+
"Cannot change a tied operand into a block address");
213+
214+
removeRegFromUses();
215+
216+
OpKind = MO_BlockAddress;
217+
Contents.OffsetedInfo.Val.BA = BA;
218+
setOffset(Offset);
219+
setTargetFlags(TargetFlags);
220+
}
221+
209222
void MachineOperand::ChangeToMCSymbol(MCSymbol *Sym, unsigned TargetFlags) {
210223
assert((!isReg() || !isTied()) &&
211224
"Cannot change a tied operand into an MCSymbol");

llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,8 @@ bool RISCVAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
323323
// RISCVDAGToDAGISel::SelectInlineAsmMemoryOperand).
324324
if (!AddrReg.isReg())
325325
return true;
326-
if (!Offset.isImm() && !Offset.isGlobal() && !Offset.isBlockAddress())
326+
if (!Offset.isImm() && !Offset.isGlobal() && !Offset.isBlockAddress() &&
327+
!Offset.isMCSymbol())
327328
return true;
328329

329330
MCOperand MCO;
@@ -332,7 +333,7 @@ bool RISCVAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
332333

333334
if (Offset.isImm())
334335
OS << MCO.getImm();
335-
else if (Offset.isGlobal() || Offset.isBlockAddress())
336+
else if (Offset.isGlobal() || Offset.isBlockAddress() || Offset.isMCSymbol())
336337
OS << *MCO.getExpr();
337338
OS << "(" << RISCVInstPrinter::getRegisterName(AddrReg.getReg()) << ")";
338339
return false;

llvm/lib/Target/RISCV/RISCVMergeBaseOffset.cpp

Lines changed: 73 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,8 @@ bool RISCVMergeBaseOffsetOpt::foldIntoMemoryOps(MachineInstr &Hi,
362362
// Tail: lw vreg3, 8(vreg2)
363363

364364
std::optional<int64_t> CommonOffset;
365+
DenseMap<const MachineInstr *, SmallVector<unsigned>>
366+
InlineAsmMemoryOpIndexesMap;
365367
for (const MachineInstr &UseMI : MRI->use_instructions(DestReg)) {
366368
switch (UseMI.getOpcode()) {
367369
default:
@@ -396,6 +398,49 @@ bool RISCVMergeBaseOffsetOpt::foldIntoMemoryOps(MachineInstr &Hi,
396398
if (CommonOffset && Offset != CommonOffset)
397399
return false;
398400
CommonOffset = Offset;
401+
break;
402+
}
403+
case RISCV::INLINEASM:
404+
case RISCV::INLINEASM_BR: {
405+
SmallVector<unsigned> InlineAsmMemoryOpIndexes;
406+
unsigned NumOps = 0;
407+
for (unsigned I = InlineAsm::MIOp_FirstOperand;
408+
I < UseMI.getNumOperands(); I += 1 + NumOps) {
409+
const MachineOperand &FlagsMO = UseMI.getOperand(I);
410+
// Should be an imm.
411+
if (!FlagsMO.isImm())
412+
continue;
413+
414+
const InlineAsm::Flag Flags(FlagsMO.getImm());
415+
NumOps = Flags.getNumOperandRegisters();
416+
417+
// Memory constraints have two operands.
418+
if (NumOps != 2 || !Flags.isMemKind())
419+
continue;
420+
421+
// We can't do this for constraint A because AMO instructions don't have
422+
// an immediate offset field.
423+
if (Flags.getMemoryConstraintID() == InlineAsm::ConstraintCode::A)
424+
return false;
425+
426+
const MachineOperand &AddrMO = UseMI.getOperand(I + 1);
427+
if (!AddrMO.isReg() || AddrMO.getReg() != DestReg)
428+
continue;
429+
430+
const MachineOperand &OffsetMO = UseMI.getOperand(I + 2);
431+
if (!OffsetMO.isImm())
432+
continue;
433+
434+
// All inline asm memory operands must use the same offset.
435+
int64_t Offset = OffsetMO.getImm();
436+
if (CommonOffset && Offset != CommonOffset)
437+
return false;
438+
CommonOffset = Offset;
439+
InlineAsmMemoryOpIndexes.push_back(I + 1);
440+
}
441+
InlineAsmMemoryOpIndexesMap.insert(
442+
std::make_pair(&UseMI, InlineAsmMemoryOpIndexes));
443+
break;
399444
}
400445
}
401446
}
@@ -420,13 +465,36 @@ bool RISCVMergeBaseOffsetOpt::foldIntoMemoryOps(MachineInstr &Hi,
420465
// Update the immediate in the load/store instructions to add the offset.
421466
for (MachineInstr &UseMI :
422467
llvm::make_early_inc_range(MRI->use_instructions(DestReg))) {
423-
UseMI.removeOperand(2);
424-
UseMI.addOperand(ImmOp);
425-
// Update the base reg in the Tail instruction to feed from LUI.
426-
// Output of Hi is only used in Lo, no need to use MRI->replaceRegWith().
427-
UseMI.getOperand(1).setReg(Hi.getOperand(0).getReg());
468+
if (UseMI.getOpcode() == RISCV::INLINEASM ||
469+
UseMI.getOpcode() == RISCV::INLINEASM_BR) {
470+
auto &InlineAsmMemoryOpIndexes = InlineAsmMemoryOpIndexesMap[&UseMI];
471+
for (unsigned I : InlineAsmMemoryOpIndexes) {
472+
MachineOperand &MO = UseMI.getOperand(I + 1);
473+
switch (ImmOp.getType()) {
474+
case MachineOperand::MO_GlobalAddress:
475+
MO.ChangeToGA(ImmOp.getGlobal(), ImmOp.getOffset(),
476+
ImmOp.getTargetFlags());
477+
break;
478+
case MachineOperand::MO_MCSymbol:
479+
MO.ChangeToMCSymbol(ImmOp.getMCSymbol(), ImmOp.getTargetFlags());
480+
MO.setOffset(ImmOp.getOffset());
481+
break;
482+
case MachineOperand::MO_BlockAddress:
483+
MO.ChangeToBA(ImmOp.getBlockAddress(), ImmOp.getOffset(),
484+
ImmOp.getTargetFlags());
485+
break;
486+
default:
487+
report_fatal_error("unsupported machine operand type");
488+
break;
489+
}
490+
}
491+
} else {
492+
UseMI.removeOperand(2);
493+
UseMI.addOperand(ImmOp);
494+
}
428495
}
429496

497+
MRI->replaceRegWith(Lo.getOperand(0).getReg(), Hi.getOperand(0).getReg());
430498
Lo.eraseFromParent();
431499
return true;
432500
}

0 commit comments

Comments
 (0)