diff options
author | Sam Parker <sam.parker@arm.com> | 2019-09-17 07:43:04 +0000 |
---|---|---|
committer | Sam Parker <sam.parker@arm.com> | 2019-09-17 07:43:04 +0000 |
commit | 26a475afe5cf9acf8dfe3e6cf8ebf1343ec3b72c (patch) | |
tree | d8f2fae86fa0461c8b15d67ae7ad40560d95f6c2 | |
parent | 30d86f1858dbeaaeb5d5a2a6ba8631f7f839e094 (diff) | |
download | bcm5719-llvm-26a475afe5cf9acf8dfe3e6cf8ebf1343ec3b72c.tar.gz bcm5719-llvm-26a475afe5cf9acf8dfe3e6cf8ebf1343ec3b72c.zip |
[ARM][MVE] Add invalidForTailPredication to TSFlags
Set this bit for the MVE reduction instructions to prevent a loop from
becoming tail predicated in their presence.
Differential Revision: https://reviews.llvm.org/D67444
llvm-svn: 372076
-rw-r--r-- | llvm/lib/Target/ARM/ARMInstrFormats.td | 3 | ||||
-rw-r--r-- | llvm/lib/Target/ARM/ARMInstrMVE.td | 7 | ||||
-rw-r--r-- | llvm/lib/Target/ARM/MCTargetDesc/ARMBaseInfo.h | 4 | ||||
-rw-r--r-- | llvm/unittests/Target/ARM/CMakeLists.txt | 17 | ||||
-rw-r--r-- | llvm/unittests/Target/ARM/MachineInstrTest.cpp | 166 |
5 files changed, 197 insertions, 0 deletions
diff --git a/llvm/lib/Target/ARM/ARMInstrFormats.td b/llvm/lib/Target/ARM/ARMInstrFormats.td index 043b54a7deb..53af05cf5f4 100644 --- a/llvm/lib/Target/ARM/ARMInstrFormats.td +++ b/llvm/lib/Target/ARM/ARMInstrFormats.td @@ -408,6 +408,8 @@ class InstTemplate<AddrMode am, int sz, IndexMode im, // 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<string>(f), "Pseudo"); @@ -419,6 +421,7 @@ class InstTemplate<AddrMode am, int sz, IndexMode im, let TSFlags{14} = canXformTo16Bit; let TSFlags{18-15} = D.Value; let TSFlags{19} = thumbArithFlagSetting; + let TSFlags{20} = invalidForTailPredication; let Constraints = cstr; let Itinerary = itin; diff --git a/llvm/lib/Target/ARM/ARMInstrMVE.td b/llvm/lib/Target/ARM/ARMInstrMVE.td index 9623b4d1d57..fdc162eacca 100644 --- a/llvm/lib/Target/ARM/ARMInstrMVE.td +++ b/llvm/lib/Target/ARM/ARMInstrMVE.td @@ -506,6 +506,7 @@ class MVE_VABAV<string suffix, bit U, bits<2> size, list<dag> pattern=[]> 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 @@ class MVE_VADDV<string iname, string suffix, dag iops, string cstr, let Inst{5} = A; let Inst{3-1} = Qm{2-0}; let Inst{0} = 0b0; + let invalidForTailPredication = 1; } multiclass MVE_VADDV_A<string suffix, bit U, bits<2> size, @@ -582,6 +584,7 @@ class MVE_VADDLV<string iname, string suffix, dag iops, string cstr, let Inst{5} = A; let Inst{3-1} = Qm{2-0}; let Inst{0} = 0b0; + let invalidForTailPredication = 1; } multiclass MVE_VADDLV_A<string suffix, bit U, list<dag> pattern=[]> { @@ -619,6 +622,7 @@ class MVE_VMINMAXNMV<string iname, string suffix, bit sz, let Inst{0} = 0b0; let Predicates = [HasMVEFloat]; + let invalidForTailPredication = 1; } multiclass MVE_VMINMAXNMV_fty<string iname, bit bit_7, list<dag> pattern=[]> { @@ -655,6 +659,7 @@ class MVE_VMINMAXV<string iname, string suffix, bit U, bits<2> size, let Inst{6-5} = 0b00; let Inst{3-1} = Qm{2-0}; let Inst{0} = 0b0; + let invalidForTailPredication = 1; } multiclass MVE_VMINMAXV_ty<string iname, bit bit_7, list<dag> pattern=[]> { @@ -727,6 +732,7 @@ class MVE_VMLAMLSDAV<string iname, string suffix, dag iops, string cstr, let Inst{5} = A; let Inst{3-1} = Qm{2-0}; let Inst{0} = bit_0; + let invalidForTailPredication = 1; } multiclass MVE_VMLAMLSDAV_A<string iname, string x, string suffix, @@ -802,6 +808,7 @@ class MVE_VMLALDAVBase<string iname, string suffix, dag iops, string cstr, let Inst{5} = A; let Inst{3-1} = Qm{2-0}; let Inst{0} = bit_0; + let invalidForTailPredication = 1; } multiclass MVE_VMLALDAVBase_A<string iname, string x, string suffix, diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMBaseInfo.h b/llvm/lib/Target/ARM/MCTargetDesc/ARMBaseInfo.h index c4daafe8ee9..6893229580c 100644 --- a/llvm/lib/Target/ARM/MCTargetDesc/ARMBaseInfo.h +++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMBaseInfo.h @@ -393,6 +393,10 @@ namespace ARMII { // in an IT block). ThumbArithFlagSetting = 1 << 19, + // Whether an instruction should be excluded from an MVE tail-predicated + // loop. + InvalidForTailPredication = 1 << 20, + //===------------------------------------------------------------------===// // Code domain. DomainShift = 15, diff --git a/llvm/unittests/Target/ARM/CMakeLists.txt b/llvm/unittests/Target/ARM/CMakeLists.txt new file mode 100644 index 00000000000..0fdd9552730 --- /dev/null +++ b/llvm/unittests/Target/ARM/CMakeLists.txt @@ -0,0 +1,17 @@ +include_directories( + ${CMAKE_SOURCE_DIR}/lib/Target/ARM + ${CMAKE_BINARY_DIR}/lib/Target/ARM + ) + +set(LLVM_LINK_COMPONENTS + ARMCodeGen + ARMDesc + ARMInfo + MC + Support + Target +) + +add_llvm_unittest(ARMTests + MachineInstrTest.cpp + ) diff --git a/llvm/unittests/Target/ARM/MachineInstrTest.cpp b/llvm/unittests/Target/ARM/MachineInstrTest.cpp new file mode 100644 index 00000000000..77bba08dcbc --- /dev/null +++ b/llvm/unittests/Target/ARM/MachineInstrTest.cpp @@ -0,0 +1,166 @@ +#include "ARMBaseInstrInfo.h" +#include "ARMSubtarget.h" +#include "ARMTargetMachine.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" + +#include "gtest/gtest.h" + +using namespace llvm; + +// Test for instructions that aren't immediately obviously valid within a +// tail-predicated loop. This should be marked up in their tablegen +// descriptions. Currently the horizontal vector operations are tagged. +// TODO Add instructions that perform: +// - truncation, +// - extensions, +// - byte swapping, +// - others? +TEST(MachineInstrInvalidTailPredication, IsCorrect) { + LLVMInitializeARMTargetInfo(); + LLVMInitializeARMTarget(); + LLVMInitializeARMTargetMC(); + + auto TT(Triple::normalize("thumbv8.1m.main-arm-none-eabi")); + std::string Error; + const Target *T = TargetRegistry::lookupTarget(TT, Error); + if (!T) { + dbgs() << Error; + return; + } + + TargetOptions Options; + auto TM = std::unique_ptr<LLVMTargetMachine>( + static_cast<LLVMTargetMachine*>( + 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"; + } +} |