Index: llvm/lib/Target/AArch64/AArch64FrameLowering.cpp =================================================================== --- llvm/lib/Target/AArch64/AArch64FrameLowering.cpp +++ llvm/lib/Target/AArch64/AArch64FrameLowering.cpp @@ -2030,6 +2030,10 @@ else llvm_unreachable("Unsupported register class."); + // The last SVE callee-save must be aligned to 16 bytes, similar to the last + // non-paired GPRs. + bool NeedsSVEFixup = (i+1 == Count); + // Add the next reg to the pair if it is in the same register class. if (i + 1 < Count) { unsigned NextReg = CSI[i + 1].getReg(); @@ -2051,6 +2055,9 @@ break; case RegPairInfo::PPR: case RegPairInfo::ZPR: + if (!AArch64::PPRRegClass.contains(NextReg) && + !AArch64::ZPRRegClass.contains(NextReg)) + NeedsSVEFixup = true; break; } } @@ -2115,6 +2122,12 @@ MFI.setObjectAlignment(RPI.FrameIdx, Align(16)); } + if (NeedsSVEFixup) { + NeedsSVEFixup = false; + ScalableByteOffset = alignDown(ScalableByteOffset, 16); + MFI.setObjectAlignment(RPI.FrameIdx, Align(16)); + } + int Offset = RPI.isScalable() ? ScalableByteOffset : ByteOffset; assert(Offset % Scale == 0); RPI.Offset = Offset / Scale; Index: llvm/test/CodeGen/AArch64/framelayout-sve.mir =================================================================== --- llvm/test/CodeGen/AArch64/framelayout-sve.mir +++ llvm/test/CodeGen/AArch64/framelayout-sve.mir @@ -370,13 +370,13 @@ ... # CHECK-LABEL: name: save_restore_pregs_sve # CHECK: $sp = frame-setup ADDVL_XXI $sp, -1 -# CHECK: frame-setup STR_PXI killed $p6, $sp, 5 +# CHECK: frame-setup STR_PXI killed $p6, $sp, 0 # CHECK: frame-setup STR_PXI killed $p5, $sp, 6 # CHECK: frame-setup STR_PXI killed $p4, $sp, 7 # CHECK: $sp = frame-setup SUBXri $sp, 32, 0 # CHECK: $sp = frame-destroy ADDXri $sp, 32, 0 -# CHECK: $p6 = frame-destroy LDR_PXI $sp, 5 +# CHECK: $p6 = frame-destroy LDR_PXI $sp, 0 # CHECK: $p5 = frame-destroy LDR_PXI $sp, 6 # CHECK: $p4 = frame-destroy LDR_PXI $sp, 7 # CHECK: $sp = frame-destroy ADDVL_XXI $sp, 1 @@ -430,7 +430,7 @@ # CHECK: $sp = frame-setup STPXpre killed ${{[a-z0-9]+}}, killed $x21, $sp, -4 # CHECK: frame-setup STPXi killed $x20, killed $x19, $sp, 2 # CHECK: $sp = frame-setup ADDVL_XXI $sp, -19 -# CHECK: frame-setup STR_PXI killed $p15, $sp, 4 +# CHECK: frame-setup STR_PXI killed $p15, $sp, 0 # CHECK: frame-setup STR_PXI killed $p14, $sp, 5 # CHECK: frame-setup STR_PXI killed $p5, $sp, 14 # CHECK: frame-setup STR_PXI killed $p4, $sp, 15 @@ -441,7 +441,7 @@ # CHECK: $sp = frame-setup SUBXri $sp, 32, 0 # CHECK: $sp = frame-destroy ADDXri $sp, 32, 0 -# CHECK: $p15 = frame-destroy LDR_PXI $sp, 4 +# CHECK: $p15 = frame-destroy LDR_PXI $sp, 0 # CHECK: $p14 = frame-destroy LDR_PXI $sp, 5 # CHECK: $p5 = frame-destroy LDR_PXI $sp, 14 # CHECK: $p4 = frame-destroy LDR_PXI $sp, 15 @@ -495,7 +495,7 @@ # CHECK: $sp = frame-setup STPXpre killed $fp, killed $lr, $sp, -2 # CHECK-NEXT: $fp = frame-setup ADDXri $sp, 0, 0 # CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -19 -# CHECK-NEXT: STR_PXI killed $p15, $sp, 4 +# CHECK-NEXT: STR_PXI killed $p15, $sp, 0 # CHECK-NEXT: STR_PXI killed $p14, $sp, 5 # CHECK: STR_PXI killed $p5, $sp, 14 # CHECK-NEXT: STR_PXI killed $p4, $sp, 15 @@ -507,7 +507,7 @@ # CHECK-NEXT: $sp = ANDXri killed $[[TMP]] # CHECK: $sp = frame-destroy ADDVL_XXI $fp, -19 -# CHECK-NEXT: $p15 = frame-destroy LDR_PXI $sp, 4 +# CHECK-NEXT: $p15 = frame-destroy LDR_PXI $sp, 0 # CHECK-NEXT: $p14 = frame-destroy LDR_PXI $sp, 5 # CHECK: $p5 = frame-destroy LDR_PXI $sp, 14 # CHECK-NEXT: $p4 = frame-destroy LDR_PXI $sp, 15 @@ -588,7 +588,7 @@ # CHECK: bb.0.entry: # CHECK-NEXT: $sp = frame-setup STRXpre killed $[[SCRATCH:[a-z0-9]+]], $sp, -16 # CHECK-NEXT: $sp = frame-setup ADDVL_XXI $sp, -3 -# CHECK-NEXT: STR_PXI killed $p15, $sp, 6 +# CHECK-NEXT: STR_PXI killed $p15, $sp, 0 # CHECK-NEXT: STR_PXI killed $p4, $sp, 7 # CHECK-NEXT: STR_ZXI killed $z23, $sp, 1 # CHECK-NEXT: STR_ZXI killed $z8, $sp, 2