forked from OSchip/llvm-project
[ARM] Refactor handling of IT mask operands.
During assembly, the mask operand to an IT instruction (storing the sequence of T/E for 'Then' and 'Else') is parsed out of the mnemonic into a representation that encodes 'Then' and 'Else' in the same way regardless of the condition code. At some point during encoding it has to be converted into the instruction encoding used in the architecture, in which the mask encodes a sequence of replacement low-order bits for the condition code, so that which bit value means 'then' and which 'else' depends on whether the original condition code had its low bit set. Previously, that transformation was done by processInstruction(), half way through assembly. So an MCOperand storing an IT mask would sometimes store it in one format, and sometimes in the other, depending on where in the assembly pipeline you were. You can see this in diagnostics from `llvm-mc -debug -triple=thumbv8a -show-inst`, for example: if you give it an instruction such as `itete eq`, you'd see an `<MCOperand Imm:5>` in a diagnostic become `<MCOperand Imm:11>` in the final output. Having the same data structure store values with time-dependent semantics is confusing already, and it will get more confusing when we introduce the MVE VPT instruction which reuses the Then/Else bitmask idea in a different context. So I'm refactoring: now, all `ARMOperand` and `MCOperand` representations of an IT mask work exactly the same way, namely, 0 means 'Then' and 1 means 'Else', regardless of what original predicate is being referred to. The architectural encoding of IT that depends on the original condition is now constructed at the point when we turn the `MCOperand` into the final instruction bit pattern, and decoded similarly in the disassembler. The previous condition-independent parse-time format used 0 for Else and 1 for Then. I've taken the opportunity to flip the sense of it while I'm changing all of this anyway, because it seems to me more natural to use 0 for 'leave the starting condition unchanged' and 1 for 'invert it', as if those bits were an XOR mask. Reviewers: ostannard Subscribers: javed.absar, kristof.beyls, hiraditya, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D63219 llvm-svn: 363244
This commit is contained in:
parent
86b7f865ac
commit
848d3d0d2c
|
@ -25,6 +25,7 @@ def it_mask_asmoperand : AsmOperandClass { let Name = "ITMask"; }
|
|||
def it_mask : Operand<i32> {
|
||||
let PrintMethod = "printThumbITMask";
|
||||
let ParserMatchClass = it_mask_asmoperand;
|
||||
let EncoderMethod = "getITMaskOpValue";
|
||||
}
|
||||
|
||||
// t2_shift_imm: An integer that encodes a shift amount and the type of shift
|
||||
|
|
|
@ -90,6 +90,16 @@ static cl::opt<bool> AddBuildAttributes("arm-add-build-attributes",
|
|||
|
||||
enum VectorLaneTy { NoLanes, AllLanes, IndexedLane };
|
||||
|
||||
static inline unsigned extractITMaskBit(unsigned Mask, unsigned Position) {
|
||||
// Position==0 means we're not in an IT block at all. Position==1
|
||||
// means we want the first state bit, which is always 0 (Then).
|
||||
// Position==2 means we want the second state bit, stored at bit 3
|
||||
// of Mask, and so on downwards. So (5 - Position) will shift the
|
||||
// right bit down to bit 0, including the always-0 bit at bit 4 for
|
||||
// the mandatory initial Then.
|
||||
return (Mask >> (5 - Position) & 1);
|
||||
}
|
||||
|
||||
class UnwindContext {
|
||||
using Locs = SmallVector<SMLoc, 4>;
|
||||
|
||||
|
@ -226,11 +236,10 @@ class ARMAsmParser : public MCTargetAsmParser {
|
|||
}
|
||||
|
||||
// Emit the IT instruction
|
||||
unsigned Mask = getITMaskEncoding();
|
||||
MCInst ITInst;
|
||||
ITInst.setOpcode(ARM::t2IT);
|
||||
ITInst.addOperand(MCOperand::createImm(ITState.Cond));
|
||||
ITInst.addOperand(MCOperand::createImm(Mask));
|
||||
ITInst.addOperand(MCOperand::createImm(ITState.Mask));
|
||||
Out.EmitInstruction(ITInst, getSTI());
|
||||
|
||||
// Emit the conditonal instructions
|
||||
|
@ -288,27 +297,10 @@ class ARMAsmParser : public MCTargetAsmParser {
|
|||
return MRI->getSubReg(QReg, ARM::dsub_0);
|
||||
}
|
||||
|
||||
// Get the encoding of the IT mask, as it will appear in an IT instruction.
|
||||
unsigned getITMaskEncoding() {
|
||||
assert(inITBlock());
|
||||
unsigned Mask = ITState.Mask;
|
||||
unsigned TZ = countTrailingZeros(Mask);
|
||||
if ((ITState.Cond & 1) == 0) {
|
||||
assert(Mask && TZ <= 3 && "illegal IT mask value!");
|
||||
Mask ^= (0xE << TZ) & 0xF;
|
||||
}
|
||||
return Mask;
|
||||
}
|
||||
|
||||
// Get the condition code corresponding to the current IT block slot.
|
||||
ARMCC::CondCodes currentITCond() {
|
||||
unsigned MaskBit;
|
||||
if (ITState.CurPosition == 1)
|
||||
MaskBit = 1;
|
||||
else
|
||||
MaskBit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
|
||||
|
||||
return MaskBit ? ITState.Cond : ARMCC::getOppositeCondition(ITState.Cond);
|
||||
unsigned MaskBit = extractITMaskBit(ITState.Mask, ITState.CurPosition);
|
||||
return MaskBit ? ARMCC::getOppositeCondition(ITState.Cond) : ITState.Cond;
|
||||
}
|
||||
|
||||
// Invert the condition of the current IT block slot without changing any
|
||||
|
@ -338,7 +330,7 @@ class ARMAsmParser : public MCTargetAsmParser {
|
|||
// Keep any existing condition bits.
|
||||
NewMask |= ITState.Mask & (0xE << TZ);
|
||||
// Insert the new condition bit.
|
||||
NewMask |= (Cond == ITState.Cond) << TZ;
|
||||
NewMask |= (Cond != ITState.Cond) << TZ;
|
||||
// Move the trailing 1 down one bit.
|
||||
NewMask |= 1 << (TZ - 1);
|
||||
ITState.Mask = NewMask;
|
||||
|
@ -353,9 +345,10 @@ class ARMAsmParser : public MCTargetAsmParser {
|
|||
ITState.IsExplicit = false;
|
||||
}
|
||||
|
||||
// Create a new explicit IT block with the given condition and mask. The mask
|
||||
// should be in the parsed format, with a 1 implying 't', regardless of the
|
||||
// low bit of the condition.
|
||||
// Create a new explicit IT block with the given condition and mask.
|
||||
// The mask should be in the format used in ARMOperand and
|
||||
// MCOperand, with a 1 implying 'e', regardless of the low bit of
|
||||
// the condition.
|
||||
void startExplicitITBlock(ARMCC::CondCodes Cond, unsigned Mask) {
|
||||
assert(!inITBlock());
|
||||
ITState.Cond = Cond;
|
||||
|
@ -3355,10 +3348,10 @@ void ARMOperand::print(raw_ostream &OS) const {
|
|||
break;
|
||||
case k_ITCondMask: {
|
||||
static const char *const MaskStr[] = {
|
||||
"(invalid)", "(teee)", "(tee)", "(teet)",
|
||||
"(te)", "(tete)", "(tet)", "(tett)",
|
||||
"(t)", "(ttee)", "(tte)", "(ttet)",
|
||||
"(tt)", "(ttte)", "(ttt)", "(tttt)"
|
||||
"(invalid)", "(tttt)", "(ttt)", "(ttte)",
|
||||
"(tt)", "(ttet)", "(tte)", "(ttee)",
|
||||
"(t)", "(tett)", "(tet)", "(tete)",
|
||||
"(te)", "(teet)", "(tee)", "(teee)",
|
||||
};
|
||||
assert((ITMask.Mask & 0xf) == ITMask.Mask);
|
||||
OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
|
||||
|
@ -6272,11 +6265,14 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
|
|||
|
||||
Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
|
||||
|
||||
// Handle the IT instruction ITMask. Convert it to a bitmask. This
|
||||
// is the mask as it will be for the IT encoding if the conditional
|
||||
// encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
|
||||
// where the conditional bit0 is zero, the instruction post-processing
|
||||
// will adjust the mask accordingly.
|
||||
// Handle the mask for IT instructions. In ARMOperand and MCOperand,
|
||||
// this is stored in a format independent of the condition code: the
|
||||
// lowest set bit indicates the end of the encoding, and above that,
|
||||
// a 1 bit indicates 'else', and an 0 indicates 'then'. E.g.
|
||||
// IT -> 1000
|
||||
// ITx -> x100 (ITT -> 0100, ITE -> 1100)
|
||||
// ITxy -> xy10 (e.g. ITET -> 1010)
|
||||
// ITxyz -> xyz1 (e.g. ITEET -> 1101)
|
||||
if (Mnemonic == "it") {
|
||||
SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
|
||||
if (ITMask.size() > 3) {
|
||||
|
@ -6289,7 +6285,7 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
|
|||
return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
|
||||
}
|
||||
Mask >>= 1;
|
||||
if (ITMask[i - 1] == 't')
|
||||
if (ITMask[i - 1] == 'e')
|
||||
Mask |= 8;
|
||||
}
|
||||
Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
|
||||
|
@ -6681,11 +6677,10 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst,
|
|||
unsigned Cond = Inst.getOperand(0).getImm();
|
||||
unsigned Mask = Inst.getOperand(1).getImm();
|
||||
|
||||
// Mask hasn't been modified to the IT instruction encoding yet so
|
||||
// conditions only allowing a 't' are a block of 1s starting at bit 3
|
||||
// followed by all 0s. Easiest way is to just list the 4 possibilities.
|
||||
if (Cond == ARMCC::AL && Mask != 8 && Mask != 12 && Mask != 14 &&
|
||||
Mask != 15)
|
||||
// Conditions only allowing a 't' are those with no set bit except
|
||||
// the lowest-order one that indicates the end of the sequence. In
|
||||
// other words, powers of 2.
|
||||
if (Cond == ARMCC::AL && countPopulation(Mask) != 1)
|
||||
return Error(Loc, "unpredictable IT predicate sequence");
|
||||
break;
|
||||
}
|
||||
|
@ -9260,15 +9255,11 @@ bool ARMAsmParser::processInstruction(MCInst &Inst,
|
|||
}
|
||||
case ARM::ITasm:
|
||||
case ARM::t2IT: {
|
||||
MCOperand &MO = Inst.getOperand(1);
|
||||
unsigned Mask = MO.getImm();
|
||||
ARMCC::CondCodes Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
|
||||
|
||||
// Set up the IT block state according to the IT instruction we just
|
||||
// matched.
|
||||
assert(!inITBlock() && "nested IT blocks?!");
|
||||
startExplicitITBlock(Cond, Mask);
|
||||
MO.setImm(getITMaskEncoding());
|
||||
startExplicitITBlock(ARMCC::CondCodes(Inst.getOperand(0).getImm()),
|
||||
Inst.getOperand(1).getImm());
|
||||
break;
|
||||
}
|
||||
case ARM::t2LSLrr:
|
||||
|
|
|
@ -63,22 +63,19 @@ namespace {
|
|||
return ITStates.size() == 1;
|
||||
}
|
||||
|
||||
// Called when decoding an IT instruction. Sets the IT state for the following
|
||||
// instructions that for the IT block. Firstcond and Mask correspond to the
|
||||
// fields in the IT instruction encoding.
|
||||
// Called when decoding an IT instruction. Sets the IT state for
|
||||
// the following instructions that for the IT block. Firstcond
|
||||
// corresponds to the field in the IT instruction encoding; Mask
|
||||
// is in the MCOperand format in which 1 means 'else' and 0 'then'.
|
||||
void setITState(char Firstcond, char Mask) {
|
||||
// (3 - the number of trailing zeros) is the number of then / else.
|
||||
unsigned CondBit0 = Firstcond & 1;
|
||||
unsigned NumTZ = countTrailingZeros<uint8_t>(Mask);
|
||||
unsigned char CCBits = static_cast<unsigned char>(Firstcond & 0xf);
|
||||
assert(NumTZ <= 3 && "Invalid IT mask!");
|
||||
// push condition codes onto the stack the correct order for the pops
|
||||
for (unsigned Pos = NumTZ+1; Pos <= 3; ++Pos) {
|
||||
bool T = ((Mask >> Pos) & 1) == CondBit0;
|
||||
if (T)
|
||||
ITStates.push_back(CCBits);
|
||||
else
|
||||
ITStates.push_back(CCBits ^ 1);
|
||||
unsigned Else = (Mask >> Pos) & 1;
|
||||
ITStates.push_back(CCBits ^ Else);
|
||||
}
|
||||
ITStates.push_back(CCBits);
|
||||
}
|
||||
|
@ -5176,6 +5173,16 @@ static DecodeStatus DecodeIT(MCInst &Inst, unsigned Insn,
|
|||
if (mask == 0x0)
|
||||
return MCDisassembler::Fail;
|
||||
|
||||
// IT masks are encoded as a sequence of replacement low-order bits
|
||||
// for the condition code. So if the low bit of the starting
|
||||
// condition code is 1, then we have to flip all the bits above the
|
||||
// terminating bit (which is the lowest 1 bit).
|
||||
if (pred & 1) {
|
||||
unsigned LowBit = mask & -mask;
|
||||
unsigned BitsAboveLowBit = 0xF & (-LowBit << 1);
|
||||
mask ^= BitsAboveLowBit;
|
||||
}
|
||||
|
||||
Inst.addOperand(MCOperand::createImm(pred));
|
||||
Inst.addOperand(MCOperand::createImm(mask));
|
||||
return S;
|
||||
|
|
|
@ -1039,16 +1039,13 @@ void ARMInstPrinter::printThumbITMask(const MCInst *MI, unsigned OpNum,
|
|||
raw_ostream &O) {
|
||||
// (3 - the number of trailing zeros) is the number of then / else.
|
||||
unsigned Mask = MI->getOperand(OpNum).getImm();
|
||||
unsigned Firstcond = MI->getOperand(OpNum - 1).getImm();
|
||||
unsigned CondBit0 = Firstcond & 1;
|
||||
unsigned NumTZ = countTrailingZeros(Mask);
|
||||
assert(NumTZ <= 3 && "Invalid IT mask!");
|
||||
for (unsigned Pos = 3, e = NumTZ; Pos > e; --Pos) {
|
||||
bool T = ((Mask >> Pos) & 1) == CondBit0;
|
||||
if (T)
|
||||
O << 't';
|
||||
else
|
||||
if ((Mask >> Pos) & 1)
|
||||
O << 'e';
|
||||
else
|
||||
O << 't';
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -162,6 +162,9 @@ public:
|
|||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const;
|
||||
|
||||
uint32_t getITMaskOpValue(const MCInst &MI, unsigned OpIdx,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const;
|
||||
|
||||
/// getAddrModeImm12OpValue - Return encoding info for 'reg +/- imm12'
|
||||
/// operand.
|
||||
|
@ -829,6 +832,33 @@ getT2AdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
|
|||
return Val;
|
||||
}
|
||||
|
||||
/// getITMaskOpValue - Return the architectural encoding of an IT
|
||||
/// predication mask, given the MCOperand format.
|
||||
uint32_t ARMMCCodeEmitter::
|
||||
getITMaskOpValue(const MCInst &MI, unsigned OpIdx,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const {
|
||||
const MCOperand MaskMO = MI.getOperand(OpIdx);
|
||||
assert(MaskMO.isImm() && "Unexpected operand type!");
|
||||
|
||||
unsigned Mask = MaskMO.getImm();
|
||||
|
||||
// IT masks are encoded as a sequence of replacement low-order bits
|
||||
// for the condition code. So if the low bit of the starting
|
||||
// condition code is 1, then we have to flip all the bits above the
|
||||
// terminating bit (which is the lowest 1 bit).
|
||||
assert(OpIdx > 0 && "IT mask appears first!");
|
||||
const MCOperand CondMO = MI.getOperand(OpIdx-1);
|
||||
assert(CondMO.isImm() && "Unexpected operand type!");
|
||||
if (CondMO.getImm() & 1) {
|
||||
unsigned LowBit = Mask & -Mask;
|
||||
unsigned BitsAboveLowBit = 0xF & (-LowBit << 1);
|
||||
Mask ^= BitsAboveLowBit;
|
||||
}
|
||||
|
||||
return Mask;
|
||||
}
|
||||
|
||||
/// getThumbAdrLabelOpValue - Return encoding info for 8-bit immediate ADR label
|
||||
/// target.
|
||||
uint32_t ARMMCCodeEmitter::
|
||||
|
|
|
@ -245,7 +245,7 @@ bool Thumb2ITBlockPass::InsertITInstructions(MachineBasicBlock &MBB) {
|
|||
unsigned NPredReg = 0;
|
||||
ARMCC::CondCodes NCC = getITInstrPredicate(*NMI, NPredReg);
|
||||
if (NCC == CC || NCC == OCC) {
|
||||
Mask |= (NCC & 1) << Pos;
|
||||
Mask |= ((NCC ^ CC) & 1) << Pos;
|
||||
// Add implicit use of ITSTATE.
|
||||
NMI->addOperand(MachineOperand::CreateReg(ARM::ITSTATE, false/*ifDef*/,
|
||||
true/*isImp*/, false/*isKill*/));
|
||||
|
@ -269,8 +269,6 @@ bool Thumb2ITBlockPass::InsertITInstructions(MachineBasicBlock &MBB) {
|
|||
|
||||
// Finalize IT mask.
|
||||
Mask |= (1 << Pos);
|
||||
// Tag along (firstcond[0] << 4) with the mask.
|
||||
Mask |= (CC & 1) << 4;
|
||||
MIB.addImm(Mask);
|
||||
|
||||
// Last instruction in IT block kills ITSTATE.
|
||||
|
|
Loading…
Reference in New Issue