1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-25 04:02:41 +01:00

[ARM][MVE] Add target flag for narrowing insts

Add a flag, 'RetainsPreviousHalfElement', for operations that operate
on top/bottom halves of their input and only write to half of their
destination, leaving the other half to retain its previous value.

Differential Revision: https://reviews.llvm.org/D76608
This commit is contained in:
Sam Parker 2020-03-24 08:23:05 +00:00
parent 3c07f2a94c
commit 392ec3c3a9
4 changed files with 111 additions and 1 deletions

View File

@ -408,6 +408,7 @@ class InstTemplate<AddrMode am, int sz, IndexMode im,
bit thumbArithFlagSetting = 0;
bit validForTailPredication = 0;
bit retainsPreviousHalfElement = 0;
// If this is a pseudo instruction, mark it isCodeGenOnly.
let isCodeGenOnly = !eq(!cast<string>(f), "Pseudo");
@ -421,6 +422,7 @@ class InstTemplate<AddrMode am, int sz, IndexMode im,
let TSFlags{18-15} = D.Value;
let TSFlags{19} = thumbArithFlagSetting;
let TSFlags{20} = validForTailPredication;
let TSFlags{21} = retainsPreviousHalfElement;
let Constraints = cstr;
let Itinerary = itin;

View File

@ -2688,6 +2688,7 @@ class MVE_VxSHRN<string iname, string suffix, bit bit_12, bit bit_28,
let Inst{4} = 0b0;
let Inst{0} = 0b1;
let validForTailPredication = 1;
let retainsPreviousHalfElement = 1;
}
def MVE_VRSHRNi16bh : MVE_VxSHRN<"vrshrnb", "i16", 0b0, 0b1, shr_imm8> {
@ -2730,6 +2731,7 @@ class MVE_VxQRSHRUN<string iname, string suffix, bit bit_28, bit bit_12,
let Inst{4} = 0b0;
let Inst{0} = 0b0;
let validForTailPredication = 1;
let retainsPreviousHalfElement = 1;
}
def MVE_VQRSHRUNs16bh : MVE_VxQRSHRUN<
@ -2779,6 +2781,7 @@ class MVE_VxQRSHRN<string iname, string suffix, bit bit_0, bit bit_12,
let Inst{4} = 0b0;
let Inst{0} = bit_0;
let validForTailPredication = 1;
let retainsPreviousHalfElement = 1;
}
multiclass MVE_VxQRSHRN_types<string iname, bit bit_0, bit bit_12> {
@ -4492,6 +4495,7 @@ class MVE_VxMOVxN<string iname, string suffix, bit bit_28, bit bit_17,
let Inst{7} = !if(!eq(bit_17, 0), 1, 0);
let Inst{0} = 0b1;
let validForTailPredication = 1;
let retainsPreviousHalfElement = 1;
}
multiclass MVE_VxMOVxN_halves<string iname, string suffix,
@ -4589,6 +4593,7 @@ class MVE_VCVT_ff<string iname, string suffix, bit op, bit T,
let Inst{0} = 0b1;
let Predicates = [HasMVEFloat];
let retainsPreviousHalfElement = 1;
}
multiclass MVE_VCVT_f2h_m<string iname, int half> {

View File

@ -396,6 +396,10 @@ namespace ARMII {
// Whether an instruction can be included in an MVE tail-predicated loop.
ValidForTailPredication = 1 << 20,
// Whether an instruction writes to the top/bottom half of a vector element
// and leaves the other half untouched.
RetainsPreviousHalfElement = 1 << 21,
//===------------------------------------------------------------------===//
// Code domain.
DomainShift = 15,

View File

@ -10,11 +10,110 @@
using namespace llvm;
TEST(MachineInstructionRetainsPreviousHalfElement, IsCorrect) {
using namespace ARM;
auto RetainsPreviousHalfElement = [](unsigned Opcode) {
switch (Opcode) {
default:
break;
case MVE_VMOVNi16bh:
case MVE_VMOVNi16th:
case MVE_VMOVNi32bh:
case MVE_VMOVNi32th:
case MVE_VQMOVNs16bh:
case MVE_VQMOVNs16th:
case MVE_VQMOVNs32bh:
case MVE_VQMOVNs32th:
case MVE_VQMOVNu16bh:
case MVE_VQMOVNu16th:
case MVE_VQMOVNu32bh:
case MVE_VQMOVNu32th:
case MVE_VQMOVUNs16bh:
case MVE_VQMOVUNs16th:
case MVE_VQMOVUNs32bh:
case MVE_VQMOVUNs32th:
case MVE_VQRSHRNbhs16:
case MVE_VQRSHRNbhs32:
case MVE_VQRSHRNbhu16:
case MVE_VQRSHRNbhu32:
case MVE_VQRSHRNths16:
case MVE_VQRSHRNths32:
case MVE_VQRSHRNthu16:
case MVE_VQRSHRNthu32:
case MVE_VQRSHRUNs16bh:
case MVE_VQRSHRUNs16th:
case MVE_VQRSHRUNs32bh:
case MVE_VQRSHRUNs32th:
case MVE_VQSHRNbhs16:
case MVE_VQSHRNbhs32:
case MVE_VQSHRNbhu16:
case MVE_VQSHRNbhu32:
case MVE_VQSHRNths16:
case MVE_VQSHRNths32:
case MVE_VQSHRNthu16:
case MVE_VQSHRNthu32:
case MVE_VQSHRUNs16bh:
case MVE_VQSHRUNs16th:
case MVE_VQSHRUNs32bh:
case MVE_VQSHRUNs32th:
case MVE_VRSHRNi16bh:
case MVE_VRSHRNi16th:
case MVE_VRSHRNi32bh:
case MVE_VRSHRNi32th:
case MVE_VSHRNi16bh:
case MVE_VSHRNi16th:
case MVE_VSHRNi32bh:
case MVE_VSHRNi32th:
case MVE_VCVTf16f32bh:
case MVE_VCVTf16f32th:
case MVE_VCVTf32f16bh:
case MVE_VCVTf32f16th:
return true;
}
return false;
};
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)));
ARMSubtarget ST(TM->getTargetTriple(), std::string(TM->getTargetCPU()),
std::string(TM->getTargetFeatureString()),
*static_cast<const ARMBaseTargetMachine *>(TM.get()), false);
const ARMBaseInstrInfo *TII = ST.getInstrInfo();
auto MII = TM->getMCInstrInfo();
for (unsigned i = 0; i < ARM::INSTRUCTION_LIST_END; ++i) {
const MCInstrDesc &Desc = TII->get(i);
uint64_t Flags = Desc.TSFlags;
if ((Flags & ARMII::DomainMask) != ARMII::DomainMVE)
continue;
bool Valid = (Flags & ARMII::RetainsPreviousHalfElement) != 0;
ASSERT_EQ(RetainsPreviousHalfElement(i), Valid)
<< MII->getName(i)
<< ": mismatched expectation for tail-predicated safety\n";
}
}
// Test for instructions that aren't immediately obviously valid within a
// tail-predicated loop. This should be marked up in their tablegen
// descriptions. Currently we, conservatively, disallow:
// - cross beat carries.
// - narrowing of results.
// - complex operations.
// - horizontal operations.
// - byte swapping.