diff options
author | Simon Tatham <simon.tatham@arm.com> | 2019-02-25 10:39:53 +0000 |
---|---|---|
committer | Simon Tatham <simon.tatham@arm.com> | 2019-02-25 10:39:53 +0000 |
commit | b70fc0c5fdbbbd9ed96b9d8af595aebea3470714 (patch) | |
tree | 20d96c503f8d6c412480c933eca9c55a6a63e5cd /llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp | |
parent | 542e5d7bb5ca0657586d4a5a5d487aa93d727695 (diff) | |
download | llvm-b70fc0c5fdbbbd9ed96b9d8af595aebea3470714.zip llvm-b70fc0c5fdbbbd9ed96b9d8af595aebea3470714.tar.gz llvm-b70fc0c5fdbbbd9ed96b9d8af595aebea3470714.tar.bz2 |
[ARM] Make fullfp16 instructions not conditionalisable.
More or less all the instructions defined in the v8.2a full-fp16
extension are defined as UNPREDICTABLE if you put them in an IT block
(Thumb) or use with any condition other than AL (ARM). LLVM didn't
know that, and was happy to conditionalise them.
In order to force these instructions to count as not predicable, I had
to make a small Tablegen change. The code generation back end mostly
decides if an instruction was predicable by looking for something it
can identify as a predicate operand; there's an isPredicable bit flag
that overrides that check in the positive direction, but nothing that
overrides it in the negative direction.
(I considered the alternative approach of actually removing the
predicate operand from those instructions, but thought that it would
be more painful overall for instructions differing only in data type
to have different shapes of operand list. This way, the only code that
has to notice the difference is the if-converter.)
So I've added an isUnpredicable bit alongside isPredicable, and set
that bit on the right subset of FP16 instructions, and also on the
VSEL, VMAXNM/VMINNM and VRINT[ANPM] families which should be
unpredicable for all data types.
I've included a couple of representative regression tests, both of
which previously caused an fp16 instruction to be conditionalised in
ARM state and (with -arm-no-restrict-it) to be put in an IT block in
Thumb.
Reviewers: SjoerdMeijer, t.p.northover, efriedma
Reviewed By: efriedma
Subscribers: jdoerfert, javed.absar, kristof.beyls, hiraditya, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D57823
llvm-svn: 354768
Diffstat (limited to 'llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp')
-rw-r--r-- | llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp | 16 |
1 files changed, 12 insertions, 4 deletions
diff --git a/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp b/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp index 1ac1ade..b65a075 100644 --- a/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp +++ b/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp @@ -119,7 +119,7 @@ private: mutable ITStatus ITBlock; DecodeStatus AddThumbPredicate(MCInst&) const; - void UpdateThumbVFPPredicate(MCInst&) const; + void UpdateThumbVFPPredicate(DecodeStatus &, MCInst&) const; }; } // end anonymous namespace @@ -630,6 +630,8 @@ ThumbDisassembler::AddThumbPredicate(MCInst &MI) const { for (unsigned i = 0; i < NumOps; ++i, ++I) { if (I == MI.end()) break; if (OpInfo[i].isPredicate()) { + if (CC != ARMCC::AL && !ARMInsts[MI.getOpcode()].isPredicable()) + Check(S, SoftFail); I = MI.insert(I, MCOperand::createImm(CC)); ++I; if (CC == ARMCC::AL) @@ -655,7 +657,8 @@ ThumbDisassembler::AddThumbPredicate(MCInst &MI) const { // mode, the auto-generated decoder will give them an (incorrect) // predicate operand. We need to rewrite these operands based on the IT // context as a post-pass. -void ThumbDisassembler::UpdateThumbVFPPredicate(MCInst &MI) const { +void ThumbDisassembler::UpdateThumbVFPPredicate( + DecodeStatus &S, MCInst &MI) const { unsigned CC; CC = ITBlock.getITCC(); if (CC == 0xF) @@ -668,6 +671,8 @@ void ThumbDisassembler::UpdateThumbVFPPredicate(MCInst &MI) const { unsigned short NumOps = ARMInsts[MI.getOpcode()].NumOperands; for (unsigned i = 0; i < NumOps; ++i, ++I) { if (OpInfo[i].isPredicate() ) { + if (CC != ARMCC::AL && !ARMInsts[MI.getOpcode()].isPredicable()) + Check(S, SoftFail); I->setImm(CC); ++I; if (CC == ARMCC::AL) @@ -773,7 +778,7 @@ DecodeStatus ThumbDisassembler::getInstruction(MCInst &MI, uint64_t &Size, decodeInstruction(DecoderTableVFP32, MI, Insn32, Address, this, STI); if (Result != MCDisassembler::Fail) { Size = 4; - UpdateThumbVFPPredicate(MI); + UpdateThumbVFPPredicate(Result, MI); return Result; } } @@ -1110,16 +1115,19 @@ static DecodeStatus DecodeDPairSpacedRegisterClass(MCInst &Inst, static DecodeStatus DecodePredicateOperand(MCInst &Inst, unsigned Val, uint64_t Address, const void *Decoder) { + DecodeStatus S = MCDisassembler::Success; if (Val == 0xF) return MCDisassembler::Fail; // AL predicate is not allowed on Thumb1 branches. if (Inst.getOpcode() == ARM::tBcc && Val == 0xE) return MCDisassembler::Fail; + if (Val != ARMCC::AL && !ARMInsts[Inst.getOpcode()].isPredicable()) + Check(S, MCDisassembler::SoftFail); Inst.addOperand(MCOperand::createImm(Val)); if (Val == ARMCC::AL) { Inst.addOperand(MCOperand::createReg(0)); } else Inst.addOperand(MCOperand::createReg(ARM::CPSR)); - return MCDisassembler::Success; + return S; } static DecodeStatus DecodeCCOutOperand(MCInst &Inst, unsigned Val, |