[ARM] v8.3-a complex number support
New instructions are added to AArch32 and AArch64 to aid
floating-point multiplication and addition of complex numbers, where
the complex numbers are packed in a vector register as a pair of
elements. The Imaginary part of the number is placed in the more
significant element, and the Real part of the number is placed in the
less significant element.
This patch adds assembler for the ARM target.
Differential Revision: https://reviews.llvm.org/D36789
llvm-svn: 314511
diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
index 287ed20..b84a4e8 100644
--- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
+++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
@@ -1756,6 +1756,10 @@
if (Kind != k_VectorIndex) return false;
return VectorIndex.Val < 2;
}
+ bool isVectorIndex64() const {
+ if (Kind != k_VectorIndex) return false;
+ return VectorIndex.Val < 1;
+ }
bool isNEONi8splat() const {
if (!isImm()) return false;
@@ -1885,6 +1889,17 @@
return true;
}
+ template<int64_t Angle, int64_t Remainder>
+ bool isComplexRotation() const {
+ if (!isImm()) return false;
+
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+ if (!CE) return false;
+ uint64_t Value = CE->getValue();
+
+ return (Value % Angle == Remainder && Value <= 270);
+ }
+
void addExpr(MCInst &Inst, const MCExpr *Expr) const {
// Add as immediates when possible. Null MCExpr = 0.
if (!Expr)
@@ -2628,6 +2643,11 @@
Inst.addOperand(MCOperand::createImm(getVectorIndex()));
}
+ void addVectorIndex64Operands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::createImm(getVectorIndex()));
+ }
+
void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
// The immediate encodes the type of constant as well as the value.
@@ -2740,6 +2760,18 @@
Inst.addOperand(MCOperand::createImm(Imm | 0x1e00));
}
+ void addComplexRotationEvenOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+ Inst.addOperand(MCOperand::createImm(CE->getValue() / 90));
+ }
+
+ void addComplexRotationOddOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+ Inst.addOperand(MCOperand::createImm((CE->getValue() - 90) / 180));
+ }
+
void print(raw_ostream &OS) const override;
static std::unique_ptr<ARMOperand> CreateITMask(unsigned Mask, SMLoc S) {
@@ -5432,7 +5464,8 @@
Mnemonic == "vrintp" || Mnemonic == "vrintm" || Mnemonic == "hvc" ||
Mnemonic.startswith("vsel") || Mnemonic == "vins" || Mnemonic == "vmovx" ||
Mnemonic == "bxns" || Mnemonic == "blxns" ||
- Mnemonic == "vudot" || Mnemonic == "vsdot")
+ Mnemonic == "vudot" || Mnemonic == "vsdot" ||
+ Mnemonic == "vcmla" || Mnemonic == "vcadd")
return Mnemonic;
// First, split out any predication code. Ignore mnemonics we know aren't
@@ -5521,7 +5554,8 @@
Mnemonic.startswith("sha1") || Mnemonic.startswith("sha256") ||
(FullInst.startswith("vmull") && FullInst.endswith(".p64")) ||
Mnemonic == "vmovx" || Mnemonic == "vins" ||
- Mnemonic == "vudot" || Mnemonic == "vsdot") {
+ Mnemonic == "vudot" || Mnemonic == "vsdot" ||
+ Mnemonic == "vcmla" || Mnemonic == "vcadd") {
// These mnemonics are never predicable
CanAcceptPredicationCode = false;
} else if (!isThumb()) {
@@ -9155,6 +9189,10 @@
return Error(ErrorLoc, "alignment must be 64, 128, 256 or omitted");
}
}
+ case Match_InvalidComplexRotationEven:
+ return Error(IDLoc, "complex rotation must be 0, 90, 180 or 270");
+ case Match_InvalidComplexRotationOdd:
+ return Error(IDLoc, "complex rotation must be 90 or 270");
}
llvm_unreachable("Implement any new match types added!");