Skip to content

Commit cc36dbf

Browse files
committedJun 27, 2017
[globalisel][tablegen] Add support for EXTRACT_SUBREG.
Summary: After this patch, we finally have test cases that require multiple instruction emission. Depends on D33590 Reviewers: ab, qcolombet, t.p.northover, rovka, kristof.beyls Subscribers: javed.absar, llvm-commits, igorb Differential Revision: https://reviews.llvm.org/D33596 llvm-svn: 306388
1 parent 3e0d39e commit cc36dbf

File tree

5 files changed

+245
-14
lines changed

5 files changed

+245
-14
lines changed
 

‎llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -947,7 +947,7 @@ bool AArch64InstructionSelector::select(MachineInstr &I) const {
947947
const RegisterBank &SrcRB = *RBI.getRegBank(SrcReg, MRI, TRI);
948948

949949
if (DstRB.getID() != SrcRB.getID()) {
950-
DEBUG(dbgs() << "G_TRUNC input/output on different banks\n");
950+
DEBUG(dbgs() << "G_TRUNC/G_PTRTOINT input/output on different banks\n");
951951
return false;
952952
}
953953

@@ -964,16 +964,21 @@ bool AArch64InstructionSelector::select(MachineInstr &I) const {
964964

965965
if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) ||
966966
!RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
967-
DEBUG(dbgs() << "Failed to constrain G_TRUNC\n");
967+
DEBUG(dbgs() << "Failed to constrain G_TRUNC/G_PTRTOINT\n");
968968
return false;
969969
}
970970

971971
if (DstRC == SrcRC) {
972972
// Nothing to be done
973+
} else if (Opcode == TargetOpcode::G_TRUNC && DstTy == LLT::scalar(32) &&
974+
SrcTy == LLT::scalar(64)) {
975+
llvm_unreachable("TableGen can import this case");
976+
return false;
973977
} else if (DstRC == &AArch64::GPR32RegClass &&
974978
SrcRC == &AArch64::GPR64RegClass) {
975979
I.getOperand(1).setSubReg(AArch64::sub_32);
976980
} else {
981+
DEBUG(dbgs() << "Unhandled mismatched classes in G_TRUNC/G_PTRTOINT\n");
977982
return false;
978983
}
979984

‎llvm/test/CodeGen/AArch64/GlobalISel/select-trunc.mir

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ legalized: true
1515
regBankSelected: true
1616

1717
# CHECK: registers:
18-
# CHECK-NEXT: - { id: 0, class: gpr64, preferred-register: '' }
19-
# CHECK-NEXT: - { id: 1, class: gpr32, preferred-register: '' }
18+
# CHECK-NEXT: - { id: 0, class: gpr64sp, preferred-register: '' }
19+
# CHECK-NEXT: - { id: 1, class: gpr32sp, preferred-register: '' }
2020
registers:
2121
- { id: 0, class: gpr }
2222
- { id: 1, class: gpr }

‎llvm/utils/TableGen/CodeGenRegisters.cpp

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -915,6 +915,84 @@ void CodeGenRegisterClass::computeSubClasses(CodeGenRegBank &RegBank) {
915915
RC.inheritProperties(RegBank);
916916
}
917917

