[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
This commit is contained in:
Sam Parker 2019-09-17 07:43:04 +00:00
parent 30d86f1858
commit 26a475afe5
5 changed files with 197 additions and 0 deletions

View File

@ -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;

View File

@ -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,

View File

@ -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,

View File

@ -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
)

View File

@ -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";
}
}