[AArch64][AsmParser] NFC: Generalize LogicalImm[Not](32|64) code

Summary:
All variants of isLogicalImm[Not](32|64) can be combined into a single templated function, same for printLogicalImm(32|64).
By making it use a template instead, further SVE patches can use it for other data types as well (e.g. 8, 16 bits).

Reviewers: fhahn, rengolin, aadg, echristo, kristof.beyls, samparker

Reviewed By: samparker

Subscribers: aemerson, javed.absar, llvm-commits

Differential Revision: https://reviews.llvm.org/D42294

llvm-svn: 323646
This commit is contained in:
Sander de Smalen 2018-01-29 13:05:38 +00:00
parent de6fad6935
commit a1c259c22c
5 changed files with 38 additions and 72 deletions

View File

@ -501,27 +501,35 @@ def logical_imm64_XFORM : SDNodeXForm<imm, [{
let DiagnosticType = "LogicalSecondSource" in { let DiagnosticType = "LogicalSecondSource" in {
def LogicalImm32Operand : AsmOperandClass { def LogicalImm32Operand : AsmOperandClass {
let Name = "LogicalImm32"; let Name = "LogicalImm32";
let PredicateMethod = "isLogicalImm<int32_t>";
let RenderMethod = "addLogicalImmOperands<int32_t>";
} }
def LogicalImm64Operand : AsmOperandClass { def LogicalImm64Operand : AsmOperandClass {
let Name = "LogicalImm64"; let Name = "LogicalImm64";
let PredicateMethod = "isLogicalImm<int64_t>";
let RenderMethod = "addLogicalImmOperands<int64_t>";
} }
def LogicalImm32NotOperand : AsmOperandClass { def LogicalImm32NotOperand : AsmOperandClass {
let Name = "LogicalImm32Not"; let Name = "LogicalImm32Not";
let PredicateMethod = "isLogicalImm<int32_t>";
let RenderMethod = "addLogicalImmNotOperands<int32_t>";
} }
def LogicalImm64NotOperand : AsmOperandClass { def LogicalImm64NotOperand : AsmOperandClass {
let Name = "LogicalImm64Not"; let Name = "LogicalImm64Not";
let PredicateMethod = "isLogicalImm<int64_t>";
let RenderMethod = "addLogicalImmNotOperands<int64_t>";
} }
} }
def logical_imm32 : Operand<i32>, IntImmLeaf<i32, [{ def logical_imm32 : Operand<i32>, IntImmLeaf<i32, [{
return AArch64_AM::isLogicalImmediate(Imm.getZExtValue(), 32); return AArch64_AM::isLogicalImmediate(Imm.getZExtValue(), 32);
}], logical_imm32_XFORM> { }], logical_imm32_XFORM> {
let PrintMethod = "printLogicalImm32"; let PrintMethod = "printLogicalImm<int32_t>";
let ParserMatchClass = LogicalImm32Operand; let ParserMatchClass = LogicalImm32Operand;
} }
def logical_imm64 : Operand<i64>, IntImmLeaf<i64, [{ def logical_imm64 : Operand<i64>, IntImmLeaf<i64, [{
return AArch64_AM::isLogicalImmediate(Imm.getZExtValue(), 64); return AArch64_AM::isLogicalImmediate(Imm.getZExtValue(), 64);
}], logical_imm64_XFORM> { }], logical_imm64_XFORM> {
let PrintMethod = "printLogicalImm64"; let PrintMethod = "printLogicalImm<int64_t>";
let ParserMatchClass = LogicalImm64Operand; let ParserMatchClass = LogicalImm64Operand;
} }
def logical_imm32_not : Operand<i32> { def logical_imm32_not : Operand<i32> {

View File

@ -555,45 +555,23 @@ public:
return (Val >= N && Val <= M); return (Val >= N && Val <= M);
} }
bool isLogicalImm32() const { // NOTE: Also used for isLogicalImmNot as anything that can be represented as
// a logical immediate can always be represented when inverted.
template <typename T>
bool isLogicalImm() const {
if (!isImm()) if (!isImm())
return false; return false;
const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm()); const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
if (!MCE) if (!MCE)
return false; return false;
int64_t Val = MCE->getValue(); int64_t Val = MCE->getValue();
if (Val >> 32 != 0 && Val >> 32 != ~0LL) int64_t SVal = typename std::make_signed<T>::type(Val);
int64_t UVal = typename std::make_unsigned<T>::type(Val);
if (Val != SVal && Val != UVal)
return false; return false;
Val &= 0xFFFFFFFF;
return AArch64_AM::isLogicalImmediate(Val, 32);
}
bool isLogicalImm64() const { return AArch64_AM::isLogicalImmediate(UVal, sizeof(T) * 8);
if (!isImm())
return false;
const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
if (!MCE)
return false;
return AArch64_AM::isLogicalImmediate(MCE->getValue(), 64);
}
bool isLogicalImm32Not() const {
if (!isImm())
return false;
const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
if (!MCE)
return false;
int64_t Val = ~MCE->getValue() & 0xFFFFFFFF;
return AArch64_AM::isLogicalImmediate(Val, 32);
}
bool isLogicalImm64Not() const {
if (!isImm())
return false;
const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
if (!MCE)
return false;
return AArch64_AM::isLogicalImmediate(~MCE->getValue(), 64);
} }
bool isShiftedImm() const { return Kind == k_ShiftedImm; } bool isShiftedImm() const { return Kind == k_ShiftedImm; }
@ -1378,34 +1356,21 @@ public:
Inst.addOperand(MCOperand::createImm(MCE->getValue())); Inst.addOperand(MCOperand::createImm(MCE->getValue()));
} }
void addLogicalImm32Operands(MCInst &Inst, unsigned N) const { template <typename T>
void addLogicalImmOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!"); assert(N == 1 && "Invalid number of operands!");
const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm()); const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
uint64_t encoding = typename std::make_unsigned<T>::type Val = MCE->getValue();
AArch64_AM::encodeLogicalImmediate(MCE->getValue() & 0xFFFFFFFF, 32); uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Inst.addOperand(MCOperand::createImm(encoding)); Inst.addOperand(MCOperand::createImm(encoding));
} }
void addLogicalImm64Operands(MCInst &Inst, unsigned N) const { template <typename T>
void addLogicalImmNotOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!"); assert(N == 1 && "Invalid number of operands!");
const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm()); const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
uint64_t encoding = AArch64_AM::encodeLogicalImmediate(MCE->getValue(), 64); typename std::make_unsigned<T>::type Val = ~MCE->getValue();
Inst.addOperand(MCOperand::createImm(encoding)); uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
}
void addLogicalImm32NotOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
int64_t Val = ~MCE->getValue() & 0xFFFFFFFF;
uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, 32);
Inst.addOperand(MCOperand::createImm(encoding));
}
void addLogicalImm64NotOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
uint64_t encoding =
AArch64_AM::encodeLogicalImmediate(~MCE->getValue(), 64);
Inst.addOperand(MCOperand::createImm(encoding)); Inst.addOperand(MCOperand::createImm(encoding));
} }