918+
Optional<std::pair<CodeGenRegisterClass *, CodeGenRegisterClass *>>
919+
CodeGenRegisterClass::getMatchingSubClassWithSubRegs(
920+
CodeGenRegBank &RegBank, const CodeGenSubRegIndex *SubIdx) const {
921+
auto SizeOrder = [](const CodeGenRegisterClass *A,
922+
const CodeGenRegisterClass *B) {
923+
return A->getMembers().size() >= B->getMembers().size();
924+
};
925+
926+
auto &RegClasses = RegBank.getRegClasses();
927+
928+
// Find all the subclasses of this one that fully support the sub-register
929+
// index and order them by size. BiggestSuperRC should always be first.
930+
CodeGenRegisterClass *BiggestSuperRegRC = getSubClassWithSubReg(SubIdx);
931+
if (!BiggestSuperRegRC)
932+
return None;
933+
BitVector SuperRegRCsBV = BiggestSuperRegRC->getSubClasses();
934+
std::vector<CodeGenRegisterClass *> SuperRegRCs;
935+
for (auto &RC : RegClasses)
936+
if (SuperRegRCsBV[RC.EnumValue])
937+
SuperRegRCs.emplace_back(&RC);
938+
std::sort(SuperRegRCs.begin(), SuperRegRCs.end(), SizeOrder);
939+
assert(SuperRegRCs.front() == BiggestSuperRegRC && "Biggest class wasn't first");
940+
941+
// Find all the subreg classes and order them by size too.
942+
std::vector<std::pair<CodeGenRegisterClass *, BitVector>> SuperRegClasses;
943+
for (auto &RC: RegClasses) {
944+
BitVector SuperRegClassesBV(RegClasses.size());
945+
RC.getSuperRegClasses(SubIdx, SuperRegClassesBV);
946+
if (SuperRegClassesBV.any())
947+
SuperRegClasses.push_back(std::make_pair(&RC, SuperRegClassesBV));
948+
}
949+
std::sort(SuperRegClasses.begin(), SuperRegClasses.end(),
950+
[&](const std::pair<CodeGenRegisterClass *, BitVector> &A,
951+
const std::pair<CodeGenRegisterClass *, BitVector> &B) {
952+
return SizeOrder(A.first, B.first);
953+
});
954+
955+
// Find the biggest subclass and subreg class such that R:subidx is in the
956+
// subreg class for all R in subclass.
957+
//
958+
// For example:
959+
// All registers in X86's GR64 have a sub_32bit subregister but no class
960+
// exists that contains all the 32-bit subregisters because GR64 contains RIP
961+
// but GR32 does not contain EIP. Instead, we constrain SuperRegRC to
962+
// GR32_with_sub_8bit (which is identical to GR32_with_sub_32bit) and then,
963+
// having excluded RIP, we are able to find a SubRegRC (GR32).
964+
CodeGenRegisterClass *ChosenSuperRegClass = nullptr;
965+
CodeGenRegisterClass *SubRegRC = nullptr;
966+
for (auto *SuperRegRC : SuperRegRCs) {
967+
for (const auto &SuperRegClassPair : SuperRegClasses) {
968+
const BitVector &SuperRegClassBV = SuperRegClassPair.second;
969+
if (SuperRegClassBV[SuperRegRC->EnumValue]) {
970+
SubRegRC = SuperRegClassPair.first;
971+
ChosenSuperRegClass = SuperRegRC;
972+
973+
// If SubRegRC is bigger than SuperRegRC then there are members of
974+
// SubRegRC that don't have super registers via SubIdx. Keep looking to
975+
// find a better fit and fall back on this one if there isn't one.
976+
//
977+
// This is intended to prevent X86 from making odd choices such as
978+
// picking LOW32_ADDR_ACCESS_RBP instead of GR32 in the example above.
979+
// LOW32_ADDR_ACCESS_RBP is a valid choice but contains registers that
980+
// aren't subregisters of SuperRegRC whereas GR32 has a direct 1:1
981+
// mapping.
982+
if (SuperRegRC->getMembers().size() >= SubRegRC->getMembers().size())
983+
return std::make_pair(ChosenSuperRegClass, SubRegRC);
984+
}
985+
}
986+
987+
// If we found a fit but it wasn't quite ideal because SubRegRC had excess
988+
// registers, then we're done.
989+
if (ChosenSuperRegClass)
990+
return std::make_pair(ChosenSuperRegClass, SubRegRC);
991+
}
992+
993+
return None;
994+
}
995+
918996
void CodeGenRegisterClass::getSuperRegClasses(const CodeGenSubRegIndex *SubIdx,
919997
BitVector &Out) const {
920998
auto FindI = SuperRegClasses.find(SubIdx);

‎llvm/utils/TableGen/CodeGenRegisters.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,9 @@ namespace llvm {
329329
const std::string &getName() const { return Name; }
330330
std::string getQualifiedName() const;
331331
ArrayRef<MVT::SimpleValueType> getValueTypes() const {return VTs;}
332+
bool hasValueType(MVT::SimpleValueType VT) const {
333+
return std::find(VTs.begin(), VTs.end(), VT) != VTs.end();
334+
}
332335
unsigned getNumValueTypes() const { return VTs.size(); }
333336

334337
MVT::SimpleValueType getValueTypeNum(unsigned VTNum) const {
@@ -360,6 +363,18 @@ namespace llvm {
360363
return SubClassWithSubReg.lookup(SubIdx);
361364
}
362365

366+
/// Find largest subclass where all registers have SubIdx subregisters in
367+
/// SubRegClass and the largest subregister class that contains those
368+
/// subregisters without (as far as possible) also containing additional registers.
369+
///
370+
/// This can be used to find a suitable pair of classes for subregister copies.
371+
/// \return std::pair<SubClass, SubRegClass> where SubClass is a SubClass is
372+
/// a class where every register has SubIdx and SubRegClass is a class where
373+
/// every register is covered by the SubIdx subregister of SubClass.
374+
Optional<std::pair<CodeGenRegisterClass *, CodeGenRegisterClass *>>
375+
getMatchingSubClassWithSubRegs(CodeGenRegBank &RegBank,
376+
const CodeGenSubRegIndex *SubIdx) const;
377+
363378
void setSubClassWithSubReg(const CodeGenSubRegIndex *SubIdx,
364379
CodeGenRegisterClass *SubRC) {
365380
SubClassWithSubReg[SubIdx] = SubRC;
@@ -370,7 +385,7 @@ namespace llvm {
370385
void getSuperRegClasses(const CodeGenSubRegIndex *SubIdx,
371386
BitVector &Out) const;
372387

373-
// addSuperRegClass - Add a class containing only SudIdx super-registers.
388+
// addSuperRegClass - Add a class containing only SubIdx super-registers.
374389
void addSuperRegClass(CodeGenSubRegIndex *SubIdx,
375390
CodeGenRegisterClass *SuperRC) {
376391
SuperRegClasses[SubIdx].insert(SuperRC);

‎llvm/utils/TableGen/GlobalISelEmitter.cpp

Lines changed: 142 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -832,7 +832,13 @@ class InstructionOperandMatcher : public OperandPredicateMatcher {
832832
//===- Actions ------------------------------------------------------------===//
833833
class OperandRenderer {
834834
public:
835-
enum RendererKind { OR_Copy, OR_Imm, OR_Register, OR_ComplexPattern };
835+
enum RendererKind {
836+
OR_Copy,
837+
OR_CopySubReg,
838+
OR_Imm,
839+
OR_Register,
840+
OR_ComplexPattern
841+
};
836842

837843
protected:
838844
RendererKind Kind;
@@ -877,6 +883,42 @@ class CopyRenderer : public OperandRenderer {
877883
}
878884
};
879885

886+
/// A CopySubRegRenderer emits code to copy a single register operand from an
887+
/// existing instruction to the one being built and indicate that only a
888+
/// subregister should be copied.
889+
class CopySubRegRenderer : public OperandRenderer {
890+
protected:
891+
/// The matcher for the instruction that this operand is copied from.
892+
/// This provides the facility for looking up an a operand by it's name so
893+
/// that it can be used as a source for the instruction being built.
894+
const InstructionMatcher &Matched;
895+
/// The name of the operand.
896+
const StringRef SymbolicName;
897+
/// The subregister to extract.
898+
const CodeGenSubRegIndex *SubReg;
899+
900+
public:
901+
CopySubRegRenderer(const InstructionMatcher &Matched, StringRef SymbolicName,
902+
const CodeGenSubRegIndex *SubReg)
903+
: OperandRenderer(OR_CopySubReg), Matched(Matched),
904+
SymbolicName(SymbolicName), SubReg(SubReg) {}
905+
906+
static bool classof(const OperandRenderer *R) {
907+
return R->getKind() == OR_CopySubReg;
908+
}
909+
910+
const StringRef getSymbolicName() const { return SymbolicName; }
911+
912+
void emitCxxRenderStmts(raw_ostream &OS, RuleMatcher &Rule) const override {
913+
const OperandMatcher &Operand = Matched.getOperand(SymbolicName);
914+
StringRef InsnVarName =
915+
Rule.getInsnVarName(Operand.getInstructionMatcher());
916+
std::string OperandExpr = Operand.getOperandExpr(InsnVarName);
917+
OS << " MIB.addReg(" << OperandExpr << ".getReg() /*" << SymbolicName
918+
<< "*/, 0, " << SubReg->EnumValue << ");\n";
919+
}
920+
};
921+
880922
/// Adds a specific physical register to the instruction being built.
881923
/// This is typically useful for WZR/XZR on AArch64.
882924
class AddRegisterRenderer : public OperandRenderer {
@@ -1292,6 +1334,7 @@ class GlobalISelEmitter {
12921334
const RecordKeeper &RK;
12931335
const CodeGenDAGPatterns CGP;
12941336
const CodeGenTarget &Target;
1337+
CodeGenRegBank CGRegs;
12951338

12961339
/// Keep track of the equivalence between SDNodes and Instruction.
12971340
/// This is defined using 'GINodeEquiv' in the target description.
@@ -1315,9 +1358,9 @@ class GlobalISelEmitter {
13151358
Error importChildMatcher(InstructionMatcher &InsnMatcher,
13161359
const TreePatternNode *SrcChild, unsigned OpIdx,
13171360
unsigned &TempOpIdx) const;
1318-
Expected<BuildMIAction &> createAndImportInstructionRenderer(
1319-
RuleMatcher &M, const TreePatternNode *Dst,
1320-
const InstructionMatcher &InsnMatcher) const;
1361+
Expected<BuildMIAction &>
1362+
createAndImportInstructionRenderer(RuleMatcher &M, const TreePatternNode *Dst,
1363+
const InstructionMatcher &InsnMatcher);
13211364
Error importExplicitUseRenderer(BuildMIAction &DstMIBuilder,
13221365
TreePatternNode *DstChild,
13231366
const InstructionMatcher &InsnMatcher) const;
@@ -1354,7 +1397,7 @@ const CodeGenInstruction *GlobalISelEmitter::findNodeEquiv(Record *N) const {
13541397
}
13551398

13561399
GlobalISelEmitter::GlobalISelEmitter(RecordKeeper &RK)
1357-
: RK(RK), CGP(RK), Target(CGP.getTargetInfo()) {}
1400+
: RK(RK), CGP(RK), Target(CGP.getTargetInfo()), CGRegs(RK) {}
13581401

13591402
//===- Emitter ------------------------------------------------------------===//
13601403

@@ -1585,7 +1628,7 @@ Error GlobalISelEmitter::importExplicitUseRenderer(
15851628

15861629
Expected<BuildMIAction &> GlobalISelEmitter::createAndImportInstructionRenderer(
15871630
RuleMatcher &M, const TreePatternNode *Dst,
1588-
const InstructionMatcher &InsnMatcher) const {
1631+
const InstructionMatcher &InsnMatcher) {
15891632
Record *DstOp = Dst->getOperator();
15901633
if (!DstOp->isSubClassOf("Instruction")) {
15911634
if (DstOp->isSubClassOf("ValueType"))
@@ -1597,13 +1640,17 @@ Expected<BuildMIAction &> GlobalISelEmitter::createAndImportInstructionRenderer(
15971640

15981641
unsigned DstINumUses = DstI->Operands.size() - DstI->Operands.NumDefs;
15991642
unsigned ExpectedDstINumUses = Dst->getNumChildren();
1643+
bool IsExtractSubReg = false;
16001644

16011645
// COPY_TO_REGCLASS is just a copy with a ConstrainOperandToRegClassAction
1602-
// attached.
1646+
// attached. Similarly for EXTRACT_SUBREG except that's a subregister copy.
16031647
if (DstI->TheDef->getName() == "COPY_TO_REGCLASS") {
16041648
DstI = &Target.getInstruction(RK.getDef("COPY"));
16051649
DstINumUses--; // Ignore the class constraint.
16061650
ExpectedDstINumUses--;
1651+
} else if (DstI->TheDef->getName() == "EXTRACT_SUBREG") {
1652+
DstI = &Target.getInstruction(RK.getDef("COPY"));
1653+
IsExtractSubReg = true;
16071654
}
16081655

16091656
auto &DstMIBuilder = M.addAction<BuildMIAction>("NewI", DstI, InsnMatcher);
@@ -1614,6 +1661,32 @@ Expected<BuildMIAction &> GlobalISelEmitter::createAndImportInstructionRenderer(
16141661
DstMIBuilder.addRenderer<CopyRenderer>(InsnMatcher, DstIOperand.Name);
16151662
}
16161663

1664+
// EXTRACT_SUBREG needs to use a subregister COPY.
1665+
if (IsExtractSubReg) {
1666+
if (!Dst->getChild(0)->isLeaf())
1667+
return failedImport("EXTRACT_SUBREG child #1 is not a leaf");
1668+
1669+
if (DefInit *SubRegInit = dyn_cast<DefInit>(Dst->getChild(1)->getLeafValue())) {
1670+
CodeGenRegisterClass *RC = CGRegs.getRegClass(
1671+
getInitValueAsRegClass(Dst->getChild(0)->getLeafValue()));
1672+
CodeGenSubRegIndex *SubIdx = CGRegs.getSubRegIdx(SubRegInit->getDef());
1673+
1674+
const auto &SrcRCDstRCPair =
1675+
RC->getMatchingSubClassWithSubRegs(CGRegs, SubIdx);
1676+
if (SrcRCDstRCPair.hasValue()) {
1677+
assert(SrcRCDstRCPair->second && "Couldn't find a matching subclass");
1678+
if (SrcRCDstRCPair->first != RC)
1679+
return failedImport("EXTRACT_SUBREG requires an additional COPY");
1680+
}
1681+
1682+
DstMIBuilder.addRenderer<CopySubRegRenderer>(
1683+
InsnMatcher, Dst->getChild(0)->getName(), SubIdx);
1684+
return DstMIBuilder;
1685+
}
1686+
1687+
return failedImport("EXTRACT_SUBREG child #1 is not a subreg index");
1688+
}
1689+
16171690
// Render the explicit uses.
16181691
unsigned Child = 0;
16191692
unsigned NumDefaultOps = 0;
@@ -1740,6 +1813,16 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) {
17401813
if (DstIOpRec == nullptr)
17411814
return failedImport(
17421815
"COPY_TO_REGCLASS operand #1 isn't a register class");
1816+
} else if (DstI.TheDef->getName() == "EXTRACT_SUBREG") {
1817+
if (!Dst->getChild(0)->isLeaf())
1818+
return failedImport("EXTRACT_SUBREG operand #0 isn't a leaf");
1819+
1820+
// We can assume that a subregister is in the same bank as it's super register.
1821+
DstIOpRec = getInitValueAsRegClass(Dst->getChild(0)->getLeafValue());
1822+
1823+
if (DstIOpRec == nullptr)
1824+
return failedImport(
1825+
"EXTRACT_SUBREG operand #0 isn't a register class");
17431826
} else if (DstIOpRec->isSubClassOf("RegisterOperand"))
17441827
DstIOpRec = DstIOpRec->getValueAsDef("RegClass");
17451828
else if (!DstIOpRec->isSubClassOf("RegisterClass"))
@@ -1776,8 +1859,58 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) {
17761859

17771860
M.addAction<ConstrainOperandToRegClassAction>(
17781861
"NewI", 0, Target.getRegisterClass(DstIOpRec));
1779-
} else
1780-
M.addAction<ConstrainOperandsToDefinitionAction>("NewI");
1862+
1863+
// We're done with this pattern! It's eligible for GISel emission; return
1864+
// it.
1865+
++NumPatternImported;
1866+
return std::move(M);
1867+
}
1868+
1869+
if (DstI.TheDef->getName() == "EXTRACT_SUBREG") {
1870+
// EXTRACT_SUBREG selects into a subregister COPY but unlike most
1871+
// instructions, the result register class is controlled by the
1872+
// subregisters of the operand. As a result, we must constrain the result
1873+
// class rather than check that it's already the right one.
1874+
if (!Dst->getChild(0)->isLeaf())
1875+
return failedImport("EXTRACT_SUBREG child #1 is not a leaf");
1876+
1877+
if (DefInit *SubRegInit =
1878+
dyn_cast<DefInit>(Dst->getChild(1)->getLeafValue())) {
1879+
// Constrain the result to the same register bank as the operand.
1880+
Record *DstIOpRec =
1881+
getInitValueAsRegClass(Dst->getChild(0)->getLeafValue());
1882+
1883+
if (DstIOpRec == nullptr)
1884+
return failedImport("EXTRACT_SUBREG operand #1 isn't a register class");
1885+
1886+
CodeGenSubRegIndex *SubIdx = CGRegs.getSubRegIdx(SubRegInit->getDef());
1887+
CodeGenRegisterClass *SrcRC = CGRegs.getRegClass(
1888+
getInitValueAsRegClass(Dst->getChild(0)->getLeafValue()));
1889+
1890+
// It would be nice to leave this constraint implicit but we're required
1891+
// to pick a register class so constrain the result to a register class
1892+
// that can hold the correct MVT.
1893+
//
1894+
// FIXME: This may introduce an extra copy if the chosen class doesn't
1895+
// actually contain the subregisters.
1896+
assert(Src->getExtTypes().size() == 1);
1897+
1898+
const auto &SrcRCDstRCPair =
1899+
SrcRC->getMatchingSubClassWithSubRegs(CGRegs, SubIdx);
1900+
assert(SrcRCDstRCPair->second && "Couldn't find a matching subclass");
1901+
M.addAction<ConstrainOperandToRegClassAction>("NewI", 0, *SrcRCDstRCPair->second);
1902+
M.addAction<ConstrainOperandToRegClassAction>("NewI", 1, *SrcRCDstRCPair->first);
1903+
1904+
// We're done with this pattern! It's eligible for GISel emission; return
1905+
// it.
1906+
++NumPatternImported;
1907+
return std::move(M);
1908+
}
1909+
1910+
return failedImport("EXTRACT_SUBREG child #1 is not a subreg index");
1911+
}
1912+
1913+
M.addAction<ConstrainOperandsToDefinitionAction>("NewI");
17811914

17821915
// We're done with this pattern! It's eligible for GISel emission; return it.
17831916
++NumPatternImported;

0 commit comments

Comments
 (0)
Please sign in to comment.