diff --git a/llvm/test/TableGen/simplify-patfrag.td b/llvm/test/TableGen/simplify-patfrag.td new file mode 100644 index 00000000000000..693658317d5d01 --- /dev/null +++ b/llvm/test/TableGen/simplify-patfrag.td @@ -0,0 +1,38 @@ +// RUN: llvm-tblgen -gen-dag-isel -I %p/../../include %s 2>&1 | FileCheck %s + +include "llvm/Target/Target.td" + +// Minimal Target definition +def DemoInstrInfo : InstrInfo; +def Demo : Target { + let InstructionSet = DemoInstrInfo; +} + +// Some registers which can hold ints or floats +foreach i = 0-7 in + def "R" # i: Register<"r" # i>; +def GPR : RegisterClass<"Demo", [i32, f32], 32, (sequence "R%u", 0, 7)>; + +// Instruction to convert an int to a float +def i2f : Instruction { + let Size = 2; + let OutOperandList = (outs GPR:$dst); + let InOperandList = (ins GPR:$src); + let AsmString = "i2f $dst, $src"; +} + +// Some kind of special type-conversion node supported by this target +def specialconvert : SDNode<"TEST_TARGET_ISD::SPECIAL_CONVERT", SDTUnaryOp>; + +// A PatFrags that matches either bitconvert or the special version +def anyconvert : PatFrags<(ops node:$src), + [(bitconvert node:$src), + (specialconvert node:$src)]>; + +// And a rule that matches that PatFrag and turns it into i2f +def : Pat<(f32 (anyconvert (i32 GPR:$val))), (i2f GPR:$val)>; + +// CHECK: SwitchOpcode{{.*}}ISD::BITCAST +// CHECK: MorphNodeTo1{{.*}}i2f +// CHECK: SwitchOpcode{{.*}}TEST_TARGET_ISD::SPECIAL_CONVERT +// CHECK: MorphNodeTo1{{.*}}i2f diff --git a/llvm/utils/TableGen/CodeGenDAGPatterns.cpp b/llvm/utils/TableGen/CodeGenDAGPatterns.cpp index 703cd515a071b3..0ea90d7dbb65d8 100644 --- a/llvm/utils/TableGen/CodeGenDAGPatterns.cpp +++ b/llvm/utils/TableGen/CodeGenDAGPatterns.cpp @@ -2918,8 +2918,15 @@ static bool SimplifyTree(TreePatternNodePtr &N) { // If we have a bitconvert with a resolved type and if the source and // destination types are the same, then the bitconvert is useless, remove it. + // + // We make an exception if the types are completely empty. This can come up + // when the pattern being simplified is in the Fragments list of a PatFrags, + // so that the operand is just an untyped "node". In that situation we leave + // bitconverts unsimplified, and simplify them later once the fragment is + // expanded into its true context. if (N->getOperator()->getName() == "bitconvert" && N->getExtType(0).isValueTypeByHwMode(false) && + !N->getExtType(0).empty() && N->getExtType(0) == N->getChild(0)->getExtType(0) && N->getName().empty()) { N = N->getChildShared(0);