[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 {
def LogicalImm32Operand : AsmOperandClass {
let Name = "LogicalImm32";
let PredicateMethod = "isLogicalImm<int32_t>";
let RenderMethod = "addLogicalImmOperands<int32_t>";
}
def LogicalImm64Operand : AsmOperandClass {
let Name = "LogicalImm64";
let PredicateMethod = "isLogicalImm<int64_t>";
let RenderMethod = "addLogicalImmOperands<int64_t>";
}
def LogicalImm32NotOperand : AsmOperandClass {
let Name = "LogicalImm32Not";
let PredicateMethod = "isLogicalImm<int32_t>";
let RenderMethod = "addLogicalImmNotOperands<int32_t>";
}
def LogicalImm64NotOperand : AsmOperandClass {
let Name = "LogicalImm64Not";
let PredicateMethod = "isLogicalImm<int64_t>";
let RenderMethod = "addLogicalImmNotOperands<int64_t>";
}
}
def logical_imm32 : Operand<i32>, IntImmLeaf<i32, [{
return AArch64_AM::isLogicalImmediate(Imm.getZExtValue(), 32);
}], logical_imm32_XFORM> {
let PrintMethod = "printLogicalImm32";
let PrintMethod = "printLogicalImm<int32_t>";
let ParserMatchClass = LogicalImm32Operand;
}
def logical_imm64 : Operand<i64>, IntImmLeaf<i64, [{
return AArch64_AM::isLogicalImmediate(Imm.getZExtValue(), 64);
}], logical_imm64_XFORM> {
let PrintMethod = "printLogicalImm64";
let PrintMethod = "printLogicalImm<int64_t>";
let ParserMatchClass = LogicalImm64Operand;
}
def logical_imm32_not : Operand<i32> {

View File

@ -555,45 +555,23 @@ public:
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())
return false;
const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
if (!MCE)
return false;
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;
Val &= 0xFFFFFFFF;
return AArch64_AM::isLogicalImmediate(Val, 32);
}
bool isLogicalImm64() const {
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);
return AArch64_AM::isLogicalImmediate(UVal, sizeof(T) * 8);
}
bool isShiftedImm() const { return Kind == k_ShiftedImm; }
@ -1378,34 +1356,21 @@ public:
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!");
const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
uint64_t encoding =
AArch64_AM::encodeLogicalImmediate(MCE->getValue() & 0xFFFFFFFF, 32);
typename std::make_unsigned<T>::type Val = MCE->getValue();
uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
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!");
const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
uint64_t encoding = AArch64_AM::encodeLogicalImmediate(MCE->getValue(), 64);
Inst.addOperand(MCOperand::createImm(encoding));
}
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);
typename std::make_unsigned<T>::type Val = ~MCE->getValue();
uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
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>
void AArch64InstPrinter::printLogicalImm(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, 32));
}
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));
O.write_hex(AArch64_AM::decodeLogicalImmediate(Val, 8 * sizeof(T)));
}
void AArch64InstPrinter::printShifter(const MCInst *MI, unsigned OpNum,

View File

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

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,
uint64_t &Encoding) {
if (Imm == 0ULL || Imm == ~0ULL ||
(RegSize != 64 && (Imm >> RegSize != 0 || Imm == ~0U)))
(RegSize != 64 &&
(Imm >> RegSize != 0 || Imm == (~0ULL >> (64 - RegSize)))))
return false;
// First, determine the element size.