diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.h b/llvm/lib/Target/AArch64/AArch64ISelLowering.h --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.h +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.h @@ -1201,7 +1201,8 @@ unsigned Depth) const override; bool isTargetCanonicalConstantNode(SDValue Op) const override; - + bool decomposeMulByConstant(LLVMContext &Context, EVT VT, + SDValue C) const override; // With the exception of data-predicate transitions, no instructions are // required to cast between legal scalable vector types. However: // 1. Packed and unpacked types have different bit lengths, meaning BITCAST diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -24327,6 +24327,19 @@ return Ty1 == Ty2 && (Ty1 == LLT::scalar(32) || Ty1 == LLT::scalar(64)); } +bool AArch64TargetLowering::decomposeMulByConstant(LLVMContext &Context, EVT VT, + SDValue C) const { + if (VT == MVT::v2i64) + return true; + + APInt MulC; + if (!ISD::isConstantSplatVector(C.getNode(), MulC)) + return false; + + return (MulC + 1).isPowerOf2() || (MulC - 1).isPowerOf2() || + (1 - MulC).isPowerOf2() || (-(MulC + 1)).isPowerOf2(); +} + bool AArch64TargetLowering::isComplexDeinterleavingSupported() const { return Subtarget->hasComplxNum(); }