diff --git a/llvm/include/llvm/Target/Target.td b/llvm/include/llvm/Target/Target.td --- a/llvm/include/llvm/Target/Target.td +++ b/llvm/include/llvm/Target/Target.td @@ -871,6 +871,11 @@ dag DefaultOps = defaultops; } +/// OperandWithOverridableDefaultOps - Similar to +/// OperandWithDefaultOps, but permits patterns to specify their own value. +class OperandWithOverridableDefaultOps + : OperandWithDefaultOps; + /// PredicateOperand - This can be used to define a predicate operand for an /// instruction. OpTypes specifies the MIOperandInfo for the operand, and /// AlwaysVal specifies the value of this predicate when set to "always diff --git a/llvm/test/TableGen/DAGDefaultOps.td b/llvm/test/TableGen/DAGDefaultOps.td new file mode 100644 --- /dev/null +++ b/llvm/test/TableGen/DAGDefaultOps.td @@ -0,0 +1,97 @@ +// RUN: llvm-tblgen -gen-dag-isel -I %p/../../include %s -o %t +// RUN: FileCheck --check-prefix=ADD %s < %t +// RUN: FileCheck --check-prefix=ADDINT %s < %t +// RUN: FileCheck --check-prefix=SUB %s < %t +// RUN: FileCheck --check-prefix=MULINT %s < %t + +include "llvm/Target/Target.td" + +def TestInstrInfo : InstrInfo; +def TestTarget : Target { + let InstructionSet = TestInstrInfo; +} + +class TestEncoding : Instruction { + field bits<32> Inst; +} + +class TestReg : Register<"R"#index, []> { + let HWEncoding{15-4} = 0; + let HWEncoding{3-0} = !cast>(index); +} +foreach i = 0-15 in + def "R"#i : TestReg; + +def Reg : RegisterClass<"TestTarget", [i32], 32, (sequence "R%d", 0, 15)>; + +def IntOperand: Operand; +def OptionalIntOperand: OperandWithOverridableDefaultOps; + +class RRI Opcode> : TestEncoding { + dag OutOperandList = (outs Reg:$dest); + dag InOperandList = (ins Reg:$src1, Reg:$src2, OptionalIntOperand:$imm); + string AsmString = Mnemonic # " $dest1, $src1, $src2, #$imm"; + string AsmVariantName = ""; + field bits<4> dest; + field bits<4> src1; + field bits<4> src2; + field bits<16> imm; + let Inst{31-28} = Opcode; + let Inst{27-24} = dest; + let Inst{23-20} = src1; + let Inst{19-16} = src2; + let Inst{15-0} = imm; +} + +def AddRRI : RRI<"add", 0b0001>; + +// I define one of these intrinsics with IntrNoMem and the other +// without it, so that they'll match different top-level DAG opcodes +// (INTRINSIC_WO_CHAIN and INTRINSIC_W_CHAIN), which makes the +// FileCheck-herding easier, because every case I want to detect +// should show up as a separate top-level switch element. +def int_addplus1 : Intrinsic< + [llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mul3 : Intrinsic< + [llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty]>; + +def AddPat : Pat<(add i32:$x, i32:$y), + (AddRRI Reg:$x, Reg:$y)>; +def Add1Pat : Pat<(int_addplus1 i32:$x, i32:$y), + (AddRRI Reg:$x, Reg:$y, (i32 1))>; + +def SubRRI : RRI<"sub", 0b0010> { + let Pattern = [(set Reg:$dest, (sub Reg:$src1, Reg:$src2))]; +} + +def MulRRI : RRI<"mul", 0b0011> { + let Pattern = [(set Reg:$dest, (int_mul3 Reg:$src1, Reg:$src2, i32:$imm))]; +} + +// ADD: SwitchOpcode{{.*}}TARGET_VAL(ISD::ADD) +// ADD-NEXT: OPC_RecordChild0 +// ADD-NEXT: OPC_RecordChild1 +// ADD-NEXT: OPC_EmitInteger, MVT::i32, 0 +// ADD-NEXT: OPC_MorphNodeTo1, TARGET_VAL(::AddRRI) + +// ADDINT: SwitchOpcode{{.*}}TARGET_VAL(ISD::INTRINSIC_WO_CHAIN) +// ADDINT-NEXT: OPC_CheckChild0Integer +// ADDINT-NEXT: OPC_RecordChild1 +// ADDINT-NEXT: OPC_RecordChild2 +// ADDINT-NEXT: OPC_EmitInteger, MVT::i32, 1 +// ADDINT-NEXT: OPC_MorphNodeTo1, TARGET_VAL(::AddRRI) + +// SUB: SwitchOpcode{{.*}}TARGET_VAL(ISD::SUB) +// SUB-NEXT: OPC_RecordChild0 +// SUB-NEXT: OPC_RecordChild1 +// SUB-NEXT: OPC_EmitInteger, MVT::i32, 0 +// SUB-NEXT: OPC_MorphNodeTo1, TARGET_VAL(::SubRRI) + +// MULINT: SwitchOpcode{{.*}}TARGET_VAL(ISD::INTRINSIC_W_CHAIN) +// MULINT-NEXT: OPC_RecordNode +// MULINT-NEXT: OPC_CheckChild1Integer +// MULINT-NEXT: OPC_RecordChild2 +// MULINT-NEXT: OPC_RecordChild3 +// MULINT-NEXT: OPC_RecordChild4 +// MULINT-NEXT: OPC_EmitMergeInputChains +// MULINT-NEXT: OPC_MorphNodeTo1, TARGET_VAL(::MulRRI) diff --git a/llvm/utils/TableGen/CodeGenDAGPatterns.h b/llvm/utils/TableGen/CodeGenDAGPatterns.h --- a/llvm/utils/TableGen/CodeGenDAGPatterns.h +++ b/llvm/utils/TableGen/CodeGenDAGPatterns.h @@ -1282,6 +1282,15 @@ unsigned allocateScope() { return ++NumScopes; } + bool operandHasDefault(Record *Op) const { + return Op->isSubClassOf("OperandWithDefaultOps") && + !getDefaultOperand(Op).DefaultOps.empty(); + } + + bool operandDefaultIsMandatory(Record *Op) const { + return !Op->isSubClassOf("OperandWithOverridableDefaultOps"); + } + private: void ParseNodeInfo(); void ParseNodeTransforms(); diff --git a/llvm/utils/TableGen/CodeGenDAGPatterns.cpp b/llvm/utils/TableGen/CodeGenDAGPatterns.cpp --- a/llvm/utils/TableGen/CodeGenDAGPatterns.cpp +++ b/llvm/utils/TableGen/CodeGenDAGPatterns.cpp @@ -2441,14 +2441,18 @@ for (unsigned i = 0, e = Inst.getNumOperands(); i != e; ++i) { Record *OperandNode = Inst.getOperand(i); - // If the instruction expects a predicate or optional def operand, we - // codegen this by setting the operand to it's default value if it has a - // non-empty DefaultOps field. - if (OperandNode->isSubClassOf("OperandWithDefaultOps") && - !CDP.getDefaultOperand(OperandNode).DefaultOps.empty()) + // If the operand has a default value which is not marked as + // overridable by patterns, or if it has a default that _is_ + // overridable but we've run out of child nodes to override it + // with, then we will use the operand's default value, so we do + // not consume a child of the pattern DAG. + if (CDP.operandHasDefault(OperandNode) && + (ChildNo >= getNumChildren() || + CDP.operandDefaultIsMandatory(OperandNode))) continue; - // Verify that we didn't run out of provided operands. + // If we have run out of child nodes and there _isn't_ a default + // value we can use for the next operand, give an error. if (ChildNo >= getNumChildren()) { emitTooFewOperandsError(TP, getOperator()->getName(), getNumChildren()); return false; diff --git a/llvm/utils/TableGen/DAGISelMatcherGen.cpp b/llvm/utils/TableGen/DAGISelMatcherGen.cpp --- a/llvm/utils/TableGen/DAGISelMatcherGen.cpp +++ b/llvm/utils/TableGen/DAGISelMatcherGen.cpp @@ -798,10 +798,12 @@ InstOpNo != e; ++InstOpNo) { // Determine what to emit for this operand. Record *OperandNode = II.Operands[InstOpNo].Rec; - if (OperandNode->isSubClassOf("OperandWithDefaultOps") && - !CGP.getDefaultOperand(OperandNode).DefaultOps.empty()) { - // This is a predicate or optional def operand; emit the - // 'default ops' operands. + if (CGP.operandHasDefault(OperandNode) && + (ChildNo >= N->getNumChildren() || + CGP.operandDefaultIsMandatory(OperandNode))) { + // This is a predicate or optional def operand, which the + // pattern either has not overridden or is not allowed to + // override; emit the 'default ops' operands. const DAGDefaultOperand &DefaultOp = CGP.getDefaultOperand(OperandNode); for (unsigned i = 0, e = DefaultOp.DefaultOps.size(); i != e; ++i)