summaryrefslogtreecommitdiff
path: root/clang/lib/CodeGen/CGExprScalar.cpp
diff options
context:
space:
mode:
authorBradley Smith <bradley.smith@arm.com>2021-07-26 10:34:08 +0000
committerBradley Smith <bradley.smith@arm.com>2021-08-04 16:10:37 +0000
commite57e1e4e00264b77b2b35ad2bf419a48aecdd6bc (patch)
tree85a0a4a20e1faed7eb6a1b0dc7835016dacaacd9 /clang/lib/CodeGen/CGExprScalar.cpp
parent66d4430492131a2205f159071c15e90c10e2fced (diff)
[clang][AArch64][SVE] Avoid going through memory for fixed/scalable predicate casts
For fixed SVE types, predicates are represented using vectors of i8, where as for scalable types they are represented using vectors of i1. We can avoid going through memory for casts between these by bitcasting the i1 scalable vectors to/from a scalable i8 vector of matching size, which can then use the existing vector insert/extract logic. Differential Revision: https://reviews.llvm.org/D106860
Diffstat (limited to 'clang/lib/CodeGen/CGExprScalar.cpp')
-rw-r--r--clang/lib/CodeGen/CGExprScalar.cpp34
1 files changed, 28 insertions, 6 deletions
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp
index 418f23bd1a97..e47701915f2f 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -2063,11 +2063,25 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
// perform the bitcast.
if (const auto *FixedSrc = dyn_cast<llvm::FixedVectorType>(SrcTy)) {
if (const auto *ScalableDst = dyn_cast<llvm::ScalableVectorType>(DstTy)) {
+ // If we are casting a fixed i8 vector to a scalable 16 x i1 predicate
+ // vector, use a vector insert and bitcast the result.
+ bool NeedsBitCast = false;
+ auto PredType = llvm::ScalableVectorType::get(Builder.getInt1Ty(), 16);
+ llvm::Type *OrigType = DstTy;
+ if (ScalableDst == PredType &&
+ FixedSrc->getElementType() == Builder.getInt8Ty()) {
+ DstTy = llvm::ScalableVectorType::get(Builder.getInt8Ty(), 2);
+ ScalableDst = dyn_cast<llvm::ScalableVectorType>(DstTy);
+ NeedsBitCast = true;
+ }
if (FixedSrc->getElementType() == ScalableDst->getElementType()) {
llvm::Value *UndefVec = llvm::UndefValue::get(DstTy);
llvm::Value *Zero = llvm::Constant::getNullValue(CGF.CGM.Int64Ty);
- return Builder.CreateInsertVector(DstTy, UndefVec, Src, Zero,
- "castScalableSve");
+ llvm::Value *Result = Builder.CreateInsertVector(
+ DstTy, UndefVec, Src, Zero, "castScalableSve");
+ if (NeedsBitCast)
+ Result = Builder.CreateBitCast(Result, OrigType);
+ return Result;
}
}
}
@@ -2077,6 +2091,15 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
// perform the bitcast.
if (const auto *ScalableSrc = dyn_cast<llvm::ScalableVectorType>(SrcTy)) {
if (const auto *FixedDst = dyn_cast<llvm::FixedVectorType>(DstTy)) {
+ // If we are casting a scalable 16 x i1 predicate vector to a fixed i8
+ // vector, bitcast the source and use a vector extract.
+ auto PredType = llvm::ScalableVectorType::get(Builder.getInt1Ty(), 16);
+ if (ScalableSrc == PredType &&
+ FixedDst->getElementType() == Builder.getInt8Ty()) {
+ SrcTy = llvm::ScalableVectorType::get(Builder.getInt8Ty(), 2);
+ ScalableSrc = dyn_cast<llvm::ScalableVectorType>(SrcTy);
+ Src = Builder.CreateBitCast(Src, SrcTy);
+ }
if (ScalableSrc->getElementType() == FixedDst->getElementType()) {
llvm::Value *Zero = llvm::Constant::getNullValue(CGF.CGM.Int64Ty);
return Builder.CreateExtractVector(DstTy, Src, Zero, "castFixedSve");
@@ -2087,10 +2110,9 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
// Perform VLAT <-> VLST bitcast through memory.
// TODO: since the llvm.experimental.vector.{insert,extract} intrinsics
// require the element types of the vectors to be the same, we
- // need to keep this around for casting between predicates, or more
- // generally for bitcasts between VLAT <-> VLST where the element
- // types of the vectors are not the same, until we figure out a better
- // way of doing these casts.
+ // need to keep this around for bitcasts between VLAT <-> VLST where
+ // the element types of the vectors are not the same, until we figure
+ // out a better way of doing these casts.
if ((isa<llvm::FixedVectorType>(SrcTy) &&
isa<llvm::ScalableVectorType>(DstTy)) ||
(isa<llvm::ScalableVectorType>(SrcTy) &&