[globalisel][tablegen] Generalize pointer-type inference by introducing ptypeN. NFC

ptypeN is functionally the same as typeN except that it informs the
SelectionDAG importer that an operand should be treated as a pointer even
if it was written as iN. This is important for patterns that use iN instead
of iPTR to represent pointers. E.g.:
  (set GPR64:$dst, (load GPR64:$addr))

Previously, this was handled as a hardcoded special case for the appropriate
operands to G_LOAD and G_STORE.

llvm-svn: 318574
This commit is contained in:
Daniel Sanders 2017-11-18 00:16:44 +00:00
parent 0b44f44bcf
commit c54aa9c844
5 changed files with 30 additions and 6 deletions

View File

@ -469,7 +469,7 @@ def G_FLOG2 : Instruction {
// Generic load. Expects a MachineMemOperand in addition to explicit operands. // Generic load. Expects a MachineMemOperand in addition to explicit operands.
def G_LOAD : Instruction { def G_LOAD : Instruction {
let OutOperandList = (outs type0:$dst); let OutOperandList = (outs type0:$dst);
let InOperandList = (ins type1:$addr); let InOperandList = (ins ptype1:$addr);
let hasSideEffects = 0; let hasSideEffects = 0;
let mayLoad = 1; let mayLoad = 1;
} }
@ -477,7 +477,7 @@ def G_LOAD : Instruction {
// Generic store. Expects a MachineMemOperand in addition to explicit operands. // Generic store. Expects a MachineMemOperand in addition to explicit operands.
def G_STORE : Instruction { def G_STORE : Instruction {
let OutOperandList = (outs); let OutOperandList = (outs);
let InOperandList = (ins type0:$src, type1:$addr); let InOperandList = (ins type0:$src, ptype1:$addr);
let hasSideEffects = 0; let hasSideEffects = 0;
let mayStore = 1; let mayStore = 1;
} }

View File

@ -792,6 +792,7 @@ def f64imm : Operand<f64>;
// have the same LLT). // have the same LLT).
class TypedOperand<string Ty> : Operand<untyped> { class TypedOperand<string Ty> : Operand<untyped> {
let OperandType = Ty; let OperandType = Ty;
bit IsPointer = 0;
} }
def type0 : TypedOperand<"OPERAND_GENERIC_0">; def type0 : TypedOperand<"OPERAND_GENERIC_0">;
@ -801,6 +802,15 @@ def type3 : TypedOperand<"OPERAND_GENERIC_3">;
def type4 : TypedOperand<"OPERAND_GENERIC_4">; def type4 : TypedOperand<"OPERAND_GENERIC_4">;
def type5 : TypedOperand<"OPERAND_GENERIC_5">; def type5 : TypedOperand<"OPERAND_GENERIC_5">;
let IsPointer = 1 in {
def ptype0 : TypedOperand<"OPERAND_GENERIC_0">;
def ptype1 : TypedOperand<"OPERAND_GENERIC_1">;
def ptype2 : TypedOperand<"OPERAND_GENERIC_2">;
def ptype3 : TypedOperand<"OPERAND_GENERIC_3">;
def ptype4 : TypedOperand<"OPERAND_GENERIC_4">;
def ptype5 : TypedOperand<"OPERAND_GENERIC_5">;
}
/// zero_reg definition - Special node to stand for the zero register. /// zero_reg definition - Special node to stand for the zero register.
/// ///
def zero_reg; def zero_reg;

View File

@ -430,6 +430,17 @@ FlattenAsmStringVariants(StringRef Cur, unsigned Variant) {
return Res; return Res;
} }
bool CodeGenInstruction::isOperandAPointer(unsigned i) const {
if (DagInit *ConstraintList = TheDef->getValueAsDag("InOperandList")) {
if (i < ConstraintList->getNumArgs()) {
if (DefInit *Constraint = dyn_cast<DefInit>(ConstraintList->getArg(i))) {
return Constraint->getDef()->isSubClassOf("TypedOperand") &&
Constraint->getDef()->getValueAsBit("IsPointer");
}
}
}
return false;
}
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
/// CodeGenInstAlias Implementation /// CodeGenInstAlias Implementation

View File

@ -284,6 +284,12 @@ template <typename T> class ArrayRef;
/// include text from the specified variant, returning the new string. /// include text from the specified variant, returning the new string.
static std::string FlattenAsmStringVariants(StringRef AsmString, static std::string FlattenAsmStringVariants(StringRef AsmString,
unsigned Variant); unsigned Variant);
// Is the specified operand in a generic instruction implicitly a pointer.
// This can be used on intructions that use typeN or ptypeN to identify
// operands that should be considered as pointers even though SelectionDAG
// didn't make a distinction between integer and pointers.
bool isOperandAPointer(unsigned i) const;
}; };

View File

@ -2546,10 +2546,7 @@ Expected<InstructionMatcher &> GlobalISelEmitter::createAndImportSelDAGMatcher(
// SelectionDAG allows pointers to be represented with iN since it doesn't // SelectionDAG allows pointers to be represented with iN since it doesn't
// distinguish between pointers and integers but they are different types in GlobalISel. // distinguish between pointers and integers but they are different types in GlobalISel.
// Coerce integers to pointers to address space 0 if the context indicates a pointer. // Coerce integers to pointers to address space 0 if the context indicates a pointer.
// TODO: Find a better way to do this, SDTCisPtrTy? bool OperandIsAPointer = SrcGIOrNull->isOperandAPointer(i);
bool OperandIsAPointer =
(SrcGIOrNull->TheDef->getName() == "G_LOAD" && i == 0) ||
(SrcGIOrNull->TheDef->getName() == "G_STORE" && i == 1);
// For G_INTRINSIC/G_INTRINSIC_W_SIDE_EFFECTS, the operand immediately // For G_INTRINSIC/G_INTRINSIC_W_SIDE_EFFECTS, the operand immediately
// following the defs is an intrinsic ID. // following the defs is an intrinsic ID.