View File

@ -907,20 +907,13 @@ void AArch64InstPrinter::printAddSubImm(const MCInst *MI, unsigned OpNum,
} }
} }
void AArch64InstPrinter::printLogicalImm32(const MCInst *MI, unsigned OpNum, template <typename T>
const MCSubtargetInfo &STI, void AArch64InstPrinter::printLogicalImm(const MCInst *MI, unsigned OpNum,
raw_ostream &O) { const MCSubtargetInfo &STI,
raw_ostream &O) {
uint64_t Val = MI->getOperand(OpNum).getImm(); uint64_t Val = MI->getOperand(OpNum).getImm();
O << "#0x"; O << "#0x";
O.write_hex(AArch64_AM::decodeLogicalImmediate(Val, 32)); O.write_hex(AArch64_AM::decodeLogicalImmediate(Val, 8 * sizeof(T)));
}
void AArch64InstPrinter::printLogicalImm64(const MCInst *MI, unsigned OpNum,
const MCSubtargetInfo &STI,
raw_ostream &O) {
uint64_t Val = MI->getOperand(OpNum).getImm();
O << "#0x";
O.write_hex(AArch64_AM::decodeLogicalImmediate(Val, 64));
} }
void AArch64InstPrinter::printShifter(const MCInst *MI, unsigned OpNum, void AArch64InstPrinter::printShifter(const MCInst *MI, unsigned OpNum,
@ -1369,4 +1362,4 @@ void AArch64InstPrinter::printSVERegOp(const MCInst *MI, unsigned OpNum,
O << getRegisterName(Reg); O << getRegisterName(Reg);
if (suffix != 0) if (suffix != 0)
O << '.' << suffix; O << '.' << suffix;
} }

View File

@ -71,10 +71,9 @@ protected:
const MCSubtargetInfo &STI, raw_ostream &O); const MCSubtargetInfo &STI, raw_ostream &O);
void printAddSubImm(const MCInst *MI, unsigned OpNum, void printAddSubImm(const MCInst *MI, unsigned OpNum,
const MCSubtargetInfo &STI, raw_ostream &O); const MCSubtargetInfo &STI, raw_ostream &O);
void printLogicalImm32(const MCInst *MI, unsigned OpNum, template <typename T>
const MCSubtargetInfo &STI, raw_ostream &O); void printLogicalImm(const MCInst *MI, unsigned OpNum,
void printLogicalImm64(const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI, raw_ostream &O);
const MCSubtargetInfo &STI, raw_ostream &O);
void printShifter(const MCInst *MI, unsigned OpNum, void printShifter(const MCInst *MI, unsigned OpNum,
const MCSubtargetInfo &STI, raw_ostream &O); const MCSubtargetInfo &STI, raw_ostream &O);
void printShiftedRegister(const MCInst *MI, unsigned OpNum, void printShiftedRegister(const MCInst *MI, unsigned OpNum,

View File

@ -213,7 +213,8 @@ static inline uint64_t ror(uint64_t elt, unsigned size) {
static inline bool processLogicalImmediate(uint64_t Imm, unsigned RegSize, static inline bool processLogicalImmediate(uint64_t Imm, unsigned RegSize,
uint64_t &Encoding) { uint64_t &Encoding) {
if (Imm == 0ULL || Imm == ~0ULL || if (Imm == 0ULL || Imm == ~0ULL ||
(RegSize != 64 && (Imm >> RegSize != 0 || Imm == ~0U))) (RegSize != 64 &&
(Imm >> RegSize != 0 || Imm == (~0ULL >> (64 - RegSize)))))
return false; return false;
// First, determine the element size. // First, determine the element size.