From c54aa9c844e15e1fc35c6dbf73392bd54aec45ed Mon Sep 17 00:00:00 2001 From: Daniel Sanders Date: Sat, 18 Nov 2017 00:16:44 +0000 Subject: [PATCH] [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 --- llvm/include/llvm/Target/GenericOpcodes.td | 4 ++-- llvm/include/llvm/Target/Target.td | 10 ++++++++++ llvm/utils/TableGen/CodeGenInstruction.cpp | 11 +++++++++++ llvm/utils/TableGen/CodeGenInstruction.h | 6 ++++++ llvm/utils/TableGen/GlobalISelEmitter.cpp | 5 +---- 5 files changed, 30 insertions(+), 6 deletions(-) diff --git a/llvm/include/llvm/Target/GenericOpcodes.td b/llvm/include/llvm/Target/GenericOpcodes.td index 6e6b5820d4b6..557217c34562 100644 --- a/llvm/include/llvm/Target/GenericOpcodes.td +++ b/llvm/include/llvm/Target/GenericOpcodes.td @@ -469,7 +469,7 @@ def G_FLOG2 : Instruction { // Generic load. Expects a MachineMemOperand in addition to explicit operands. def G_LOAD : Instruction { let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type1:$addr); + let InOperandList = (ins ptype1:$addr); let hasSideEffects = 0; let mayLoad = 1; } @@ -477,7 +477,7 @@ def G_LOAD : Instruction { // Generic store. Expects a MachineMemOperand in addition to explicit operands. def G_STORE : Instruction { let OutOperandList = (outs); - let InOperandList = (ins type0:$src, type1:$addr); + let InOperandList = (ins type0:$src, ptype1:$addr); let hasSideEffects = 0; let mayStore = 1; } diff --git a/llvm/include/llvm/Target/Target.td b/llvm/include/llvm/Target/Target.td index 302ca34e07d8..86fa3c03fb50 100644 --- a/llvm/include/llvm/Target/Target.td +++ b/llvm/include/llvm/Target/Target.td @@ -792,6 +792,7 @@ def f64imm : Operand; // have the same LLT). class TypedOperand : Operand { let OperandType = Ty; + bit IsPointer = 0; } def type0 : TypedOperand<"OPERAND_GENERIC_0">; @@ -801,6 +802,15 @@ def type3 : TypedOperand<"OPERAND_GENERIC_3">; def type4 : TypedOperand<"OPERAND_GENERIC_4">; 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. /// def zero_reg; diff --git a/llvm/utils/TableGen/CodeGenInstruction.cpp b/llvm/utils/TableGen/CodeGenInstruction.cpp index 8fa3050e0780..44ee16f6fd74 100644 --- a/llvm/utils/TableGen/CodeGenInstruction.cpp +++ b/llvm/utils/TableGen/CodeGenInstruction.cpp @@ -430,6 +430,17 @@ FlattenAsmStringVariants(StringRef Cur, unsigned Variant) { return Res; } +bool CodeGenInstruction::isOperandAPointer(unsigned i) const { + if (DagInit *ConstraintList = TheDef->getValueAsDag("InOperandList")) { + if (i < ConstraintList->getNumArgs()) { + if (DefInit *Constraint = dyn_cast(ConstraintList->getArg(i))) { + return Constraint->getDef()->isSubClassOf("TypedOperand") && + Constraint->getDef()->getValueAsBit("IsPointer"); + } + } + } + return false; +} //===----------------------------------------------------------------------===// /// CodeGenInstAlias Implementation diff --git a/llvm/utils/TableGen/CodeGenInstruction.h b/llvm/utils/TableGen/CodeGenInstruction.h index e173e153879c..9cff95b1247f 100644 --- a/llvm/utils/TableGen/CodeGenInstruction.h +++ b/llvm/utils/TableGen/CodeGenInstruction.h @@ -284,6 +284,12 @@ template class ArrayRef; /// include text from the specified variant, returning the new string. static std::string FlattenAsmStringVariants(StringRef AsmString, 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; }; diff --git a/llvm/utils/TableGen/GlobalISelEmitter.cpp b/llvm/utils/TableGen/GlobalISelEmitter.cpp index 56a638483c01..505864bb0d5a 100644 --- a/llvm/utils/TableGen/GlobalISelEmitter.cpp +++ b/llvm/utils/TableGen/GlobalISelEmitter.cpp @@ -2546,10 +2546,7 @@ Expected GlobalISelEmitter::createAndImportSelDAGMatcher( // SelectionDAG allows pointers to be represented with iN since it doesn't // 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. - // TODO: Find a better way to do this, SDTCisPtrTy? - bool OperandIsAPointer = - (SrcGIOrNull->TheDef->getName() == "G_LOAD" && i == 0) || - (SrcGIOrNull->TheDef->getName() == "G_STORE" && i == 1); + bool OperandIsAPointer = SrcGIOrNull->isOperandAPointer(i); // For G_INTRINSIC/G_INTRINSIC_W_SIDE_EFFECTS, the operand immediately // following the defs is an intrinsic ID.