Skip to content

Commit 2deea18

Browse files
committed
[globalisel][tablegen] Revise API for ComplexPattern operands to improve flexibility.
Summary: Some targets need to be able to do more complex rendering than just adding an operand or two to an instruction. For example, it may need to insert an instruction to extract a subreg first, or it may need to perform an operation on the operand. In SelectionDAG, targets would create SDNode's to achieve the desired effect during the complex pattern predicate. This worked because SelectionDAG had a form of garbage collection that would take care of SDNode's that were created but not used due to a later predicate rejecting a match. This doesn't translate well to GlobalISel and the churn was wasteful. The API changes in this patch enable GlobalISel to accomplish the same thing without the waste. The API is now: InstructionSelector::OptionalComplexRendererFn selectArithImmed(MachineOperand &Root) const; where Root is the root of the match. The return value can be omitted to indicate that the predicate failed to match, or a function with the signature ComplexRendererFn can be returned. For example: return OptionalComplexRendererFn( [=](MachineInstrBuilder &MIB) { MIB.addImm(Immed).addImm(ShVal); }); adds two immediate operands to the rendered instruction. Immed and ShVal are captured from the predicate function. As an added bonus, this also reduces the amount of information we need to provide to GIComplexOperandMatcher. Depends on D31418 Reviewers: aditya_nandakumar, t.p.northover, qcolombet, rovka, ab, javed.absar Reviewed By: ab Subscribers: dberris, kristof.beyls, igorb, llvm-commits Differential Revision: https://reviews.llvm.org/D31761 llvm-svn: 301079
1 parent 3016d3c commit 2deea18

File tree

10 files changed

+61
-155
lines changed

10 files changed

+61
-155
lines changed

llvm/include/llvm/CodeGen/GlobalISel/InstructionSelector.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,11 @@
1919
#include "llvm/ADT/Optional.h"
2020
#include <cstdint>
2121
#include <bitset>
22+
#include <functional>
2223

