[llvm] [AArch64][GISel] Always fold G_SHL into addressing mode where possible, unless the subtarget has addr-lsl-slow-14 (PR #96603)
Thorsten Schütt via llvm-commits
llvm-commits at lists.llvm.org
Fri Jun 28 09:55:09 PDT 2024
================
@@ -6717,19 +6722,70 @@ AArch64InstructionSelector::selectNegArithImmed(MachineOperand &Root) const {
return select12BitValueWithLeftShift(Immed);
}
+/// Checks if we are sure that folding MI into load/store addressing mode is
+/// beneficial or not.
+///
+/// Returns:
+/// - true if fodling MI would be beneficial.
+/// - false if folding MI would be bad.
+/// - std::nullopt if it is not sure whether folding MI is beneficial.
+///
+/// \p MI can be the offset operand of G_PTR_ADD, e.g. G_SHL in the example:
+///
+/// %13:gpr(s64) = G_CONSTANT i64 1
+/// %8:gpr(s64) = G_SHL %6, %13(s64)
+/// %9:gpr(p0) = G_PTR_ADD %0, %8(s64)
+/// %12:gpr(s32) = G_LOAD %9(p0) :: (load (s16))
+std::optional<bool> AArch64InstructionSelector::isWorthFoldingIntoAddrMode(
+ MachineInstr &MI, const MachineRegisterInfo &MRI) const {
+ if (MI.getOpcode() == AArch64::G_SHL) {
+ // Address operands with shifts are free, except for running on sub targets
+ // with AddrLSLSlow14.
+ if (const auto ValAndVeg = getIConstantVRegValWithLookThrough(
+ MI.getOperand(2).getReg(), MRI)) {
+ const APInt ShiftVal = ValAndVeg->Value;
+
+ // Don't fold if we know this will be slow.
+ return !(STI.hasAddrLSLSlow14() && (ShiftVal == 1 || ShiftVal == 4));
+ }
+ }
+ return std::nullopt;
+}
+
/// Return true if it is worth folding MI into an extended register. That is,
/// if it's safe to pull it into the addressing mode of a load or store as a
/// shift.
+/// \p IsAddrOperand whether the def of MI is used as an address operand
+/// (e.g. feeding into an LDR/STR).
bool AArch64InstructionSelector::isWorthFoldingIntoExtendedReg(
- MachineInstr &MI, const MachineRegisterInfo &MRI) const {
+ MachineInstr &MI, const MachineRegisterInfo &MRI,
+ bool IsAddrOperand) const {
+
// Always fold if there is one use, or if we're optimizing for size.
Register DefReg = MI.getOperand(0).getReg();
if (MRI.hasOneNonDBGUse(DefReg) ||
MI.getParent()->getParent()->getFunction().hasOptSize())
return true;
- // FIXME: Consider checking HasAddrLSLSlow14 and HasALULSLFast as
- // appropriate.
+ if (IsAddrOperand) {
+ // If we are already sure that folding MI is good or bad, return the result.
+ if (const auto Worth = isWorthFoldingIntoAddrMode(MI, MRI))
+ return Worth.value();
----------------
tschuett wrote:
optionals are odd, see https://en.cppreference.com/w/cpp/utility/optional.
```
return *Worth;
```
https://github.com/llvm/llvm-project/pull/96603
More information about the llvm-commits
mailing list