diff --git a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp --- a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp @@ -5092,12 +5092,17 @@ SDValue &OffImm) { const EVT MemVT = getMemVTFromNode(*(CurDAG->getContext()), Root); const DataLayout &DL = CurDAG->getDataLayout(); + const MachineFrameInfo &MFI = MF->getFrameInfo(); if (N.getOpcode() == ISD::FrameIndex) { int FI = cast(N)->getIndex(); - Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy(DL)); - OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i64); - return true; + // We can only encode VL scaled offsets, so only fold in frame indexes + // referencing SVE objects. + if (FI == 0 || MFI.getStackID(FI) == TargetStackID::ScalableVector) { + Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy(DL)); + OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i64); + return true; + } } if (MemVT == EVT()) @@ -5124,7 +5129,10 @@ Base = N.getOperand(0); if (Base.getOpcode() == ISD::FrameIndex) { int FI = cast(Base)->getIndex(); - Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy(DL)); + // We can only encode VL scaled offsets, so only fold in frame indexes + // referencing SVE objects. + if (FI == 0 || MFI.getStackID(FI) == TargetStackID::ScalableVector) + Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy(DL)); } OffImm = CurDAG->getTargetConstant(Offset, SDLoc(N), MVT::i64); diff --git a/llvm/test/CodeGen/AArch64/sve-fixed-length-frame-offests.ll b/llvm/test/CodeGen/AArch64/sve-fixed-length-frame-offests.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/sve-fixed-length-frame-offests.ll @@ -0,0 +1,31 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -debug-only=isel < %s 2>&1 | FileCheck %s + +; REQUIRES: asserts + +target triple = "aarch64-unknown-linux-gnu" + +; Ensure that only no offset frame indexes are folded into SVE load/stores when +; accessing fixed width objects. +define void @foo(<8 x i64>* %a) #0 { +; CHECK-LABEL: foo: +; CHECK: SelectionDAG has 14 nodes: +; CHECK-NEXT: t0: ch = EntryToken +; CHECK-NEXT: t12: nxv2i1 = PTRUE_D TargetConstant:i32<31> +; CHECK-NEXT: t2: i64,ch = CopyFromReg t0, Register:i64 %0 +; CHECK-NEXT: t18: nxv2i64,ch = LD1D_IMM t12, t2, TargetConstant:i64<0>, t0 +; CHECK-NEXT: t8: i64 = ADDXri TargetFrameIndex:i64<1>, TargetConstant:i32<0>, TargetConstant:i32<0> +; CHECK-NEXT: t17: ch = ST1D_IMM t18, t12, TargetFrameIndex:i64<0>, TargetConstant:i64<0>, t0 +; CHECK-NEXT: t16: ch = ST1D_IMM t18, t12, t8, TargetConstant:i64<0>, t17 +; CHECK-NEXT: t10: ch = RET_ReallyLR t16 +; CHECK-EMPTY: +entry: + %r0 = alloca <8 x i64> + %r1 = alloca <8 x i64> + %r = load volatile <8 x i64>, <8 x i64>* %a + store volatile <8 x i64> %r, <8 x i64>* %r0 + store volatile <8 x i64> %r, <8 x i64>* %r1 + ret void +} + +attributes #0 = { nounwind "target-features"="+sve" vscale_range(4,4) }