2324
namespace llvm {
2425
class MachineInstr;
26+
class MachineInstrBuilder;
2527
class MachineFunction;
2628
class MachineOperand;
2729
class MachineRegisterInfo;
@@ -76,6 +78,8 @@ class InstructionSelector {
7678
virtual bool select(MachineInstr &I) const = 0;
7779

7880
protected:
81+
typedef std::function<void(MachineInstrBuilder &)> ComplexRendererFn;
82+
7983
InstructionSelector();
8084

8185
/// Mutate the newly-selected instruction \p I to constrain its (possibly

llvm/include/llvm/CodeGen/MachineOperand.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@ class MachineOperand {
6565
MO_CFIIndex, ///< MCCFIInstruction index.
6666
MO_IntrinsicID, ///< Intrinsic ID for ISel
6767
MO_Predicate, ///< Generic predicate for ISel
68-
MO_Placeholder, ///< Placeholder for GlobalISel ComplexPattern result.
6968
};
7069

7170
private:
@@ -768,11 +767,6 @@ class MachineOperand {
768767
return Op;
769768
}
770769

771-
static MachineOperand CreatePlaceholder() {
772-
MachineOperand Op(MachineOperand::MO_Placeholder);
773-
return Op;
774-
}
775-
776770
friend class MachineInstr;
777771
friend class MachineRegisterInfo;
778772
private:

llvm/include/llvm/Target/GlobalISel/Target.td

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,21 +30,13 @@ def s64 : LLT;
3030
// Definitions that inherit from this may also inherit from
3131
// GIComplexPatternEquiv to enable the import of SelectionDAG patterns involving
3232
// those ComplexPatterns.
33-
class GIComplexOperandMatcher<LLT type, dag operands, string matcherfn> {
33+
class GIComplexOperandMatcher<LLT type, string matcherfn> {
3434
// The expected type of the root of the match.
3535
//
3636
// TODO: We should probably support, any-type, any-scalar, and multiple types
3737
// in the future.
3838
LLT Type = type;
3939

40-
// The operands that result from a successful match
41-
// Should be of the form '(ops ty1, ty2, ...)' where ty1/ty2 are definitions
42-
// that inherit from Operand.
43-
//
44-
// FIXME: Which definition is used for ty1/ty2 doesn't actually matter at the
45-
// moment. Only the number of operands is used.
46-
dag Operands = operands;
47-
4840
// The function that determines whether the operand matches. It should be of
4941
// the form:
5042
// bool select(const MatchOperand &Root, MatchOperand &Result1)

llvm/lib/CodeGen/MIRPrinter.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -925,9 +925,6 @@ void MIPrinter::print(const MachineOperand &Op, const TargetRegisterInfo *TRI,
925925
<< CmpInst::getPredicateName(Pred) << ')';
926926
break;
927927
}
928-
case MachineOperand::MO_Placeholder:
929-
OS << "<placeholder>";
930-
break;
931928
}
932929
}
933930

llvm/lib/CodeGen/MachineInstr.cpp

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -287,8 +287,6 @@ bool MachineOperand::isIdenticalTo(const MachineOperand &Other) const {
287287
return getIntrinsicID() == Other.getIntrinsicID();
288288
case MachineOperand::MO_Predicate:
289289
return getPredicate() == Other.getPredicate();
290-
case MachineOperand::MO_Placeholder:
291-
return true;
292290
}
293291
llvm_unreachable("Invalid machine operand type");
294292
}
@@ -337,8 +335,6 @@ hash_code llvm::hash_value(const MachineOperand &MO) {
337335
return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getIntrinsicID());
338336
case MachineOperand::MO_Predicate:
339337
return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getPredicate());
340-
case MachineOperand::MO_Placeholder:
341-
return hash_combine();
342338
}
343339
llvm_unreachable("Invalid machine operand type");
344340
}
@@ -515,9 +511,6 @@ void MachineOperand::print(raw_ostream &OS, ModuleSlotTracker &MST,
515511
<< CmpInst::getPredicateName(Pred) << '>';
516512
break;
517513
}
518-
case MachineOperand::MO_Placeholder:
519-
OS << "<placeholder>";
520-
break;
521514
}
522515
if (unsigned TF = getTargetFlags())
523516
OS << "[TF=" << TF << ']';

llvm/lib/Target/AArch64/AArch64InstrFormats.td

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -693,11 +693,11 @@ def addsub_shifted_imm32_neg : addsub_shifted_imm_neg<i32>;
693693
def addsub_shifted_imm64_neg : addsub_shifted_imm_neg<i64>;
694694

695695
def gi_addsub_shifted_imm32 :
696-
GIComplexOperandMatcher<s32, (ops i32imm, i32imm), "selectArithImmed">,
696+
GIComplexOperandMatcher<s32, "selectArithImmed">,
697697
GIComplexPatternEquiv<addsub_shifted_imm32>;
698698

699699
def gi_addsub_shifted_imm64 :
700-
GIComplexOperandMatcher<s64, (ops i32imm, i32imm), "selectArithImmed">,
700+
GIComplexOperandMatcher<s64, "selectArithImmed">,
701701
GIComplexPatternEquiv<addsub_shifted_imm64>;
702702

703703
class neg_addsub_shifted_imm<ValueType Ty>

llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,7 @@ class AArch64InstructionSelector : public InstructionSelector {
6767
bool selectCompareBranch(MachineInstr &I, MachineFunction &MF,
6868
MachineRegisterInfo &MRI) const;
6969

70-
bool selectArithImmed(MachineOperand &Root, MachineOperand &Result1,
71-
MachineOperand &Result2) const;
70+
ComplexRendererFn selectArithImmed(MachineOperand &Root) const;
7271

7372
const AArch64TargetMachine &TM;
7473
const AArch64Subtarget &STI;
@@ -1329,9 +1328,8 @@ bool AArch64InstructionSelector::select(MachineInstr &I) const {
13291328
/// SelectArithImmed - Select an immediate value that can be represented as
13301329
/// a 12-bit value shifted left by either 0 or 12. If so, return true with
13311330
/// Val set to the 12-bit value and Shift set to the shifter operand.
1332-
bool AArch64InstructionSelector::selectArithImmed(
1333-
MachineOperand &Root, MachineOperand &Result1,
1334-
MachineOperand &Result2) const {
1331+
InstructionSelector::ComplexRendererFn
1332+
AArch64InstructionSelector::selectArithImmed(MachineOperand &Root) const {
13351333
MachineInstr &MI = *Root.getParent();
13361334
MachineBasicBlock &MBB = *MI.getParent();
13371335
MachineFunction &MF = *MBB.getParent();
@@ -1350,13 +1348,13 @@ bool AArch64InstructionSelector::selectArithImmed(
13501348
else if (Root.isReg()) {
13511349
MachineInstr *Def = MRI.getVRegDef(Root.getReg());
13521350
if (Def->getOpcode() != TargetOpcode::G_CONSTANT)
1353-
return false;
1351+
return nullptr;
13541352
MachineOperand &Op1 = Def->getOperand(1);
13551353
if (!Op1.isCImm() || Op1.getCImm()->getBitWidth() > 64)
1356-
return false;
1354+
return nullptr;
13571355
Immed = Op1.getCImm()->getZExtValue();
13581356
} else
1359-
return false;
1357+
return nullptr;
13601358

13611359
unsigned ShiftAmt;
13621360

@@ -1366,14 +1364,10 @@ bool AArch64InstructionSelector::selectArithImmed(
13661364
ShiftAmt = 12;
13671365
Immed = Immed >> 12;
13681366
} else
1369-
return false;
1367+
return nullptr;
13701368

13711369
unsigned ShVal = AArch64_AM::getShifterImm(AArch64_AM::LSL, ShiftAmt);
1372-
Result1.ChangeToImmediate(Immed);
1373-
Result1.clearParent();
1374-
Result2.ChangeToImmediate(ShVal);
1375-
Result2.clearParent();
1376-
return true;
1370+
return [=](MachineInstrBuilder &MIB) { MIB.addImm(Immed).addImm(ShVal); };
13771371
}
13781372

13791373
namespace llvm {

llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -661,7 +661,6 @@ static bool IsAnAddressOperand(const MachineOperand &MO) {
661661
return false;
662662
case MachineOperand::MO_IntrinsicID:
663663
case MachineOperand::MO_Predicate:
664-
case MachineOperand::MO_Placeholder:
665664
llvm_unreachable("should not exist post-isel");
666665
}
667666
llvm_unreachable("unhandled machine operand type");

llvm/test/TableGen/GlobalISelEmitter.td

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ def complex : Operand<i32>, ComplexPattern<i32, 2, "SelectComplexPattern", []> {
2222
let MIOperandInfo = (ops i32imm, i32imm);
2323
}
2424
def gi_complex :
25-
GIComplexOperandMatcher<s32, (ops i32imm, i32imm), "selectComplexPattern">,
25+
GIComplexOperandMatcher<s32, "selectComplexPattern">,
2626
GIComplexPatternEquiv<complex>;
2727

2828
def m1 : OperandWithDefaultOps <i32, (ops (i32 -1))>;
@@ -72,17 +72,15 @@ def HasB : Predicate<"Subtarget->hasB()">;
7272
// CHECK-NEXT: ((/* src1 */ (MRI.getType(MI0.getOperand(1).getReg()) == (LLT::scalar(32))) &&
7373
// CHECK-NEXT: ((&RBI.getRegBankFromRegClass(MyTarget::GPR32RegClass) == RBI.getRegBank(MI0.getOperand(1).getReg(), MRI, TRI))))) &&
7474
// CHECK-NEXT: ((/* src2 */ (MRI.getType(MI0.getOperand(2).getReg()) == (LLT::scalar(32))) &&
75-
// CHECK-NEXT: (selectComplexPattern(MI0.getOperand(2), TempOp0, TempOp1)))) &&
75+
// CHECK-NEXT: ((Renderer0 = selectComplexPattern(MI0.getOperand(2)))))) &&
7676
// CHECK-NEXT: ((/* src3 */ (MRI.getType(MI0.getOperand(3).getReg()) == (LLT::scalar(32))) &&
77-
// CHECK-NEXT: (selectComplexPattern(MI0.getOperand(3), TempOp2, TempOp3))))) {
77+
// CHECK-NEXT: ((Renderer1 = selectComplexPattern(MI0.getOperand(3))))))) {
7878
// CHECK-NEXT: // (select:i32 GPR32:i32:$src1, complex:i32:$src2, complex:i32:$src3) => (INSN2:i32 GPR32:i32:$src1, complex:i32:$src3, complex:i32:$src2)
7979
// CHECK-NEXT: MachineInstrBuilder MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(MyTarget::INSN2));
8080
// CHECK-NEXT: MIB.add(MI0.getOperand(0)/*dst*/);
8181
// CHECK-NEXT: MIB.add(MI0.getOperand(1)/*src1*/);
82-
// CHECK-NEXT: MIB.add(TempOp2);
83-
// CHECK-NEXT: MIB.add(TempOp3);
84-
// CHECK-NEXT: MIB.add(TempOp0);
85-
// CHECK-NEXT: MIB.add(TempOp1);
82+
// CHECK-NEXT: Renderer1(MIB);
83+
// CHECK-NEXT: Renderer0(MIB);
8684
// CHECK-NEXT: for (const auto *FromMI : {&MI0, })
8785
// CHECK-NEXT: for (const auto &MMO : FromMI->memoperands())
8886
// CHECK-NEXT: MIB.addMemOperand(MMO);
@@ -263,13 +261,12 @@ def MUL : I<(outs GPR32:$dst), (ins GPR32:$src2, GPR32:$src1),
263261
// CHECK-NEXT: ((/* src1 */ (MRI.getType(MI0.getOperand(1).getReg()) == (LLT::scalar(32))) &&
264262
// CHECK-NEXT: ((&RBI.getRegBankFromRegClass(MyTarget::GPR32RegClass) == RBI.getRegBank(MI0.getOperand(1).getReg(), MRI, TRI))))) &&
265263
// CHECK-NEXT: ((/* src2 */ (MRI.getType(MI0.getOperand(2).getReg()) == (LLT::scalar(32))) &&
266-
// CHECK-NEXT: (selectComplexPattern(MI0.getOperand(2), TempOp0, TempOp1))))) {
264+
// CHECK-NEXT: ((Renderer0 = selectComplexPattern(MI0.getOperand(2))))))) {
267265
// CHECK-NEXT: // (sub:i32 GPR32:i32:$src1, complex:i32:$src2) => (INSN1:i32 GPR32:i32:$src1, complex:i32:$src2)
268266
// CHECK-NEXT: MachineInstrBuilder MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(MyTarget::INSN1));
269267
// CHECK-NEXT: MIB.add(MI0.getOperand(0)/*dst*/);
270268
// CHECK-NEXT: MIB.add(MI0.getOperand(1)/*src1*/);
271-
// CHECK-NEXT: MIB.add(TempOp0);
272-
// CHECK-NEXT: MIB.add(TempOp1);
269+
// CHECK-NEXT: Renderer0(MIB);
273270
// CHECK-NEXT: for (const auto *FromMI : {&MI0, })
274271
// CHECK-NEXT: for (const auto &MMO : FromMI->memoperands())
275272
// CHECK-NEXT: MIB.addMemOperand(MMO);

0 commit comments

Comments
 (0)