Skip to content

Commit 778a484

Browse files
[InlineAsm] Steal a bit to denote a register is foldable (#70738)
When using the inline asm constraint string "rm" (or "g"), we generally would like the compiler to choose "r", but it is permitted to choose "m" if there's register pressure. This is distinct from "r" in which the register is not permitted to be spilled to the stack. The decision of which to use must be made at some point. Currently, the instruction selection frameworks (ISELs) make the choice, and the register allocators had better be able to handle the result. Steal a bit from Storage when using register operands to disambiguate between the two cases. Add helpers/getters/setters, and print in MIR when such a register is foldable. The getter will later be used by the register allocation frameworks (and asserted by the ISELs) while the setters will be used by the instruction selection frameworks. Link: #20571
1 parent 17798ad commit 778a484

File tree

4 files changed

+61
-5
lines changed

4 files changed

+61
-5
lines changed

llvm/include/llvm/CodeGen/MachineInstr.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1364,6 +1364,10 @@ class MachineInstr
13641364
return getOpcode() == TargetOpcode::INLINEASM ||
13651365
getOpcode() == TargetOpcode::INLINEASM_BR;
13661366
}
1367+
/// Returns true if the register operand can be folded with a load or store
1368+
/// into a frame index. Does so by checking the InlineAsm::Flag immediate
1369+
/// operand at OpId - 1.
1370+
bool mayFoldInlineAsmRegOp(unsigned OpId) const;
13671371

13681372
bool isStackAligningInlineAsm() const;
13691373
InlineAsm::AsmDialect getInlineAsmDialect() const;

llvm/include/llvm/IR/InlineAsm.h

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -291,18 +291,23 @@ class InlineAsm final : public Value {
291291
// Bits 30-16 - A ConstraintCode:: value indicating the original
292292
// constraint code. (MemConstraintCode)
293293
// Else:
294-
// Bits 30-16 - The register class ID to use for the operand. (RegClass)
294+
// Bits 29-16 - The register class ID to use for the operand. (RegClass)
295+
// Bit 30 - If the register is permitted to be spilled.
296+
// (RegMayBeFolded)
297+
// Defaults to false "r", may be set for constraints like
298+
// "rm" (or "g").
295299
//
296-
// As such, MatchedOperandNo, MemConstraintCode, and RegClass are views of
297-
// the same slice of bits, but are mutually exclusive depending on the
298-
// fields IsMatched then KindField.
300+
// As such, MatchedOperandNo, MemConstraintCode, and
301+
// (RegClass+RegMayBeFolded) are views of the same slice of bits, but are
302+
// mutually exclusive depending on the fields IsMatched then KindField.
299303
class Flag {
300304
uint32_t Storage;
301305
using KindField = Bitfield::Element<Kind, 0, 3, Kind::Func>;
302306
using NumOperands = Bitfield::Element<unsigned, 3, 13>;
303307
using MatchedOperandNo = Bitfield::Element<unsigned, 16, 15>;
304308
using MemConstraintCode = Bitfield::Element<ConstraintCode, 16, 15, ConstraintCode::Max>;
305-
using RegClass = Bitfield::Element<unsigned, 16, 15>;
309+
using RegClass = Bitfield::Element<unsigned, 16, 14>;
310+
using RegMayBeFolded = Bitfield::Element<bool, 30, 1>;
306311
using IsMatched = Bitfield::Element<bool, 31, 1>;
307312

308313

@@ -413,6 +418,26 @@ class InlineAsm final : public Value {
413418
"Flag is not a memory or function constraint!");
414419
Bitfield::set<MemConstraintCode>(Storage, ConstraintCode::Unknown);
415420
}
421+
422+
/// Set a bit to denote that while this operand is some kind of register
423+
/// (use, def, ...), a memory flag did appear in the original constraint
424+
/// list. This is set by the instruction selection framework, and consumed
425+
/// by the register allocator. While the register allocator is generally
426+
/// responsible for spilling registers, we need to be able to distinguish
427+
/// between registers that the register allocator has permission to fold
428+
/// ("rm") vs ones it does not ("r"). This is because the inline asm may use
429+
/// instructions which don't support memory addressing modes for that
430+
/// operand.
431+
void setRegMayBeFolded(bool B) {
432+
assert((isRegDefKind() || isRegDefEarlyClobberKind() || isRegUseKind()) &&
433+
"Must be reg");
434+
Bitfield::set<RegMayBeFolded>(Storage, B);
435+
}
436+
bool getRegMayBeFolded() const {
437+
assert((isRegDefKind() || isRegDefEarlyClobberKind() || isRegUseKind()) &&
438+
"Must be reg");
439+
return Bitfield::get<RegMayBeFolded>(Storage);
440+
}
416441
};
417442

418443
static std::vector<StringRef> getExtraInfoNames(unsigned ExtraInfo) {

llvm/lib/CodeGen/MachineInstr.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1792,6 +1792,12 @@ void MachineInstr::print(raw_ostream &OS, ModuleSlotTracker &MST,
17921792
if (F.isUseOperandTiedToDef(TiedTo))
17931793
OS << " tiedto:$" << TiedTo;
17941794

1795+
if ((F.isRegDefKind() || F.isRegDefEarlyClobberKind() ||
1796+
F.isRegUseKind()) &&
1797+
F.getRegMayBeFolded()) {
1798+
OS << " foldable";
1799+
}
1800+
17951801
OS << ']';
17961802

17971803
// Compute the index of the next operand descriptor.
@@ -2526,3 +2532,20 @@ void MachineInstr::insert(mop_iterator InsertBefore,
25262532
tieOperands(Tie1, Tie2);
25272533
}
25282534
}
2535+
2536+
bool MachineInstr::mayFoldInlineAsmRegOp(unsigned OpId) const {
2537+
assert(OpId && "expected non-zero operand id");
2538+
assert(isInlineAsm() && "should only be used on inline asm");
2539+
2540+
if (!getOperand(OpId).isReg())
2541+
return false;
2542+
2543+
const MachineOperand &MD = getOperand(OpId - 1);
2544+
if (!MD.isImm())
2545+
return false;
2546+
2547+
InlineAsm::Flag F(MD.getImm());
2548+
if (F.isRegUseKind() || F.isRegDefKind() || F.isRegDefEarlyClobberKind())
2549+
return F.getRegMayBeFolded();
2550+
return false;
2551+
}

llvm/lib/CodeGen/TargetInstrInfo.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1639,6 +1639,10 @@ std::string TargetInstrInfo::createMIROperandComment(
16391639
if (F.isUseOperandTiedToDef(TiedTo))
16401640
OS << " tiedto:$" << TiedTo;
16411641

1642+
if ((F.isRegDefKind() || F.isRegDefEarlyClobberKind() || F.isRegUseKind()) &&
1643+
F.getRegMayBeFolded())
1644+
OS << " foldable";
1645+
16421646
return OS.str();
16431647
}
16441648

0 commit comments

Comments
 (0)