-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[TTI][TLI] Support scalable immediates with isLegalAddImmediate #84173
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[TTI][TLI] Support scalable immediates with isLegalAddImmediate #84173
Conversation
@llvm/pr-subscribers-backend-loongarch @llvm/pr-subscribers-backend-systemz Author: Graham Hunter (huntergr-arm) ChangesAdds a second parameter (default to 0) to isLegalAddImmediate, to represent a scalable immediate. Extends the AArch64 implementation to match immediates based on vscale * base_register_size * immediate in the range [-32,31]. See the vscale-aware LSR RFC for reference: https://discourse.llvm.org/t/rfc-vscale-aware-loopstrengthreduce/77131 Full diff: https://github.com/llvm/llvm-project/pull/84173.diff 21 Files Affected:
diff --git a/llvm/include/llvm/Analysis/TargetTransformInfo.h b/llvm/include/llvm/Analysis/TargetTransformInfo.h
index 4eab357f1b33b6..f9dd7bbc3dcec8 100644
--- a/llvm/include/llvm/Analysis/TargetTransformInfo.h
+++ b/llvm/include/llvm/Analysis/TargetTransformInfo.h
@@ -694,7 +694,7 @@ class TargetTransformInfo {
/// Return true if the specified immediate is legal add immediate, that
/// is the target has add instructions which can add a register with the
/// immediate without having to materialize the immediate into a register.
- bool isLegalAddImmediate(int64_t Imm) const;
+ bool isLegalAddImmediate(int64_t Imm, int64_t ScalableImm = 0) const;
/// Return true if the specified immediate is legal icmp immediate,
/// that is the target has icmp instructions which can compare a register
@@ -1834,7 +1834,7 @@ class TargetTransformInfo::Concept {
APInt &UndefElts, APInt &UndefElts2, APInt &UndefElts3,
std::function<void(Instruction *, unsigned, APInt, APInt &)>
SimplifyAndSetOp) = 0;
- virtual bool isLegalAddImmediate(int64_t Imm) = 0;
+ virtual bool isLegalAddImmediate(int64_t Imm, int64_t ScalableImm) = 0;
virtual bool isLegalICmpImmediate(int64_t Imm) = 0;
virtual bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV,
int64_t BaseOffset, bool HasBaseReg,
@@ -2292,8 +2292,8 @@ class TargetTransformInfo::Model final : public TargetTransformInfo::Concept {
IC, II, DemandedElts, UndefElts, UndefElts2, UndefElts3,
SimplifyAndSetOp);
}
- bool isLegalAddImmediate(int64_t Imm) override {
- return Impl.isLegalAddImmediate(Imm);
+ bool isLegalAddImmediate(int64_t Imm, int64_t ScalableImm) override {
+ return Impl.isLegalAddImmediate(Imm, ScalableImm);
}
bool isLegalICmpImmediate(int64_t Imm) override {
return Impl.isLegalICmpImmediate(Imm);
diff --git a/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h b/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h
index 95fb13d1c97154..7fbdfe3fc68437 100644
--- a/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h
+++ b/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h
@@ -214,7 +214,9 @@ class TargetTransformInfoImplBase {
void getPeelingPreferences(Loop *, ScalarEvolution &,
TTI::PeelingPreferences &) const {}
- bool isLegalAddImmediate(int64_t Imm) const { return false; }
+ bool isLegalAddImmediate(int64_t Imm, int64_t ScalableImm) const {
+ return false;
+ }
bool isLegalICmpImmediate(int64_t Imm) const { return false; }
diff --git a/llvm/include/llvm/CodeGen/BasicTTIImpl.h b/llvm/include/llvm/CodeGen/BasicTTIImpl.h
index 61f6564e8cd79b..ac8cd28689d35a 100644
--- a/llvm/include/llvm/CodeGen/BasicTTIImpl.h
+++ b/llvm/include/llvm/CodeGen/BasicTTIImpl.h
@@ -324,8 +324,8 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
return nullptr;
}
- bool isLegalAddImmediate(int64_t imm) {
- return getTLI()->isLegalAddImmediate(imm);
+ bool isLegalAddImmediate(int64_t Imm, int64_t ScalableImm) {
+ return getTLI()->isLegalAddImmediate(Imm, ScalableImm);
}
bool isLegalICmpImmediate(int64_t imm) {
diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h
index 2f164a460db843..57844dd82d6410 100644
--- a/llvm/include/llvm/CodeGen/TargetLowering.h
+++ b/llvm/include/llvm/CodeGen/TargetLowering.h
@@ -2766,8 +2766,8 @@ class TargetLoweringBase {
/// Return true if the specified immediate is legal add immediate, that is the
/// target has add instructions which can add a register with the immediate
/// without having to materialize the immediate into a register.
- virtual bool isLegalAddImmediate(int64_t) const {
- return true;
+ virtual bool isLegalAddImmediate(int64_t, int64_t ScalableImm = 0) const {
+ return !ScalableImm;
}
/// Return true if the specified immediate is legal for the value input of a
diff --git a/llvm/lib/Analysis/TargetTransformInfo.cpp b/llvm/lib/Analysis/TargetTransformInfo.cpp
index 15311be4dba277..8791ae4c3744e5 100644
--- a/llvm/lib/Analysis/TargetTransformInfo.cpp
+++ b/llvm/lib/Analysis/TargetTransformInfo.cpp
@@ -391,8 +391,9 @@ void TargetTransformInfo::getPeelingPreferences(Loop *L, ScalarEvolution &SE,
return TTIImpl->getPeelingPreferences(L, SE, PP);
}
-bool TargetTransformInfo::isLegalAddImmediate(int64_t Imm) const {
- return TTIImpl->isLegalAddImmediate(Imm);
+bool TargetTransformInfo::isLegalAddImmediate(int64_t Imm,
+ int64_t ScalableImm) const {
+ return TTIImpl->isLegalAddImmediate(Imm, ScalableImm);
}
bool TargetTransformInfo::isLegalICmpImmediate(int64_t Imm) const {
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 2290223a06f8ef..e53e8ce6a3d227 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -16559,7 +16559,25 @@ LLT AArch64TargetLowering::getOptimalMemOpLLT(
}
// 12-bit optionally shifted immediates are legal for adds.
-bool AArch64TargetLowering::isLegalAddImmediate(int64_t Immed) const {
+bool AArch64TargetLowering::isLegalAddImmediate(int64_t Immed,
+ int64_t ScalableImm) const {
+ if (ScalableImm) {
+ // Scalable immediates require SVE support; mixed fixed + scalable
+ // immediates are not supported by the current instructions.
+ if (Immed || !Subtarget->hasSVE())
+ return false;
+
+ // addvl's immediates are in terms of the number of bytes in a register.
+ // Since there are 16 in the base supported size (128bits), we need to
+ // divide the immediate by that much to give us a useful immediate to
+ // multiply by vscale. We can't have a remainder as a result of this.
+ if (ScalableImm % 16 != 0)
+ return false;
+ int64_t Imm = ScalableImm / 16;
+
+ return Imm >= -32 && Imm <= 31;
+ }
+
if (Immed == std::numeric_limits<int64_t>::min()) {
LLVM_DEBUG(dbgs() << "Illegal add imm " << Immed
<< ": avoid UB for INT64_MIN\n");
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.h b/llvm/lib/Target/AArch64/AArch64ISelLowering.h
index 68341c199e0a2a..adec93d7e6aea1 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.h
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.h
@@ -688,7 +688,7 @@ class AArch64TargetLowering : public TargetLowering {
bool lowerInterleaveIntrinsicToStore(IntrinsicInst *II,
StoreInst *SI) const override;
- bool isLegalAddImmediate(int64_t) const override;
+ bool isLegalAddImmediate(int64_t Imm, int64_t ScalableImm = 0) const override;
bool isLegalICmpImmediate(int64_t) const override;
bool isMulAddWithConstProfitable(SDValue AddNode,
diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp
index dc81178311b6d8..65a15f959ff4d9 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.cpp
+++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp
@@ -19722,7 +19722,8 @@ bool ARMTargetLowering::isLegalICmpImmediate(int64_t Imm) const {
/// *or sub* immediate, that is the target has add or sub instructions which can
/// add a register with the immediate without having to materialize the
/// immediate into a register.
-bool ARMTargetLowering::isLegalAddImmediate(int64_t Imm) const {
+bool ARMTargetLowering::isLegalAddImmediate(int64_t Imm,
+ int64_t ScalableImm) const {
// Same encoding for add/sub, just flip the sign.
int64_t AbsImm = std::abs(Imm);
if (!Subtarget->isThumb())
diff --git a/llvm/lib/Target/ARM/ARMISelLowering.h b/llvm/lib/Target/ARM/ARMISelLowering.h
index b13ddf697cb806..70bbb15a1772f8 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.h
+++ b/llvm/lib/Target/ARM/ARMISelLowering.h
@@ -494,7 +494,8 @@ class VectorType;
/// add immediate, that is the target has add instructions which can
/// add a register and the immediate without having to materialize
/// the immediate into a register.
- bool isLegalAddImmediate(int64_t Imm) const override;
+ bool isLegalAddImmediate(int64_t Imm,
+ int64_t ScalableImm = 0) const override;
/// getPreIndexedAddressParts - returns true by value, base pointer and
/// offset pointer and addressing mode by reference if the node's address
diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
index c8e955a23336d7..f975fc52b2f774 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
@@ -4933,7 +4933,8 @@ bool LoongArchTargetLowering::isLegalICmpImmediate(int64_t Imm) const {
return isInt<12>(Imm);
}
-bool LoongArchTargetLowering::isLegalAddImmediate(int64_t Imm) const {
+bool LoongArchTargetLowering::isLegalAddImmediate(int64_t Imm,
+ int64_t ScalableImm) const {
return isInt<12>(Imm);
}
diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
index 9e9ac0b8269291..b59a4dfcd9ead3 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
@@ -222,7 +222,7 @@ class LoongArchTargetLowering : public TargetLowering {
Instruction *I = nullptr) const override;
bool isLegalICmpImmediate(int64_t Imm) const override;
- bool isLegalAddImmediate(int64_t Imm) const override;
+ bool isLegalAddImmediate(int64_t Imm, int64_t ScalableImm = 0) const override;
bool isZExtFree(SDValue Val, EVT VT2) const override;
bool isSExtCheaperThanZExt(EVT SrcVT, EVT DstVT) const override;
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index 68c80dd9aa5c76..2aaf7b24d52544 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -17300,7 +17300,8 @@ bool PPCTargetLowering::isLegalICmpImmediate(int64_t Imm) const {
return isInt<16>(Imm) || isUInt<16>(Imm);
}
-bool PPCTargetLowering::isLegalAddImmediate(int64_t Imm) const {
+bool PPCTargetLowering::isLegalAddImmediate(int64_t Imm,
+ int64_t ScalableImm) const {
return isInt<16>(Imm) || isUInt<16>(Imm);
}
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.h b/llvm/lib/Target/PowerPC/PPCISelLowering.h
index 0bdfdcd15441f4..a1b404bd655b36 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.h
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.h
@@ -1023,7 +1023,8 @@ namespace llvm {
/// add immediate, that is the target has add instructions which can
/// add a register and the immediate without having to materialize
/// the immediate into a register.
- bool isLegalAddImmediate(int64_t Imm) const override;
+ bool isLegalAddImmediate(int64_t Imm,
+ int64_t ScalableImm = 0) const override;
/// isTruncateFree - Return true if it's free to truncate a value of
/// type Ty1 to type Ty2. e.g. On PPC it's free to truncate a i64 value in
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 4c3dc63afd878d..c6b02b8b26856b 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -1783,8 +1783,9 @@ bool RISCVTargetLowering::isLegalICmpImmediate(int64_t Imm) const {
return isInt<12>(Imm);
}
-bool RISCVTargetLowering::isLegalAddImmediate(int64_t Imm) const {
- return isInt<12>(Imm);
+bool RISCVTargetLowering::isLegalAddImmediate(int64_t Imm,
+ int64_t ScalableImm) const {
+ return !ScalableImm && isInt<12>(Imm);
}
// On RV32, 64-bit integers are split into their high and low parts and held
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.h b/llvm/lib/Target/RISCV/RISCVISelLowering.h
index f90cb4df604761..61fb5809c9b8dd 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.h
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.h
@@ -475,7 +475,7 @@ class RISCVTargetLowering : public TargetLowering {
unsigned AS,
Instruction *I = nullptr) const override;
bool isLegalICmpImmediate(int64_t Imm) const override;
- bool isLegalAddImmediate(int64_t Imm) const override;
+ bool isLegalAddImmediate(int64_t Imm, int64_t ScalableImm = 0) const override;
bool isTruncateFree(Type *SrcTy, Type *DstTy) const override;
bool isTruncateFree(EVT SrcVT, EVT DstVT) const override;
bool isZExtFree(SDValue Val, EVT VT2) const override;
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
index 3b85a6ac0371ed..a2aa33ff059489 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
@@ -944,7 +944,8 @@ bool SystemZTargetLowering::isLegalICmpImmediate(int64_t Imm) const {
return isInt<32>(Imm) || isUInt<32>(Imm);
}
-bool SystemZTargetLowering::isLegalAddImmediate(int64_t Imm) const {
+bool SystemZTargetLowering::isLegalAddImmediate(int64_t Imm,
+ int64_t ScalableImm) const {
// We can use ALGFI or SLGFI.
return isUInt<32>(Imm) || isUInt<32>(-Imm);
}
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.h b/llvm/lib/Target/SystemZ/SystemZISelLowering.h
index baf4ba41654879..274b23b4d28935 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.h
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.h
@@ -477,7 +477,7 @@ class SystemZTargetLowering : public TargetLowering {
AtomicExpansionKind
shouldExpandAtomicRMWInIR(AtomicRMWInst *RMW) const override;
bool isLegalICmpImmediate(int64_t Imm) const override;
- bool isLegalAddImmediate(int64_t Imm) const override;
+ bool isLegalAddImmediate(int64_t Imm, int64_t ScalableImm = 0) const override;
bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty,
unsigned AS,
Instruction *I = nullptr) const override;
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 6eaaec407dbb08..d5f5ef24e56d5d 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -33882,7 +33882,8 @@ bool X86TargetLowering::isLegalICmpImmediate(int64_t Imm) const {
return isInt<32>(Imm);
}
-bool X86TargetLowering::isLegalAddImmediate(int64_t Imm) const {
+bool X86TargetLowering::isLegalAddImmediate(int64_t Imm,
+ int64_t ScalableImm) const {
// Can also use sub to handle negated immediates.
return isInt<32>(Imm);
}
diff --git a/llvm/lib/Target/X86/X86ISelLowering.h b/llvm/lib/Target/X86/X86ISelLowering.h
index fe1943b5760844..b3cccee0e67bf1 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.h
+++ b/llvm/lib/Target/X86/X86ISelLowering.h
@@ -1329,7 +1329,8 @@ namespace llvm {
/// add immediate, that is the target has add instructions which can
/// add a register and the immediate without having to materialize
/// the immediate into a register.
- bool isLegalAddImmediate(int64_t Imm) const override;
+ bool isLegalAddImmediate(int64_t Imm,
+ int64_t ScalableImm = 0) const override;
bool isLegalStoreImmediate(int64_t Imm) const override;
diff --git a/llvm/unittests/Target/AArch64/CMakeLists.txt b/llvm/unittests/Target/AArch64/CMakeLists.txt
index dacd919ba1e33b..64ab991ac479a4 100644
--- a/llvm/unittests/Target/AArch64/CMakeLists.txt
+++ b/llvm/unittests/Target/AArch64/CMakeLists.txt
@@ -29,6 +29,7 @@ add_llvm_target_unittest(AArch64Tests
MatrixRegisterAliasing.cpp
SMEAttributesTest.cpp
AArch64SVESchedPseudoTest.cpp
+ Immediates.cpp
)
set_property(TARGET AArch64Tests PROPERTY FOLDER "Tests/UnitTests/TargetTests")
diff --git a/llvm/unittests/Target/AArch64/Immediates.cpp b/llvm/unittests/Target/AArch64/Immediates.cpp
new file mode 100644
index 00000000000000..5f5895e44c6110
--- /dev/null
+++ b/llvm/unittests/Target/AArch64/Immediates.cpp
@@ -0,0 +1,75 @@
+#include "AArch64Subtarget.h"
+#include "AArch64TargetMachine.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/MC/TargetRegistry.h"
+#include "llvm/Support/TargetSelect.h"
+
+#include "gtest/gtest.h"
+#include <initializer_list>
+#include <memory>
+
+using namespace llvm;
+
+namespace {
+
+struct TestCase {
+ int64_t FixedImm;
+ int64_t ScalableImm;
+ bool Result;
+};
+
+const std::initializer_list<TestCase> Tests = {
+ // FixedImm, ScalableImm, Result
+ // No change, easily 'supported'
+ {0, 0, true},
+
+ // Simple fixed immediate cases
+ // +8
+ {8, 0, true},
+ // -16
+ {-16, 0, true},
+
+ // Scalable; addvl increments by whole registers, range [-32,31]
+ // +(16 * vscale), one register's worth
+ {0, 16, true},
+ // +(8 * vscale), half a register's worth
+ {0, 8, false},
+ // -(32 * 16 * vscale)
+ {0, -512, true},
+ // -(33 * 16 * vscale)
+ {0, -528, false},
+ // +(31 * 16 * vscale)
+ {0, 496, true},
+ // +(32 * 16 * vscale)
+ {0, 512, false},
+
+ // Mixed; not supported.
+ // +(16 + (16 * vscale)) -- one register's worth + 16
+ {16, 16, false},
+};
+} // namespace
+
+TEST(Immediates, Immediates) {
+ LLVMInitializeAArch64TargetInfo();
+ LLVMInitializeAArch64Target();
+ LLVMInitializeAArch64TargetMC();
+
+ std::string Error;
+ auto TT = Triple::normalize("aarch64");
+ const Target *T = TargetRegistry::lookupTarget(TT, Error);
+
+ std::unique_ptr<TargetMachine> TM(
+ T->createTargetMachine(TT, "generic", "+sve", TargetOptions(),
+ std::nullopt, std::nullopt,
+ CodeGenOptLevel::Default));
+ AArch64Subtarget ST(TM->getTargetTriple(), TM->getTargetCPU(),
+ TM->getTargetCPU(), TM->getTargetFeatureString(), *TM,
+ true);
+
+ auto *TLI = ST.getTargetLowering();
+
+ for (const auto &Test : Tests) {
+ ASSERT_EQ(TLI->isLegalAddImmediate(Test.FixedImm, Test.ScalableImm),
+ Test.Result);
+ }
+}
|
@llvm/pr-subscribers-backend-x86 Author: Graham Hunter (huntergr-arm) ChangesAdds a second parameter (default to 0) to isLegalAddImmediate, to represent a scalable immediate. Extends the AArch64 implementation to match immediates based on vscale * base_register_size * immediate in the range [-32,31]. See the vscale-aware LSR RFC for reference: https://discourse.llvm.org/t/rfc-vscale-aware-loopstrengthreduce/77131 Full diff: https://github.com/llvm/llvm-project/pull/84173.diff 21 Files Affected:
diff --git a/llvm/include/llvm/Analysis/TargetTransformInfo.h b/llvm/include/llvm/Analysis/TargetTransformInfo.h
index 4eab357f1b33b6..f9dd7bbc3dcec8 100644
--- a/llvm/include/llvm/Analysis/TargetTransformInfo.h
+++ b/llvm/include/llvm/Analysis/TargetTransformInfo.h
@@ -694,7 +694,7 @@ class TargetTransformInfo {
/// Return true if the specified immediate is legal add immediate, that
/// is the target has add instructions which can add a register with the
/// immediate without having to materialize the immediate into a register.
- bool isLegalAddImmediate(int64_t Imm) const;
+ bool isLegalAddImmediate(int64_t Imm, int64_t ScalableImm = 0) const;
/// Return true if the specified immediate is legal icmp immediate,
/// that is the target has icmp instructions which can compare a register
@@ -1834,7 +1834,7 @@ class TargetTransformInfo::Concept {
APInt &UndefElts, APInt &UndefElts2, APInt &UndefElts3,
std::function<void(Instruction *, unsigned, APInt, APInt &)>
SimplifyAndSetOp) = 0;
- virtual bool isLegalAddImmediate(int64_t Imm) = 0;
+ virtual bool isLegalAddImmediate(int64_t Imm, int64_t ScalableImm) = 0;
virtual bool isLegalICmpImmediate(int64_t Imm) = 0;
virtual bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV,
int64_t BaseOffset, bool HasBaseReg,
@@ -2292,8 +2292,8 @@ class TargetTransformInfo::Model final : public TargetTransformInfo::Concept {
IC, II, DemandedElts, UndefElts, UndefElts2, UndefElts3,
SimplifyAndSetOp);
}
- bool isLegalAddImmediate(int64_t Imm) override {
- return Impl.isLegalAddImmediate(Imm);
+ bool isLegalAddImmediate(int64_t Imm, int64_t ScalableImm) override {
+ return Impl.isLegalAddImmediate(Imm, ScalableImm);
}
bool isLegalICmpImmediate(int64_t Imm) override {
return Impl.isLegalICmpImmediate(Imm);
diff --git a/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h b/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h
index 95fb13d1c97154..7fbdfe3fc68437 100644
--- a/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h
+++ b/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h
@@ -214,7 +214,9 @@ class TargetTransformInfoImplBase {
void getPeelingPreferences(Loop *, ScalarEvolution &,
TTI::PeelingPreferences &) const {}
- bool isLegalAddImmediate(int64_t Imm) const { return false; }
+ bool isLegalAddImmediate(int64_t Imm, int64_t ScalableImm) const {
+ return false;
+ }
bool isLegalICmpImmediate(int64_t Imm) const { return false; }
diff --git a/llvm/include/llvm/CodeGen/BasicTTIImpl.h b/llvm/include/llvm/CodeGen/BasicTTIImpl.h
index 61f6564e8cd79b..ac8cd28689d35a 100644
--- a/llvm/include/llvm/CodeGen/BasicTTIImpl.h
+++ b/llvm/include/llvm/CodeGen/BasicTTIImpl.h
@@ -324,8 +324,8 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
return nullptr;
}
- bool isLegalAddImmediate(int64_t imm) {
- return getTLI()->isLegalAddImmediate(imm);
+ bool isLegalAddImmediate(int64_t Imm, int64_t ScalableImm) {
+ return getTLI()->isLegalAddImmediate(Imm, ScalableImm);
}
bool isLegalICmpImmediate(int64_t imm) {
diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h
index 2f164a460db843..57844dd82d6410 100644
--- a/llvm/include/llvm/CodeGen/TargetLowering.h
+++ b/llvm/include/llvm/CodeGen/TargetLowering.h
@@ -2766,8 +2766,8 @@ class TargetLoweringBase {
/// Return true if the specified immediate is legal add immediate, that is the
/// target has add instructions which can add a register with the immediate
/// without having to materialize the immediate into a register.
- virtual bool isLegalAddImmediate(int64_t) const {
- return true;
+ virtual bool isLegalAddImmediate(int64_t, int64_t ScalableImm = 0) const {
+ return !ScalableImm;
}
/// Return true if the specified immediate is legal for the value input of a
diff --git a/llvm/lib/Analysis/TargetTransformInfo.cpp b/llvm/lib/Analysis/TargetTransformInfo.cpp
index 15311be4dba277..8791ae4c3744e5 100644
--- a/llvm/lib/Analysis/TargetTransformInfo.cpp
+++ b/llvm/lib/Analysis/TargetTransformInfo.cpp
@@ -391,8 +391,9 @@ void TargetTransformInfo::getPeelingPreferences(Loop *L, ScalarEvolution &SE,
return TTIImpl->getPeelingPreferences(L, SE, PP);
}
-bool TargetTransformInfo::isLegalAddImmediate(int64_t Imm) const {
- return TTIImpl->isLegalAddImmediate(Imm);
+bool TargetTransformInfo::isLegalAddImmediate(int64_t Imm,
+ int64_t ScalableImm) const {
+ return TTIImpl->isLegalAddImmediate(Imm, ScalableImm);
}
bool TargetTransformInfo::isLegalICmpImmediate(int64_t Imm) const {
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 2290223a06f8ef..e53e8ce6a3d227 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -16559,7 +16559,25 @@ LLT AArch64TargetLowering::getOptimalMemOpLLT(
}
// 12-bit optionally shifted immediates are legal for adds.
-bool AArch64TargetLowering::isLegalAddImmediate(int64_t Immed) const {
+bool AArch64TargetLowering::isLegalAddImmediate(int64_t Immed,
+ int64_t ScalableImm) const {
+ if (ScalableImm) {
+ // Scalable immediates require SVE support; mixed fixed + scalable
+ // immediates are not supported by the current instructions.
+ if (Immed || !Subtarget->hasSVE())
+ return false;
+
+ // addvl's immediates are in terms of the number of bytes in a register.
+ // Since there are 16 in the base supported size (128bits), we need to
+ // divide the immediate by that much to give us a useful immediate to
+ // multiply by vscale. We can't have a remainder as a result of this.
+ if (ScalableImm % 16 != 0)
+ return false;
+ int64_t Imm = ScalableImm / 16;
+
+ return Imm >= -32 && Imm <= 31;
+ }
+
if (Immed == std::numeric_limits<int64_t>::min()) {
LLVM_DEBUG(dbgs() << "Illegal add imm " << Immed
<< ": avoid UB for INT64_MIN\n");
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.h b/llvm/lib/Target/AArch64/AArch64ISelLowering.h
index 68341c199e0a2a..adec93d7e6aea1 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.h
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.h
@@ -688,7 +688,7 @@ class AArch64TargetLowering : public TargetLowering {
bool lowerInterleaveIntrinsicToStore(IntrinsicInst *II,
StoreInst *SI) const override;
- bool isLegalAddImmediate(int64_t) const override;
+ bool isLegalAddImmediate(int64_t Imm, int64_t ScalableImm = 0) const override;
bool isLegalICmpImmediate(int64_t) const override;
bool isMulAddWithConstProfitable(SDValue AddNode,
diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp
index dc81178311b6d8..65a15f959ff4d9 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.cpp
+++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp
@@ -19722,7 +19722,8 @@ bool ARMTargetLowering::isLegalICmpImmediate(int64_t Imm) const {
/// *or sub* immediate, that is the target has add or sub instructions which can
/// add a register with the immediate without having to materialize the
/// immediate into a register.
-bool ARMTargetLowering::isLegalAddImmediate(int64_t Imm) const {
+bool ARMTargetLowering::isLegalAddImmediate(int64_t Imm,
+ int64_t ScalableImm) const {
// Same encoding for add/sub, just flip the sign.
int64_t AbsImm = std::abs(Imm);
if (!Subtarget->isThumb())
diff --git a/llvm/lib/Target/ARM/ARMISelLowering.h b/llvm/lib/Target/ARM/ARMISelLowering.h
index b13ddf697cb806..70bbb15a1772f8 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.h
+++ b/llvm/lib/Target/ARM/ARMISelLowering.h
@@ -494,7 +494,8 @@ class VectorType;
/// add immediate, that is the target has add instructions which can
/// add a register and the immediate without having to materialize
/// the immediate into a register.
- bool isLegalAddImmediate(int64_t Imm) const override;
+ bool isLegalAddImmediate(int64_t Imm,
+ int64_t ScalableImm = 0) const override;
/// getPreIndexedAddressParts - returns true by value, base pointer and
/// offset pointer and addressing mode by reference if the node's address
diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
index c8e955a23336d7..f975fc52b2f774 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
@@ -4933,7 +4933,8 @@ bool LoongArchTargetLowering::isLegalICmpImmediate(int64_t Imm) const {
return isInt<12>(Imm);
}
-bool LoongArchTargetLowering::isLegalAddImmediate(int64_t Imm) const {
+bool LoongArchTargetLowering::isLegalAddImmediate(int64_t Imm,
+ int64_t ScalableImm) const {
return isInt<12>(Imm);
}
diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
index 9e9ac0b8269291..b59a4dfcd9ead3 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
@@ -222,7 +222,7 @@ class LoongArchTargetLowering : public TargetLowering {
Instruction *I = nullptr) const override;
bool isLegalICmpImmediate(int64_t Imm) const override;
- bool isLegalAddImmediate(int64_t Imm) const override;
+ bool isLegalAddImmediate(int64_t Imm, int64_t ScalableImm = 0) const override;
bool isZExtFree(SDValue Val, EVT VT2) const override;
bool isSExtCheaperThanZExt(EVT SrcVT, EVT DstVT) const override;
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index 68c80dd9aa5c76..2aaf7b24d52544 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -17300,7 +17300,8 @@ bool PPCTargetLowering::isLegalICmpImmediate(int64_t Imm) const {
return isInt<16>(Imm) || isUInt<16>(Imm);
}
-bool PPCTargetLowering::isLegalAddImmediate(int64_t Imm) const {
+bool PPCTargetLowering::isLegalAddImmediate(int64_t Imm,
+ int64_t ScalableImm) const {
return isInt<16>(Imm) || isUInt<16>(Imm);
}
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.h b/llvm/lib/Target/PowerPC/PPCISelLowering.h
index 0bdfdcd15441f4..a1b404bd655b36 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.h
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.h
@@ -1023,7 +1023,8 @@ namespace llvm {
/// add immediate, that is the target has add instructions which can
/// add a register and the immediate without having to materialize
/// the immediate into a register.
- bool isLegalAddImmediate(int64_t Imm) const override;
+ bool isLegalAddImmediate(int64_t Imm,
+ int64_t ScalableImm = 0) const override;
/// isTruncateFree - Return true if it's free to truncate a value of
/// type Ty1 to type Ty2. e.g. On PPC it's free to truncate a i64 value in
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 4c3dc63afd878d..c6b02b8b26856b 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -1783,8 +1783,9 @@ bool RISCVTargetLowering::isLegalICmpImmediate(int64_t Imm) const {
return isInt<12>(Imm);
}
-bool RISCVTargetLowering::isLegalAddImmediate(int64_t Imm) const {
- return isInt<12>(Imm);
+bool RISCVTargetLowering::isLegalAddImmediate(int64_t Imm,
+ int64_t ScalableImm) const {
+ return !ScalableImm && isInt<12>(Imm);
}
// On RV32, 64-bit integers are split into their high and low parts and held
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.h b/llvm/lib/Target/RISCV/RISCVISelLowering.h
index f90cb4df604761..61fb5809c9b8dd 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.h
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.h
@@ -475,7 +475,7 @@ class RISCVTargetLowering : public TargetLowering {
unsigned AS,
Instruction *I = nullptr) const override;
bool isLegalICmpImmediate(int64_t Imm) const override;
- bool isLegalAddImmediate(int64_t Imm) const override;
+ bool isLegalAddImmediate(int64_t Imm, int64_t ScalableImm = 0) const override;
bool isTruncateFree(Type *SrcTy, Type *DstTy) const override;
bool isTruncateFree(EVT SrcVT, EVT DstVT) const override;
bool isZExtFree(SDValue Val, EVT VT2) const override;
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
index 3b85a6ac0371ed..a2aa33ff059489 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
@@ -944,7 +944,8 @@ bool SystemZTargetLowering::isLegalICmpImmediate(int64_t Imm) const {
return isInt<32>(Imm) || isUInt<32>(Imm);
}
-bool SystemZTargetLowering::isLegalAddImmediate(int64_t Imm) const {
+bool SystemZTargetLowering::isLegalAddImmediate(int64_t Imm,
+ int64_t ScalableImm) const {
// We can use ALGFI or SLGFI.
return isUInt<32>(Imm) || isUInt<32>(-Imm);
}
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.h b/llvm/lib/Target/SystemZ/SystemZISelLowering.h
index baf4ba41654879..274b23b4d28935 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.h
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.h
@@ -477,7 +477,7 @@ class SystemZTargetLowering : public TargetLowering {
AtomicExpansionKind
shouldExpandAtomicRMWInIR(AtomicRMWInst *RMW) const override;
bool isLegalICmpImmediate(int64_t Imm) const override;
- bool isLegalAddImmediate(int64_t Imm) const override;
+ bool isLegalAddImmediate(int64_t Imm, int64_t ScalableImm = 0) const override;
bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty,
unsigned AS,
Instruction *I = nullptr) const override;
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 6eaaec407dbb08..d5f5ef24e56d5d 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -33882,7 +33882,8 @@ bool X86TargetLowering::isLegalICmpImmediate(int64_t Imm) const {
return isInt<32>(Imm);
}
-bool X86TargetLowering::isLegalAddImmediate(int64_t Imm) const {
+bool X86TargetLowering::isLegalAddImmediate(int64_t Imm,
+ int64_t ScalableImm) const {
// Can also use sub to handle negated immediates.
return isInt<32>(Imm);
}
diff --git a/llvm/lib/Target/X86/X86ISelLowering.h b/llvm/lib/Target/X86/X86ISelLowering.h
index fe1943b5760844..b3cccee0e67bf1 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.h
+++ b/llvm/lib/Target/X86/X86ISelLowering.h
@@ -1329,7 +1329,8 @@ namespace llvm {
/// add immediate, that is the target has add instructions which can
/// add a register and the immediate without having to materialize
/// the immediate into a register.
- bool isLegalAddImmediate(int64_t Imm) const override;
+ bool isLegalAddImmediate(int64_t Imm,
+ int64_t ScalableImm = 0) const override;
bool isLegalStoreImmediate(int64_t Imm) const override;
diff --git a/llvm/unittests/Target/AArch64/CMakeLists.txt b/llvm/unittests/Target/AArch64/CMakeLists.txt
index dacd919ba1e33b..64ab991ac479a4 100644
--- a/llvm/unittests/Target/AArch64/CMakeLists.txt
+++ b/llvm/unittests/Target/AArch64/CMakeLists.txt
@@ -29,6 +29,7 @@ add_llvm_target_unittest(AArch64Tests
MatrixRegisterAliasing.cpp
SMEAttributesTest.cpp
AArch64SVESchedPseudoTest.cpp
+ Immediates.cpp
)
set_property(TARGET AArch64Tests PROPERTY FOLDER "Tests/UnitTests/TargetTests")
diff --git a/llvm/unittests/Target/AArch64/Immediates.cpp b/llvm/unittests/Target/AArch64/Immediates.cpp
new file mode 100644
index 00000000000000..5f5895e44c6110
--- /dev/null
+++ b/llvm/unittests/Target/AArch64/Immediates.cpp
@@ -0,0 +1,75 @@
+#include "AArch64Subtarget.h"
+#include "AArch64TargetMachine.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/MC/TargetRegistry.h"
+#include "llvm/Support/TargetSelect.h"
+
+#include "gtest/gtest.h"
+#include <initializer_list>
+#include <memory>
+
+using namespace llvm;
+
+namespace {
+
+struct TestCase {
+ int64_t FixedImm;
+ int64_t ScalableImm;
+ bool Result;
+};
+
+const std::initializer_list<TestCase> Tests = {
+ // FixedImm, ScalableImm, Result
+ // No change, easily 'supported'
+ {0, 0, true},
+
+ // Simple fixed immediate cases
+ // +8
+ {8, 0, true},
+ // -16
+ {-16, 0, true},
+
+ // Scalable; addvl increments by whole registers, range [-32,31]
+ // +(16 * vscale), one register's worth
+ {0, 16, true},
+ // +(8 * vscale), half a register's worth
+ {0, 8, false},
+ // -(32 * 16 * vscale)
+ {0, -512, true},
+ // -(33 * 16 * vscale)
+ {0, -528, false},
+ // +(31 * 16 * vscale)
+ {0, 496, true},
+ // +(32 * 16 * vscale)
+ {0, 512, false},
+
+ // Mixed; not supported.
+ // +(16 + (16 * vscale)) -- one register's worth + 16
+ {16, 16, false},
+};
+} // namespace
+
+TEST(Immediates, Immediates) {
+ LLVMInitializeAArch64TargetInfo();
+ LLVMInitializeAArch64Target();
+ LLVMInitializeAArch64TargetMC();
+
+ std::string Error;
+ auto TT = Triple::normalize("aarch64");
+ const Target *T = TargetRegistry::lookupTarget(TT, Error);
+
+ std::unique_ptr<TargetMachine> TM(
+ T->createTargetMachine(TT, "generic", "+sve", TargetOptions(),
+ std::nullopt, std::nullopt,
+ CodeGenOptLevel::Default));
+ AArch64Subtarget ST(TM->getTargetTriple(), TM->getTargetCPU(),
+ TM->getTargetCPU(), TM->getTargetFeatureString(), *TM,
+ true);
+
+ auto *TLI = ST.getTargetLowering();
+
+ for (const auto &Test : Tests) {
+ ASSERT_EQ(TLI->isLegalAddImmediate(Test.FixedImm, Test.ScalableImm),
+ Test.Result);
+ }
+}
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
Can you remind us where these functions are used? It might be simpler to have separate methods and move the scalable vs normal immediate check out a level. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm confused as to how this will work - how do you indicate when to test for a legal scalar or scalable immediate? Suppose you want to know if 0 is legal?
I'm modifying these to handle the uses in LoopStrengthReduce, specifically for GenerateReassociationsImpl and GenerateCrossUseConstantOffsets. Since we're just asking about a single immediate (rather than a whole addressing mode, as in PR #83255 ) then it's fine to make a second interface. Will do so. |
5125e75
to
2a0017d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is looking sensible to me, I have some comments below from experimenting with some values.
/// Return true if the specified immediate is legal add of a scalable | ||
/// immediate, that is the target has add instructions which can add a | ||
/// register with the immediate (multiplied by vscale) without having to | ||
/// materialize the immediate into a register. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe:
"Return true if the add of the specified scalable immediate is legal, that is..."
// +(16 * vscale), one register's worth | ||
{16, true}, | ||
// +(8 * vscale), half a register's worth | ||
{8, false}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
8 could be a inch
if that wouldn't cause problems with your analysis. Same for 2 and 4.
@@ -16595,6 +16595,21 @@ bool AArch64TargetLowering::isLegalAddImmediate(int64_t Immed) const { | |||
return IsLegal; | |||
} | |||
|
|||
bool AArch64TargetLowering::isLegalAddScalableImmediate(int64_t Imm) const { | |||
// Scalable immediates require SVE support. | |||
if (!Subtarget->hasSVE()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should all of this require sve2? Otherwise we don't generate the instructions.
Adds an interface to determine whether an immediate would be legal within an add instruction, when said immediate is multiplied by vscale.
2a0017d
to
f2704d2
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. This looks sensible to me.
…ate (llvm#84173) Adds a second parameter (default to 0) to isLegalAddImmediate, to represent a scalable immediate. Extends the AArch64 implementation to match immediates based on what addvl and inc[h|w|d] support.
llvm#84173 added uses of std::labs on an int64_t which leads to this warning on Arm 32 bit: /home/david.spickett/llvm-project/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp:16655:12: warning: absolute value function 'labs' given an argument of type 'long long' but has parameter of type 'long' which may cause truncation of value [-Wabsolute-value] return std::labs(Imm / 4) <= 16; ^ /home/david.spickett/llvm-project/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp:16655:12: note: use function 'std::abs' instead return std::labs(Imm / 4) <= 16; ^~~~~~~~~ std::abs Since int64_t is "long long" on Arm, not "long". Use std::abs instead since it has versions for "long" and "long long", we'll pick up the right one at compile time (https://en.cppreference.com/w/cpp/numeric/math/abs).
llvm#84173 added uses of std::labs on an int64_t which leads to this warning on Arm 32 bit: ``` /home/david.spickett/llvm-project/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp:16655:12: warning: absolute value function 'labs' given an argument of type 'long long' but has parameter of type 'long' which may cause truncation of value [-Wabsolute-value] return std::labs(Imm / 4) <= 16; ^ /home/david.spickett/llvm-project/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp:16655:12: note: use function 'std::abs' instead return std::labs(Imm / 4) <= 16; ^~~~~~~~~ std::abs ``` Since int64_t is "long long" on Arm, not "long". Use std::abs instead since it has versions for "long" and "long long", we'll pick up the right one at compile time (https://en.cppreference.com/w/cpp/numeric/math/abs).
Adds a second parameter (default to 0) to isLegalAddImmediate, to represent a scalable immediate.
Extends the AArch64 implementation to match immediates based on vscale * base_register_size * immediate in the range [-32,31].
See the vscale-aware LSR RFC for reference: https://discourse.llvm.org/t/rfc-vscale-aware-loopstrengthreduce/77131