Skip to content

Commit 9dcfebf

Browse files
authored
[ARM] Auto-decode vpred_n/vpred_r operands (#160282)
Make the operands auto-decodable by adding `bits<0>` fields to instructions. Now we try to decode a vpred_n/vpred_r operand only if the instruction being decoded has one. We still need post-decoding pass to check/advance VPT state. Part of #156540.
1 parent 9e4af2f commit 9dcfebf

File tree

3 files changed

+47
-56
lines changed

3 files changed

+47
-56
lines changed

llvm/lib/Target/ARM/ARMInstrCDE.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,7 @@ class CDE_Vec_Instr<bit acc, dag oops, dag iops, string asm, string cstr,
268268
!con(iops, (ins vpred:$vp)), asm,
269269
!strconcat(cstr, vpred.vpred_constraint)>,
270270
CDE_RequiresQReg {
271+
bits<0> vp;
271272
}
272273

273274

llvm/lib/Target/ARM/ARMInstrMVE.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,7 @@ class MVE_p<dag oops, dag iops, InstrItinClass itin, string iname,
409409
!strconcat(iname, "${vp}",
410410
!if(!eq(suffix, ""), "", !strconcat(".", suffix))),
411411
ops, !strconcat(cstr, vpred.vpred_constraint), vecsize, pattern> {
412+
bits<0> vp;
412413
let Inst{31-29} = 0b111;
413414
let Inst{27-26} = 0b11;
414415
}

llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp

Lines changed: 45 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -639,6 +639,43 @@ static DecodeStatus DecodeCCOutOperand(MCInst &Inst,
639639
return MCDisassembler::Success;
640640
}
641641

642+
static DecodeStatus DecodeVpredNOperand(MCInst &Inst,
643+
const MCDisassembler *Decoder) {
644+
const auto *D = static_cast<const ARMDisassembler *>(Decoder);
645+
unsigned VCC = D->VPTBlock.getVPTPred();
646+
MCRegister CondReg = VCC == ARMVCC::None ? ARM::NoRegister : ARM::P0;
647+
648+
Inst.addOperand(MCOperand::createImm(VCC)); // $cond
649+
Inst.addOperand(MCOperand::createReg(CondReg)); // $cond_reg
650+
Inst.addOperand(MCOperand::createReg(ARM::NoRegister)); // $tp_reg
651+
652+
return MCDisassembler::Success;
653+
}
654+
655+
static DecodeStatus DecodeVpredROperand(MCInst &Inst,
656+
const MCDisassembler *Decoder) {
657+
const auto *D = static_cast<const ARMDisassembler *>(Decoder);
658+
unsigned VCC = D->VPTBlock.getVPTPred();
659+
MCRegister CondReg = VCC == ARMVCC::None ? ARM::NoRegister : ARM::P0;
660+
661+
Inst.addOperand(MCOperand::createImm(VCC)); // $cond
662+
Inst.addOperand(MCOperand::createReg(CondReg)); // $cond_reg
663+
Inst.addOperand(MCOperand::createReg(ARM::NoRegister)); // $tp_reg
664+
665+
// The last sub-operand ($inactive) is tied to an output operand.
666+
// The output operand has already been decoded, so just copy it.
667+
const MCInstrDesc &MCID = D->MCII->get(Inst.getOpcode());
668+
unsigned InactiveOpIdx = Inst.getNumOperands();
669+
int TiedOpIdx = MCID.getOperandConstraint(InactiveOpIdx, MCOI::TIED_TO);
670+
assert(TiedOpIdx >= 0 &&
671+
"Inactive register in vpred_r is not tied to an output!");
672+
673+
// Make a copy of the operand to ensure it is not invalidated when MI grows.
674+
Inst.addOperand(MCOperand(Inst.getOperand(TiedOpIdx))); // $inactive
675+
676+
return MCDisassembler::Success;
677+
}
678+
642679
static DecodeStatus DecodeSORegImmOperand(MCInst &Inst, unsigned Val,
643680
uint64_t Address,
644681
const MCDisassembler *Decoder) {
@@ -2777,6 +2814,7 @@ static DecodeStatus DecodeMVEModImmInstruction(MCInst &Inst, unsigned Insn,
27772814

27782815
Inst.addOperand(MCOperand::createImm(imm));
27792816

2817+
Check(S, DecodeVpredROperand(Inst, Decoder));
27802818
return S;
27812819
}
27822820

@@ -2802,6 +2840,7 @@ static DecodeStatus DecodeMVEVADCInstruction(MCInst &Inst, unsigned Insn,
28022840
if (!fieldFromInstruction(Insn, 12, 1)) // I bit clear => need input FPSCR
28032841
Inst.addOperand(MCOperand::createReg(ARM::FPSCR_NZCV));
28042842

2843+
Check(S, DecodeVpredROperand(Inst, Decoder));
28052844
return S;
28062845
}
28072846

@@ -5466,30 +5505,6 @@ static DecodeStatus DecodeVPTMaskOperand(MCInst &Inst, unsigned Val,
54665505
return S;
54675506
}
54685507

5469-
static DecodeStatus DecodeVpredROperand(MCInst &Inst, unsigned RegNo,
5470-
uint64_t Address,
5471-
const MCDisassembler *Decoder) {
5472-
// The vpred_r operand type includes an MQPR register field derived
5473-
// from the encoding. But we don't actually want to add an operand
5474-
// to the MCInst at this stage, because AddThumbPredicate will do it
5475-
// later, and will infer the register number from the TIED_TO
5476-
// constraint. So this is a deliberately empty decoder method that
5477-
// will inhibit the auto-generated disassembly code from adding an
5478-
// operand at all.
5479-
return MCDisassembler::Success;
5480-
}
5481-
5482-
[[maybe_unused]] static DecodeStatus
5483-
DecodeVpredNOperand(MCInst &Inst, unsigned RegNo, uint64_t Address,
5484-
const MCDisassembler *Decoder) {
5485-
// Similar to above, we want to ensure that no operands are added for the
5486-
// vpred operands. (This is marked "maybe_unused" for the moment; because
5487-
// DecoderEmitter currently (wrongly) omits operands with no instruction bits,
5488-
// the decoder doesn't actually call it yet. That will be addressed in a
5489-
// future change.)
5490-
return MCDisassembler::Success;
5491-
}
5492-
54935508
static DecodeStatus
54945509
DecodeRestrictedIPredicateOperand(MCInst &Inst, unsigned Val, uint64_t Address,
54955510
const MCDisassembler *Decoder) {
@@ -5668,6 +5683,7 @@ DecodeMVE_MEM_pre(MCInst &Inst, unsigned Val, uint64_t Address,
56685683
if (!Check(S, AddrDecoder(Inst, addr, Address, Decoder)))
56695684
return MCDisassembler::Fail;
56705685

5686+
Check(S, DecodeVpredNOperand(Inst, Decoder));
56715687
return S;
56725688
}
56735689

@@ -5871,7 +5887,7 @@ static DecodeStatus DecodeMVEVCVTt1fp(MCInst &Inst, unsigned Insn,
58715887
return MCDisassembler::Fail;
58725888
if (!Check(S, DecodeVCVTImmOperand(Inst, imm6, Address, Decoder)))
58735889
return MCDisassembler::Fail;
5874-
5890+
Check(S, DecodeVpredROperand(Inst, Decoder));
58755891
return S;
58765892
}
58775893

@@ -5906,6 +5922,7 @@ static DecodeStatus DecodeMVEVCMP(MCInst &Inst, unsigned Insn, uint64_t Address,
59065922
if (!Check(S, predicate_decoder(Inst, fc, Address, Decoder)))
59075923
return MCDisassembler::Fail;
59085924

5925+
Check(S, DecodeVpredNOperand(Inst, Decoder));
59095926
return S;
59105927
}
59115928

@@ -5916,6 +5933,7 @@ static DecodeStatus DecodeMveVCTP(MCInst &Inst, unsigned Insn, uint64_t Address,
59165933
unsigned Rn = fieldFromInstruction(Insn, 16, 4);
59175934
if (!Check(S, DecoderGPRRegisterClass(Inst, Rn, Address, Decoder)))
59185935
return MCDisassembler::Fail;
5936+
Check(S, DecodeVpredNOperand(Inst, Decoder));
59195937
return S;
59205938
}
59215939

@@ -5925,6 +5943,7 @@ static DecodeStatus DecodeMVEVPNOT(MCInst &Inst, unsigned Insn,
59255943
DecodeStatus S = MCDisassembler::Success;
59265944
Inst.addOperand(MCOperand::createReg(ARM::VPR));
59275945
Inst.addOperand(MCOperand::createReg(ARM::VPR));
5946+
Check(S, DecodeVpredNOperand(Inst, Decoder));
59285947
return S;
59295948
}
59305949

@@ -6199,15 +6218,13 @@ ARMDisassembler::AddThumbPredicate(MCInst &MI) const {
61996218
(isVectorPredicable(MI) && ITBlock.instrInITBlock()))
62006219
S = SoftFail;
62016220

6202-
// If we're in an IT/VPT block, base the predicate on that. Otherwise,
6221+
// If we're in an IT block, base the predicate on that. Otherwise,
62036222
// assume a predicate of AL.
62046223
unsigned CC = ARMCC::AL;
6205-
unsigned VCC = ARMVCC::None;
62066224
if (ITBlock.instrInITBlock()) {
62076225
CC = ITBlock.getITCC();
62086226
ITBlock.advanceITState();
62096227
} else if (VPTBlock.instrInVPTBlock()) {
6210-
VCC = VPTBlock.getVPTPred();
62116228
VPTBlock.advanceVPTState();
62126229
}
62136230

@@ -6230,34 +6247,6 @@ ARMDisassembler::AddThumbPredicate(MCInst &MI) const {
62306247
Check(S, SoftFail);
62316248
}
62326249

6233-
MCInst::iterator VCCI = MI.begin();
6234-
unsigned VCCPos;
6235-
for (VCCPos = 0; VCCPos < MCID.NumOperands; ++VCCPos, ++VCCI) {
6236-
if (ARM::isVpred(MCID.operands()[VCCPos].OperandType) || VCCI == MI.end())
6237-
break;
6238-
}
6239-
6240-
if (isVectorPredicable(MI)) {
6241-
VCCI = MI.insert(VCCI, MCOperand::createImm(VCC));
6242-
++VCCI;
6243-
if (VCC == ARMVCC::None)
6244-
VCCI = MI.insert(VCCI, MCOperand::createReg(0));
6245-
else
6246-
VCCI = MI.insert(VCCI, MCOperand::createReg(ARM::P0));
6247-
++VCCI;
6248-
VCCI = MI.insert(VCCI, MCOperand::createReg(0));
6249-
++VCCI;
6250-
if (MCID.operands()[VCCPos].OperandType == ARM::OPERAND_VPRED_R) {
6251-
int TiedOp = MCID.getOperandConstraint(VCCPos + 3, MCOI::TIED_TO);
6252-
assert(TiedOp >= 0 &&
6253-
"Inactive register in vpred_r is not tied to an output!");
6254-
// Copy the operand to ensure it's not invalidated when MI grows.
6255-
MI.insert(VCCI, MCOperand(MI.getOperand(TiedOp)));
6256-
}
6257-
} else if (VCC != ARMVCC::None) {
6258-
Check(S, SoftFail);
6259-
}
6260-
62616250
return S;
62626251
}
62636252

0 commit comments

Comments
 (0)