[SveEmitter] Add support for _n form builtins
The ACLE has builtins that take a scalar value that is to be expanded
into a vector by the operation. While the ISA may have an instruction
that takes an immediate or a scalar to represent this, the LLVM IR
intrinsic may not, so Clang will have to splat the scalar value.
This patch also adds the _n forms for svabd, svadd, svdiv, svdivr,
svmax, svmin, svmul, svmulh, svub and svsubr.
Reviewers: SjoerdMeijer, efriedma, rovka
Reviewed By: SjoerdMeijer
Tags: #clang
Differential Revision: https://reviews.llvm.org/D77594
diff --git a/clang/utils/TableGen/SveEmitter.cpp b/clang/utils/TableGen/SveEmitter.cpp
index a32345e..b51047f 100644
--- a/clang/utils/TableGen/SveEmitter.cpp
+++ b/clang/utils/TableGen/SveEmitter.cpp
@@ -208,6 +208,21 @@
return BrOpen != std::string::npos && BrClose != std::string::npos;
}
+ /// Return true if the intrinsic takes a splat operand.
+ bool hasSplat() const {
+ // These prototype modifiers are described in arm_sve.td.
+ return Proto.find_first_of("ajfrKLR") != std::string::npos;
+ }
+
+ /// Return the parameter index of the splat operand.
+ unsigned getSplatIdx() const {
+ // These prototype modifiers are described in arm_sve.td.
+ auto Idx = Proto.find_first_of("ajfrKLR");
+ assert(Idx != std::string::npos && Idx > 0 &&
+ "Prototype has no splat operand");
+ return Idx - 1;
+ }
+
/// Emits the intrinsic declaration to the ostream.
void emitIntrinsic(raw_ostream &OS) const;
@@ -278,6 +293,12 @@
return encodeFlag(MT, "MergeTypeMask");
}
+ // Returns the SVETypeFlags for the given splat operand.
+ unsigned encodeSplatOperand(unsigned SplatIdx) {
+ assert(SplatIdx < 7 && "SplatIdx out of encodable range");
+ return encodeFlag(SplatIdx + 1, "SplatOperandMask");
+ }
+
// Returns the SVETypeFlags value for the given SVEType.
uint64_t encodeTypeFlags(const SVEType &T);
@@ -476,6 +497,10 @@
Bitwidth = 16;
ElementBitwidth = 1;
break;
+ case 'a':
+ Bitwidth = ElementBitwidth;
+ NumVectors = 0;
+ break;
case 'u':
Predicate = false;
Signed = false;
@@ -631,6 +656,8 @@
this->Flags |= Emitter.encodeTypeFlags(BaseType);
this->Flags |= Emitter.encodeMemoryElementType(MemoryElementTy);
this->Flags |= Emitter.encodeMergeType(MergeTy);
+ if (hasSplat())
+ this->Flags |= Emitter.encodeSplatOperand(getSplatIdx());
}
std::string Intrinsic::getBuiltinTypeStr() {