[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/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 57d57af..3e24f0f 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -7746,6 +7746,21 @@
return Builder.CreateCall(F, {Val, Predicate, BasePtr});
}
+constexpr unsigned SVEBitsPerBlock = 128;
+
+static llvm::VectorType* getSVEVectorForElementType(llvm::Type *EltTy) {
+ unsigned NumElts = SVEBitsPerBlock / EltTy->getScalarSizeInBits();
+ return llvm::VectorType::get(EltTy, { NumElts, true });
+}
+
+// Limit the usage of scalable llvm IR generated by the ACLE by using the
+// sve dup.x intrinsic instead of IRBuilder::CreateVectorSplat.
+Value *CodeGenFunction::EmitSVEDupX(Value* Scalar) {
+ auto F = CGM.getIntrinsic(Intrinsic::aarch64_sve_dup_x,
+ getSVEVectorForElementType(Scalar->getType()));
+ return Builder.CreateCall(F, Scalar);
+}
+
static void InsertExplicitZeroOperand(CGBuilderTy &Builder, llvm::Type *Ty,
SmallVectorImpl<Value *> &Ops) {
auto *SplatZero = Constant::getNullValue(Ty);
@@ -7816,6 +7831,12 @@
}
}
+ // Splat scalar operand to vector (intrinsics with _n infix)
+ if (TypeFlags.hasSplatOperand()) {
+ unsigned OpNo = TypeFlags.getSplatOperand();
+ Ops[OpNo] = EmitSVEDupX(Ops[OpNo]);
+ }
+
// Predicated intrinsics with _z suffix need a select w/ zeroinitializer.
if (TypeFlags.getMergeType() == SVETypeFlags::MergeZero) {
llvm::Type *OpndTy = Ops[1]->getType();