Index: llvm/trunk/lib/Target/ARM/ARMInstrFormats.td =================================================================== --- llvm/trunk/lib/Target/ARM/ARMInstrFormats.td +++ llvm/trunk/lib/Target/ARM/ARMInstrFormats.td @@ -408,6 +408,8 @@ // mnemonic (when not in an IT block) or preclude it (when in an IT block). bit thumbArithFlagSetting = 0; + bit invalidForTailPredication = 0; + // If this is a pseudo instruction, mark it isCodeGenOnly. let isCodeGenOnly = !eq(!cast(f), "Pseudo"); @@ -419,6 +421,7 @@ let TSFlags{14} = canXformTo16Bit; let TSFlags{18-15} = D.Value; let TSFlags{19} = thumbArithFlagSetting; + let TSFlags{20} = invalidForTailPredication; let Constraints = cstr; let Itinerary = itin; Index: llvm/trunk/lib/Target/ARM/ARMInstrMVE.td =================================================================== --- llvm/trunk/lib/Target/ARM/ARMInstrMVE.td +++ llvm/trunk/lib/Target/ARM/ARMInstrMVE.td @@ -506,6 +506,7 @@ let Inst{5} = Qm{3}; let Inst{3-1} = Qm{2-0}; let Inst{0} = 0b1; + let invalidForTailPredication = 1; } def MVE_VABAVs8 : MVE_VABAV<"s8", 0b0, 0b00>; @@ -532,6 +533,7 @@ let Inst{5} = A; let Inst{3-1} = Qm{2-0}; let Inst{0} = 0b0; + let invalidForTailPredication = 1; } multiclass MVE_VADDV_A size, @@ -582,6 +584,7 @@ let Inst{5} = A; let Inst{3-1} = Qm{2-0}; let Inst{0} = 0b0; + let invalidForTailPredication = 1; } multiclass MVE_VADDLV_A pattern=[]> { @@ -619,6 +622,7 @@ let Inst{0} = 0b0; let Predicates = [HasMVEFloat]; + let invalidForTailPredication = 1; } multiclass MVE_VMINMAXNMV_fty pattern=[]> { @@ -655,6 +659,7 @@ let Inst{6-5} = 0b00; let Inst{3-1} = Qm{2-0}; let Inst{0} = 0b0; + let invalidForTailPredication = 1; } multiclass MVE_VMINMAXV_ty pattern=[]> { @@ -727,6 +732,7 @@ let Inst{5} = A; let Inst{3-1} = Qm{2-0}; let Inst{0} = bit_0; + let invalidForTailPredication = 1; } multiclass MVE_VMLAMLSDAV_A( + static_cast( + T->createTargetMachine(TT, "generic", "", Options, None, None, + CodeGenOpt::Default))); + auto MII = TM->getMCInstrInfo(); + + using namespace ARM; + + auto IsInvalidTPOpcode = [](unsigned Opcode) { + switch (Opcode) { + case MVE_VABAVs8: + case MVE_VABAVs16: + case MVE_VABAVs32: + case MVE_VABAVu8: + case MVE_VABAVu16: + case MVE_VABAVu32: + case MVE_VADDVs8acc: + case MVE_VADDVs16acc: + case MVE_VADDVs32acc: + case MVE_VADDVu8acc: + case MVE_VADDVu16acc: + case MVE_VADDVu32acc: + case MVE_VADDVs8no_acc: + case MVE_VADDVs16no_acc: + case MVE_VADDVs32no_acc: + case MVE_VADDVu8no_acc: + case MVE_VADDVu16no_acc: + case MVE_VADDVu32no_acc: + case MVE_VADDLVs32no_acc: + case MVE_VADDLVu32no_acc: + case MVE_VADDLVs32acc: + case MVE_VADDLVu32acc: + case MVE_VMLADAVas16: + case MVE_VMLADAVas32: + case MVE_VMLADAVas8: + case MVE_VMLADAVau16: + case MVE_VMLADAVau32: + case MVE_VMLADAVau8: + case MVE_VMLADAVaxs16: + case MVE_VMLADAVaxs32: + case MVE_VMLADAVaxs8: + case MVE_VMLADAVs16: + case MVE_VMLADAVs32: + case MVE_VMLADAVs8: + case MVE_VMLADAVu16: + case MVE_VMLADAVu32: + case MVE_VMLADAVu8: + case MVE_VMLADAVxs16: + case MVE_VMLADAVxs32: + case MVE_VMLADAVxs8: + case MVE_VMLALDAVas16: + case MVE_VMLALDAVas32: + case MVE_VMLALDAVau16: + case MVE_VMLALDAVau32: + case MVE_VMLALDAVaxs16: + case MVE_VMLALDAVaxs32: + case MVE_VMLALDAVs16: + case MVE_VMLALDAVs32: + case MVE_VMLALDAVu16: + case MVE_VMLALDAVu32: + case MVE_VMLALDAVxs16: + case MVE_VMLALDAVxs32: + case MVE_VMLSDAVas16: + case MVE_VMLSDAVas32: + case MVE_VMLSDAVas8: + case MVE_VMLSDAVaxs16: + case MVE_VMLSDAVaxs32: + case MVE_VMLSDAVaxs8: + case MVE_VMLSDAVs16: + case MVE_VMLSDAVs32: + case MVE_VMLSDAVs8: + case MVE_VMLSDAVxs16: + case MVE_VMLSDAVxs32: + case MVE_VMLSDAVxs8: + case MVE_VMLSLDAVas16: + case MVE_VMLSLDAVas32: + case MVE_VMLSLDAVaxs16: + case MVE_VMLSLDAVaxs32: + case MVE_VMLSLDAVs16: + case MVE_VMLSLDAVs32: + case MVE_VMLSLDAVxs16: + case MVE_VMLSLDAVxs32: + case MVE_VRMLALDAVHas32: + case MVE_VRMLALDAVHau32: + case MVE_VRMLALDAVHaxs32: + case MVE_VRMLALDAVHs32: + case MVE_VRMLALDAVHu32: + case MVE_VRMLALDAVHxs32: + case MVE_VRMLSLDAVHas32: + case MVE_VRMLSLDAVHaxs32: + case MVE_VRMLSLDAVHs32: + case MVE_VRMLSLDAVHxs32: + case MVE_VMAXNMVf16: + case MVE_VMINNMVf16: + case MVE_VMAXNMVf32: + case MVE_VMINNMVf32: + case MVE_VMAXNMAVf16: + case MVE_VMINNMAVf16: + case MVE_VMAXNMAVf32: + case MVE_VMINNMAVf32: + case MVE_VMAXVs8: + case MVE_VMAXVs16: + case MVE_VMAXVs32: + case MVE_VMAXVu8: + case MVE_VMAXVu16: + case MVE_VMAXVu32: + case MVE_VMINVs8: + case MVE_VMINVs16: + case MVE_VMINVs32: + case MVE_VMINVu8: + case MVE_VMINVu16: + case MVE_VMINVu32: + case MVE_VMAXAVs8: + case MVE_VMAXAVs16: + case MVE_VMAXAVs32: + case MVE_VMINAVs8: + case MVE_VMINAVs16: + case MVE_VMINAVs32: + return true; + default: + return false; + } + }; + + for (unsigned i = 0; i < ARM::INSTRUCTION_LIST_END; ++i) { + uint64_t Flags = MII->get(i).TSFlags; + bool Invalid = (Flags & ARMII::InvalidForTailPredication) != 0; + ASSERT_EQ(IsInvalidTPOpcode(i), Invalid) + << MII->getName(i) + << ": mismatched expectation for tail-predicated safety\n"; + } +}