llvm.org GIT mirror llvm / db81564
TableGen support for parameterized register class information This replaces TableGen's type inference to operate on parameterized types instead of MVTs, and as a consequence, some interfaces have changed: - Uses of MVTs are replaced by ValueTypeByHwMode. - EEVT::TypeSet is replaced by TypeSetByHwMode. This affects the way that types and type sets are printed, and the tests relying on that have been updated. There are certain users of the inferred types outside of TableGen itself, namely FastISel and GlobalISel. For those users, the way that the types are accessed have changed. For typical scenarios, these replacements can be used: - TreePatternNode::getType(ResNo) -> getSimpleType(ResNo) - TreePatternNode::hasTypeSet(ResNo) -> hasConcreteType(ResNo) - TypeSet::isConcrete -> TypeSetByHwMode::isValueTypeByHwMode(false) For more information, please refer to the review page. Differential Revision: https://reviews.llvm.org/D31951 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@313271 91177308-0d34-0410-b5e6-96231b3b80d8 Krzysztof Parzyszek 2 years ago
23 changed file(s) with 2306 addition(s) and 1206 deletion(s). Raw diff Collapse all Expand all
1919 // description classes.
2020
2121 class RegisterClass; // Forward def
22
23 class HwMode {
24 // A string representing subtarget features that turn on this HW mode.
25 // For example, "+feat1,-feat2" will indicate that the mode is active
26 // when "feat1" is enabled and "feat2" is disabled at the same time.
27 // Any other features are not checked.
28 // When multiple modes are used, they should be mutually exclusive,
29 // otherwise the results are unpredictable.
30 string Features = FS;
31 }
32
33 // A special mode recognized by tablegen. This mode is considered active
34 // when no other mode is active. For targets that do not use specific hw
35 // modes, this is the only mode.
36 def DefaultMode : HwMode<"">;
37
38 // A class used to associate objects with HW modes. It is only intended to
39 // be used as a base class, where the derived class should contain a member
40 // "Objects", which is a list of the same length as the list of modes.
41 // The n-th element on the Objects list will be associated with the n-th
42 // element on the Modes list.
43 class HwModeSelect Ms> {
44 list Modes = Ms;
45 }
46
47 // A common class that implements a counterpart of ValueType, which is
48 // dependent on a HW mode. This class inherits from ValueType itself,
49 // which makes it possible to use objects of this class where ValueType
50 // objects could be used. This is specifically applicable to selection
51 // patterns.
52 class ValueTypeByHwMode Ms, list Ts>
53 : HwModeSelect, ValueType<0, 0> {
54 // The length of this list must be the same as the length of Ms.
55 list Objects = Ts;
56 }
57
58 // A class representing the register size, spill size and spill alignment
59 // in bits of a register.
60 class RegInfo {
61 int RegSize = RS; // Register size in bits.
62 int SpillSize = SS; // Spill slot size in bits.
63 int SpillAlignment = SA; // Spill slot alignment in bits.
64 }
65
66 // The register size/alignment information, parameterized by a HW mode.
67 class RegInfoByHwMode Ms = [], list Ts = []>
68 : HwModeSelect {
69 // The length of this list must be the same as the length of Ms.
70 list Objects = Ts;
71 }
2272
2373 // SubRegIndex - Use instances of SubRegIndex to identify subregisters.
2474 class SubRegIndex {
154204 dag regList, RegAltNameIndex idx = NoRegAltName>
155205 : DAGOperand {
156206 string Namespace = namespace;
207
208 // The register size/alignment information, parameterized by a HW mode.
209 RegInfoByHwMode RegInfos;
157210
158211 // RegType - Specify the list ValueType of the registers in this register
159212 // class. Note that all registers in a register class must have the same
4848
4949 // Instance variables filled by tablegen, do not use!
5050 const MCRegisterClass *MC;
51 const uint16_t SpillSize, SpillAlignment;
52 const MVT::SimpleValueType *VTs;
5351 const uint32_t *SubClassMask;
5452 const uint16_t *SuperRegIndices;
5553 const LaneBitmask LaneMask;
221219 public:
222220 using regclass_iterator = const TargetRegisterClass * const *;
223221 using vt_iterator = const MVT::SimpleValueType *;
224
222 struct RegClassInfo {
223 unsigned RegSize, SpillSize, SpillAlignment;
224 vt_iterator VTList;
225 };
225226 private:
226227 const TargetRegisterInfoDesc *InfoDesc; // Extra desc array for codegen
227228 const char *const *SubRegIndexNames; // Names of subreg indexes.
230231
231232 regclass_iterator RegClassBegin, RegClassEnd; // List of regclasses
232233 LaneBitmask CoveringLanes;
234 const RegClassInfo *const RCInfos;
235 unsigned HwMode;
233236
234237 protected:
235238 TargetRegisterInfo(const TargetRegisterInfoDesc *ID,
237240 regclass_iterator RegClassEnd,
238241 const char *const *SRINames,
239242 const LaneBitmask *SRILaneMasks,
240 LaneBitmask CoveringLanes);
243 LaneBitmask CoveringLanes,
244 const RegClassInfo *const RSI,
245 unsigned Mode = 0);
241246 virtual ~TargetRegisterInfo();
242247
243248 public:
305310
306311 /// Return the size in bits of a register from class RC.
307312 unsigned getRegSizeInBits(const TargetRegisterClass &RC) const {
308 return RC.SpillSize * 8;
313 return getRegClassInfo(RC).RegSize;
309314 }
310315
311316 /// Return the size in bytes of the stack slot allocated to hold a spilled
312317 /// copy of a register from class RC.
313318 unsigned getSpillSize(const TargetRegisterClass &RC) const {
314 return RC.SpillSize;
319 return getRegClassInfo(RC).SpillSize / 8;
315320 }
316321
317322 /// Return the minimum required alignment in bytes for a spill slot for
318323 /// a register of this class.
319324 unsigned getSpillAlignment(const TargetRegisterClass &RC) const {
320 return RC.SpillAlignment;
325 return getRegClassInfo(RC).SpillAlignment / 8;
321326 }
322327
323328 /// Return true if the given TargetRegisterClass has the ValueType T.
324329 bool isTypeLegalForClass(const TargetRegisterClass &RC, MVT T) const {
325 for (int i = 0; RC.VTs[i] != MVT::Other; ++i)
326 if (MVT(RC.VTs[i]) == T)
330 for (auto I = legalclasstypes_begin(RC); *I != MVT::Other; ++I)
331 if (MVT(*I) == T)
327332 return true;
328333 return false;
329334 }
331336 /// Loop over all of the value types that can be represented by values
332337 /// in the given register class.
333338 vt_iterator legalclasstypes_begin(const TargetRegisterClass &RC) const {
334 return RC.VTs;
339 return getRegClassInfo(RC).VTList;
335340 }
336341
337342 vt_iterator legalclasstypes_end(const TargetRegisterClass &RC) const {
338 vt_iterator I = RC.VTs;
343 vt_iterator I = legalclasstypes_begin(RC);
339344 while (*I != MVT::Other)
340345 ++I;
341346 return I;
653658 //===--------------------------------------------------------------------===//
654659 // Register Class Information
655660 //
656
661 protected:
662 const RegClassInfo &getRegClassInfo(const TargetRegisterClass &RC) const {
663 return RCInfos[getNumRegClasses() * HwMode + RC.getID()];
664 }
665
666 public:
657667 /// Register class iterators
658668 regclass_iterator regclass_begin() const { return RegClassBegin; }
659669 regclass_iterator regclass_end() const { return RegClassEnd; }
4040 regclass_iterator RCB, regclass_iterator RCE,
4141 const char *const *SRINames,
4242 const LaneBitmask *SRILaneMasks,
43 LaneBitmask SRICoveringLanes)
43 LaneBitmask SRICoveringLanes,
44 const RegClassInfo *const RCIs,
45 unsigned Mode)
4446 : InfoDesc(ID), SubRegIndexNames(SRINames),
4547 SubRegIndexLaneMasks(SRILaneMasks),
4648 RegClassBegin(RCB), RegClassEnd(RCE),
47 CoveringLanes(SRICoveringLanes) {
49 CoveringLanes(SRICoveringLanes),
50 RCInfos(RCIs), HwMode(Mode) {
4851 }
4952
5053 TargetRegisterInfo::~TargetRegisterInfo() = default;
146146 // CHECK-NEXT: // MIs[0] src3
147147 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/3, /*Type*/GILLT_s32,
148148 // CHECK-NEXT: GIM_CheckComplexPattern, /*MI*/0, /*Op*/3, /*Renderer*/1, GICP_gi_complex,
149 // CHECK-NEXT: // (select:i32 GPR32:i32:$src1, complex:i32:$src2, complex:i32:$src3) => (INSN2:i32 GPR32:i32:$src1, complex:i32:$src3, complex:i32:$src2)
149 // CHECK-NEXT: // (select:{ *:[i32] } GPR32:{ *:[i32] }:$src1, complex:{ *:[i32] }:$src2, complex:{ *:[i32] }:$src3) => (INSN2:{ *:[i32] } GPR32:{ *:[i32] }:$src1, complex:{ *:[i32] }:$src3, complex:{ *:[i32] }:$src2)
150150 // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::INSN2,
151151 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
152152 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/1, // src1
195195 // CHECK-NEXT: GIM_CheckType, /*MI*/1, /*Op*/3, /*Type*/GILLT_s32,
196196 // CHECK-NEXT: GIM_CheckComplexPattern, /*MI*/1, /*Op*/3, /*Renderer*/2, GICP_gi_complex,
197197 // CHECK-NEXT: GIM_CheckIsSafeToFold, /*InsnID*/1,
198 // CHECK-NEXT: // (select:i32 GPR32:i32:$src1, complex:i32:$src2, (select:i32 GPR32:i32:$src3, complex:i32:$src4, complex:i32:$src5)) => (INSN3:i32 GPR32:i32:$src1, complex:i32:$src2, GPR32:i32:$src3, complex:i32:$src4, complex:i32:$src5)
198 // CHECK-NEXT: // (select:{ *:[i32] } GPR32:{ *:[i32] }:$src1, complex:{ *:[i32] }:$src2, (select:{ *:[i32] } GPR32:{ *:[i32] }:$src3, complex:{ *:[i32] }:$src4, complex:{ *:[i32] }:$src5)) => (INSN3:{ *:[i32] } GPR32:{ *:[i32] }:$src1, complex:{ *:[i32] }:$src2, GPR32:{ *:[i32] }:$src3, complex:{ *:[i32] }:$src4, complex:{ *:[i32] }:$src5)
199199 // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::INSN3,
200200 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
201201 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/1, // src1
229229 // CHECK-NEXT: // MIs[0] src2
230230 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/2, /*Type*/GILLT_s32,
231231 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/2, /*RC*/MyTarget::GPR32RegClassID,
232 // CHECK-NEXT: // (add:i32 GPR32:i32:$src1, GPR32:i32:$src2) => (ADD:i32 GPR32:i32:$src1, GPR32:i32:$src2)
232 // CHECK-NEXT: // (add:{ *:[i32] } GPR32:{ *:[i32] }:$src1, GPR32:{ *:[i32] }:$src2) => (ADD:{ *:[i32] } GPR32:{ *:[i32] }:$src1, GPR32:{ *:[i32] }:$src2)
233233 // CHECK-NEXT: GIR_MutateOpcode, /*InsnID*/0, /*RecycleInsnID*/0, /*Opcode*/MyTarget::ADD,
234234 // CHECK-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
235235 // CHECK-NEXT: GIR_Done,
252252 // CHECK-NEXT: // MIs[0] src1
253253 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/2, /*Type*/GILLT_s32,
254254 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/2, /*RC*/MyTarget::GPR32RegClassID,
255 // CHECK-NEXT: // (intrinsic_wo_chain:i32 [[ID:[0-9]+]]:iPTR, GPR32:i32:$src1) => (MOV:i32 GPR32:i32:$src1)
255 // CHECK-NEXT: // (intrinsic_wo_chain:{ *:[i32] } [[ID:[0-9]+]]:{ *:[iPTR] }, GPR32:{ *:[i32] }:$src1) => (MOV:{ *:[i32] } GPR32:{ *:[i32] }:$src1)
256256
257257 // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::MOV,
258258 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
291291 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/2, /*Type*/GILLT_s32,
292292 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/2, /*RC*/MyTarget::GPR32RegClassID,
293293 // CHECK-NEXT: GIM_CheckIsSafeToFold, /*InsnID*/1,
294 // CHECK-NEXT: // (mul:i32 (add:i32 GPR32:i32:$src1, GPR32:i32:$src2), GPR32:i32:$src3) => (MULADD:i32 GPR32:i32:$src1, GPR32:i32:$src2, GPR32:i32:$src3)
294 // CHECK-NEXT: // (mul:{ *:[i32] } (add:{ *:[i32] } GPR32:{ *:[i32] }:$src1, GPR32:{ *:[i32] }:$src2), GPR32:{ *:[i32] }:$src3) => (MULADD:{ *:[i32] } GPR32:{ *:[i32] }:$src1, GPR32:{ *:[i32] }:$src2, GPR32:{ *:[i32] }:$src3)
295295 // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::MULADD,
296296 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
297297 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/1, /*OpIdx*/1, // src1
327327 // CHECK-NEXT: GIM_CheckType, /*MI*/1, /*Op*/2, /*Type*/GILLT_s32,
328328 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/1, /*Op*/2, /*RC*/MyTarget::GPR32RegClassID,
329329 // CHECK-NEXT: GIM_CheckIsSafeToFold, /*InsnID*/1,
330 // CHECK-NEXT: // (mul:i32 GPR32:i32:$src3, (add:i32 GPR32:i32:$src1, GPR32:i32:$src2)) => (MULADD:i32 GPR32:i32:$src1, GPR32:i32:$src2, GPR32:i32:$src3)
330 // CHECK-NEXT: // (mul:{ *:[i32] } GPR32:{ *:[i32] }:$src3, (add:{ *:[i32] } GPR32:{ *:[i32] }:$src1, GPR32:{ *:[i32] }:$src2)) => (MULADD:{ *:[i32] } GPR32:{ *:[i32] }:$src1, GPR32:{ *:[i32] }:$src2, GPR32:{ *:[i32] }:$src3)
331331 // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::MULADD,
332332 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
333333 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/1, /*OpIdx*/1, // src1
358358 // CHECK-NEXT: // MIs[0] src2
359359 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/2, /*Type*/GILLT_s32,
360360 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/2, /*RC*/MyTarget::GPR32RegClassID,
361 // CHECK-NEXT: // (mul:i32 GPR32:i32:$src1, GPR32:i32:$src2) => (MUL:i32 GPR32:i32:$src2, GPR32:i32:$src1)
361 // CHECK-NEXT: // (mul:{ *:[i32] } GPR32:{ *:[i32] }:$src1, GPR32:{ *:[i32] }:$src2) => (MUL:{ *:[i32] } GPR32:{ *:[i32] }:$src2, GPR32:{ *:[i32] }:$src1)
362362 // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::MUL,
363363 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
364364 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/2, // src2
409409 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/2, /*Op*/2, /*RC*/MyTarget::GPR32RegClassID,
410410 // CHECK-NEXT: GIM_CheckIsSafeToFold, /*InsnID*/1,
411411 // CHECK-NEXT: GIM_CheckIsSafeToFold, /*InsnID*/2,
412 // CHECK-NEXT: // (sub:i32 (sub:i32 GPR32:i32:$src1, GPR32:i32:$src2), (sub:i32 GPR32:i32:$src3, GPR32:i32:$src4)) => (INSNBOB:i32 GPR32:i32:$src1, GPR32:i32:$src2, GPR32:i32:$src3, GPR32:i32:$src4)
412 // CHECK-NEXT: // (sub:{ *:[i32] } (sub:{ *:[i32] } GPR32:{ *:[i32] }:$src1, GPR32:{ *:[i32] }:$src2), (sub:{ *:[i32] } GPR32:{ *:[i32] }:$src3, GPR32:{ *:[i32] }:$src4)) => (INSNBOB:{ *:[i32] } GPR32:{ *:[i32] }:$src1, GPR32:{ *:[i32] }:$src2, GPR32:{ *:[i32] }:$src3, GPR32:{ *:[i32] }:$src4)
413413 // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::INSNBOB,
414414 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
415415 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/1, /*OpIdx*/1, // src1
441441 // CHECK-NEXT: // MIs[0] src2
442442 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/2, /*Type*/GILLT_s32,
443443 // CHECK-NEXT: GIM_CheckComplexPattern, /*MI*/0, /*Op*/2, /*Renderer*/0, GICP_gi_complex,
444 // CHECK-NEXT: // (sub:i32 GPR32:i32:$src1, complex:i32:$src2) => (INSN1:i32 GPR32:i32:$src1, complex:i32:$src2)
444 // CHECK-NEXT: // (sub:{ *:[i32] } GPR32:{ *:[i32] }:$src1, complex:{ *:[i32] }:$src2) => (INSN1:{ *:[i32] } GPR32:{ *:[i32] }:$src1, complex:{ *:[i32] }:$src2)
445445 // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::INSN1,
446446 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
447447 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/1, // src1
469469 // CHECK-NEXT: // MIs[0] Operand 2
470470 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/2, /*Type*/GILLT_s32,
471471 // CHECK-NEXT: GIM_CheckConstantInt, /*MI*/0, /*Op*/2, -2
472 // CHECK-NEXT: // (xor:i32 GPR32:i32:$src1, -2:i32) => (XORI:i32 GPR32:i32:$src1)
472 // CHECK-NEXT: // (xor:{ *:[i32] } GPR32:{ *:[i32] }:$src1, -2:{ *:[i32] }) => (XORI:{ *:[i32] } GPR32:{ *:[i32] }:$src1)
473473 // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::XORI,
474474 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
475475 // CHECK-NEXT: GIR_AddImm, /*InsnID*/0, /*Imm*/-1,
498498 // CHECK-NEXT: // MIs[0] Operand 2
499499 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/2, /*Type*/GILLT_s32,
500500 // CHECK-NEXT: GIM_CheckConstantInt, /*MI*/0, /*Op*/2, -3
501 // CHECK-NEXT: // (xor:i32 GPR32:i32:$src1, -3:i32) => (XOR:i32 GPR32:i32:$src1)
501 // CHECK-NEXT: // (xor:{ *:[i32] } GPR32:{ *:[i32] }:$src1, -3:{ *:[i32] }) => (XOR:{ *:[i32] } GPR32:{ *:[i32] }:$src1)
502502 // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::XOR,
503503 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
504504 // CHECK-NEXT: GIR_AddRegister, /*InsnID*/0, MyTarget::R0,
527527 // CHECK-NEXT: // MIs[0] Operand 2
528528 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/2, /*Type*/GILLT_s32,
529529 // CHECK-NEXT: GIM_CheckConstantInt, /*MI*/0, /*Op*/2, -4
530 // CHECK-NEXT: // (xor:i32 GPR32:i32:$src1, -4:i32) => (XORlike:i32 GPR32:i32:$src1)
530 // CHECK-NEXT: // (xor:{ *:[i32] } GPR32:{ *:[i32] }:$src1, -4:{ *:[i32] }) => (XORlike:{ *:[i32] } GPR32:{ *:[i32] }:$src1)
531531 // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::XORlike,
532532 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
533533 // CHECK-NEXT: GIR_AddImm, /*InsnID*/0, /*Imm*/-1,
557557 // CHECK-NEXT: // MIs[0] Operand 2
558558 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/2, /*Type*/GILLT_s32,
559559 // CHECK-NEXT: GIM_CheckConstantInt, /*MI*/0, /*Op*/2, -5,
560 // CHECK-NEXT: // (xor:i32 GPR32:i32:$src1, -5:i32) => (XORManyDefaults:i32 GPR32:i32:$src1)
560 // CHECK-NEXT: // (xor:{ *:[i32] } GPR32:{ *:[i32] }:$src1, -5:{ *:[i32] }) => (XORManyDefaults:{ *:[i32] } GPR32:{ *:[i32] }:$src1)
561561 // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::XORManyDefaults,
562562 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
563563 // CHECK-NEXT: GIR_AddImm, /*InsnID*/0, /*Imm*/-1,
590590 // CHECK-NEXT: // MIs[0] Operand 2
591591 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/2, /*Type*/GILLT_s32,
592592 // CHECK-NEXT: GIM_CheckConstantInt, /*MI*/0, /*Op*/2, -1,
593 // CHECK-NEXT: // (xor:i32 GPR32:i32:$Wm, -1:i32) => (ORN:i32 R0:i32, GPR32:i32:$Wm)
593 // CHECK-NEXT: // (xor:{ *:[i32] } GPR32:{ *:[i32] }:$Wm, -1:{ *:[i32] }) => (ORN:{ *:[i32] } R0:{ *:[i32] }, GPR32:{ *:[i32] }:$Wm)
594594 // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::ORN,
595595 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
596596 // CHECK-NEXT: GIR_AddRegister, /*InsnID*/0, MyTarget::R0,
615615 // CHECK-NEXT: // MIs[0] src1
616616 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/1, /*Type*/GILLT_s32,
617617 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/1, /*RC*/MyTarget::FPR32RegClassID,
618 // CHECK-NEXT: // (bitconvert:i32 FPR32:f32:$src1) => (COPY_TO_REGCLASS:i32 FPR32:f32:$src1, GPR32:i32)
618 // CHECK-NEXT: // (bitconvert:{ *:[i32] } FPR32:{ *:[f32] }:$src1) => (COPY_TO_REGCLASS:{ *:[i32] } FPR32:{ *:[f32] }:$src1, GPR32:{ *:[i32] })
619619 // CHECK-NEXT: GIR_MutateOpcode, /*InsnID*/0, /*RecycleInsnID*/0, /*Opcode*/TargetOpcode::COPY,
620620 // CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/0, /*Op*/0, /*RC GPR32*/1,
621621 // CHECK-NEXT: GIR_Done,
634634 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR32RegClassID,
635635 // CHECK-NEXT: // MIs[0] Operand 1
636636 // CHECK-NEXT: GIM_CheckLiteralInt, /*MI*/0, /*Op*/1, 1,
637 // CHECK-NEXT: // 1:i32 => (MOV1:i32)
637 // CHECK-NEXT: // 1:{ *:[i32] } => (MOV1:{ *:[i32] })
638638 // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::MOV1,
639639 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
640640 // CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0,
655655 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR32RegClassID,
656656 // CHECK-NEXT: // MIs[0] Operand 1
657657 // CHECK-NEXT: // No operand predicates
658 // CHECK-NEXT: // (imm:i32)<>:$imm => (MOVimm8:i32 (imm:i32):$imm)
658 // CHECK-NEXT: // (imm:{ *:[i32] })<>:$imm => (MOVimm8:{ *:[i32] } (imm:{ *:[i32] }):$imm)
659659 // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::MOVimm8,
660660 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
661661 // CHECK-NEXT: GIR_CopyConstantAsSImm, /*NewInsnID*/0, /*OldInsnID*/0, // imm
677677 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR32RegClassID,
678678 // CHECK-NEXT: // MIs[0] Operand 1
679679 // CHECK-NEXT: // No operand predicates
680 // CHECK-NEXT: // (imm:i32):$imm => (MOVimm:i32 (imm:i32):$imm)
680 // CHECK-NEXT: // (imm:{ *:[i32] }):$imm => (MOVimm:{ *:[i32] } (imm:{ *:[i32] }):$imm)
681681 // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::MOVimm,
682682 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
683683 // CHECK-NEXT: GIR_CopyConstantAsSImm, /*NewInsnID*/0, /*OldInsnID*/0, // imm
695695 // CHECK-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_BR,
696696 // CHECK-NEXT: // MIs[0] target
697697 // CHECK-NEXT: GIM_CheckIsMBB, /*MI*/0, /*Op*/0,
698 // CHECK-NEXT: // (br (bb:Other):$target) => (BR (bb:Other):$target)
698 // CHECK-NEXT: // (br (bb:{ *:[Other] }):$target) => (BR (bb:{ *:[Other] }):$target)
699699 // CHECK-NEXT: GIR_MutateOpcode, /*InsnID*/0, /*RecycleInsnID*/0, /*Opcode*/MyTarget::BR,
700700 // CHECK-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
701701 // CHECK-NEXT: GIR_Done,
0 // RUN: not llvm-tblgen -gen-dag-isel -I %p/../../include %s 2>&1 | FileCheck %s
1
2 // The HwModeSelect class is intended to serve as a base class for other
3 // classes that are then used to select a value based on the HW mode.
4 // It contains a list of HW modes, and a derived class should provide a
5 // list of corresponding values.
6 // These two lists must have the same size. Make sure that a violation of
7 // this requirement is diagnosed.
8
9 include "llvm/Target/Target.td"
10
11 def TestTargetInstrInfo : InstrInfo;
12
13 def TestTarget : Target {
14 let InstructionSet = TestTargetInstrInfo;
15 }
16
17 def TestReg : Register<"testreg">;
18 def TestClass : RegisterClass<"TestTarget", [i32], 32, (add TestReg)>;
19
20 def TestMode1 : HwMode<"+feat1">;
21 def TestMode2 : HwMode<"+feat2">;
22
23 def BadDef : ValueTypeByHwMode<[TestMode1, TestMode2, DefaultMode],
24 [i8, i16, i32, i64]>;
25
26 // CHECK: error: in record BadDef derived from HwModeSelect: the lists Modes and Objects should have the same size
77 CallingConvEmitter.cpp
88 CodeEmitterGen.cpp
99 CodeGenDAGPatterns.cpp
10 CodeGenHwModes.cpp
1011 CodeGenInstruction.cpp
1112 CodeGenMapTable.cpp
1213 CodeGenRegisters.cpp
2223 FastISelEmitter.cpp
2324 FixedLenDecoderEmitter.cpp
2425 GlobalISelEmitter.cpp
26 InfoByHwMode.cpp
2527 InstrInfoEmitter.cpp
2628 IntrinsicEmitter.cpp
2729 OptParserEmitter.cpp
1313
1414 #include "CodeGenDAGPatterns.h"
1515 #include "llvm/ADT/STLExtras.h"
16 #include "llvm/ADT/SmallSet.h"
1617 #include "llvm/ADT/SmallString.h"
1718 #include "llvm/ADT/StringExtras.h"
1819 #include "llvm/ADT/Twine.h"
2324 #include
2425 #include
2526 #include
27 #include
2628 using namespace llvm;
2729
2830 #define DEBUG_TYPE "dag-patterns"
2931
30 //===----------------------------------------------------------------------===//
31 // EEVT::TypeSet Implementation
32 //===----------------------------------------------------------------------===//
33
34 static inline bool isInteger(MVT::SimpleValueType VT) {
35 return MVT(VT).isInteger();
36 }
37 static inline bool isFloatingPoint(MVT::SimpleValueType VT) {
38 return MVT(VT).isFloatingPoint();
39 }
40 static inline bool isVector(MVT::SimpleValueType VT) {
41 return MVT(VT).isVector();
42 }
43 static inline bool isScalar(MVT::SimpleValueType VT) {
44 return !MVT(VT).isVector();
45 }
46
47 EEVT::TypeSet::TypeSet(MVT::SimpleValueType VT, TreePattern &TP) {
48 if (VT == MVT::iAny)
49 EnforceInteger(TP);
50 else if (VT == MVT::fAny)
51 EnforceFloatingPoint(TP);
52 else if (VT == MVT::vAny)
53 EnforceVector(TP);
54 else {
55 assert((VT < MVT::LAST_VALUETYPE || VT == MVT::iPTR ||
56 VT == MVT::iPTRAny || VT == MVT::Any) && "Not a concrete type!");
57 TypeVec.push_back(VT);
58 }
59 }
60
61
62 EEVT::TypeSet::TypeSet(ArrayRef VTList) {
63 assert(!VTList.empty() && "empty list?");
64 TypeVec.append(VTList.begin(), VTList.end());
65
66 if (!VTList.empty())
67 assert(VTList[0] != MVT::iAny && VTList[0] != MVT::vAny &&
68 VTList[0] != MVT::fAny);
69
70 // Verify no duplicates.
71 array_pod_sort(TypeVec.begin(), TypeVec.end());
72 assert(std::unique(TypeVec.begin(), TypeVec.end()) == TypeVec.end());
73 }
74
75 /// FillWithPossibleTypes - Set to all legal types and return true, only valid
76 /// on completely unknown type sets.
77 bool EEVT::TypeSet::FillWithPossibleTypes(TreePattern &TP,
78 bool (*Pred)(MVT::SimpleValueType),
79 const char *PredicateName) {
80 assert(isCompletelyUnknown());
81 ArrayRef LegalTypes =
82 TP.getDAGPatterns().getTargetInfo().getLegalValueTypes();
83
32 static inline bool isIntegerOrPtr(MVT VT) {
33 return VT.isInteger() || VT == MVT::iPTR;
34 }
35 static inline bool isFloatingPoint(MVT VT) {
36 return VT.isFloatingPoint();
37 }
38 static inline bool isVector(MVT VT) {
39 return VT.isVector();
40 }
41 static inline bool isScalar(MVT VT) {
42 return !VT.isVector();
43 }
44
45 template
46 static bool berase_if(std::set &S, Predicate P) {
47 bool Erased = false;
48 for (auto I = S.begin(); I != S.end(); ) {
49 if (P(*I)) {
50 Erased = true;
51 I = S.erase(I);
52 } else
53 ++I;
54 }
55 return Erased;
56 }
57
58 // --- TypeSetByHwMode
59
60 // This is a parameterized type-set class. For each mode there is a list
61 // of types that are currently possible for a given tree node. Type
62 // inference will apply to each mode separately.
63
64 TypeSetByHwMode::TypeSetByHwMode(ArrayRef VTList) {
65 for (const ValueTypeByHwMode &VVT : VTList)
66 insert(VVT);
67 }
68
69 bool TypeSetByHwMode::isValueTypeByHwMode(bool AllowEmpty) const {
70 for (const auto &I : *this) {
71 if (I.second.size() > 1)
72 return false;
73 if (!AllowEmpty && I.second.empty())
74 return false;
75 }
76 return true;
77 }
78
79 ValueTypeByHwMode TypeSetByHwMode::getValueTypeByHwMode() const {
80 assert(isValueTypeByHwMode(true) &&
81 "The type set has multiple types for at least one HW mode");
82 ValueTypeByHwMode VVT;
83 for (const auto &I : *this) {
84 MVT T = I.second.empty() ? MVT::Other : *I.second.begin();
85 VVT.getOrCreateTypeForMode(I.first, T);
86 }
87 return VVT;
88 }
89
90 bool TypeSetByHwMode::isPossible() const {
91 for (const auto &I : *this)
92 if (!I.second.empty())
93 return true;
94 return false;
95 }
96
97 bool TypeSetByHwMode::insert(const ValueTypeByHwMode &VVT) {
98 bool Changed = false;
99 std::set Modes;
100 for (const auto &P : VVT) {
101 unsigned M = P.first;
102 Modes.insert(M);
103 // Make sure there exists a set for each specific mode from VVT.
104 Changed |= getOrCreate(M).insert(P.second).second;
105 }
106
107 // If VVT has a default mode, add the corresponding type to all
108 // modes in "this" that do not exist in VVT.
109 if (Modes.count(DefaultMode)) {
110 MVT DT = VVT.getType(DefaultMode);
111 for (auto &I : *this)
112 if (!Modes.count(I.first))
113 Changed |= I.second.insert(DT).second;
114 }
115
116 return Changed;
117 }
118
119 // Constrain the type set to be the intersection with VTS.
120 bool TypeSetByHwMode::constrain(const TypeSetByHwMode &VTS) {
121 bool Changed = false;
122 if (hasDefault()) {
123 for (const auto &I : VTS) {
124 unsigned M = I.first;
125 if (M == DefaultMode || hasMode(M))
126 continue;
127 Map[M] = Map[DefaultMode];
128 Changed = true;
129 }
130 }
131
132 for (auto &I : *this) {
133 unsigned M = I.first;
134 SetType &S = I.second;
135 if (VTS.hasMode(M) || VTS.hasDefault()) {
136 Changed |= intersect(I.second, VTS.get(M));
137 } else if (!S.empty()) {
138 S.clear();
139 Changed = true;
140 }
141 }
142 return Changed;
143 }
144
145 template
146 bool TypeSetByHwMode::constrain(Predicate P) {
147 bool Changed = false;
148 for (auto &I : *this)
149 Changed |= berase_if(I.second, std::not1(std::ref(P)));
150 return Changed;
151 }
152
153 template
154 bool TypeSetByHwMode::assign_if(const TypeSetByHwMode &VTS, Predicate P) {
155 assert(empty());
156 for (const auto &I : VTS) {
157 SetType &S = getOrCreate(I.first);
158 for (auto J : I.second)
159 if (P(J))
160 S.insert(J);
161 }
162 return !empty();
163 }
164
165 std::string TypeSetByHwMode::getAsString() const {
166 std::stringstream str;
167 std::vector Modes;
168
169 for (const auto &I : *this)
170 Modes.push_back(I.first);
171 if (Modes.empty())
172 return "{}";
173 array_pod_sort(Modes.begin(), Modes.end());
174
175 str << '{';
176 for (unsigned M : Modes) {
177 const SetType &S = get(M);
178 str << ' ' << getModeName(M) << ':' << getAsString(S);
179 }
180 str << " }";
181 return str.str();
182 }
183
184 std::string TypeSetByHwMode::getAsString(const SetType &S) {
185 std::vector Types(S.begin(), S.end());
186 array_pod_sort(Types.begin(), Types.end());
187
188 std::stringstream str;
189 str << '[';
190 for (unsigned i = 0, e = Types.size(); i != e; ++i) {
191 str << ValueTypeByHwMode::getMVTName(Types[i]);
192 if (i != e-1)
193 str << ' ';
194 }
195 str << ']';
196 return str.str();
197 }
198
199 bool TypeSetByHwMode::operator==(const TypeSetByHwMode &VTS) const {
200 bool HaveDefault = hasDefault();
201 if (HaveDefault != VTS.hasDefault())
202 return false;
203
204 std::set Modes;
205 for (auto &I : *this)
206 Modes.insert(I.first);
207 for (const auto &I : VTS)
208 Modes.insert(I.first);
209
210 if (HaveDefault) {
211 // Both sets have default mode.
212 for (unsigned M : Modes) {
213 if (get(M) != VTS.get(M))
214 return false;
215 }
216 } else {
217 // Neither set has default mode.
218 for (unsigned M : Modes) {
219 // If there is no default mode, an empty set is equivalent to not having
220 // the corresponding mode.
221 bool NoModeThis = !hasMode(M) || get(M).empty();
222 bool NoModeVTS = !VTS.hasMode(M) || VTS.get(M).empty();
223 if (NoModeThis != NoModeVTS)
224 return false;
225 if (!NoModeThis)
226 if (get(M) != VTS.get(M))
227 return false;
228 }
229 }
230
231 return true;
232 }
233
234 LLVM_DUMP_METHOD
235 void TypeSetByHwMode::dump() const {
236 dbgs() << getAsString() << '\n';
237 }
238
239 bool TypeSetByHwMode::intersect(SetType &Out, const SetType &In) {
240 bool OutP = Out.count(MVT::iPTR), InP = In.count(MVT::iPTR);
241 auto Int = [&In](MVT T) -> bool { return !In.count(T); };
242
243 if (OutP == InP)
244 return berase_if(Out, Int);
245
246 // Compute the intersection of scalars separately to account for only
247 // one set containing iPTR.
248 // The itersection of iPTR with a set of integer scalar types that does not
249 // include iPTR will result in the most specific scalar type:
250 // - iPTR is more specific than any set with two elements or more
251 // - iPTR is less specific than any single integer scalar type.
252 // For example
253 // { iPTR } * { i32 } -> { i32 }
254 // { iPTR } * { i32 i64 } -> { iPTR }
255
256 SetType Diff;
257 if (InP) {
258 std::copy_if(Out.begin(), Out.end(), std::inserter(Diff, Diff.end()),
259 [&In](MVT T) { return !In.count(T); });
260 berase_if(Out, [&Diff](MVT T) { return Diff.count(T); });
261 } else {
262 std::copy_if(In.begin(), In.end(), std::inserter(Diff, Diff.end()),
263 [&Out](MVT T) { return !Out.count(T); });
264 Out.erase(MVT::iPTR);
265 }
266
267 bool Changed = berase_if(Out, Int);
268 unsigned NumD = Diff.size();
269 if (NumD == 0)
270 return Changed;
271
272 if (NumD == 1) {
273 Out.insert(*Diff.begin());
274 // This is a change only if Out was the one with iPTR (which is now
275 // being replaced).
276 Changed |= OutP;
277 } else {
278 Out.insert(MVT::iPTR);
279 Changed |= InP;
280 }
281 return Changed;
282 }
283
284 void TypeSetByHwMode::validate() const {
285 #ifndef NDEBUG
286 if (empty())
287 return;
288 bool AllEmpty = true;
289 for (const auto &I : *this)
290 AllEmpty &= I.second.empty();
291 assert(!AllEmpty &&
292 "type set is empty for each HW mode: type contradiction?");
293 #endif
294 }
295
296 // --- TypeInfer
297
298 bool TypeInfer::MergeInTypeInfo(TypeSetByHwMode &Out,
299 const TypeSetByHwMode &In) {
300 ValidateOnExit _1(Out);
301 In.validate();
302 if (In.empty() || Out == In || TP.hasError())
303 return false;
304 if (Out.empty()) {
305 Out = In;
306 return true;
307 }
308
309 bool Changed = Out.constrain(In);
310 if (Changed && Out.empty())
311 TP.error("Type contradiction");
312
313 return Changed;
314 }
315
316 bool TypeInfer::forceArbitrary(TypeSetByHwMode &Out) {
317 ValidateOnExit _1(Out);
84318 if (TP.hasError())
85319 return false;
86
87 for (MVT::SimpleValueType VT : LegalTypes)
88 if (!Pred || Pred(VT))
89 TypeVec.push_back(VT);
90
91 // If we have nothing that matches the predicate, bail out.
92 if (TypeVec.empty()) {
93 TP.error("Type inference contradiction found, no " +
94 std::string(PredicateName) + " types found");
95 return false;
96 }
97 // No need to sort with one element.
98 if (TypeVec.size() == 1) return true;
99
100 // Remove duplicates.
101 array_pod_sort(TypeVec.begin(), TypeVec.end());
102 TypeVec.erase(std::unique(TypeVec.begin(), TypeVec.end()), TypeVec.end());
103
104 return true;
105 }
106
107 /// hasIntegerTypes - Return true if this TypeSet contains iAny or an
108 /// integer value type.
109 bool EEVT::TypeSet::hasIntegerTypes() const {
110 return any_of(TypeVec, isInteger);
111 }
112
113 /// hasFloatingPointTypes - Return true if this TypeSet contains an fAny or
114 /// a floating point value type.
115 bool EEVT::TypeSet::hasFloatingPointTypes() const {
116 return any_of(TypeVec, isFloatingPoint);
117 }
118
119 /// hasScalarTypes - Return true if this TypeSet contains a scalar value type.
120 bool EEVT::TypeSet::hasScalarTypes() const {
121 return any_of(TypeVec, isScalar);
122 }
123
124 /// hasVectorTypes - Return true if this TypeSet contains a vAny or a vector
125 /// value type.
126 bool EEVT::TypeSet::hasVectorTypes() const {
127 return any_of(TypeVec, isVector);
128 }
129
130
131 std::string EEVT::TypeSet::getName() const {
132 if (TypeVec.empty()) return "";
133
134 std::string Result;
135
136 for (unsigned i = 0, e = TypeVec.size(); i != e; ++i) {
137 std::string VTName = llvm::getEnumName(TypeVec[i]);
138 // Strip off MVT:: prefix if present.
139 if (VTName.substr(0,5) == "MVT::")
140 VTName = VTName.substr(5);
141 if (i) Result += ':';
142 Result += VTName;
143 }
144
145 if (TypeVec.size() == 1)
146 return Result;
147 return "{" + Result + "}";
148 }
149
150 /// MergeInTypeInfo - This merges in type information from the specified
151 /// argument. If 'this' changes, it returns true. If the two types are
152 /// contradictory (e.g. merge f32 into i32) then this flags an error.
153 bool EEVT::TypeSet::MergeInTypeInfo(const EEVT::TypeSet &InVT, TreePattern &TP){
154 if (InVT.isCompletelyUnknown() || *this == InVT || TP.hasError())
155 return false;
156
157 if (isCompletelyUnknown()) {
158 *this = InVT;
159 return true;
160 }
161
162 assert(!TypeVec.empty() && !InVT.TypeVec.empty() && "No unknowns");
163
164 // Handle the abstract cases, seeing if we can resolve them better.
165 switch (TypeVec[0]) {
166 default: break;
167 case MVT::iPTR:
168 case MVT::iPTRAny:
169 if (InVT.hasIntegerTypes()) {
170 EEVT::TypeSet InCopy(InVT);
171 InCopy.EnforceInteger(TP);
172 InCopy.EnforceScalar(TP);
173
174 if (InCopy.isConcrete()) {
175 // If the RHS has one integer type, upgrade iPTR to i32.
176 TypeVec[0] = InVT.TypeVec[0];
177 return true;
178 }
179
180 // If the input has multiple scalar integers, this doesn't add any info.
181 if (!InCopy.isCompletelyUnknown())
182 return false;
183 }
184 break;
185 }
186
187 // If the input constraint is iAny/iPTR and this is an integer type list,
188 // remove non-integer types from the list.
189 if ((InVT.TypeVec[0] == MVT::iPTR || InVT.TypeVec[0] == MVT::iPTRAny) &&
190 hasIntegerTypes()) {
191 bool MadeChange = EnforceInteger(TP);
192
193 // If we're merging in iPTR/iPTRAny and the node currently has a list of
194 // multiple different integer types, replace them with a single iPTR.
195 if ((InVT.TypeVec[0] == MVT::iPTR || InVT.TypeVec[0] == MVT::iPTRAny) &&
196 TypeVec.size() != 1) {
197 TypeVec.assign(1, InVT.TypeVec[0]);
198 MadeChange = true;
199 }
200
201 return MadeChange;
202 }
203
204 // If this is a type list and the RHS is a typelist as well, eliminate entries
205 // from this list that aren't in the other one.
206 TypeSet InputSet(*this);
207
208 TypeVec.clear();
209 std::set_intersection(InputSet.TypeVec.begin(), InputSet.TypeVec.end(),
210 InVT.TypeVec.begin(), InVT.TypeVec.end(),
211 std::back_inserter(TypeVec));
212
213 // If the intersection is the same size as the original set then we're done.
214 if (TypeVec.size() == InputSet.TypeVec.size())
215 return false;
216
217 // If we removed all of our types, we have a type contradiction.
218 if (!TypeVec.empty())
219 return true;
220
221 // FIXME: Really want an SMLoc here!
222 TP.error("Type inference contradiction found, merging '" +
223 InVT.getName() + "' into '" + InputSet.getName() + "'");
224 return false;
225 }
226
227 /// EnforceInteger - Remove all non-integer types from this set.
228 bool EEVT::TypeSet::EnforceInteger(TreePattern &TP) {
320 assert(!Out.empty() && "cannot pick from an empty set");
321
322 bool Changed = false;
323 for (auto &I : Out) {
324 TypeSetByHwMode::SetType &S = I.second;
325 if (S.size() <= 1)
326 continue;
327 MVT T = *S.begin(); // Pick the first element.
328 S.clear();
329 S.insert(T);
330 Changed = true;
331 }
332 return Changed;
333 }
334
335 bool TypeInfer::EnforceInteger(TypeSetByHwMode &Out) {
336 ValidateOnExit _1(Out);
229337 if (TP.hasError())
230338 return false;
231 // If we know nothing, then get the full set.
232 if (TypeVec.empty())
233 return FillWithPossibleTypes(TP, isInteger, "integer");
234
235 if (!hasFloatingPointTypes())
236 return false;
237
238 TypeSet InputSet(*this);
239
240 // Filter out all the fp types.
241 erase_if(TypeVec, [](MVT::SimpleValueType VT) { return !isInteger(VT); });
242
243 if (TypeVec.empty()) {
244 TP.error("Type inference contradiction found, '" +
245 InputSet.getName() + "' needs to be integer");
246 return false;
247 }
248 return true;
249 }
250
251 /// EnforceFloatingPoint - Remove all integer types from this set.
252 bool EEVT::TypeSet::EnforceFloatingPoint(TreePattern &TP) {
339 if (!Out.empty())
340 return Out.constrain(isIntegerOrPtr);
341
342 return Out.assign_if(getLegalTypes(), isIntegerOrPtr);
343 }
344
345 bool TypeInfer::EnforceFloatingPoint(TypeSetByHwMode &Out) {
346 ValidateOnExit _1(Out);
253347 if (TP.hasError())
254348 return false;
255 // If we know nothing, then get the full set.
256 if (TypeVec.empty())
257 return FillWithPossibleTypes(TP, isFloatingPoint, "floating point");
258
259 if (!hasIntegerTypes())
260 return false;
261
262 TypeSet InputSet(*this);
263
264 // Filter out all the integer types.
265 erase_if(TypeVec,
266 [](MVT::SimpleValueType VT) { return !isFloatingPoint(VT); });
267
268 if (TypeVec.empty()) {
269 TP.error("Type inference contradiction found, '" +
270 InputSet.getName() + "' needs to be floating point");
271 return false;
272 }
273 return true;
274 }
275
276 /// EnforceScalar - Remove all vector types from this.
277 bool EEVT::TypeSet::EnforceScalar(TreePattern &TP) {
349 if (!Out.empty())
350 return Out.constrain(isFloatingPoint);
351
352 return Out.assign_if(getLegalTypes(), isFloatingPoint);
353 }
354
355 bool TypeInfer::EnforceScalar(TypeSetByHwMode &Out) {
356 ValidateOnExit _1(Out);
278357 if (TP.hasError())
279358 return false;
280
281 // If we know nothing, then get the full set.
282 if (TypeVec.empty())
283 return FillWithPossibleTypes(TP, isScalar, "scalar");
284
285 if (!hasVectorTypes())
286 return false;
287
288 TypeSet InputSet(*this);
289
290 // Filter out all the vector types.
291 erase_if(TypeVec, [](MVT::SimpleValueType VT) { return !isScalar(VT); });
292
293 if (TypeVec.empty()) {
294 TP.error("Type inference contradiction found, '" +
295 InputSet.getName() + "' needs to be scalar");
296 return false;
297 }
298 return true;
299 }
300
301 /// EnforceVector - Remove all vector types from this.
302 bool EEVT::TypeSet::EnforceVector(TreePattern &TP) {
359 if (!Out.empty())
360 return Out.constrain(isScalar);
361
362 return Out.assign_if(getLegalTypes(), isScalar);
363 }
364
365 bool TypeInfer::EnforceVector(TypeSetByHwMode &Out) {
366 ValidateOnExit _1(Out);
303367 if (TP.hasError())
304368 return false;
305
306 // If we know nothing, then get the full set.
307 if (TypeVec.empty())
308 return FillWithPossibleTypes(TP, isVector, "vector");
309
310 TypeSet InputSet(*this);
311 bool MadeChange = false;
312
313 // Filter out all the scalar types.
314 erase_if(TypeVec, [](MVT::SimpleValueType VT) { return !isVector(VT); });
315
316 if (TypeVec.empty()) {
317 TP.error("Type inference contradiction found, '" +
318 InputSet.getName() + "' needs to be a vector");
369 if (!Out.empty())
370 return Out.constrain(isVector);
371
372 return Out.assign_if(getLegalTypes(), isVector);
373 }
374
375 bool TypeInfer::EnforceAny(TypeSetByHwMode &Out) {
376 ValidateOnExit _1(Out);
377 if (TP.hasError() || !Out.empty())
319378 return false;
320 }
321 return MadeChange;
322 }
323
324
325
326 /// EnforceSmallerThan - 'this' must be a smaller VT than Other. For vectors
327 /// this should be based on the element type. Update this and other based on
328 /// this information.
329 bool EEVT::TypeSet::EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP) {
379
380 Out = getLegalTypes();
381 return true;
382 }
383
384 template
385 static Iter min_if(Iter B, Iter E, Pred P, Less L) {
386 if (B == E)
387 return E;
388 Iter Min = E;
389 for (Iter I = B; I != E; ++I) {
390 if (!P(*I))
391 continue;
392 if (Min == E || L(*I, *Min))
393 Min = I;
394 }
395 return Min;
396 }
397
398 template
399 static Iter max_if(Iter B, Iter E, Pred P, Less L) {
400 if (B == E)
401 return E;
402 Iter Max = E;
403 for (Iter I = B; I != E; ++I) {
404 if (!P(*I))
405 continue;
406 if (Max == E || L(*Max, *I))
407 Max = I;
408 }
409 return Max;
410 }
411
412 /// Make sure that for each type in Small, there exists a larger type in Big.
413 bool TypeInfer::EnforceSmallerThan(TypeSetByHwMode &Small,
414 TypeSetByHwMode &Big) {
415 ValidateOnExit _1(Small), _2(Big);
330416 if (TP.hasError())
331417 return false;
332
333 // Both operands must be integer or FP, but we don't care which.
334 bool MadeChange = false;
335
336 if (isCompletelyUnknown())
337 MadeChange = FillWithPossibleTypes(TP);
338
339 if (Other.isCompletelyUnknown())
340 MadeChange = Other.FillWithPossibleTypes(TP);
341
342 // If one side is known to be integer or known to be FP but the other side has
343 // no information, get at least the type integrality info in there.
344 if (!hasFloatingPointTypes())
345 MadeChange |= Other.EnforceInteger(TP);
346 else if (!hasIntegerTypes())
347 MadeChange |= Other.EnforceFloatingPoint(TP);
348 if (!Other.hasFloatingPointTypes())
349 MadeChange |= EnforceInteger(TP);
350 else if (!Other.hasIntegerTypes())
351 MadeChange |= EnforceFloatingPoint(TP);
352
353 assert(!isCompletelyUnknown() && !Other.isCompletelyUnknown() &&
354 "Should have a type list now");
355
356 // If one contains vectors but the other doesn't pull vectors out.
357 if (!hasVectorTypes())
358 MadeChange |= Other.EnforceScalar(TP);
359 else if (!hasScalarTypes())
360 MadeChange |= Other.EnforceVector(TP);
361 if (!Other.hasVectorTypes())
362 MadeChange |= EnforceScalar(TP);
363 else if (!Other.hasScalarTypes())
364 MadeChange |= EnforceVector(TP);
365
366 // This code does not currently handle nodes which have multiple types,
367 // where some types are integer, and some are fp. Assert that this is not
368 // the case.
369 assert(!(hasIntegerTypes() && hasFloatingPointTypes()) &&
370 !(Other.hasIntegerTypes() && Other.hasFloatingPointTypes()) &&
371 "SDTCisOpSmallerThanOp does not handle mixed int/fp types!");
372
418 bool Changed = false;
419
420 if (Small.empty())
421 Changed |= EnforceAny(Small);
422 if (Big.empty())
423 Changed |= EnforceAny(Big);
424
425 assert(Small.hasDefault() && Big.hasDefault());
426
427 std::vector Modes = union_modes(Small, Big);
428
429 // 1. Only allow integer or floating point types and make sure that
430 // both sides are both integer or both floating point.
431 // 2. Make sure that either both sides have vector types, or neither
432 // of them does.
433 for (unsigned M : Modes) {
434 TypeSetByHwMode::SetType &S = Small.get(M);
435 TypeSetByHwMode::SetType &B = Big.get(M);
436
437 if (any_of(S, isIntegerOrPtr) && any_of(S, isIntegerOrPtr)) {
438 auto NotInt = std::not1(std::ref(isIntegerOrPtr));
439 Changed |= berase_if(S, NotInt) |
440 berase_if(B, NotInt);
441 } else if (any_of(S, isFloatingPoint) && any_of(B, isFloatingPoint)) {
442 auto NotFP = std::not1(std::ref(isFloatingPoint));
443 Changed |= berase_if(S, NotFP) |
444 berase_if(B, NotFP);
445 } else if (S.empty() || B.empty()) {
446 Changed = !S.empty() || !B.empty();
447 S.clear();
448 B.clear();
449 } else {
450 TP.error("Incompatible types");
451 return Changed;
452 }
453
454 if (none_of(S, isVector) || none_of(B, isVector)) {
455 Changed |= berase_if(S, isVector) |
456 berase_if(B, isVector);
457 }
458 }
459
460 auto LT = [](MVT A, MVT B) -> bool {
461 return A.getScalarSizeInBits() < B.getScalarSizeInBits() ||
462 (A.getScalarSizeInBits() == B.getScalarSizeInBits() &&
463 A.getSizeInBits() < B.getSizeInBits());
464 };
465 auto LE = [](MVT A, MVT B) -> bool {
466 // This function is used when removing elements: when a vector is compared
467 // to a non-vector, it should return false (to avoid removal).
468 if (A.isVector() != B.isVector())
469 return false;
470
471 // Note on the < comparison below:
472 // X86 has patterns like
473 // (set VR128X:$dst, (v16i8 (X86vtrunc (v4i32 VR128X:$src1)))),
474 // where the truncated vector is given a type v16i8, while the source
475 // vector has type v4i32. They both have the same size in bits.
476 // The minimal type in the result is obviously v16i8, and when we remove
477 // all types from the source that are smaller-or-equal than v8i16, the
478 // only source type would also be removed (since it's equal in size).
479 return A.getScalarSizeInBits() <= B.getScalarSizeInBits() ||
480 A.getSizeInBits() < B.getSizeInBits();
481 };
482
483 for (unsigned M : Modes) {
484 TypeSetByHwMode::SetType &S = Small.get(M);
485 TypeSetByHwMode::SetType &B = Big.get(M);
486 // MinS = min scalar in Small, remove all scalars from Big that are
487 // smaller-or-equal than MinS.
488 auto MinS = min_if(S.begin(), S.end(), isScalar, LT);
489 if (MinS != S.end()) {
490 Changed |= berase_if(B, std::bind(LE, std::placeholders::_1, *MinS));
491 if (B.empty()) {
492 TP.error("Type contradiction in " +
493 Twine(__func__) + ":" + Twine(__LINE__));
494 return Changed;
495 }
496 }
497 // MaxS = max scalar in Big, remove all scalars from Small that are
498 // larger than MaxS.
499 auto MaxS = max_if(B.begin(), B.end(), isScalar, LT);
500 if (MaxS != B.end()) {
501 Changed |= berase_if(S, std::bind(LE, *MaxS, std::placeholders::_1));
502 if (B.empty()) {
503 TP.error("Type contradiction in " +
504 Twine(__func__) + ":" + Twine(__LINE__));
505 return Changed;
506 }
507 }
508
509 // MinV = min vector in Small, remove all vectors from Big that are
510 // smaller-or-equal than MinV.
511 auto MinV = min_if(S.begin(), S.end(), isVector, LT);
512 if (MinV != S.end()) {
513 Changed |= berase_if(B, std::bind(LE, std::placeholders::_1, *MinV));
514 if (B.empty()) {
515 TP.error("Type contradiction in " +
516 Twine(__func__) + ":" + Twine(__LINE__));
517 return Changed;
518 }
519 }
520 // MaxV = max vector in Big, remove all vectors from Small that are
521 // larger than MaxV.
522 auto MaxV = max_if(B.begin(), B.end(), isVector, LT);
523 if (MaxV != B.end()) {
524 Changed |= berase_if(S, std::bind(LE, *MaxV, std::placeholders::_1));
525 if (B.empty()) {
526 TP.error("Type contradiction in " +
527 Twine(__func__) + ":" + Twine(__LINE__));
528 return Changed;
529 }
530 }
531 }
532
533 return Changed;
534 }
535
536 /// 1. Ensure that for each type T in Vec, T is a vector type, and that
537 /// for each type U in Elem, U is a scalar type.
538 /// 2. Ensure that for each (scalar) type U in Elem, there exists a (vector)
539 /// type T in Vec, such that U is the element type of T.
540 bool TypeInfer::EnforceVectorEltTypeIs(TypeSetByHwMode &Vec,
541 TypeSetByHwMode &Elem) {
542 ValidateOnExit _1(Vec), _2(Elem);
373543 if (TP.hasError())
374544 return false;
375
376 // Okay, find the smallest type from current set and remove anything the
377 // same or smaller from the other set. We need to ensure that the scalar
378 // type size is smaller than the scalar size of the smallest type. For
379 // vectors, we also need to make sure that the total size is no larger than
380 // the size of the smallest type.
381 {
382 TypeSet InputSet(Other);
383 MVT Smallest = *std::min_element(TypeVec.begin(), TypeVec.end(),
384 [](MVT A, MVT B) {
385 return A.getScalarSizeInBits() < B.getScalarSizeInBits() ||
386 (A.getScalarSizeInBits() == B.getScalarSizeInBits() &&
387 A.getSizeInBits() < B.getSizeInBits());
388 });
389
390 auto I = remove_if(Other.TypeVec, [Smallest](MVT OtherVT) {
391 // Don't compare vector and non-vector types.
392 if (OtherVT.isVector() != Smallest.isVector())
393 return false;
394 // The getSizeInBits() check here is only needed for vectors, but is
395 // a subset of the scalar check for scalars so no need to qualify.
396 return OtherVT.getScalarSizeInBits() <= Smallest.getScalarSizeInBits() ||
397 OtherVT.getSizeInBits() < Smallest.getSizeInBits();
398 });
399 MadeChange |= I != Other.TypeVec.end(); // If we're about to remove types.
400 Other.TypeVec.erase(I, Other.TypeVec.end());
401
402 if (Other.TypeVec.empty()) {
403 TP.error("Type inference contradiction found, '" + InputSet.getName() +
404 "' has nothing larger than '" + getName() +"'!");
405 return false;
406 }
407 }
408
409 // Okay, find the largest type from the other set and remove anything the
410 // same or smaller from the current set. We need to ensure that the scalar
411 // type size is larger than the scalar size of the largest type. For
412 // vectors, we also need to make sure that the total size is no smaller than
413 // the size of the largest type.
414 {
415 TypeSet InputSet(*this);
416 MVT Largest = *std::max_element(Other.TypeVec.begin(), Other.TypeVec.end(),
417 [](MVT A, MVT B) {
418 return A.getScalarSizeInBits() < B.getScalarSizeInBits() ||
419 (A.getScalarSizeInBits() == B.getScalarSizeInBits() &&
420 A.getSizeInBits() < B.getSizeInBits());
421 });
422 auto I = remove_if(TypeVec, [Largest](MVT OtherVT) {
423 // Don't compare vector and non-vector types.
424 if (OtherVT.isVector() != Largest.isVector())
425 return false;
426 return OtherVT.getScalarSizeInBits() >= Largest.getScalarSizeInBits() ||
427 OtherVT.getSizeInBits() > Largest.getSizeInBits();
428 });
429 MadeChange |= I != TypeVec.end(); // If we're about to remove types.
430 TypeVec.erase(I, TypeVec.end());
431
432 if (TypeVec.empty()) {
433 TP.error("Type inference contradiction found, '" + InputSet.getName() +
434 "' has nothing smaller than '" + Other.getName() +"'!");
435 return false;
436 }
437 }
438
439 return MadeChange;
440 }
441
442 /// EnforceVectorEltTypeIs - 'this' is now constrained to be a vector type
443 /// whose element is specified by VTOperand.
444 bool EEVT::TypeSet::EnforceVectorEltTypeIs(MVT::SimpleValueType VT,
445 TreePattern &TP) {
446 bool MadeChange = false;
447
448 MadeChange |= EnforceVector(TP);
449
450 TypeSet InputSet(*this);
451
452 // Filter out all the types which don't have the right element type.
453 auto I = remove_if(TypeVec, [VT](MVT VVT) {
454 return VVT.getVectorElementType().SimpleTy != VT;
455 });
456 MadeChange |= I != TypeVec.end();
457 TypeVec.erase(I, TypeVec.end());
458
459 if (TypeVec.empty()) { // FIXME: Really want an SMLoc here!
460 TP.error("Type inference contradiction found, forcing '" +
461 InputSet.getName() + "' to have a vector element of type " +
462 getEnumName(VT));
463 return false;
464 }
465
466 return MadeChange;
467 }
468
469 /// EnforceVectorEltTypeIs - 'this' is now constrained to be a vector type
470 /// whose element is specified by VTOperand.
471 bool EEVT::TypeSet::EnforceVectorEltTypeIs(EEVT::TypeSet &VTOperand,
472 TreePattern &TP) {
545 bool Changed = false;
546
547 if (Vec.empty())
548 Changed |= EnforceVector(Vec);
549 if (Elem.empty())
550 Changed |= EnforceScalar(Elem);
551
552 for (unsigned M : union_modes(Vec, Elem)) {
553 TypeSetByHwMode::SetType &V = Vec.get(M);
554 TypeSetByHwMode::SetType &E = Elem.get(M);
555
556 Changed |= berase_if(V, isScalar); // Scalar = !vector
557 Changed |= berase_if(E, isVector); // Vector = !scalar
558 assert(!V.empty() && !E.empty());
559
560 SmallSet VT, ST;
561 // Collect element types from the "vector" set.
562 for (MVT T : V)
563 VT.insert(T.getVectorElementType());
564 // Collect scalar types from the "element" set.
565 for (MVT T : E)
566 ST.insert(T);
567
568 // Remove from V all (vector) types whose element type is not in S.
569 Changed |= berase_if(V, [&ST](MVT T) -> bool {
570 return !ST.count(T.getVectorElementType());
571 });
572 // Remove from E all (scalar) types, for which there is no corresponding
573 // type in V.
574 Changed |= berase_if(E, [&VT](MVT T) -> bool { return !VT.count(T); });
575
576 if (V.empty() || E.empty()) {
577 TP.error("Type contradiction in " +
578 Twine(__func__) + ":" + Twine(__LINE__));
579 return Changed;
580 }
581 }
582
583 return Changed;
584 }
585
586 bool TypeInfer::EnforceVectorEltTypeIs(TypeSetByHwMode &Vec,
587 const ValueTypeByHwMode &VVT) {
588 TypeSetByHwMode Tmp(VVT);
589 ValidateOnExit _1(Vec), _2(Tmp);
590 return EnforceVectorEltTypeIs(Vec, Tmp);
591 }
592
593 /// Ensure that for each type T in Sub, T is a vector type, and there
594 /// exists a type U in Vec such that U is a vector type with the same
595 /// element type as T and at least as many elements as T.
596 bool TypeInfer::EnforceVectorSubVectorTypeIs(TypeSetByHwMode &Vec,
597 TypeSetByHwMode &Sub) {
598 ValidateOnExit _1(Vec), _2(Sub);
473599 if (TP.hasError())
474600 return false;
475601
476 // "This" must be a vector and "VTOperand" must be a scalar.
477 bool MadeChange = false;
478 MadeChange |= EnforceVector(TP);
479 MadeChange |= VTOperand.EnforceScalar(TP);
480
481 // If we know the vector type, it forces the scalar to agree.
482 if (isConcrete()) {
483 MVT IVT = getConcrete();
484 IVT = IVT.getVectorElementType();
485 return MadeChange || VTOperand.MergeInTypeInfo(IVT.SimpleTy, TP);
486 }
487
488 // If the scalar type is known, filter out vector types whose element types
489 // disagree.
490 if (!VTOperand.isConcrete())
491 return MadeChange;
492
493 MVT::SimpleValueType VT = VTOperand.getConcrete();
494
495 MadeChange |= EnforceVectorEltTypeIs(VT, TP);
496
497 return MadeChange;
498 }
499
500 /// EnforceVectorSubVectorTypeIs - 'this' is now constrained to be a
501 /// vector type specified by VTOperand.
502 bool EEVT::TypeSet::EnforceVectorSubVectorTypeIs(EEVT::TypeSet &VTOperand,
503 TreePattern &TP) {
602 /// Return true if B is a suB-vector of P, i.e. P is a suPer-vector of B.
603 auto IsSubVec = [](MVT B, MVT P) -> bool {
604 if (!B.isVector() || !P.isVector())
605 return false;
606 if (B.getVectorElementType() != P.getVectorElementType())
607 return false;
608 return B.getVectorNumElements() < P.getVectorNumElements();
609 };
610
611 /// Return true if S has no element (vector type) that T is a sub-vector of,
612 /// i.e. has the same element type as T and more elements.
613 auto NoSubV = [&IsSubVec](const TypeSetByHwMode::SetType &S, MVT T) -> bool {
614 for (const auto &I : S)
615 if (IsSubVec(T, I))
616 return false;
617 return true;
618 };
619
620 /// Return true if S has no element (vector type) that T is a super-vector
621 /// of, i.e. has the same element type as T and fewer elements.
622 auto NoSupV = [&IsSubVec](const TypeSetByHwMode::SetType &S, MVT T) -> bool {
623 for (const auto &I : S)
624 if (IsSubVec(I, T))
625 return false;
626 return true;
627 };
628
629 bool Changed = false;
630
631 if (Vec.empty())
632 Changed |= EnforceVector(Vec);
633 if (Sub.empty())
634 Changed |= EnforceVector(Sub);
635
636 for (unsigned M : union_modes(Vec, Sub)) {
637 TypeSetByHwMode::SetType &S = Sub.get(M);
638 TypeSetByHwMode::SetType &V = Vec.get(M);
639
640 Changed |= berase_if(S, isScalar);
641 if (S.empty()) {
642 TP.error("Type contradiction in " +
643 Twine(__func__) + ":" + Twine(__LINE__));
644 return Changed;
645 }
646
647 // Erase all types from S that are not sub-vectors of a type in V.
648 Changed |= berase_if(S, std::bind(NoSubV, V, std::placeholders::_1));
649 if (S.empty()) {
650 TP.error("Type contradiction in " +
651 Twine(__func__) + ":" + Twine(__LINE__));
652 return Changed;
653 }
654
655 // Erase all types from V that are not super-vectors of a type in S.
656 Changed |= berase_if(V, std::bind(NoSupV, S, std::placeholders::_1));
657 if (V.empty()) {
658 TP.error("Type contradiction in " +
659 Twine(__func__) + ":" + Twine(__LINE__));
660 return Changed;
661 }
662 }
663
664 return Changed;
665 }
666
667 /// 1. Ensure that V has a scalar type iff W has a scalar type.
668 /// 2. Ensure that for each vector type T in V, there exists a vector
669 /// type U in W, such that T and U have the same number of elements.
670 /// 3. Ensure that for each vector type U in W, there exists a vector
671 /// type T in V, such that T and U have the same number of elements
672 /// (reverse of 2).
673 bool TypeInfer::EnforceSameNumElts(TypeSetByHwMode &V, TypeSetByHwMode &W) {
674 ValidateOnExit _1(V), _2(W);
504675 if (TP.hasError())
505676 return false;
506677
507 // "This" must be a vector and "VTOperand" must be a vector.
508 bool MadeChange = false;
509 MadeChange |= EnforceVector(TP);
510 MadeChange |= VTOperand.EnforceVector(TP);
511
512 // If one side is known to be integer or known to be FP but the other side has
513 // no information, get at least the type integrality info in there.
514 if (!hasFloatingPointTypes())
515 MadeChange |= VTOperand.EnforceInteger(TP);
516 else if (!hasIntegerTypes())
517 MadeChange |= VTOperand.EnforceFloatingPoint(TP);
518 if (!VTOperand.hasFloatingPointTypes())
519 MadeChange |= EnforceInteger(TP);
520 else if (!VTOperand.hasIntegerTypes())
521 MadeChange |= EnforceFloatingPoint(TP);
522
523 assert(!isCompletelyUnknown() && !VTOperand.isCompletelyUnknown() &&
524 "Should have a type list now");
525
526 // If we know the vector type, it forces the scalar types to agree.
527 // Also force one vector to have more elements than the other.
528 if (isConcrete()) {
529 MVT IVT = getConcrete();
530 unsigned NumElems = IVT.getVectorNumElements();
531 IVT = IVT.getVectorElementType();
532
533 EEVT::TypeSet EltTypeSet(IVT.SimpleTy, TP);
534 MadeChange |= VTOperand.EnforceVectorEltTypeIs(EltTypeSet, TP);
535
536 // Only keep types that have less elements than VTOperand.
537 TypeSet InputSet(VTOperand);
538
539 auto I = remove_if(VTOperand.TypeVec, [NumElems](MVT VVT) {
540 return VVT.getVectorNumElements() >= NumElems;
541 });
542 MadeChange |= I != VTOperand.TypeVec.end();
543 VTOperand.TypeVec.erase(I, VTOperand.TypeVec.end());
544
545 if (VTOperand.TypeVec.empty()) { // FIXME: Really want an SMLoc here!
546 TP.error("Type inference contradiction found, forcing '" +
547 InputSet.getName() + "' to have less vector elements than '" +
548 getName() + "'");
549 return false;
550 }
551 } else if (VTOperand.isConcrete()) {
552 MVT IVT = VTOperand.getConcrete();
553 unsigned NumElems = IVT.getVectorNumElements();
554 IVT = IVT.getVectorElementType();
555
556 EEVT::TypeSet EltTypeSet(IVT.SimpleTy, TP);
557 MadeChange |= EnforceVectorEltTypeIs(EltTypeSet, TP);
558
559 // Only keep types that have more elements than 'this'.
560 TypeSet InputSet(*this);
561
562 auto I = remove_if(TypeVec, [NumElems](MVT VVT) {
563 return VVT.getVectorNumElements() <= NumElems;
564 });
565 MadeChange |= I != TypeVec.end();
566 TypeVec.erase(I, TypeVec.end());
567
568 if (TypeVec.empty()) { // FIXME: Really want an SMLoc here!
569 TP.error("Type inference contradiction found, forcing '" +
570 InputSet.getName() + "' to have more vector elements than '" +
571 VTOperand.getName() + "'");
572 return false;
573 }
574 }
575
576 return MadeChange;
577 }
578
579 /// EnforceameNumElts - If VTOperand is a scalar, then 'this' is a scalar. If
580 /// VTOperand is a vector, then 'this' must have the same number of elements.
581 bool EEVT::TypeSet::EnforceSameNumElts(EEVT::TypeSet &VTOperand,
582 TreePattern &TP) {
678 bool Changed = false;
679 if (V.empty())
680 Changed |= EnforceAny(V);
681 if (W.empty())
682 Changed |= EnforceAny(W);
683
684 // An actual vector type cannot have 0 elements, so we can treat scalars
685 // as zero-length vectors. This way both vectors and scalars can be
686 // processed identically.
687 auto NoLength = [](const SmallSet &Lengths, MVT T) -> bool {
688 return !Lengths.count(T.isVector() ? T.getVectorNumElements() : 0);
689 };
690
691 for (unsigned M : union_modes(V, W)) {
692 TypeSetByHwMode::SetType &VS = V.get(M);
693 TypeSetByHwMode::SetType &WS = W.get(M);
694
695 SmallSet VN, WN;
696 for (MVT T : VS)
697 VN.insert(T.isVector() ? T.getVectorNumElements() : 0);
698 for (MVT T : WS)
699 WN.insert(T.isVector() ? T.getVectorNumElements() : 0);
700
701 Changed |= berase_if(VS, std::bind(NoLength, WN, std::placeholders::_1));
702 Changed |= berase_if(WS, std::bind(NoLength, VN, std::placeholders::_1));
703 }
704 return Changed;
705 }
706
707 /// 1. Ensure that for each type T in A, there exists a type U in B,
708 /// such that T and U have equal size in bits.
709 /// 2. Ensure that for each type U in B, there exists a type T in A
710 /// such that T and U have equal size in bits (reverse of 1).
711 bool TypeInfer::EnforceSameSize(TypeSetByHwMode &A, TypeSetByHwMode &B) {
712 ValidateOnExit _1(A), _2(B);
583713 if (TP.hasError())
584714 return false;
585
586 bool MadeChange = false;
587
588 if (isCompletelyUnknown())
589 MadeChange = FillWithPossibleTypes(TP);
590
591 if (VTOperand.isCompletelyUnknown())
592 MadeChange = VTOperand.FillWithPossibleTypes(TP);
593
594 // If one contains vectors but the other doesn't pull vectors out.
595 if (!hasVectorTypes())
596 MadeChange |= VTOperand.EnforceScalar(TP);
597 else if (!hasScalarTypes())
598 MadeChange |= VTOperand.EnforceVector(TP);
599 if (!VTOperand.hasVectorTypes())
600 MadeChange |= EnforceScalar(TP);
601 else if (!VTOperand.hasScalarTypes())
602 MadeChange |= EnforceVector(TP);
603
604 // If one type is a vector, make sure the other has the same element count.
605 // If this a scalar, then we are already done with the above.
606 if (isConcrete()) {
607 MVT IVT = getConcrete();
608 if (IVT.isVector()) {
609 unsigned NumElems = IVT.getVectorNumElements();
610
611 // Only keep types that have same elements as 'this'.
612 TypeSet InputSet(VTOperand);
613
614 auto I = remove_if(VTOperand.TypeVec, [NumElems](MVT VVT) {
615 return VVT.getVectorNumElements() != NumElems;
616 });
617 MadeChange |= I != VTOperand.TypeVec.end();
618 VTOperand.TypeVec.erase(I, VTOperand.TypeVec.end());
619
620 if (VTOperand.TypeVec.empty()) { // FIXME: Really want an SMLoc here!
621 TP.error("Type inference contradiction found, forcing '" +
622 InputSet.getName() + "' to have same number elements as '" +
623 getName() + "'");
624 return false;
625 }
626 }
627 } else if (VTOperand.isConcrete()) {
628 MVT IVT = VTOperand.getConcrete();
629 if (IVT.isVector()) {
630 unsigned NumElems = IVT.getVectorNumElements();
631
632 // Only keep types that have same elements as VTOperand.
633 TypeSet InputSet(*this);
634
635 auto I = remove_if(TypeVec, [NumElems](MVT VVT) {
636 return VVT.getVectorNumElements() != NumElems;
637 });
638 MadeChange |= I != TypeVec.end();
639 TypeVec.erase(I, TypeVec.end());
640
641 if (TypeVec.empty()) { // FIXME: Really want an SMLoc here!
642 TP.error("Type inference contradiction found, forcing '" +
643 InputSet.getName() + "' to have same number elements than '" +
644 VTOperand.getName() + "'");
645 return false;
646 }
647 }
648 }
649
650 return MadeChange;
651 }
652
653 /// EnforceSameSize - 'this' is now constrained to be same size as VTOperand.
654 bool EEVT::TypeSet::EnforceSameSize(EEVT::TypeSet &VTOperand,
655 TreePattern &TP) {
656 if (TP.hasError())
657 return false;
658
659 bool MadeChange = false;
660
661 if (isCompletelyUnknown())
662 MadeChange = FillWithPossibleTypes(TP);
663
664 if (VTOperand.isCompletelyUnknown())
665 MadeChange = VTOperand.FillWithPossibleTypes(TP);
666
667 // If we know one of the types, it forces the other type agree.
668 if (isConcrete()) {
669 MVT IVT = getConcrete();
670 unsigned Size = IVT.getSizeInBits();
671
672 // Only keep types that have the same size as 'this'.
673 TypeSet InputSet(VTOperand);
674
675 auto I = remove_if(VTOperand.TypeVec,
676 [&](MVT VT) { return VT.getSizeInBits() != Size; });
677 MadeChange |= I != VTOperand.TypeVec.end();
678 VTOperand.TypeVec.erase(I, VTOperand.TypeVec.end());
679
680 if (VTOperand.TypeVec.empty()) { // FIXME: Really want an SMLoc here!
681 TP.error("Type inference contradiction found, forcing '" +
682 InputSet.getName() + "' to have same size as '" +
683 getName() + "'");
684 return false;
685 }
686 } else if (VTOperand.isConcrete()) {
687 MVT IVT = VTOperand.getConcrete();
688 unsigned Size = IVT.getSizeInBits();
689
690 // Only keep types that have the same size as VTOperand.
691 TypeSet InputSet(*this);
692
693 auto I =
694 remove_if(TypeVec, [&](MVT VT) { return VT.getSizeInBits() != Size; });
695 MadeChange |= I != TypeVec.end();
696 TypeVec.erase(I, TypeVec.end());
697
698 if (TypeVec.empty()) { // FIXME: Really want an SMLoc here!
699 TP.error("Type inference contradiction found, forcing '" +
700 InputSet.getName() + "' to have same size as '" +
701 VTOperand.getName() + "'");
702 return false;
703 }
704 }
705
706 return MadeChange;
707 }
708
709 //===----------------------------------------------------------------------===//
710 // Helpers for working with extended types.
711
712 /// Dependent variable map for CodeGenDAGPattern variant generation.
713 typedef std::map DepVarMap;
714
715 static void FindDepVarsOf(TreePatternNode *N, DepVarMap &DepMap) {
716 if (N->isLeaf()) {
717 if (isa(N->getLeafValue()))
718 DepMap[N->getName()]++;
715 bool Changed = false;
716 if (A.empty())
717 Changed |= EnforceAny(A);
718 if (B.empty())
719 Changed |= EnforceAny(B);
720
721 auto NoSize = [](const SmallSet &Sizes, MVT T) -> bool {
722 return !Sizes.count(T.getSizeInBits());
723 };
724
725 for (unsigned M : union_modes(A, B)) {
726 TypeSetByHwMode::SetType &AS = A.get(M);
727 TypeSetByHwMode::SetType &BS = B.get(M);
728 SmallSet AN, BN;
729
730 for (MVT T : AS)
731 AN.insert(T.getSizeInBits());
732 for (MVT T : BS)
733 BN.insert(T.getSizeInBits());
734
735 Changed |= berase_if(AS, std::bind(NoSize, BN, std::placeholders::_1));
736 Changed |= berase_if(BS, std::bind(NoSize, AN, std::placeholders::_1));
737 }
738
739 return Changed;
740 }
741
742 void TypeInfer::expandOverloads(TypeSetByHwMode &VTS) {
743 ValidateOnExit _1(VTS);
744 TypeSetByHwMode Legal = getLegalTypes();
745 bool HaveLegalDef = Legal.hasDefault();
746
747 for (auto &I : VTS) {
748 unsigned M = I.first;
749 if (!Legal.hasMode(M) && !HaveLegalDef) {
750 TP.error("Invalid mode " + Twine(M));
751 return;
752 }
753 expandOverloads(I.second, Legal.get(M));
754 }
755 }
756
757 void TypeInfer::expandOverloads(TypeSetByHwMode::SetType &Out,
758 const TypeSetByHwMode::SetType &Legal) {
759 std::set Ovs;
760 for (auto I = Out.begin(); I != Out.end(); ) {
761 if (I->isOverloaded()) {
762 Ovs.insert(*I);
763 I = Out.erase(I);
764 continue;
765 }
766 ++I;
767 }
768
769 for (MVT Ov : Ovs) {
770 switch (Ov.SimpleTy) {
771 case MVT::iPTRAny:
772 Out.insert(MVT::iPTR);
773 return;
774 case MVT::iAny:
775 for (MVT T : MVT::integer_valuetypes())
776 if (Legal.count(T))
777 Out.insert(T);
778 for (MVT T : MVT::integer_vector_valuetypes())
779 if (Legal.count(T))
780 Out.insert(T);
781 return;
782 case MVT::fAny:
783 for (MVT T : MVT::fp_valuetypes())
784 if (Legal.count(T))
785 Out.insert(T);
786 for (MVT T : MVT::fp_vector_valuetypes())
787 if (Legal.count(T))
788 Out.insert(T);
789 return;
790 case MVT::vAny:
791 for (MVT T : MVT::vector_valuetypes())
792 if (Legal.count(T))
793 Out.insert(T);
794 return;
795 case MVT::Any:
796 for (MVT T : MVT::all_valuetypes())
797 if (Legal.count(T))
798 Out.insert(T);
799 return;
800 default:
801 break;
802 }
803 }
804 }
805
806
807 TypeSetByHwMode TypeInfer::getLegalTypes() {
808 TypeSetByHwMode VTS;
809 TypeSetByHwMode::SetType &DS = VTS.getOrCreate(DefaultMode);
810 const TypeSetByHwMode <S = TP.getDAGPatterns().getLegalTypes();
811
812 if (!CodeGen) {
813 assert(LTS.hasDefault());
814 const TypeSetByHwMode::SetType &S = LTS.get(DefaultMode);
815 DS.insert(S.begin(), S.end());
719816 } else {
720 for (size_t i = 0, e = N->getNumChildren(); i != e; ++i)
721 FindDepVarsOf(N->getChild(i), DepMap);
722 }
723 }
724
725 /// Find dependent variables within child patterns.
726 static void FindDepVars(TreePatternNode *N, MultipleUseVarSet &DepVars) {
727 DepVarMap depcounts;
728 FindDepVarsOf(N, depcounts);
729 for (const std::pair &Pair : depcounts) {
730 if (Pair.second > 1)
731 DepVars.insert(Pair.first);
732 }
733 }
734
735 #ifndef NDEBUG
736 /// Dump the dependent variable set.
737 LLVM_DUMP_METHOD
738 static void DumpDepVars(MultipleUseVarSet &DepVars) {
739 if (DepVars.empty()) {
740 DEBUG(errs() << "");
741 } else {
742 DEBUG(errs() << "[ ");
743 for (const std::string &DepVar : DepVars) {
744 DEBUG(errs() << DepVar << " ");
745 }
746 DEBUG(errs() << "]");
747 }
748 }
749 #endif
750
817 for (const auto &I : LTS)
818 DS.insert(I.second.begin(), I.second.end());
819 }
820 return VTS;
821 }
751822
752823 //===----------------------------------------------------------------------===//
753824 // TreePredicateFn Implementation
814885 // PatternToMatch implementation
815886 //
816887
817
818888 /// getPatternSize - Return the 'size' of this pattern. We want to match large
819889 /// patterns before small ones. This is used to determine the size of a
820890 /// pattern.
842912 // Count children in the count if they are also nodes.
843913 for (unsigned i = 0, e = P->getNumChildren(); i != e; ++i) {
844914 TreePatternNode *Child = P->getChild(i);
845 if (!Child->isLeaf() && Child->getNumTypes() &&
846 Child->getType(0) != MVT::Other)
847 Size += getPatternSize(Child, CGP);
848 else if (Child->isLeaf()) {
915 if (!Child->isLeaf() && Child->getNumTypes()) {
916 const TypeSetByHwMode &T0 = Child->getType(0);
917 // At this point, all variable type sets should be simple, i.e. only
918 // have a default mode.
919 if (T0.getMachineValueType() != MVT::Other) {
920 Size += getPatternSize(Child, CGP);
921 continue;
922 }
923 }
924 if (Child->isLeaf()) {
849925 if (isa(Child->getLeafValue()))
850926 Size += 5; // Matches a ConstantSDNode (+3) and a specific value (+2).
851927 else if (Child->getComplexPatternInfo(CGP))
865941 return getPatternSize(getSrcPattern(), CGP) + getAddedComplexity();
866942 }
867943
868
869944 /// getPredicateCheck - Return a single string containing all of this
870945 /// pattern's predicates concatenated with "&&" operators.
871946 ///
872947 std::string PatternToMatch::getPredicateCheck() const {
873 SmallVector PredicateRecs;
874 for (Init *I : Predicates->getValues()) {
875 if (DefInit *Pred = dyn_cast(I)) {
876 Record *Def = Pred->getDef();
877 if (!Def->isSubClassOf("Predicate")) {
878 #ifndef NDEBUG
879 Def->dump();
880 #endif
881 llvm_unreachable("Unknown predicate type!");
882 }
883 PredicateRecs.push_back(Def);
884 }
885 }
886 // Sort so that different orders get canonicalized to the same string.
887 std::sort(PredicateRecs.begin(), PredicateRecs.end(), LessRecord());
888
889 SmallString<128> PredicateCheck;
890 for (Record *Pred : PredicateRecs) {
891 if (!PredicateCheck.empty())
892 PredicateCheck += " && ";
893 PredicateCheck += "(";
894 PredicateCheck += Pred->getValueAsString("CondString");
895 PredicateCheck += ")";
896 }
897
898 return PredicateCheck.str();
948 SmallVector PredList;
949 for (const Predicate &P : Predicates)
950 PredList.push_back(&P);
951 std::sort(PredList.begin(), PredList.end(), deref());
952
953 std::string Check;
954 for (unsigned i = 0, e = PredList.size(); i != e; ++i) {
955 if (i != 0)
956 Check += " && ";
957 Check += '(' + PredList[i]->getCondString() + ')';
958 }
959 return Check;
899960 }
900961
901962 //===----------------------------------------------------------------------===//
902963 // SDTypeConstraint implementation
903964 //
904965
905 SDTypeConstraint::SDTypeConstraint(Record *R) {
966 SDTypeConstraint::SDTypeConstraint(Record *R, const CodeGenHwModes &CGH) {
906967 OperandNo = R->getValueAsInt("OperandNum");
907968
908969 if (R->isSubClassOf("SDTCisVT")) {
909970 ConstraintType = SDTCisVT;
910 x.SDTCisVT_Info.VT = getValueType(R->getValueAsDef("VT"));
911 if (x.SDTCisVT_Info.VT == MVT::isVoid)
912 PrintFatalError(R->getLoc(), "Cannot use 'Void' as type to SDTCisVT");
913
971 VVT = getValueTypeByHwMode(R->getValueAsDef("VT"), CGH);
972 for (const auto &P : VVT)
973 if (P.second == MVT::isVoid)
974 PrintFatalError(R->getLoc(), "Cannot use 'Void' as type to SDTCisVT");
914975 } else if (R->isSubClassOf("SDTCisPtrTy")) {
915976 ConstraintType = SDTCisPtrTy;
916977 } else if (R->isSubClassOf("SDTCisInt")) {
9391000 R->getValueAsInt("OtherOpNum");
9401001 } else if (R->isSubClassOf("SDTCVecEltisVT")) {
9411002 ConstraintType = SDTCVecEltisVT;
942 x.SDTCVecEltisVT_Info.VT = getValueType(R->getValueAsDef("VT"));
943 if (MVT(x.SDTCVecEltisVT_Info.VT).isVector())
944 PrintFatalError(R->getLoc(), "Cannot use vector type as SDTCVecEltisVT");
945 if (!MVT(x.SDTCVecEltisVT_Info.VT).isInteger() &&
946 !MVT(x.SDTCVecEltisVT_Info.VT).isFloatingPoint())
947 PrintFatalError(R->getLoc(), "Must use integer or floating point type "
948 "as SDTCVecEltisVT");
1003 VVT = getValueTypeByHwMode(R->getValueAsDef("VT"), CGH);
1004 for (const auto &P : VVT) {
1005 MVT T = P.second;
1006 if (T.isVector())
1007 PrintFatalError(R->getLoc(),
1008 "Cannot use vector type as SDTCVecEltisVT");
1009 if (!T.isInteger() && !T.isFloatingPoint())
1010 PrintFatalError(R->getLoc(), "Must use integer or floating point type "
1011 "as SDTCVecEltisVT");
1012 }
9491013 } else if (R->isSubClassOf("SDTCisSameNumEltsAs")) {
9501014 ConstraintType = SDTCisSameNumEltsAs;
9511015 x.SDTCisSameNumEltsAs_Info.OtherOperandNum =
9951059
9961060 unsigned ResNo = 0; // The result number being referenced.
9971061 TreePatternNode *NodeToApply = getOperandNum(OperandNo, N, NodeInfo, ResNo);
1062 TypeInfer &TI = TP.getInfer();
9981063
9991064 switch (ConstraintType) {
10001065 case SDTCisVT:
10011066 // Operand must be a particular type.
1002 return NodeToApply->UpdateNodeType(ResNo, x.SDTCisVT_Info.VT, TP);
1067 return NodeToApply->UpdateNodeType(ResNo, VVT, TP);
10031068 case SDTCisPtrTy:
10041069 // Operand must be same as target pointer type.
10051070 return NodeToApply->UpdateNodeType(ResNo, MVT::iPTR, TP);
10061071 case SDTCisInt:
10071072 // Require it to be one of the legal integer VTs.
1008 return NodeToApply->getExtType(ResNo).EnforceInteger(TP);
1073 return TI.EnforceInteger(NodeToApply->getExtType(ResNo));
10091074 case SDTCisFP:
10101075 // Require it to be one of the legal fp VTs.
1011 return NodeToApply->getExtType(ResNo).EnforceFloatingPoint(TP);
1076 return TI.EnforceFloatingPoint(NodeToApply->getExtType(ResNo));
10121077 case SDTCisVec:
10131078 // Require it to be one of the legal vector VTs.
1014 return NodeToApply->getExtType(ResNo).EnforceVector(TP);
1079 return TI.EnforceVector(NodeToApply->getExtType(ResNo));
10151080 case SDTCisSameAs: {
10161081 unsigned OResNo = 0;
10171082 TreePatternNode *OtherNode =
10291094 TP.error(N->getOperator()->getName() + " expects a VT operand!");
10301095 return false;
10311096 }
1032 MVT::SimpleValueType VT =
1033 getValueType(static_cast(NodeToApply->getLeafValue())->getDef());
1034
1035 EEVT::TypeSet TypeListTmp(VT, TP);
1097 DefInit *DI = static_cast(NodeToApply->getLeafValue());
1098 const CodeGenTarget &T = TP.getDAGPatterns().getTargetInfo();
1099 auto VVT = getValueTypeByHwMode(DI->getDef(), T.getHwModes());
1100 TypeSetByHwMode TypeListTmp(VVT);
10361101
10371102 unsigned OResNo = 0;
10381103 TreePatternNode *OtherNode =
10391104 getOperandNum(x.SDTCisVTSmallerThanOp_Info.OtherOperandNum, N, NodeInfo,
10401105 OResNo);
10411106
1042 return TypeListTmp.EnforceSmallerThan(OtherNode->getExtType(OResNo), TP);
1107 return TI.EnforceSmallerThan(TypeListTmp, OtherNode->getExtType(OResNo));
10431108 }
10441109 case SDTCisOpSmallerThanOp: {
10451110 unsigned BResNo = 0;
10461111 TreePatternNode *BigOperand =
10471112 getOperandNum(x.SDTCisOpSmallerThanOp_Info.BigOperandNum, N, NodeInfo,
10481113 BResNo);
1049 return NodeToApply->getExtType(ResNo).
1050 EnforceSmallerThan(BigOperand->getExtType(BResNo), TP);
1114 return TI.EnforceSmallerThan(NodeToApply->getExtType(ResNo),
1115 BigOperand->getExtType(BResNo));
10511116 }
10521117 case SDTCisEltOfVec: {
10531118 unsigned VResNo = 0;
10541119 TreePatternNode *VecOperand =
10551120 getOperandNum(x.SDTCisEltOfVec_Info.OtherOperandNum, N, NodeInfo,
10561121 VResNo);
1057
10581122 // Filter vector types out of VecOperand that don't have the right element
10591123 // type.
1060 return VecOperand->getExtType(VResNo).
1061 EnforceVectorEltTypeIs(NodeToApply->getExtType(ResNo), TP);
1124 return TI.EnforceVectorEltTypeIs(VecOperand->getExtType(VResNo),
1125 NodeToApply->getExtType(ResNo));
10621126 }
10631127 case SDTCisSubVecOfVec: {
10641128 unsigned VResNo = 0;
10681132
10691133 // Filter vector types out of BigVecOperand that don't have the
10701134 // right subvector type.
1071 return BigVecOperand->getExtType(VResNo).
1072 EnforceVectorSubVectorTypeIs(NodeToApply->getExtType(ResNo), TP);
1135 return TI.EnforceVectorSubVectorTypeIs(BigVecOperand->getExtType(VResNo),
1136 NodeToApply->getExtType(ResNo));
10731137 }
10741138 case SDTCVecEltisVT: {
1075 return NodeToApply->getExtType(ResNo).
1076 EnforceVectorEltTypeIs(x.SDTCVecEltisVT_Info.VT, TP);
1139 return TI.EnforceVectorEltTypeIs(NodeToApply->getExtType(ResNo), VVT);
10771140 }
10781141 case SDTCisSameNumEltsAs: {
10791142 unsigned OResNo = 0;
10801143 TreePatternNode *OtherNode =
10811144 getOperandNum(x.SDTCisSameNumEltsAs_Info.OtherOperandNum,
10821145 N, NodeInfo, OResNo);
1083 return OtherNode->getExtType(OResNo).
1084 EnforceSameNumElts(NodeToApply->getExtType(ResNo), TP);
1146 return TI.EnforceSameNumElts(OtherNode->getExtType(OResNo),
1147 NodeToApply->getExtType(ResNo));
10851148 }
10861149 case SDTCisSameSizeAs: {
10871150 unsigned OResNo = 0;
10881151 TreePatternNode *OtherNode =
10891152 getOperandNum(x.SDTCisSameSizeAs_Info.OtherOperandNum,
10901153 N, NodeInfo, OResNo);
1091 return OtherNode->getExtType(OResNo).
1092 EnforceSameSize(NodeToApply->getExtType(ResNo), TP);
1154 return TI.EnforceSameSize(OtherNode->getExtType(OResNo),
1155 NodeToApply->getExtType(ResNo));
10931156 }
10941157 }
10951158 llvm_unreachable("Invalid ConstraintType!");
11071170 return false;
11081171
11091172 // The Operand class specifies a type directly.
1110 if (Operand->isSubClassOf("Operand"))
1111 return UpdateNodeType(ResNo, getValueType(Operand->getValueAsDef("Type")),
1112 TP);
1173 if (Operand->isSubClassOf("Operand")) {
1174 Record *R = Operand->getValueAsDef("Type");
1175 const CodeGenTarget &T = TP.getDAGPatterns().getTargetInfo();
1176 return UpdateNodeType(ResNo, getValueTypeByHwMode(R, T.getHwModes()), TP);
1177 }
11131178
11141179 // PointerLikeRegClass has a type that is determined at runtime.
11151180 if (Operand->isSubClassOf("PointerLikeRegClass"))
11281193 return UpdateNodeType(ResNo, Tgt.getRegisterClass(RC).getValueTypes(), TP);
11291194 }
11301195
1196 bool TreePatternNode::ContainsUnresolvedType(TreePattern &TP) const {
1197 for (unsigned i = 0, e = Types.size(); i != e; ++i)
1198 if (!TP.getInfer().isConcrete(Types[i], true))
1199 return true;
1200 for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
1201 if (getChild(i)->ContainsUnresolvedType(TP))
1202 return true;
1203 return false;
1204 }
1205
1206 bool TreePatternNode::hasProperTypeByHwMode() const {
1207 for (const TypeSetByHwMode &S : Types)
1208 if (!S.isDefaultOnly())
1209 return true;
1210 for (TreePatternNode *C : Children)
1211 if (C->hasProperTypeByHwMode())
1212 return true;
1213 return false;
1214 }
1215
1216 bool TreePatternNode::hasPossibleType() const {
1217 for (const TypeSetByHwMode &S : Types)
1218 if (!S.isPossible())
1219 return false;
1220 for (TreePatternNode *C : Children)
1221 if (!C->hasPossibleType())
1222 return false;
1223 return true;
1224 }
1225
1226 bool TreePatternNode::setDefaultMode(unsigned Mode) {
1227 for (TypeSetByHwMode &S : Types) {
1228 S.makeSimple(Mode);
1229 // Check if the selected mode had a type conflict.
1230 if (S.get(DefaultMode).empty())
1231 return false;
1232 }
1233 for (TreePatternNode *C : Children)
1234 if (!C->setDefaultMode(Mode))
1235 return false;
1236 return true;
1237 }
11311238
11321239 //===----------------------------------------------------------------------===//
11331240 // SDNodeInfo implementation
11341241 //
1135 SDNodeInfo::SDNodeInfo(Record *R) : Def(R) {
1242 SDNodeInfo::SDNodeInfo(Record *R, const CodeGenHwModes &CGH) : Def(R) {
11361243 EnumName = R->getValueAsString("Opcode");
11371244 SDClassName = R->getValueAsString("SDClass");
11381245 Record *TypeProfile = R->getValueAsDef("TypeProfile");
11751282 // Parse the type constraints.
11761283 std::vector ConstraintList =
11771284 TypeProfile->getValueAsListOfDefs("Constraints");
1178 TypeConstraints.assign(ConstraintList.begin(), ConstraintList.end());
1285 for (Record *R : ConstraintList)
1286 TypeConstraints.emplace_back(R, CGH);
11791287 }
11801288
11811289 /// getKnownType - If the type constraints on this node imply a fixed type
11951303 switch (Constraint.ConstraintType) {
11961304 default: break;
11971305 case SDTypeConstraint::SDTCisVT:
1198 return Constraint.x.SDTCisVT_Info.VT;
1306 if (Constraint.VVT.isSimple())
1307 return Constraint.VVT.getSimple().SimpleTy;
1308 break;
11991309 case SDTypeConstraint::SDTCisPtrTy:
12001310 return MVT::iPTR;
12011311 }
12821392 OS << '(' << getOperator()->getName();
12831393
12841394 for (unsigned i = 0, e = Types.size(); i != e; ++i)
1285 OS << ':' << getExtType(i).getName();
1395 OS << ':' << getExtType(i).getAsString();
12861396
12871397 if (!isLeaf()) {
12881398 if (getNumChildren() != 0) {
13651475 /// RemoveAllTypes - Recursively strip all the types of this tree.
13661476 void TreePatternNode::RemoveAllTypes() {
13671477 // Reset to unknown type.
1368 std::fill(Types.begin(), Types.end(), EEVT::TypeSet());
1478 std::fill(Types.begin(), Types.end(), TypeSetByHwMode());
13691479 if (isLeaf()) return;
13701480 for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
13711481 getChild(i)->RemoveAllTypes();
14821592 /// When Unnamed is false, return the type of a named DAG operand such as the
14831593 /// GPR:$src operand above.
14841594 ///
1485 static EEVT::TypeSet getImplicitType(Record *R, unsigned ResNo,
1486 bool NotRegisters,
1487 bool Unnamed,
1488 TreePattern &TP) {
1595 static TypeSetByHwMode getImplicitType(Record *R, unsigned ResNo,
1596 bool NotRegisters,
1597 bool Unnamed,
1598 TreePattern &TP) {
1599 CodeGenDAGPatterns &CDP = TP.getDAGPatterns();
1600
14891601 // Check to see if this is a register operand.
14901602 if (R->isSubClassOf("RegisterOperand")) {
14911603 assert(ResNo == 0 && "Regoperand ref only has one result!");
14921604 if (NotRegisters)
1493 return EEVT::TypeSet(); // Unknown.
1605 return TypeSetByHwMode(); // Unknown.
14941606 Record *RegClass = R->getValueAsDef("RegClass");
14951607 const CodeGenTarget &T = TP.getDAGPatterns().getTargetInfo();
1496 return EEVT::TypeSet(T.getRegisterClass(RegClass).getValueTypes());
1608 return TypeSetByHwMode(T.getRegisterClass(RegClass).getValueTypes());
14971609 }
14981610
14991611 // Check to see if this is a register or a register class.
15021614 // An unnamed register class represents itself as an i32 immediate, for
15031615 // example on a COPY_TO_REGCLASS instruction.
15041616 if (Unnamed)
1505 return EEVT::TypeSet(MVT::i32, TP);
1617 return TypeSetByHwMode(MVT::i32);
15061618
15071619 // In a named operand, the register class provides the possible set of
15081620 // types.
15091621 if (NotRegisters)
1510 return EEVT::TypeSet(); // Unknown.
1622 return TypeSetByHwMode(); // Unknown.
15111623 const CodeGenTarget &T = TP.getDAGPatterns().getTargetInfo();
1512 return EEVT::TypeSet(T.getRegisterClass(R).getValueTypes());
1624 return TypeSetByHwMode(T.getRegisterClass(R).getValueTypes());
15131625 }
15141626
15151627 if (R->isSubClassOf("PatFrag")) {
15161628 assert(ResNo == 0 && "FIXME: PatFrag with multiple results?");
15171629 // Pattern fragment types will be resolved when they are inlined.
1518 return EEVT::TypeSet(); // Unknown.
1630 return TypeSetByHwMode(); // Unknown.
15191631 }
15201632
15211633 if (R->isSubClassOf("Register")) {
15221634 assert(ResNo == 0 && "Registers only produce one result!");
15231635 if (NotRegisters)
1524 return EEVT::TypeSet(); // Unknown.
1636 return TypeSetByHwMode(); // Unknown.
15251637 const CodeGenTarget &T = TP.getDAGPatterns().getTargetInfo();
1526 return EEVT::TypeSet(T.getRegisterVTs(R));
1638 return TypeSetByHwMode(T.getRegisterVTs(R));
15271639 }
15281640
15291641 if (R->isSubClassOf("SubRegIndex")) {
15301642 assert(ResNo == 0 && "SubRegisterIndices only produce one result!");
1531 return EEVT::TypeSet(MVT::i32, TP);
1643 return TypeSetByHwMode(MVT::i32);
15321644 }
15331645
15341646 if (R->isSubClassOf("ValueType")) {
15381650 // (sext_inreg GPR:$src, i16)
15391651 // ~~~
15401652 if (Unnamed)
1541 return EEVT::TypeSet(MVT::Other, TP);
1653 return TypeSetByHwMode(MVT::Other);
15421654 // With a name, the ValueType simply provides the type of the named
15431655 // variable.
15441656 //
15451657 // (sext_inreg i32:$src, i16)
15461658 // ~~~~~~~~
15471659 if (NotRegisters)
1548 return EEVT::TypeSet(); // Unknown.
1549 return EEVT::TypeSet(getValueType(R), TP);
1660 return TypeSetByHwMode(); // Unknown.
1661 const CodeGenHwModes &CGH = CDP.getTargetInfo().getHwModes();
1662 return TypeSetByHwMode(getValueTypeByHwMode(R, CGH));
15501663 }
15511664
15521665 if (R->isSubClassOf("CondCode")) {
15531666 assert(ResNo == 0 && "This node only has one result!");
15541667 // Using a CondCodeSDNode.
1555 return EEVT::TypeSet(MVT::Other, TP);
1668 return TypeSetByHwMode(MVT::Other);
15561669 }
15571670
15581671 if (R->isSubClassOf("ComplexPattern")) {
15591672 assert(ResNo == 0 && "FIXME: ComplexPattern with multiple results?");
15601673 if (NotRegisters)
1561 return EEVT::TypeSet(); // Unknown.
1562 return EEVT::TypeSet(TP.getDAGPatterns().getComplexPattern(R).getValueType(),
1563 TP);
1674 return TypeSetByHwMode(); // Unknown.
1675 return TypeSetByHwMode(CDP.getComplexPattern(R).getValueType());
15641676 }
15651677 if (R->isSubClassOf("PointerLikeRegClass")) {
15661678 assert(ResNo == 0 && "Regclass can only have one result!");
1567 return EEVT::TypeSet(MVT::iPTR, TP);
1679 TypeSetByHwMode VTS(MVT::iPTR);
1680 TP.getInfer().expandOverloads(VTS);
1681 return VTS;
15681682 }
15691683
15701684 if (R->getName() == "node" || R->getName() == "srcvalue" ||
15711685 R->getName() == "zero_reg") {
15721686 // Placeholder.
1573 return EEVT::TypeSet(); // Unknown.
1574 }
1575
1576 if (R->isSubClassOf("Operand"))
1577 return EEVT::TypeSet(getValueType(R->getValueAsDef("Type")));
1687 return TypeSetByHwMode(); // Unknown.
1688 }
1689
1690 if (R->isSubClassOf("Operand")) {
1691 const CodeGenHwModes &CGH = CDP.getTargetInfo().getHwModes();
1692 Record *T = R->getValueAsDef("Type");
1693 return TypeSetByHwMode(getValueTypeByHwMode(T, CGH));
1694 }
15781695
15791696 TP.error("Unknown node flavor used in pattern: " + R->getName());
1580 return EEVT::TypeSet(MVT::Other, TP);
1697 return TypeSetByHwMode(MVT::Other);
15811698 }
15821699
15831700
17191836 assert(Types.size() == 1 && "Invalid IntInit");
17201837
17211838 // Int inits are always integers. :)
1722 bool MadeChange = Types[0].EnforceInteger(TP);
1723
1724 if (!Types[0].isConcrete())
1839 bool MadeChange = TP.getInfer().EnforceInteger(Types[0]);
1840
1841 if (!TP.getInfer().isConcrete(Types[0], false))
17251842 return MadeChange;
17261843
1727 MVT::SimpleValueType VT = getType(0);
1728 if (VT == MVT::iPTR || VT == MVT::iPTRAny)
1729 return MadeChange;
1730
1731 unsigned Size = MVT(VT).getSizeInBits();
1732 // Make sure that the value is representable for this type.
1733 if (Size >= 32) return MadeChange;
1734
1735 // Check that the value doesn't use more bits than we have. It must either
1736 // be a sign- or zero-extended equivalent of the original.
1737 int64_t SignBitAndAbove = II->getValue() >> (Size - 1);
1738 if (SignBitAndAbove == -1 || SignBitAndAbove == 0 || SignBitAndAbove == 1)
1739 return MadeChange;
1740
1741 TP.error("Integer value '" + itostr(II->getValue()) +
1742 "' is out of range for type '" + getEnumName(getType(0)) + "'!");
1743 return false;
1744 }
1844 ValueTypeByHwMode VVT = TP.getInfer().getConcrete(Types[0], false);
1845 for (auto &P : VVT) {
1846 MVT::SimpleValueType VT = P.second.SimpleTy;
1847 if (VT == MVT::iPTR || VT == MVT::iPTRAny)
1848 continue;
1849 unsigned Size = MVT(VT).getSizeInBits();
1850 // Make sure that the value is representable for this type.
1851 if (Size >= 32)
1852 continue;
1853 // Check that the value doesn't use more bits than we have. It must
1854 // either be a sign- or zero-extended equivalent of the original.
1855 int64_t SignBitAndAbove = II->getValue() >> (Size - 1);
1856 if (SignBitAndAbove == -1 || SignBitAndAbove == 0 ||
1857 SignBitAndAbove == 1)
1858 continue;
1859
1860 TP.error("Integer value '" + itostr(II->getValue()) +
1861 "' is out of range for type '" + getEnumName(VT) + "'!");
1862 break;
1863 }
1864 return MadeChange;
1865 }
1866
17451867 return false;
17461868 }
17471869
17701892
17711893 bool MadeChange = false;
17721894 for (unsigned i = 0; i < getNumChildren(); ++i)
1773 MadeChange = getChild(i)->ApplyTypeConstraints(TP, NotRegisters);
1895 MadeChange |= getChild(i)->ApplyTypeConstraints(TP, NotRegisters);
17741896 return MadeChange;
17751897 }
17761898
18151937 return false;
18161938 }
18171939
1818 bool MadeChange = NI.ApplyTypeConstraints(this, TP);
1940 bool MadeChange = false;
18191941 for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
18201942 MadeChange |= getChild(i)->ApplyTypeConstraints(TP, NotRegisters);
1943 MadeChange |= NI.ApplyTypeConstraints(this, TP);
18211944 return MadeChange;
18221945 }
18231946
20352158
20362159 TreePattern::TreePattern(Record *TheRec, ListInit *RawPat, bool isInput,
20372160 CodeGenDAGPatterns &cdp) : TheRecord(TheRec), CDP(cdp),
2038 isInputPattern(isInput), HasError(false) {
2161 isInputPattern(isInput), HasError(false),
2162 Infer(*this) {
20392163 for (Init *I : RawPat->getValues())
20402164 Trees.push_back(ParseTreePattern(I, ""));
20412165 }
20422166
20432167 TreePattern::TreePattern(Record *TheRec, DagInit *Pat, bool isInput,
20442168 CodeGenDAGPatterns &cdp) : TheRecord(TheRec), CDP(cdp),
2045 isInputPattern(isInput), HasError(false) {
2169 isInputPattern(isInput), HasError(false),
2170 Infer(*this) {
20462171 Trees.push_back(ParseTreePattern(Pat, ""));
20472172 }
20482173
20492174 TreePattern::TreePattern(Record *TheRec, TreePatternNode *Pat, bool isInput,
20502175 CodeGenDAGPatterns &cdp) : TheRecord(TheRec), CDP(cdp),
2051 isInputPattern(isInput), HasError(false) {
2176 isInputPattern(isInput), HasError(false),
2177 Infer(*this) {
20522178 Trees.push_back(Pat);
20532179 }
20542180
21432269
21442270 // Apply the type cast.
21452271 assert(New->getNumTypes() == 1 && "FIXME: Unhandled");
2146 New->UpdateNodeType(0, getValueType(Operator), *this);
2272 const CodeGenHwModes &CGH = getDAGPatterns().getTargetInfo().getHwModes();
2273 New->UpdateNodeType(0, getValueTypeByHwMode(Operator, CGH), *this);
21472274
21482275 if (!OpName.empty())
21492276 error("ValueType cast should not have a name!");
22582385 // If we have a bitconvert with a resolved type and if the source and
22592386 // destination types are the same, then the bitconvert is useless, remove it.
22602387 if (N->getOperator()->getName() == "bitconvert" &&
2261 N->getExtType(0).isConcrete() &&
2388 N->getExtType(0).isValueTypeByHwMode(false) &&
22622389 N->getExtType(0) == N->getChild(0)->getExtType(0) &&
22632390 N->getName().empty()) {
22642391 N = N->getChild(0);
23492476
23502477 bool HasUnresolvedTypes = false;
23512478 for (const TreePatternNode *Tree : Trees)
2352 HasUnresolvedTypes |= Tree->ContainsUnresolvedType();
2479 HasUnresolvedTypes |= Tree->ContainsUnresolvedType(*this);
23532480 return !HasUnresolvedTypes;
23542481 }
23552482
23822509 //
23832510
23842511 CodeGenDAGPatterns::CodeGenDAGPatterns(RecordKeeper &R) :
2385 Records(R), Target(R) {
2512 Records(R), Target(R), LegalVTS(Target.getLegalValueTypes()) {
23862513
23872514 Intrinsics = CodeGenIntrinsicTable(Records, false);
23882515 TgtIntrinsics = CodeGenIntrinsicTable(Records, true);
23952522 ParsePatternFragments(/*OutFrags*/true);
23962523 ParsePatterns();
23972524
2525 // Break patterns with parameterized types into a series of patterns,
2526 // where each one has a fixed type and is predicated on the conditions
2527 // of the associated HW mode.
2528 ExpandHwModeBasedTypes();
2529
23982530 // Generate variants. For example, commutative patterns can match
23992531 // multiple ways. Add them to PatternsToMatch as well.
24002532 GenerateVariants();
24192551 // Parse all of the SDNode definitions for the target, populating SDNodes.
24202552 void CodeGenDAGPatterns::ParseNodeInfo() {
24212553 std::vector Nodes = Records.getAllDerivedDefinitions("SDNode");
2554 const CodeGenHwModes &CGH = getTargetInfo().getHwModes();
2555
24222556 while (!Nodes.empty()) {
2423 SDNodes.insert(std::make_pair(Nodes.back(), Nodes.back()));
2557 Record *R = Nodes.back();
2558 SDNodes.insert(std::make_pair(R, SDNodeInfo(R, CGH)));
24242559 Nodes.pop_back();
24252560 }
24262561
25742709 while (TPN->ApplyTypeConstraints(P, false))
25752710 /* Resolve all types */;
25762711
2577 if (TPN->ContainsUnresolvedType()) {
2712 if (TPN->ContainsUnresolvedType(P)) {
25782713 PrintFatalError("Value #" + Twine(i) + " of OperandWithDefaultOps '" +
25792714 DefaultOps[i]->getName() +
25802715 "' doesn't have a concrete type!");
29733108 for (unsigned k = 0, ke = Pat->getNumTypes(); k != ke; ++k) {
29743109 if (k > 0)
29753110 Types += ", ";
2976 Types += Pat->getExtType(k).getName();
3111 Types += Pat->getExtType(k).getAsString();
29773112 }
29783113 I->error("Top-level forms in instruction pattern should have"
29793114 " void types, has types " + Types);
31713306 }
31723307
31733308 Record *Instr = Entry.first;
3174 AddPatternToMatch(I,
3175 PatternToMatch(Instr,
3176 Instr->getValueAsListInit("Predicates"),
3177 SrcPattern,
3178 TheInst.getResultPattern(),
3179 TheInst.getImpResults(),
3180 Instr->getValueAsInt("AddedComplexity"),
3181 Instr->getID()));
3309 ListInit *Preds = Instr->getValueAsListInit("Predicates");
3310 int Complexity = Instr->getValueAsInt("AddedComplexity");
3311 AddPatternToMatch(
3312 I,
3313 PatternToMatch(Instr, makePredList(Preds), SrcPattern,
3314 TheInst.getResultPattern(), TheInst.getImpResults(),
3315 Complexity, Instr->getID()));
31823316 }
31833317 }
31843318
32023336 for (unsigned i = 0, e = P->getNumChildren(); i != e; ++i)
32033337 FindNames(P->getChild(i), Names, PatternTop);
32043338 }
3339 }
3340
3341 std::vector CodeGenDAGPatterns::makePredList(ListInit *L) {
3342 std::vector Preds;
3343 for (Init *I : L->getValues()) {
3344 if (DefInit *Pred = dyn_cast(I))
3345 Preds.push_back(Pred->getDef());
3346 else
3347 llvm_unreachable("Non-def on the list");
3348 }
3349
3350 // Sort so that different orders get canonicalized to the same string.
3351 std::sort(Preds.begin(), Preds.end());
3352 return Preds;
32053353 }
32063354
32073355 void CodeGenDAGPatterns::AddPatternToMatch(TreePattern *Pattern,
34083556
34093557 // If this type is already concrete or completely unknown we can't do
34103558 // anything.
3559 TypeInfer &TI = TP.getInfer();
34113560 for (unsigned i = 0, e = N->getNumTypes(); i != e; ++i) {
3412 if (N->getExtType(i).isCompletelyUnknown() || N->getExtType(i).isConcrete())
3561 if (N->getExtType(i).empty() || TI.isConcrete(N->getExtType(i), false))
34133562 continue;
34143563
3415 // Otherwise, force its type to the first possibility (an arbitrary choice).
3416 if (N->getExtType(i).MergeInTypeInfo(N->getExtType(i).getTypeList()[0], TP))
3564 // Otherwise, force its type to an arbitrary choice.
3565 if (TI.forceArbitrary(N->getExtType(i)))
34173566 return true;
34183567 }
34193568
35343683 TreePattern Temp(Result.getRecord(), DstPattern, false, *this);
35353684 Temp.InferAllTypes();
35363685
3537 AddPatternToMatch(
3538 Pattern,
3539 PatternToMatch(
3540 CurPattern, CurPattern->getValueAsListInit("Predicates"),
3541 Pattern->getTree(0), Temp.getOnlyTree(), std::move(InstImpResults),
3542 CurPattern->getValueAsInt("AddedComplexity"), CurPattern->getID()));
3543 }
3544 }
3686 // A pattern may end up with an "impossible" type, i.e. a situation
3687 // where all types have been eliminated for some node in this pattern.
3688 // This could occur for intrinsics that only make sense for a specific
3689 // value type, and use a specific register class. If, for some mode,
3690 // that register class does not accept that type, the type inference
3691 // will lead to a contradiction, which is not an error however, but
3692 // a sign that this pattern will simply never match.
3693 if (Pattern->getTree(0)->hasPossibleType() &&
3694 Temp.getOnlyTree()->hasPossibleType()) {
3695 ListInit *Preds = CurPattern->getValueAsListInit("Predicates");
3696 int Complexity = CurPattern->getValueAsInt("AddedComplexity");
3697 AddPatternToMatch(
3698 Pattern,
3699 PatternToMatch(
3700 CurPattern, makePredList(Preds), Pattern->getTree(0),
3701 Temp.getOnlyTree(), std::move(InstImpResults), Complexity,
3702 CurPattern->getID()));
3703 }
3704 }
3705 }
3706
3707 static void collectModes(std::set &Modes, const TreePatternNode *N) {
3708 for (const TypeSetByHwMode &VTS : N->getExtTypes())
3709 for (const auto &I : VTS)
3710 Modes.insert(I.first);
3711
3712 for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i)
3713 collectModes(Modes, N->getChild(i));
3714 }
3715
3716 void CodeGenDAGPatterns::ExpandHwModeBasedTypes() {
3717 const CodeGenHwModes &CGH = getTargetInfo().getHwModes();
3718 std::map> ModeChecks;
3719 std::vector Copy = PatternsToMatch;
3720 PatternsToMatch.clear();
3721
3722 auto AppendPattern = [this,&ModeChecks](PatternToMatch &P, unsigned Mode) {
3723 TreePatternNode *NewSrc = P.SrcPattern->clone();
3724 TreePatternNode *NewDst = P.DstPattern->clone();
3725 if (!NewSrc->setDefaultMode(Mode) || !NewDst->setDefaultMode(Mode)) {
3726 delete NewSrc;
3727 delete NewDst;
3728 return;
3729 }
3730
3731 std::vector Preds = P.Predicates;
3732 const std::vector &MC = ModeChecks[Mode];
3733 Preds.insert(Preds.end(), MC.begin(), MC.end());
3734 PatternsToMatch.emplace_back(P.getSrcRecord(), Preds, NewSrc, NewDst,
3735 P.getDstRegs(), P.getAddedComplexity(),
3736 Record::getNewUID(), Mode);
3737 };
3738
3739 for (PatternToMatch &P : Copy) {
3740 TreePatternNode *SrcP = nullptr, *DstP = nullptr;
3741 if (P.SrcPattern->hasProperTypeByHwMode())
3742 SrcP = P.SrcPattern;
3743 if (P.DstPattern->hasProperTypeByHwMode())
3744 DstP = P.DstPattern;
3745 if (!SrcP && !DstP) {
3746 PatternsToMatch.push_back(P);
3747 continue;
3748 }
3749
3750 std::set Modes;
3751 if (SrcP)
3752 collectModes(Modes, SrcP);
3753 if (DstP)
3754 collectModes(Modes, DstP);
3755
3756 // The predicate for the default mode needs to be constructed for each
3757 // pattern separately.
3758 // Since not all modes must be present in each pattern, if a mode m is
3759 // absent, then there is no point in constructing a check for m. If such
3760 // a check was created, it would be equivalent to checking the default
3761 // mode, except not all modes' predicates would be a part of the checking
3762 // code. The subsequently generated check for the default mode would then
3763 // have the exact same patterns, but a different predicate code. To avoid
3764 // duplicated patterns with different predicate checks, construct the
3765 // default check as a negation of all predicates that are actually present
3766 // in the source/destination patterns.
3767 std::vector DefaultPred;
3768
3769 for (unsigned M : Modes) {
3770 if (M == DefaultMode)
3771 continue;
3772 if (ModeChecks.find(M) != ModeChecks.end())
3773 continue;
3774
3775 // Fill the map entry for this mode.
3776 const HwMode &HM = CGH.getMode(M);
3777 ModeChecks[M].emplace_back(Predicate(HM.Features, true));
3778
3779 // Add negations of the HM's predicates to the default predicate.
3780 DefaultPred.emplace_back(Predicate(HM.Features, false));
3781 }
3782
3783 for (unsigned M : Modes) {
3784 if (M == DefaultMode)
3785 continue;
3786 AppendPattern(P, M);
3787 }
3788
3789 bool HasDefault = Modes.count(DefaultMode);
3790 if (HasDefault)
3791 AppendPattern(P, DefaultMode);
3792 }
3793 }
3794
3795 /// Dependent variable map for CodeGenDAGPattern variant generation
3796 typedef std::map DepVarMap;
3797
3798 static void FindDepVarsOf(TreePatternNode *N, DepVarMap &DepMap) {
3799 if (N->isLeaf()) {
3800 if (isa(N->getLeafValue()))
3801 DepMap[N->getName()]++;
3802 } else {
3803 for (size_t i = 0, e = N->getNumChildren(); i != e; ++i)
3804 FindDepVarsOf(N->getChild(i), DepMap);
3805 }
3806 }
3807
3808 /// Find dependent variables within child patterns
3809 static void FindDepVars(TreePatternNode *N, MultipleUseVarSet &DepVars) {
3810 DepVarMap depcounts;
3811 FindDepVarsOf(N, depcounts);
3812 for (const std::pair &Pair : depcounts) {
3813 if (Pair.second > 1)
3814 DepVars.insert(Pair.first);
3815 }
3816 }
3817
3818 #ifndef NDEBUG
3819 /// Dump the dependent variable set:
3820 static void DumpDepVars(MultipleUseVarSet &DepVars) {
3821 if (DepVars.empty()) {
3822 DEBUG(errs() << "");
3823 } else {
3824 DEBUG(errs() << "[ ");
3825 for (const std::string &DepVar : DepVars) {
3826 DEBUG(errs() << DepVar << " ");
3827 }
3828 DEBUG(errs() << "]");
3829 }
3830 }
3831 #endif
3832
35453833
35463834 /// CombineChildVariants - Given a bunch of permutations of each child of the
35473835 /// 'operator' node, put them together in all possible ways.
1414 #ifndef LLVM_UTILS_TABLEGEN_CODEGENDAGPATTERNS_H
1515 #define LLVM_UTILS_TABLEGEN_CODEGENDAGPATTERNS_H
1616
17 #include "CodeGenHwModes.h"
1718 #include "CodeGenIntrinsics.h"
1819 #include "CodeGenTarget.h"
1920 #include "llvm/ADT/SmallVector.h"
3536 class CodeGenDAGPatterns;
3637 class ComplexPattern;
3738
38 /// EEVT::DAGISelGenValueType - These are some extended forms of
39 /// MVT::SimpleValueType that we use as lattice values during type inference.
40 /// The existing MVT iAny, fAny and vAny types suffice to represent
41 /// arbitrary integer, floating-point, and vector types, so only an unknown
42 /// value is needed.
43 namespace EEVT {
44 /// TypeSet - This is either empty if it's completely unknown, or holds a set
45 /// of types. It is used during type inference because register classes can
46 /// have multiple possible types and we don't know which one they get until
47 /// type inference is complete.
48 ///
49 /// TypeSet can have three states:
50 /// Vector is empty: The type is completely unknown, it can be any valid
51 /// target type.
52 /// Vector has multiple constrained types: (e.g. v4i32 + v4f32) it is one
53 /// of those types only.
54 /// Vector has one concrete type: The type is completely known.
55 ///
56 class TypeSet {
57 SmallVector TypeVec;
58 public:
59 TypeSet() {}
60 TypeSet(MVT::SimpleValueType VT, TreePattern &TP);
61 TypeSet(ArrayRef VTList);
62
63 bool isCompletelyUnknown() const { return TypeVec.empty(); }
64
65 bool isConcrete() const {
66 if (TypeVec.size() != 1) return false;
67 unsigned char T = TypeVec[0]; (void)T;
68 assert(T < MVT::LAST_VALUETYPE || T == MVT::iPTR || T == MVT::iPTRAny);
69 return true;
70 }
71
72 MVT::SimpleValueType getConcrete() const {
73 assert(isConcrete() && "Type isn't concrete yet");
74 return (MVT::SimpleValueType)TypeVec[0];
75 }
76
77 bool isDynamicallyResolved() const {
78 return getConcrete() == MVT::iPTR || getConcrete() == MVT::iPTRAny;
79 }
80
81 const SmallVectorImpl &getTypeList() const {
82 assert(!TypeVec.empty() && "Not a type list!");
83 return TypeVec;
84 }
85
86 bool isVoid() const {
87 return TypeVec.size() == 1 && TypeVec[0] == MVT::isVoid;
88 }
89
90 /// hasIntegerTypes - Return true if this TypeSet contains any integer value
91 /// types.
92 bool hasIntegerTypes() const;
93
94 /// hasFloatingPointTypes - Return true if this TypeSet contains an fAny or
95 /// a floating point value type.
96 bool hasFloatingPointTypes() const;
97
98 /// hasScalarTypes - Return true if this TypeSet contains a scalar value
99 /// type.
100 bool hasScalarTypes() const;
101
102 /// hasVectorTypes - Return true if this TypeSet contains a vector value
103 /// type.
104 bool hasVectorTypes() const;
105
106 /// getName() - Return this TypeSet as a string.
107 std::string getName() const;
108
109 /// MergeInTypeInfo - This merges in type information from the specified
110 /// argument. If 'this' changes, it returns true. If the two types are
111 /// contradictory (e.g. merge f32 into i32) then this flags an error.
112 bool MergeInTypeInfo(const EEVT::TypeSet &InVT, TreePattern &TP);
113
114 bool MergeInTypeInfo(MVT::SimpleValueType InVT, TreePattern &TP) {
115 return MergeInTypeInfo(EEVT::TypeSet(InVT, TP), TP);
116 }
117
118 /// Force this type list to only contain integer types.
119 bool EnforceInteger(TreePattern &TP);
120
121 /// Force this type list to only contain floating point types.
122 bool EnforceFloatingPoint(TreePattern &TP);
123
124 /// EnforceScalar - Remove all vector types from this type list.
125 bool EnforceScalar(TreePattern &TP);
126
127 /// EnforceVector - Remove all non-vector types from this type list.
128 bool EnforceVector(TreePattern &TP);
129
130 /// EnforceSmallerThan - 'this' must be a smaller VT than Other. Update
131 /// this an other based on this information.
132 bool EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP);
133
134 /// EnforceVectorEltTypeIs - 'this' is now constrained to be a vector type
135 /// whose element is VT.
136 bool EnforceVectorEltTypeIs(EEVT::TypeSet &VT, TreePattern &TP);
137
138 /// EnforceVectorEltTypeIs - 'this' is now constrained to be a vector type
139 /// whose element is VT.
140 bool EnforceVectorEltTypeIs(MVT::SimpleValueType VT, TreePattern &TP);
141
142 /// EnforceVectorSubVectorTypeIs - 'this' is now constrained to
143 /// be a vector type VT.
144 bool EnforceVectorSubVectorTypeIs(EEVT::TypeSet &VT, TreePattern &TP);
145
146 /// EnforceSameNumElts - If VTOperand is a scalar, then 'this' is a scalar.
147 /// If VTOperand is a vector, then 'this' must have the same number of
148 /// elements.
149 bool EnforceSameNumElts(EEVT::TypeSet &VT, TreePattern &TP);
150
151 /// EnforceSameSize - 'this' is now constrained to be the same size as VT.
152 bool EnforceSameSize(EEVT::TypeSet &VT, TreePattern &TP);
153
154 bool operator!=(const TypeSet &RHS) const { return TypeVec != RHS.TypeVec; }
155 bool operator==(const TypeSet &RHS) const { return TypeVec == RHS.TypeVec; }
156
157 private:
158 /// FillWithPossibleTypes - Set to all legal types and return true, only
159 /// valid on completely unknown type sets. If Pred is non-null, only MVTs
160 /// that pass the predicate are added.
161 bool FillWithPossibleTypes(TreePattern &TP,
162 bool (*Pred)(MVT::SimpleValueType) = nullptr,
163 const char *PredicateName = nullptr);
39 struct TypeSetByHwMode : public InfoByHwMode> {
40 typedef std::set SetType;
41
42 TypeSetByHwMode() = default;
43 TypeSetByHwMode(const TypeSetByHwMode &VTS) = default;
44 TypeSetByHwMode(MVT::SimpleValueType VT)
45 : TypeSetByHwMode(ValueTypeByHwMode(VT)) {}
46 TypeSetByHwMode(ValueTypeByHwMode VT)
47 : TypeSetByHwMode(ArrayRef(&VT, 1)) {}
48 TypeSetByHwMode(ArrayRef VTList);
49
50 SetType &getOrCreate(unsigned Mode) {
51 if (hasMode(Mode))
52 return get(Mode);
53 return Map.insert({Mode,SetType()}).first->second;
54 }
55
56 bool isValueTypeByHwMode(bool AllowEmpty) const;
57 ValueTypeByHwMode getValueTypeByHwMode() const;
58 bool isMachineValueType() const {
59 return isDefaultOnly() && Map.begin()->second.size() == 1;
60 }
61
62 MVT getMachineValueType() const {
63 assert(isMachineValueType());
64 return *Map.begin()->second.begin();
65 }
66
67 bool isPossible() const;
68 bool isDefaultOnly() const {
69 return Map.size() == 1 &&
70 Map.begin()->first == DefaultMode;
71 }
72
73 bool insert(const ValueTypeByHwMode &VVT);
74 bool constrain(const TypeSetByHwMode &VTS);
75 template bool constrain(Predicate P);
76 template bool assign_if(const TypeSetByHwMode &VTS,
77 Predicate P);
78
79 std::string getAsString() const;
80 static std::string getAsString(const SetType &S);
81
82 bool operator==(const TypeSetByHwMode &VTS) const;
83 bool operator!=(const TypeSetByHwMode &VTS) const { return !(*this == VTS); }
84
85 void dump() const;
86 void validate() const;
87
88 private:
89 /// Intersect two sets. Return true if anything has changed.
90 bool intersect(SetType &Out, const SetType &In);
91 };
92
93 struct TypeInfer {
94 TypeInfer(TreePattern &T) : TP(T), ForceMode(0) {}
95
96 bool isConcrete(const TypeSetByHwMode &VTS, bool AllowEmpty) const {
97 return VTS.isValueTypeByHwMode(AllowEmpty);
98 }
99 ValueTypeByHwMode getConcrete(const TypeSetByHwMode &VTS,
100 bool AllowEmpty) const {
101 assert(VTS.isValueTypeByHwMode(AllowEmpty));
102 return VTS.getValueTypeByHwMode();
103 }
104
105 /// The protocol in the following functions (Merge*, force*, Enforce*,
106 /// expand*) is to return "true" if a change has been made, "false"
107 /// otherwise.
108
109 bool MergeInTypeInfo(TypeSetByHwMode &Out, const TypeSetByHwMode &In);
110 bool MergeInTypeInfo(TypeSetByHwMode &Out, MVT::SimpleValueType InVT) {
111 return MergeInTypeInfo(Out, TypeSetByHwMode(InVT));
112 }
113 bool MergeInTypeInfo(TypeSetByHwMode &Out, ValueTypeByHwMode InVT) {
114 return MergeInTypeInfo(Out, TypeSetByHwMode(InVT));
115 }
116
117 /// Reduce the set \p Out to have at most one element for each mode.
118 bool forceArbitrary(TypeSetByHwMode &Out);
119
120 /// The following four functions ensure that upon return the set \p Out
121 /// will only contain types of the specified kind: integer, floating-point,
122 /// scalar, or vector.
123 /// If \p Out is empty, all legal types of the specified kind will be added
124 /// to it. Otherwise, all types that are not of the specified kind will be
125 /// removed from \p Out.
126 bool EnforceInteger(TypeSetByHwMode &Out);
127 bool EnforceFloatingPoint(TypeSetByHwMode &Out);
128 bool EnforceScalar(TypeSetByHwMode &Out);
129 bool EnforceVector(TypeSetByHwMode &Out);
130
131 /// If \p Out is empty, fill it with all legal types. Otherwise, leave it
132 /// unchanged.
133 bool EnforceAny(TypeSetByHwMode &Out);
134 /// Make sure that for each type in \p Small, there exists a larger type
135 /// in \p Big.
136 bool EnforceSmallerThan(TypeSetByHwMode &Small, TypeSetByHwMode &Big);
137 /// 1. Ensure that for each type T in \p Vec, T is a vector type, and that
138 /// for each type U in \p Elem, U is a scalar type.
139 /// 2. Ensure that for each (scalar) type U in \p Elem, there exists a
140 /// (vector) type T in \p Vec, such that U is the element type of T.
141 bool EnforceVectorEltTypeIs(TypeSetByHwMode &Vec, TypeSetByHwMode &Elem);
142 bool EnforceVectorEltTypeIs(TypeSetByHwMode &Vec,
143 const ValueTypeByHwMode &VVT);
144 /// Ensure that for each type T in \p Sub, T is a vector type, and there
145 /// exists a type U in \p Vec such that U is a vector type with the same
146 /// element type as T and at least as many elements as T.
147 bool EnforceVectorSubVectorTypeIs(TypeSetByHwMode &Vec,
148 TypeSetByHwMode &Sub);
149 /// 1. Ensure that \p V has a scalar type iff \p W has a scalar type.
150 /// 2. Ensure that for each vector type T in \p V, there exists a vector
151 /// type U in \p W, such that T and U have the same number of elements.
152 /// 3. Ensure that for each vector type U in \p W, there exists a vector
153 /// type T in \p V, such that T and U have the same number of elements
154 /// (reverse of 2).
155 bool EnforceSameNumElts(TypeSetByHwMode &V, TypeSetByHwMode &W);
156 /// 1. Ensure that for each type T in \p A, there exists a type U in \p B,
157 /// such that T and U have equal size in bits.
158 /// 2. Ensure that for each type U in \p B, there exists a type T in \p A
159 /// such that T and U have equal size in bits (reverse of 1).
160 bool EnforceSameSize(TypeSetByHwMode &A, TypeSetByHwMode &B);
161
162 /// For each overloaded type (i.e. of form *Any), replace it with the
163 /// corresponding subset of legal, specific types.
164 void expandOverloads(TypeSetByHwMode &VTS);
165 void expandOverloads(TypeSetByHwMode::SetType &Out,
166 const TypeSetByHwMode::SetType &Legal);
167
168 struct ValidateOnExit {
169 ValidateOnExit(TypeSetByHwMode &T) : VTS(T) {}
170 ~ValidateOnExit() { VTS.validate(); }
171 TypeSetByHwMode &VTS;
164172 };
165 }
173
174 TreePattern &TP;
175 unsigned ForceMode; // Mode to use when set.
176 bool CodeGen = false; // Set during generation of matcher code.
177
178 private:
179 TypeSetByHwMode getLegalTypes();
180 };
166181
167182 /// Set type used to track multiply used variables in patterns
168183 typedef std::set MultipleUseVarSet;
170185 /// SDTypeConstraint - This is a discriminated union of constraints,
171186 /// corresponding to the SDTypeConstraint tablegen class in Target.td.
172187 struct SDTypeConstraint {
173 SDTypeConstraint(Record *R);
188 SDTypeConstraint(Record *R, const CodeGenHwModes &CGH);
174189
175190 unsigned OperandNo; // The operand # this constraint applies to.
176191 enum {
180195 } ConstraintType;
181196
182197 union { // The discriminated union.
183 struct {
184 MVT::SimpleValueType VT;
185 } SDTCisVT_Info;
186198 struct {
187199 unsigned OtherOperandNum;
188200 } SDTCisSameAs_Info;
199211 unsigned OtherOperandNum;
200212 } SDTCisSubVecOfVec_Info;
201213 struct {
202 MVT::SimpleValueType VT;
203 } SDTCVecEltisVT_Info;
204 struct {
205214 unsigned OtherOperandNum;
206215 } SDTCisSameNumEltsAs_Info;
207216 struct {
208217 unsigned OtherOperandNum;
209218 } SDTCisSameSizeAs_Info;
210219 } x;
220
221 // The VT for SDTCisVT and SDTCVecEltisVT.
222 // Must not be in the union because it has a non-trivial destructor.
223 ValueTypeByHwMode VVT;
211224
212225 /// ApplyTypeConstraint - Given a node in a pattern, apply this type
213226 /// constraint to the nodes operands. This returns true if it makes a
229242 int NumOperands;
230243 std::vector TypeConstraints;
231244 public:
232 SDNodeInfo(Record *R); // Parse the specified record.
245 // Parse the specified record.
246 SDNodeInfo(Record *R, const CodeGenHwModes &CGH);
233247
234248 unsigned getNumResults() const { return NumResults; }
235249
257271 /// constraints for this node to the operands of the node. This returns
258272 /// true if it makes a change, false otherwise. If a type contradiction is
259273 /// found, an error is flagged.
260 bool ApplyTypeConstraints(TreePatternNode *N, TreePattern &TP) const {
261 bool MadeChange = false;
262 for (unsigned i = 0, e = TypeConstraints.size(); i != e; ++i)
263 MadeChange |= TypeConstraints[i].ApplyTypeConstraint(N, *this, TP);
264 return MadeChange;
265 }
274 bool ApplyTypeConstraints(TreePatternNode *N, TreePattern &TP) const;
266275 };
267276
268277 /// TreePredicateFn - This is an abstraction that represents the predicates on
323332 /// The type of each node result. Before and during type inference, each
324333 /// result may be a set of possible types. After (successful) type inference,
325334 /// each is a single concrete type.
326 SmallVector> Types;
335 std::vector> Types;
327336
328337 /// Operator - The Record for the operator if this is an interior node (not
329338 /// a leaf).
366375
367376 // Type accessors.
368377 unsigned getNumTypes() const { return Types.size(); }
369 MVT::SimpleValueType getType(unsigned ResNo) const {
370 return Types[ResNo].getConcrete();
371 }
372 const SmallVectorImpl &getExtTypes() const { return Types; }
373 const EEVT::TypeSet &getExtType(unsigned ResNo) const { return Types[ResNo]; }
374 EEVT::TypeSet &getExtType(unsigned ResNo) { return Types[ResNo]; }
375 void setType(unsigned ResNo, const EEVT::TypeSet &T) { Types[ResNo] = T; }
376
377 bool hasTypeSet(unsigned ResNo) const {
378 return Types[ResNo].isConcrete();
379 }
380 bool isTypeCompletelyUnknown(unsigned ResNo) const {
381 return Types[ResNo].isCompletelyUnknown();
382 }
383 bool isTypeDynamicallyResolved(unsigned ResNo) const {
384 return Types[ResNo].isDynamicallyResolved();
378 ValueTypeByHwMode getType(unsigned ResNo) const {
379 return Types[ResNo].getValueTypeByHwMode();
380 }
381 const std::vector &getExtTypes() const { return Types; }
382 const TypeSetByHwMode &getExtType(unsigned ResNo) const {
383 return Types[ResNo];
384 }
385 TypeSetByHwMode &getExtType(unsigned ResNo) { return Types[ResNo]; }
386 void setType(unsigned ResNo, const TypeSetByHwMode &T) { Types[ResNo] = T; }
387 MVT::SimpleValueType getSimpleType(unsigned ResNo) const {
388 return Types[ResNo].getMachineValueType().SimpleTy;
389 }
390
391 bool hasConcreteType(unsigned ResNo) const {
392 return Types[ResNo].isValueTypeByHwMode(false);
393 }
394 bool isTypeCompletelyUnknown(unsigned ResNo, TreePattern &TP) const {
395 return Types[ResNo].empty();
385396 }
386397
387398 Init *getLeafValue() const { assert(isLeaf()); return Val; }
399410 if (Children[i] == N) return true;
400411 return false;
401412 }
413
414 bool hasProperTypeByHwMode() const;
415 bool hasPossibleType() const;
416 bool setDefaultMode(unsigned Mode);
402417
403418 bool hasAnyPredicate() const { return !PredicateFns.empty(); }
404419
483498 /// information. If N already contains a conflicting type, then flag an
484499 /// error. This returns true if any information was updated.
485500 ///
486 bool UpdateNodeType(unsigned ResNo, const EEVT::TypeSet &InTy,
487 TreePattern &TP) {
488 return Types[ResNo].MergeInTypeInfo(InTy, TP);
489 }
490
501 bool UpdateNodeType(unsigned ResNo, const TypeSetByHwMode &InTy,
502 TreePattern &TP);
491503 bool UpdateNodeType(unsigned ResNo, MVT::SimpleValueType InTy,
492 TreePattern &TP) {
493 return Types[ResNo].MergeInTypeInfo(EEVT::TypeSet(InTy, TP), TP);
494 }
504 TreePattern &TP);
505 bool UpdateNodeType(unsigned ResNo, ValueTypeByHwMode InTy,
506 TreePattern &TP);
495507
496508 // Update node type with types inferred from an instruction operand or result
497509 // def from the ins/outs lists.
500512
501513 /// ContainsUnresolvedType - Return true if this tree contains any
502514 /// unresolved types.
503 bool ContainsUnresolvedType() const {
504 for (unsigned i = 0, e = Types.size(); i != e; ++i)
505 if (!Types[i].isConcrete()) return true;
506
507 for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
508 if (getChild(i)->ContainsUnresolvedType()) return true;
509 return false;
510 }
515 bool ContainsUnresolvedType(TreePattern &TP) const;
511516
512517 /// canPatternMatch - If it is impossible for this pattern to match on this
513518 /// target, fill in Reason and return false. Otherwise, return true.
559564 /// number for each operand encountered in a ComplexPattern to aid in that
560565 /// check.
561566 StringMap> ComplexPatternOperands;
567
568 TypeInfer Infer;
569
562570 public:
563571
564572 /// TreePattern constructor - Parse the specified DagInits into the
624632 HasError = false;
625633 }
626634
635 TypeInfer &getInfer() { return Infer; }
636
627637 void print(raw_ostream &OS) const;
628638 void dump() const;
629639
632642 void ComputeNamedNodes();
633643 void ComputeNamedNodes(TreePatternNode *N);
634644 };
645
646
647 inline bool TreePatternNode::UpdateNodeType(unsigned ResNo,
648 const TypeSetByHwMode &InTy,
649 TreePattern &TP) {
650 TypeSetByHwMode VTS(InTy);
651 TP.getInfer().expandOverloads(VTS);
652 return TP.getInfer().MergeInTypeInfo(Types[ResNo], VTS);
653 }
654
655 inline bool TreePatternNode::UpdateNodeType(unsigned ResNo,
656 MVT::SimpleValueType InTy,
657 TreePattern &TP) {
658 TypeSetByHwMode VTS(InTy);
659 TP.getInfer().expandOverloads(VTS);
660 return TP.getInfer().MergeInTypeInfo(Types[ResNo], VTS);
661 }
662
663 inline bool TreePatternNode::UpdateNodeType(unsigned ResNo,
664 ValueTypeByHwMode InTy,
665 TreePattern &TP) {
666 TypeSetByHwMode VTS(InTy);
667 TP.getInfer().expandOverloads(VTS);
668 return TP.getInfer().MergeInTypeInfo(Types[ResNo], VTS);
669 }
670
635671
636672 /// DAGDefaultOperand - One of these is created for each OperandWithDefaultOps
637673 /// that has a set ExecuteAlways / DefaultOps field.
679715 TreePatternNode *getResultPattern() const { return ResultPattern; }
680716 };
681717
718 /// This class represents a condition that has to be satisfied for a pattern
719 /// to be tried. It is a generalization of a class "Pattern" from Target.td:
720 /// in addition to the Target.td's predicates, this class can also represent
721 /// conditions associated with HW modes. Both types will eventually become
722 /// strings containing C++ code to be executed, the difference is in how
723 /// these strings are generated.
724 class Predicate {
725 public:
726 Predicate(Record *R, bool C = true) : Def(R), IfCond(C), IsHwMode(false) {
727 assert(R->isSubClassOf("Predicate") &&
728 "Predicate objects should only be created for records derived"
729 "from Predicate class");
730 }
731 Predicate(StringRef FS, bool C = true) : Def(nullptr), Features(FS.str()),
732 IfCond(C), IsHwMode(true) {}
733
734 /// Return a string which contains the C++ condition code that will serve
735 /// as a predicate during instruction selection.
736 std::string getCondString() const {
737 // The string will excute in a subclass of SelectionDAGISel.
738 // Cast to std::string explicitly to avoid ambiguity with StringRef.
739 std::string C = IsHwMode
740 ? std::string("MF->getSubtarget().checkFeatures(\"" + Features + "\")")
741 : std::string(Def->getValueAsString("CondString"));
742 return IfCond ? C : "!("+C+')';
743 }
744 bool operator==(const Predicate &P) const {
745 return IfCond == P.IfCond && IsHwMode == P.IsHwMode && Def == P.Def;
746 }
747 bool operator<(const Predicate &P) const {
748 if (IsHwMode != P.IsHwMode)
749 return IsHwMode < P.IsHwMode;
750 assert(!Def == !P.Def && "Inconsistency between Def and IsHwMode");
751 if (IfCond != P.IfCond)
752 return IfCond < P.IfCond;
753 if (Def)
754 return LessRecord()(Def, P.Def);
755 return Features < P.Features;
756 }
757 Record *Def; ///< Predicate definition from .td file, null for
758 ///< HW modes.
759 std::string Features; ///< Feature string for HW mode.
760 bool IfCond; ///< The boolean value that the condition has to
761 ///< evaluate to for this predicate to be true.
762 bool IsHwMode; ///< Does this predicate correspond to a HW mode?
763 };
764
682765 /// PatternToMatch - Used by CodeGenDAGPatterns to keep tab of patterns
683766 /// processed to produce isel.
684767 class PatternToMatch {
685768 public:
686 PatternToMatch(Record *srcrecord, ListInit *preds, TreePatternNode *src,
687 TreePatternNode *dst, std::vector dstregs,
688 int complexity, unsigned uid)
689 : SrcRecord(srcrecord), Predicates(preds), SrcPattern(src),
690 DstPattern(dst), Dstregs(std::move(dstregs)),
691 AddedComplexity(complexity), ID(uid) {}
769 PatternToMatch(Record *srcrecord, const std::vector &preds,
770 TreePatternNode *src, TreePatternNode *dst,
771 const std::vector &dstregs,
772 int complexity, unsigned uid, unsigned setmode = 0)
773 : SrcRecord(srcrecord), SrcPattern(src), DstPattern(dst),
774 Predicates(preds), Dstregs(std::move(dstregs)),
775 AddedComplexity(complexity), ID(uid), ForceMode(setmode) {}
776
777 PatternToMatch(Record *srcrecord, std::vector &&preds,
778 TreePatternNode *src, TreePatternNode *dst,
779 std::vector &&dstregs,
780 int complexity, unsigned uid, unsigned setmode = 0)
781 : SrcRecord(srcrecord), SrcPattern(src), DstPattern(dst),
782 Predicates(preds), Dstregs(std::move(dstregs)),
783 AddedComplexity(complexity), ID(uid), ForceMode(setmode) {}
692784
693785 Record *SrcRecord; // Originating Record for the pattern.
694 ListInit *Predicates; // Top level predicate conditions to match.
695786 TreePatternNode *SrcPattern; // Source pattern to match.
696787 TreePatternNode *DstPattern; // Resulting pattern.
788 std::vector Predicates; // Top level predicate conditions
789 // to match.
697790 std::vector Dstregs; // Physical register defs being matched.
698791 int AddedComplexity; // Add to matching pattern complexity.
699792 unsigned ID; // Unique ID for the record.
793 unsigned ForceMode; // Force this mode in type inference when set.
700794
701795 Record *getSrcRecord() const { return SrcRecord; }
702 ListInit *getPredicates() const { return Predicates; }
703796 TreePatternNode *getSrcPattern() const { return SrcPattern; }
704797 TreePatternNode *getDstPattern() const { return DstPattern; }
705798 const std::vector &getDstRegs() const { return Dstregs; }
706799 int getAddedComplexity() const { return AddedComplexity; }
800 const std::vector &getPredicates() const { return Predicates; }
707801
708802 std::string getPredicateCheck() const;
709803
735829 /// value is the pattern to match, the second pattern is the result to
736830 /// emit.
737831 std::vector PatternsToMatch;
832
833 TypeSetByHwMode LegalVTS;
834
738835 public:
739836 CodeGenDAGPatterns(RecordKeeper &R);
740837
741838 CodeGenTarget &getTargetInfo() { return Target; }
742839 const CodeGenTarget &getTargetInfo() const { return Target; }
840 const TypeSetByHwMode &getLegalTypes() const { return LegalVTS; }
743841
744842 Record *getSDNodeNamed(const std::string &Name) const;
745843
849947 void ParseDefaultOperands();
850948 void ParseInstructions();
851949 void ParsePatterns();
950 void ExpandHwModeBasedTypes();
852951 void InferInstructionFlags();
853952 void GenerateVariants();
854953 void VerifyInstructionFlags();
954
955 std::vector makePredList(ListInit *L);
855956
856957 void AddPatternToMatch(TreePattern *Pattern, PatternToMatch &&PTM);
857958 void FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat,
861962 TreePatternNode*> &InstResults,
862963 std::vector &InstImpResults);
863964 };
965
966
967 inline bool SDNodeInfo::ApplyTypeConstraints(TreePatternNode *N,
968 TreePattern &TP) const {
969 bool MadeChange = false;
970 for (unsigned i = 0, e = TypeConstraints.size(); i != e; ++i)
971 MadeChange |= TypeConstraints[i].ApplyTypeConstraint(N, *this, TP);
972 return MadeChange;
973 }
864974 } // end namespace llvm
865975
866976 #endif
0 //===--- CodeGenHwModes.cpp -----------------------------------------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 // Classes to parse and store HW mode information for instruction selection
9 //===----------------------------------------------------------------------===//
10
11 #include "CodeGenHwModes.h"
12 #include "llvm/Support/Debug.h"
13 #include "llvm/Support/raw_ostream.h"
14 #include "llvm/TableGen/Error.h"
15 #include "llvm/TableGen/Record.h"
16
17 using namespace llvm;
18
19 StringRef CodeGenHwModes::DefaultModeName = "DefaultMode";
20
21 HwMode::HwMode(Record *R) {
22 Name = R->getName();
23 Features = R->getValueAsString("Features");
24 }
25
26 LLVM_DUMP_METHOD
27 void HwMode::dump() const {
28 dbgs() << Name << ": " << Features << '\n';
29 }
30
31 HwModeSelect::HwModeSelect(Record *R, CodeGenHwModes &CGH) {
32 std::vector Modes = R->getValueAsListOfDefs("Modes");
33 std::vector Objects = R->getValueAsListOfDefs("Objects");
34 if (Modes.size() != Objects.size()) {
35 PrintError(R->getLoc(), "in record " + R->getName() +
36 " derived from HwModeSelect: the lists Modes and Objects should "
37 "have the same size");
38 report_fatal_error("error in target description.");
39 }
40 for (unsigned i = 0, e = Modes.size(); i != e; ++i) {
41 unsigned ModeId = CGH.getHwModeId(Modes[i]->getName());
42 Items.push_back(std::make_pair(ModeId, Objects[i]));
43 }
44 }
45
46 LLVM_DUMP_METHOD
47 void HwModeSelect::dump() const {
48 dbgs() << '{';
49