From fc64dede4b5e96ea675b7394bcae2aed0bff4502 Mon Sep 17 00:00:00 2001 From: Koakuma Date: Sat, 31 Aug 2024 17:35:20 +0700 Subject: [PATCH 1/8] [WIP][SPARC] Allow overaligned `alloca`s SPARC doesn't do stack realignment, so let LLVM know about it in `SparcFrameLowering`. This has the side effect of making all overaligned allocations go through `LowerDYNAMIC_STACKALLOC`, so implement the missing logic there for overaligned allocations. This allows the SPARC backend to not crash on overaligned `alloca`s. --- llvm/lib/Target/Sparc/SparcFrameLowering.cpp | 34 +----- llvm/lib/Target/Sparc/SparcISelLowering.cpp | 42 ++++--- llvm/lib/Target/Sparc/SparcRegisterInfo.cpp | 23 ---- llvm/lib/Target/Sparc/SparcRegisterInfo.h | 3 - llvm/test/CodeGen/SPARC/alloca-align.ll | 113 +++++++++++++++++++ llvm/test/CodeGen/SPARC/fail-alloca-align.ll | 23 ---- llvm/test/CodeGen/SPARC/fp128.ll | 16 +-- llvm/test/CodeGen/SPARC/stack-align.ll | 53 ++++++--- 8 files changed, 184 insertions(+), 123 deletions(-) create mode 100644 llvm/test/CodeGen/SPARC/alloca-align.ll delete mode 100644 llvm/test/CodeGen/SPARC/fail-alloca-align.ll diff --git a/llvm/lib/Target/Sparc/SparcFrameLowering.cpp b/llvm/lib/Target/Sparc/SparcFrameLowering.cpp index 000418be9a9e33..b28642aee4ca06 100644 --- a/llvm/lib/Target/Sparc/SparcFrameLowering.cpp +++ b/llvm/lib/Target/Sparc/SparcFrameLowering.cpp @@ -35,7 +35,8 @@ DisableLeafProc("disable-sparc-leaf-proc", SparcFrameLowering::SparcFrameLowering(const SparcSubtarget &ST) : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, ST.is64Bit() ? Align(16) : Align(8), 0, - ST.is64Bit() ? Align(16) : Align(8)) {} + ST.is64Bit() ? Align(16) : Align(8), + /* StackRealignable */ false) {} void SparcFrameLowering::emitSPAdjustment(MachineFunction &MF, MachineBasicBlock &MBB, @@ -97,12 +98,6 @@ void SparcFrameLowering::emitPrologue(MachineFunction &MF, // Debug location must be unknown since the first debug location is used // to determine the end of the prologue. DebugLoc dl; - bool NeedsStackRealignment = RegInfo.shouldRealignStack(MF); - - if (NeedsStackRealignment && !RegInfo.canRealignStack(MF)) - report_fatal_error("Function \"" + Twine(MF.getName()) + "\" required " - "stack re-alignment, but LLVM couldn't handle it " - "(probably because it has a dynamic alloca)."); // Get the number of bytes to allocate from the FrameInfo int NumBytes = (int) MFI.getStackSize(); @@ -168,31 +163,6 @@ void SparcFrameLowering::emitPrologue(MachineFunction &MF, MCCFIInstruction::createRegister(nullptr, regOutRA, regInRA)); BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) .addCFIIndex(CFIIndex); - - if (NeedsStackRealignment) { - int64_t Bias = Subtarget.getStackPointerBias(); - unsigned regUnbiased; - if (Bias) { - // This clobbers G1 which we always know is available here. - regUnbiased = SP::G1; - // add %o6, BIAS, %g1 - BuildMI(MBB, MBBI, dl, TII.get(SP::ADDri), regUnbiased) - .addReg(SP::O6).addImm(Bias); - } else - regUnbiased = SP::O6; - - // andn %regUnbiased, MaxAlign-1, %regUnbiased - Align MaxAlign = MFI.getMaxAlign(); - BuildMI(MBB, MBBI, dl, TII.get(SP::ANDNri), regUnbiased) - .addReg(regUnbiased) - .addImm(MaxAlign.value() - 1U); - - if (Bias) { - // add %g1, -BIAS, %o6 - BuildMI(MBB, MBBI, dl, TII.get(SP::ADDri), SP::O6) - .addReg(regUnbiased).addImm(-Bias); - } - } } MachineBasicBlock::iterator SparcFrameLowering:: diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/llvm/lib/Target/Sparc/SparcISelLowering.cpp index 42b8248006d1fd..06bd2aa27e904f 100644 --- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp +++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp @@ -2764,20 +2764,27 @@ static SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG, const SparcSubtarget *Subtarget) { SDValue Chain = Op.getOperand(0); // Legalize the chain. SDValue Size = Op.getOperand(1); // Legalize the size. - MaybeAlign Alignment = - cast(Op.getOperand(2))->getMaybeAlignValue(); + SDValue Alignment = Op.getOperand(2); // Legalize the alignment. + MaybeAlign MaybeAlignment = + cast(Alignment)->getMaybeAlignValue(); Align StackAlign = Subtarget->getFrameLowering()->getStackAlign(); EVT VT = Size->getValueType(0); SDLoc dl(Op); - // TODO: implement over-aligned alloca. (Note: also implies - // supporting support for overaligned function frames + dynamic - // allocations, at all, which currently isn't supported) - if (Alignment && *Alignment > StackAlign) { - const MachineFunction &MF = DAG.getMachineFunction(); - report_fatal_error("Function \"" + Twine(MF.getName()) + "\": " - "over-aligned dynamic alloca not supported."); - } + int64_t Bias = Subtarget->getStackPointerBias(); + unsigned SPReg = SP::O6; + SDValue SP = DAG.getCopyFromReg(Chain, dl, SPReg, VT); + SDValue AlignedPtr = SP; + + bool IsOveraligned = MaybeAlignment && *MaybeAlignment > StackAlign; + if (IsOveraligned) + AlignedPtr = DAG.getNode( + ISD::AND, dl, VT, + DAG.getNode( + ISD::SUB, dl, VT, + DAG.getNode(ISD::ADD, dl, VT, SP, DAG.getConstant(Bias, dl, VT)), + Alignment), + DAG.getNode(ISD::SUB, dl, VT, DAG.getConstant(0, dl, VT), Alignment)); // The resultant pointer needs to be above the register spill area // at the bottom of the stack. @@ -2811,12 +2818,17 @@ static SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG, regSpillArea = 96; } - unsigned SPReg = SP::O6; - SDValue SP = DAG.getCopyFromReg(Chain, dl, SPReg, VT); - SDValue NewSP = DAG.getNode(ISD::SUB, dl, VT, SP, Size); // Value - Chain = DAG.getCopyToReg(SP.getValue(1), dl, SPReg, NewSP); // Output chain + AlignedPtr = DAG.getNode(ISD::SUB, dl, VT, AlignedPtr, Size); - regSpillArea += Subtarget->getStackPointerBias(); + // If we are allocating overaligned memory then the bias is already accounted + // for in AlignedPtr calculation, so: + // - We do not need to adjust the regSpillArea; but + // - We do need to decrement AlignedPtr by bias to obtain the new SP. + regSpillArea += IsOveraligned ? 0 : Bias; + SDValue NewSP = + DAG.getNode(ISD::SUB, dl, VT, AlignedPtr, + DAG.getConstant(IsOveraligned ? Bias : 0, dl, VT)); + Chain = DAG.getCopyToReg(SP.getValue(1), dl, SPReg, NewSP); SDValue NewVal = DAG.getNode(ISD::ADD, dl, VT, NewSP, DAG.getConstant(regSpillArea, dl, VT)); diff --git a/llvm/lib/Target/Sparc/SparcRegisterInfo.cpp b/llvm/lib/Target/Sparc/SparcRegisterInfo.cpp index 71a27f77d2c6bf..e4db27a63076d8 100644 --- a/llvm/lib/Target/Sparc/SparcRegisterInfo.cpp +++ b/llvm/lib/Target/Sparc/SparcRegisterInfo.cpp @@ -226,26 +226,3 @@ SparcRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, Register SparcRegisterInfo::getFrameRegister(const MachineFunction &MF) const { return SP::I6; } - -// Sparc has no architectural need for stack realignment support, -// except that LLVM unfortunately currently implements overaligned -// stack objects by depending upon stack realignment support. -// If that ever changes, this can probably be deleted. -bool SparcRegisterInfo::canRealignStack(const MachineFunction &MF) const { - if (!TargetRegisterInfo::canRealignStack(MF)) - return false; - - // Sparc always has a fixed frame pointer register, so don't need to - // worry about needing to reserve it. [even if we don't have a frame - // pointer for our frame, it still cannot be used for other things, - // or register window traps will be SADNESS.] - - // If there's a reserved call frame, we can use SP to access locals. - if (getFrameLowering(MF)->hasReservedCallFrame(MF)) - return true; - - // Otherwise, we'd need a base pointer, but those aren't implemented - // for SPARC at the moment. - - return false; -} diff --git a/llvm/lib/Target/Sparc/SparcRegisterInfo.h b/llvm/lib/Target/Sparc/SparcRegisterInfo.h index 58c85f33635f2d..eae859ce1a519e 100644 --- a/llvm/lib/Target/Sparc/SparcRegisterInfo.h +++ b/llvm/lib/Target/Sparc/SparcRegisterInfo.h @@ -40,9 +40,6 @@ struct SparcRegisterInfo : public SparcGenRegisterInfo { RegScavenger *RS = nullptr) const override; Register getFrameRegister(const MachineFunction &MF) const override; - - bool canRealignStack(const MachineFunction &MF) const override; - }; } // end namespace llvm diff --git a/llvm/test/CodeGen/SPARC/alloca-align.ll b/llvm/test/CodeGen/SPARC/alloca-align.ll new file mode 100644 index 00000000000000..1ece601437ea4a --- /dev/null +++ b/llvm/test/CodeGen/SPARC/alloca-align.ll @@ -0,0 +1,113 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 +; RUN: llc -march=sparc < %s | FileCheck %s --check-prefixes=CHECK32 +; RUN: llc -march=sparcv9 < %s | FileCheck %s --check-prefixes=CHECK64 + +define void @variable_alloca_with_overalignment(i32 %num) { +; CHECK32-LABEL: variable_alloca_with_overalignment: +; CHECK32: .cfi_startproc +; CHECK32-NEXT: ! %bb.0: +; CHECK32-NEXT: save %sp, -96, %sp +; CHECK32-NEXT: .cfi_def_cfa_register %fp +; CHECK32-NEXT: .cfi_window_save +; CHECK32-NEXT: .cfi_register %o7, %i7 +; CHECK32-NEXT: add %sp, -64, %i1 +; CHECK32-NEXT: and %i1, -64, %i1 +; CHECK32-NEXT: add %i1, -16, %sp +; CHECK32-NEXT: add %i0, 7, %i0 +; CHECK32-NEXT: and %i0, -8, %i0 +; CHECK32-NEXT: sub %sp, %i0, %i0 +; CHECK32-NEXT: add %i1, 80, %o0 +; CHECK32-NEXT: add %i0, -8, %sp +; CHECK32-NEXT: call foo +; CHECK32-NEXT: add %i0, 88, %o1 +; CHECK32-NEXT: ret +; CHECK32-NEXT: restore +; +; CHECK64-LABEL: variable_alloca_with_overalignment: +; CHECK64: .cfi_startproc +; CHECK64-NEXT: ! %bb.0: +; CHECK64-NEXT: save %sp, -128, %sp +; CHECK64-NEXT: .cfi_def_cfa_register %fp +; CHECK64-NEXT: .cfi_window_save +; CHECK64-NEXT: .cfi_register %o7, %i7 +; CHECK64-NEXT: add %sp, 1983, %i1 +; CHECK64-NEXT: and %i1, -64, %i1 +; CHECK64-NEXT: add %i1, -2063, %sp +; CHECK64-NEXT: add %i1, -1935, %o0 +; CHECK64-NEXT: srl %i0, 0, %i0 +; CHECK64-NEXT: add %i0, 15, %i0 +; CHECK64-NEXT: sethi 4194303, %i1 +; CHECK64-NEXT: or %i1, 1008, %i1 +; CHECK64-NEXT: sethi 0, %i2 +; CHECK64-NEXT: or %i2, 1, %i2 +; CHECK64-NEXT: sllx %i2, 32, %i2 +; CHECK64-NEXT: or %i2, %i1, %i1 +; CHECK64-NEXT: and %i0, %i1, %i0 +; CHECK64-NEXT: sub %sp, %i0, %i0 +; CHECK64-NEXT: add %i0, 2175, %o1 +; CHECK64-NEXT: mov %i0, %sp +; CHECK64-NEXT: call foo +; CHECK64-NEXT: add %sp, -48, %sp +; CHECK64-NEXT: add %sp, 48, %sp +; CHECK64-NEXT: ret +; CHECK64-NEXT: restore + %aligned = alloca i32, align 64 + %var_size = alloca i8, i32 %num, align 4 + call void @foo(ptr %aligned, ptr %var_size) + ret void +} + +;; Same but with the alloca itself overaligned +define void @variable_alloca_with_overalignment_2(i32 %num) { +; CHECK32-LABEL: variable_alloca_with_overalignment_2: +; CHECK32: .cfi_startproc +; CHECK32-NEXT: ! %bb.0: +; CHECK32-NEXT: save %sp, -96, %sp +; CHECK32-NEXT: .cfi_def_cfa_register %fp +; CHECK32-NEXT: .cfi_window_save +; CHECK32-NEXT: .cfi_register %o7, %i7 +; CHECK32-NEXT: add %i0, 7, %i0 +; CHECK32-NEXT: and %i0, -8, %i0 +; CHECK32-NEXT: add %sp, -64, %i1 +; CHECK32-NEXT: and %i1, -64, %i1 +; CHECK32-NEXT: sub %i1, %i0, %i0 +; CHECK32-NEXT: add %i0, -8, %sp +; CHECK32-NEXT: add %i0, 88, %o1 +; CHECK32-NEXT: call foo +; CHECK32-NEXT: mov %g0, %o0 +; CHECK32-NEXT: ret +; CHECK32-NEXT: restore +; +; CHECK64-LABEL: variable_alloca_with_overalignment_2: +; CHECK64: .cfi_startproc +; CHECK64-NEXT: ! %bb.0: +; CHECK64-NEXT: save %sp, -128, %sp +; CHECK64-NEXT: .cfi_def_cfa_register %fp +; CHECK64-NEXT: .cfi_window_save +; CHECK64-NEXT: .cfi_register %o7, %i7 +; CHECK64-NEXT: srl %i0, 0, %i0 +; CHECK64-NEXT: add %i0, 15, %i0 +; CHECK64-NEXT: sethi 4194303, %i1 +; CHECK64-NEXT: or %i1, 1008, %i1 +; CHECK64-NEXT: sethi 0, %i2 +; CHECK64-NEXT: or %i2, 1, %i2 +; CHECK64-NEXT: sllx %i2, 32, %i2 +; CHECK64-NEXT: or %i2, %i1, %i1 +; CHECK64-NEXT: and %i0, %i1, %i0 +; CHECK64-NEXT: add %sp, 1983, %i1 +; CHECK64-NEXT: and %i1, -64, %i1 +; CHECK64-NEXT: sub %i1, %i0, %i0 +; CHECK64-NEXT: add %i0, -2047, %sp +; CHECK64-NEXT: add %i0, -1919, %o1 +; CHECK64-NEXT: add %sp, -48, %sp +; CHECK64-NEXT: call foo +; CHECK64-NEXT: mov %g0, %o0 +; CHECK64-NEXT: add %sp, 48, %sp +; CHECK64-NEXT: ret +; CHECK64-NEXT: restore + %var_size = alloca i8, i32 %num, align 64 + call void @foo(ptr null, ptr %var_size) + ret void +} + +declare void @foo(ptr, ptr); diff --git a/llvm/test/CodeGen/SPARC/fail-alloca-align.ll b/llvm/test/CodeGen/SPARC/fail-alloca-align.ll deleted file mode 100644 index e2dc235389b1dc..00000000000000 --- a/llvm/test/CodeGen/SPARC/fail-alloca-align.ll +++ /dev/null @@ -1,23 +0,0 @@ -;; Sparc backend can't currently handle variable allocas with -;; alignment greater than the stack alignment. This code ought to -;; compile, but doesn't currently. - -;; RUN: not --crash llc -march=sparc < %s 2>&1 | FileCheck %s -;; RUN: not --crash llc -march=sparcv9 < %s 2>&1 | FileCheck %s -;; CHECK: ERROR: Function {{.*}} required stack re-alignment - -define void @variable_alloca_with_overalignment(i32 %num) { - %aligned = alloca i32, align 64 - %var_size = alloca i8, i32 %num, align 4 - call void @foo(ptr %aligned, ptr %var_size) - ret void -} - -;; Same but with the alloca itself overaligned -define void @variable_alloca_with_overalignment_2(i32 %num) { - %var_size = alloca i8, i32 %num, align 64 - call void @foo(ptr null, ptr %var_size) - ret void -} - -declare void @foo(ptr, ptr); diff --git a/llvm/test/CodeGen/SPARC/fp128.ll b/llvm/test/CodeGen/SPARC/fp128.ll index 80f3da285e053f..3e43d3eb5da70f 100644 --- a/llvm/test/CodeGen/SPARC/fp128.ll +++ b/llvm/test/CodeGen/SPARC/fp128.ll @@ -54,18 +54,10 @@ entry: ; CHECK-LABEL: f128_spill_large: ; CHECK: sethi 4, %g1 -; CHECK: sethi 4, %g1 -; CHECK-NEXT: add %g1, %sp, %g1 -; CHECK-NEXT: std %f{{.+}}, [%g1] -; CHECK: sethi 4, %g1 -; CHECK-NEXT: add %g1, %sp, %g1 -; CHECK-NEXT: std %f{{.+}}, [%g1+8] -; CHECK: sethi 4, %g1 -; CHECK-NEXT: add %g1, %sp, %g1 -; CHECK-NEXT: ldd [%g1], %f{{.+}} -; CHECK: sethi 4, %g1 -; CHECK-NEXT: add %g1, %sp, %g1 -; CHECK-NEXT: ldd [%g1+8], %f{{.+}} +; CHECK: std %f{{.+}}, [%fp+-16] +; CHECK-NEXT: std %f{{.+}}, [%fp+-8] +; CHECK: ldd [%fp+-16], %f{{.+}} +; CHECK-NEXT: ldd [%fp+-8], %f{{.+}} define void @f128_spill_large(ptr noalias sret(<251 x fp128>) %scalar.result, ptr byval(<251 x fp128>) %a) { entry: diff --git a/llvm/test/CodeGen/SPARC/stack-align.ll b/llvm/test/CodeGen/SPARC/stack-align.ll index 6632237f08e274..e2dfe854d643a1 100644 --- a/llvm/test/CodeGen/SPARC/stack-align.ll +++ b/llvm/test/CodeGen/SPARC/stack-align.ll @@ -1,24 +1,47 @@ -; RUN: llc -march=sparc < %s | FileCheck %s --check-prefixes=CHECK,CHECK32 -; RUN: llc -march=sparcv9 < %s | FileCheck %s --check-prefixes=CHECK,CHECK64 +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 +; RUN: llc -march=sparc < %s | FileCheck %s --check-prefixes=CHECK32 +; RUN: llc -march=sparcv9 < %s | FileCheck %s --check-prefixes=CHECK64 declare void @stack_realign_helper(i32 %a, ptr %b) ;; This is a function where we have a local variable of 64-byte -;; alignment. We want to see that the stack is aligned (the initial -;; andn), that the local var is accessed via stack pointer (to %o1), and that +;; alignment. We want to see that the stack is aligned (the initial add/and), +;; that the local var is accessed via stack pointer (to %o1), and that ;; the argument is accessed via frame pointer not stack pointer (to %o0). -;; CHECK-LABEL: stack_realign: -;; CHECK32: andn %sp, 63, %sp -;; CHECK32-NEXT: ld [%fp+92], %o0 -;; CHECK64: add %sp, 2047, %g1 -;; CHECK64-NEXT: andn %g1, 63, %g1 -;; CHECK64-NEXT: add %g1, -2047, %sp -;; CHECK64-NEXT: ld [%fp+2227], %o0 -;; CHECK-NEXT: call stack_realign_helper -;; CHECK32-NEXT: add %sp, 128, %o1 -;; CHECK64-NEXT: add %sp, 2239, %o1 - define void @stack_realign(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g) { +; CHECK32-LABEL: stack_realign: +; CHECK32: .cfi_startproc +; CHECK32-NEXT: ! %bb.0: ! %entry +; CHECK32-NEXT: save %sp, -96, %sp +; CHECK32-NEXT: .cfi_def_cfa_register %fp +; CHECK32-NEXT: .cfi_window_save +; CHECK32-NEXT: .cfi_register %o7, %i7 +; CHECK32-NEXT: ld [%fp+92], %o0 +; CHECK32-NEXT: add %sp, -64, %i0 +; CHECK32-NEXT: and %i0, -64, %i0 +; CHECK32-NEXT: add %i0, -16, %sp +; CHECK32-NEXT: call stack_realign_helper +; CHECK32-NEXT: add %i0, 80, %o1 +; CHECK32-NEXT: ret +; CHECK32-NEXT: restore +; +; CHECK64-LABEL: stack_realign: +; CHECK64: .cfi_startproc +; CHECK64-NEXT: ! %bb.0: ! %entry +; CHECK64-NEXT: save %sp, -128, %sp +; CHECK64-NEXT: .cfi_def_cfa_register %fp +; CHECK64-NEXT: .cfi_window_save +; CHECK64-NEXT: .cfi_register %o7, %i7 +; CHECK64-NEXT: add %sp, 1983, %i0 +; CHECK64-NEXT: and %i0, -64, %i0 +; CHECK64-NEXT: add %i0, -2063, %sp +; CHECK64-NEXT: add %i0, -1935, %o1 +; CHECK64-NEXT: add %sp, -48, %sp +; CHECK64-NEXT: call stack_realign_helper +; CHECK64-NEXT: ld [%fp+2227], %o0 +; CHECK64-NEXT: add %sp, 48, %sp +; CHECK64-NEXT: ret +; CHECK64-NEXT: restore entry: %aligned = alloca i32, align 64 call void @stack_realign_helper(i32 %g, ptr %aligned) From 3c870426faa9389c8849f0e0a34ec5e7c67a33e5 Mon Sep 17 00:00:00 2001 From: Koakuma Date: Wed, 4 Sep 2024 11:36:27 +0700 Subject: [PATCH 2/8] Update generic test --- llvm/test/CodeGen/Generic/ForceStackAlign.ll | 3 --- 1 file changed, 3 deletions(-) diff --git a/llvm/test/CodeGen/Generic/ForceStackAlign.ll b/llvm/test/CodeGen/Generic/ForceStackAlign.ll index 7993b3eff65b68..811a192e752ab1 100644 --- a/llvm/test/CodeGen/Generic/ForceStackAlign.ll +++ b/llvm/test/CodeGen/Generic/ForceStackAlign.ll @@ -5,9 +5,6 @@ ; CHECK-LABEL: @f ; CHECK-LABEL: @g -; Stack realignment not supported. -; XFAIL: target=sparc{{.*}} - ; NVPTX can only select dynamic_stackalloc on sm_52+ and with ptx73+ ; XFAIL: target=nvptx{{.*}} From 54408df0337fb973200673657390cda50cbc2c3f Mon Sep 17 00:00:00 2001 From: Koakuma Date: Thu, 12 Sep 2024 09:40:02 +0700 Subject: [PATCH 3/8] Apply code suggestions --- llvm/lib/Target/Sparc/SparcFrameLowering.cpp | 2 +- llvm/lib/Target/Sparc/SparcISelLowering.cpp | 29 +++++---- .../CodeGen/SPARC/2013-05-17-CallFrame.ll | 18 ++---- llvm/test/CodeGen/SPARC/alloca-align.ll | 60 +++++++------------ llvm/test/CodeGen/SPARC/stack-align.ll | 26 +++----- 5 files changed, 51 insertions(+), 84 deletions(-) diff --git a/llvm/lib/Target/Sparc/SparcFrameLowering.cpp b/llvm/lib/Target/Sparc/SparcFrameLowering.cpp index b28642aee4ca06..399d55c439cbb4 100644 --- a/llvm/lib/Target/Sparc/SparcFrameLowering.cpp +++ b/llvm/lib/Target/Sparc/SparcFrameLowering.cpp @@ -36,7 +36,7 @@ SparcFrameLowering::SparcFrameLowering(const SparcSubtarget &ST) : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, ST.is64Bit() ? Align(16) : Align(8), 0, ST.is64Bit() ? Align(16) : Align(8), - /* StackRealignable */ false) {} + /*StackRealignable=*/false) {} void SparcFrameLowering::emitSPAdjustment(MachineFunction &MF, MachineBasicBlock &MBB, diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/llvm/lib/Target/Sparc/SparcISelLowering.cpp index 06bd2aa27e904f..f1fbd5a40a27f0 100644 --- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp +++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp @@ -2764,27 +2764,28 @@ static SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG, const SparcSubtarget *Subtarget) { SDValue Chain = Op.getOperand(0); // Legalize the chain. SDValue Size = Op.getOperand(1); // Legalize the size. - SDValue Alignment = Op.getOperand(2); // Legalize the alignment. + SDValue Alignment = Op.getOperand(2); MaybeAlign MaybeAlignment = cast(Alignment)->getMaybeAlignValue(); - Align StackAlign = Subtarget->getFrameLowering()->getStackAlign(); EVT VT = Size->getValueType(0); SDLoc dl(Op); int64_t Bias = Subtarget->getStackPointerBias(); unsigned SPReg = SP::O6; SDValue SP = DAG.getCopyFromReg(Chain, dl, SPReg, VT); - SDValue AlignedPtr = SP; - - bool IsOveraligned = MaybeAlignment && *MaybeAlignment > StackAlign; - if (IsOveraligned) - AlignedPtr = DAG.getNode( - ISD::AND, dl, VT, - DAG.getNode( - ISD::SUB, dl, VT, - DAG.getNode(ISD::ADD, dl, VT, SP, DAG.getConstant(Bias, dl, VT)), - Alignment), - DAG.getNode(ISD::SUB, dl, VT, DAG.getConstant(0, dl, VT), Alignment)); + SDValue AllocatedPtr = DAG.getNode(ISD::SUB, dl, VT, SP, Size); + + bool IsOveraligned = MaybeAlignment.has_value(); + SDValue AlignedPtr = + IsOveraligned + ? DAG.getNode(ISD::AND, dl, VT, + DAG.getNode(ISD::SUB, dl, VT, + DAG.getNode(ISD::ADD, dl, VT, AllocatedPtr, + DAG.getConstant(Bias, dl, VT)), + Alignment), + DAG.getNode(ISD::SUB, dl, VT, + DAG.getConstant(0, dl, VT), Alignment)) + : AllocatedPtr; // The resultant pointer needs to be above the register spill area // at the bottom of the stack. @@ -2818,8 +2819,6 @@ static SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG, regSpillArea = 96; } - AlignedPtr = DAG.getNode(ISD::SUB, dl, VT, AlignedPtr, Size); - // If we are allocating overaligned memory then the bias is already accounted // for in AlignedPtr calculation, so: // - We do not need to adjust the regSpillArea; but diff --git a/llvm/test/CodeGen/SPARC/2013-05-17-CallFrame.ll b/llvm/test/CodeGen/SPARC/2013-05-17-CallFrame.ll index 3f6d28385e2679..39782f2ad08c62 100644 --- a/llvm/test/CodeGen/SPARC/2013-05-17-CallFrame.ll +++ b/llvm/test/CodeGen/SPARC/2013-05-17-CallFrame.ll @@ -5,19 +5,15 @@ ; (this should ideally be doing "add 4+7; and -8", instead of ; "add 7; and -8; add 8"; see comments in LowerDYNAMIC_STACKALLOC) -define void @variable_alloca_with_adj_call_stack(i32 %num) { +define void @variable_alloca_with_adj_call_stack(i32 %num) nounwind { ; V8-LABEL: variable_alloca_with_adj_call_stack: -; V8: .cfi_startproc -; V8-NEXT: ! %bb.0: ! %entry +; V8: ! %bb.0: ! %entry ; V8-NEXT: save %sp, -96, %sp -; V8-NEXT: .cfi_def_cfa_register %fp -; V8-NEXT: .cfi_window_save -; V8-NEXT: .cfi_register %o7, %i7 ; V8-NEXT: add %i0, 7, %i0 ; V8-NEXT: and %i0, -8, %i0 ; V8-NEXT: sub %sp, %i0, %i0 -; V8-NEXT: add %i0, -8, %sp -; V8-NEXT: add %i0, 88, %o0 +; V8-NEXT: add %i0, 96, %o0 +; V8-NEXT: mov %i0, %sp ; V8-NEXT: add %sp, -16, %sp ; V8-NEXT: st %o0, [%sp+104] ; V8-NEXT: st %o0, [%sp+100] @@ -34,12 +30,8 @@ define void @variable_alloca_with_adj_call_stack(i32 %num) { ; V8-NEXT: restore ; ; SPARC64-LABEL: variable_alloca_with_adj_call_stack: -; SPARC64: .cfi_startproc -; SPARC64-NEXT: ! %bb.0: ! %entry +; SPARC64: ! %bb.0: ! %entry ; SPARC64-NEXT: save %sp, -128, %sp -; SPARC64-NEXT: .cfi_def_cfa_register %fp -; SPARC64-NEXT: .cfi_window_save -; SPARC64-NEXT: .cfi_register %o7, %i7 ; SPARC64-NEXT: srl %i0, 0, %i0 ; SPARC64-NEXT: add %i0, 15, %i0 ; SPARC64-NEXT: sethi 4194303, %i1 diff --git a/llvm/test/CodeGen/SPARC/alloca-align.ll b/llvm/test/CodeGen/SPARC/alloca-align.ll index 1ece601437ea4a..797050d5a92e72 100644 --- a/llvm/test/CodeGen/SPARC/alloca-align.ll +++ b/llvm/test/CodeGen/SPARC/alloca-align.ll @@ -2,38 +2,30 @@ ; RUN: llc -march=sparc < %s | FileCheck %s --check-prefixes=CHECK32 ; RUN: llc -march=sparcv9 < %s | FileCheck %s --check-prefixes=CHECK64 -define void @variable_alloca_with_overalignment(i32 %num) { +define void @variable_alloca_with_overalignment(i32 %num) nounwind { ; CHECK32-LABEL: variable_alloca_with_overalignment: -; CHECK32: .cfi_startproc -; CHECK32-NEXT: ! %bb.0: +; CHECK32: ! %bb.0: ; CHECK32-NEXT: save %sp, -96, %sp -; CHECK32-NEXT: .cfi_def_cfa_register %fp -; CHECK32-NEXT: .cfi_window_save -; CHECK32-NEXT: .cfi_register %o7, %i7 -; CHECK32-NEXT: add %sp, -64, %i1 +; CHECK32-NEXT: add %sp, -72, %i1 ; CHECK32-NEXT: and %i1, -64, %i1 -; CHECK32-NEXT: add %i1, -16, %sp +; CHECK32-NEXT: add %i1, 96, %o0 +; CHECK32-NEXT: mov %i1, %sp ; CHECK32-NEXT: add %i0, 7, %i0 ; CHECK32-NEXT: and %i0, -8, %i0 ; CHECK32-NEXT: sub %sp, %i0, %i0 -; CHECK32-NEXT: add %i1, 80, %o0 -; CHECK32-NEXT: add %i0, -8, %sp +; CHECK32-NEXT: add %i0, 96, %o1 ; CHECK32-NEXT: call foo -; CHECK32-NEXT: add %i0, 88, %o1 +; CHECK32-NEXT: mov %i0, %sp ; CHECK32-NEXT: ret ; CHECK32-NEXT: restore ; ; CHECK64-LABEL: variable_alloca_with_overalignment: -; CHECK64: .cfi_startproc -; CHECK64-NEXT: ! %bb.0: +; CHECK64: ! %bb.0: ; CHECK64-NEXT: save %sp, -128, %sp -; CHECK64-NEXT: .cfi_def_cfa_register %fp -; CHECK64-NEXT: .cfi_window_save -; CHECK64-NEXT: .cfi_register %o7, %i7 -; CHECK64-NEXT: add %sp, 1983, %i1 +; CHECK64-NEXT: add %sp, 1967, %i1 ; CHECK64-NEXT: and %i1, -64, %i1 -; CHECK64-NEXT: add %i1, -2063, %sp -; CHECK64-NEXT: add %i1, -1935, %o0 +; CHECK64-NEXT: add %i1, -2047, %sp +; CHECK64-NEXT: add %i1, -1919, %o0 ; CHECK64-NEXT: srl %i0, 0, %i0 ; CHECK64-NEXT: add %i0, 15, %i0 ; CHECK64-NEXT: sethi 4194303, %i1 @@ -58,33 +50,25 @@ define void @variable_alloca_with_overalignment(i32 %num) { } ;; Same but with the alloca itself overaligned -define void @variable_alloca_with_overalignment_2(i32 %num) { +define void @variable_alloca_with_overalignment_2(i32 %num) nounwind { ; CHECK32-LABEL: variable_alloca_with_overalignment_2: -; CHECK32: .cfi_startproc -; CHECK32-NEXT: ! %bb.0: +; CHECK32: ! %bb.0: ; CHECK32-NEXT: save %sp, -96, %sp -; CHECK32-NEXT: .cfi_def_cfa_register %fp -; CHECK32-NEXT: .cfi_window_save -; CHECK32-NEXT: .cfi_register %o7, %i7 ; CHECK32-NEXT: add %i0, 7, %i0 ; CHECK32-NEXT: and %i0, -8, %i0 -; CHECK32-NEXT: add %sp, -64, %i1 -; CHECK32-NEXT: and %i1, -64, %i1 -; CHECK32-NEXT: sub %i1, %i0, %i0 -; CHECK32-NEXT: add %i0, -8, %sp -; CHECK32-NEXT: add %i0, 88, %o1 +; CHECK32-NEXT: sub %sp, %i0, %i0 +; CHECK32-NEXT: add %i0, -64, %i0 +; CHECK32-NEXT: and %i0, -64, %i0 +; CHECK32-NEXT: add %i0, 96, %o1 +; CHECK32-NEXT: mov %i0, %sp ; CHECK32-NEXT: call foo ; CHECK32-NEXT: mov %g0, %o0 ; CHECK32-NEXT: ret ; CHECK32-NEXT: restore ; ; CHECK64-LABEL: variable_alloca_with_overalignment_2: -; CHECK64: .cfi_startproc -; CHECK64-NEXT: ! %bb.0: +; CHECK64: ! %bb.0: ; CHECK64-NEXT: save %sp, -128, %sp -; CHECK64-NEXT: .cfi_def_cfa_register %fp -; CHECK64-NEXT: .cfi_window_save -; CHECK64-NEXT: .cfi_register %o7, %i7 ; CHECK64-NEXT: srl %i0, 0, %i0 ; CHECK64-NEXT: add %i0, 15, %i0 ; CHECK64-NEXT: sethi 4194303, %i1 @@ -94,9 +78,9 @@ define void @variable_alloca_with_overalignment_2(i32 %num) { ; CHECK64-NEXT: sllx %i2, 32, %i2 ; CHECK64-NEXT: or %i2, %i1, %i1 ; CHECK64-NEXT: and %i0, %i1, %i0 -; CHECK64-NEXT: add %sp, 1983, %i1 -; CHECK64-NEXT: and %i1, -64, %i1 -; CHECK64-NEXT: sub %i1, %i0, %i0 +; CHECK64-NEXT: sub %sp, %i0, %i0 +; CHECK64-NEXT: add %i0, 1983, %i0 +; CHECK64-NEXT: and %i0, -64, %i0 ; CHECK64-NEXT: add %i0, -2047, %sp ; CHECK64-NEXT: add %i0, -1919, %o1 ; CHECK64-NEXT: add %sp, -48, %sp diff --git a/llvm/test/CodeGen/SPARC/stack-align.ll b/llvm/test/CodeGen/SPARC/stack-align.ll index e2dfe854d643a1..c141cd25a06f52 100644 --- a/llvm/test/CodeGen/SPARC/stack-align.ll +++ b/llvm/test/CodeGen/SPARC/stack-align.ll @@ -8,34 +8,26 @@ declare void @stack_realign_helper(i32 %a, ptr %b) ;; that the local var is accessed via stack pointer (to %o1), and that ;; the argument is accessed via frame pointer not stack pointer (to %o0). -define void @stack_realign(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g) { +define void @stack_realign(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g) nounwind { ; CHECK32-LABEL: stack_realign: -; CHECK32: .cfi_startproc -; CHECK32-NEXT: ! %bb.0: ! %entry +; CHECK32: ! %bb.0: ! %entry ; CHECK32-NEXT: save %sp, -96, %sp -; CHECK32-NEXT: .cfi_def_cfa_register %fp -; CHECK32-NEXT: .cfi_window_save -; CHECK32-NEXT: .cfi_register %o7, %i7 ; CHECK32-NEXT: ld [%fp+92], %o0 -; CHECK32-NEXT: add %sp, -64, %i0 +; CHECK32-NEXT: add %sp, -72, %i0 ; CHECK32-NEXT: and %i0, -64, %i0 -; CHECK32-NEXT: add %i0, -16, %sp +; CHECK32-NEXT: add %i0, 96, %o1 ; CHECK32-NEXT: call stack_realign_helper -; CHECK32-NEXT: add %i0, 80, %o1 +; CHECK32-NEXT: mov %i0, %sp ; CHECK32-NEXT: ret ; CHECK32-NEXT: restore ; ; CHECK64-LABEL: stack_realign: -; CHECK64: .cfi_startproc -; CHECK64-NEXT: ! %bb.0: ! %entry +; CHECK64: ! %bb.0: ! %entry ; CHECK64-NEXT: save %sp, -128, %sp -; CHECK64-NEXT: .cfi_def_cfa_register %fp -; CHECK64-NEXT: .cfi_window_save -; CHECK64-NEXT: .cfi_register %o7, %i7 -; CHECK64-NEXT: add %sp, 1983, %i0 +; CHECK64-NEXT: add %sp, 1967, %i0 ; CHECK64-NEXT: and %i0, -64, %i0 -; CHECK64-NEXT: add %i0, -2063, %sp -; CHECK64-NEXT: add %i0, -1935, %o1 +; CHECK64-NEXT: add %i0, -2047, %sp +; CHECK64-NEXT: add %i0, -1919, %o1 ; CHECK64-NEXT: add %sp, -48, %sp ; CHECK64-NEXT: call stack_realign_helper ; CHECK64-NEXT: ld [%fp+2227], %o0 From cc2a061d49955864d58cf37281275c07fe676a1b Mon Sep 17 00:00:00 2001 From: Koakuma Date: Thu, 12 Sep 2024 09:41:50 +0700 Subject: [PATCH 4/8] Drop legalize comments --- llvm/lib/Target/Sparc/SparcISelLowering.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/llvm/lib/Target/Sparc/SparcISelLowering.cpp index f1fbd5a40a27f0..0be2d3e95165ae 100644 --- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp +++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp @@ -2762,8 +2762,8 @@ static SDValue LowerVAARG(SDValue Op, SelectionDAG &DAG) { static SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG, const SparcSubtarget *Subtarget) { - SDValue Chain = Op.getOperand(0); // Legalize the chain. - SDValue Size = Op.getOperand(1); // Legalize the size. + SDValue Chain = Op.getOperand(0); + SDValue Size = Op.getOperand(1); SDValue Alignment = Op.getOperand(2); MaybeAlign MaybeAlignment = cast(Alignment)->getMaybeAlignValue(); From bfc07e5d63f58190a061c622ea9b6f1cac954c9c Mon Sep 17 00:00:00 2001 From: Koakuma Date: Thu, 12 Sep 2024 13:36:10 +0700 Subject: [PATCH 5/8] Fix return value calculation Upon calculating NewSP we end up with a biased SP again, so we need to account for that in NewVal return. --- llvm/lib/Target/Sparc/SparcISelLowering.cpp | 10 ++++------ llvm/test/CodeGen/SPARC/alloca-align.ll | 4 ++-- llvm/test/CodeGen/SPARC/stack-align.ll | 2 +- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/llvm/lib/Target/Sparc/SparcISelLowering.cpp index 0be2d3e95165ae..565b2cc88d3264 100644 --- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp +++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp @@ -2819,18 +2819,16 @@ static SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG, regSpillArea = 96; } - // If we are allocating overaligned memory then the bias is already accounted - // for in AlignedPtr calculation, so: - // - We do not need to adjust the regSpillArea; but - // - We do need to decrement AlignedPtr by bias to obtain the new SP. - regSpillArea += IsOveraligned ? 0 : Bias; + // If we are allocating overaligned memory then the AlignedPtr calculation + // adds the bias into SP, so we need to restore biased SP by decrementing + // AlignedPtr back here. SDValue NewSP = DAG.getNode(ISD::SUB, dl, VT, AlignedPtr, DAG.getConstant(IsOveraligned ? Bias : 0, dl, VT)); Chain = DAG.getCopyToReg(SP.getValue(1), dl, SPReg, NewSP); SDValue NewVal = DAG.getNode(ISD::ADD, dl, VT, NewSP, - DAG.getConstant(regSpillArea, dl, VT)); + DAG.getConstant(regSpillArea + Bias, dl, VT)); SDValue Ops[2] = { NewVal, Chain }; return DAG.getMergeValues(Ops, dl); } diff --git a/llvm/test/CodeGen/SPARC/alloca-align.ll b/llvm/test/CodeGen/SPARC/alloca-align.ll index 797050d5a92e72..d90704dcf45449 100644 --- a/llvm/test/CodeGen/SPARC/alloca-align.ll +++ b/llvm/test/CodeGen/SPARC/alloca-align.ll @@ -25,7 +25,7 @@ define void @variable_alloca_with_overalignment(i32 %num) nounwind { ; CHECK64-NEXT: add %sp, 1967, %i1 ; CHECK64-NEXT: and %i1, -64, %i1 ; CHECK64-NEXT: add %i1, -2047, %sp -; CHECK64-NEXT: add %i1, -1919, %o0 +; CHECK64-NEXT: add %i1, 128, %o0 ; CHECK64-NEXT: srl %i0, 0, %i0 ; CHECK64-NEXT: add %i0, 15, %i0 ; CHECK64-NEXT: sethi 4194303, %i1 @@ -82,7 +82,7 @@ define void @variable_alloca_with_overalignment_2(i32 %num) nounwind { ; CHECK64-NEXT: add %i0, 1983, %i0 ; CHECK64-NEXT: and %i0, -64, %i0 ; CHECK64-NEXT: add %i0, -2047, %sp -; CHECK64-NEXT: add %i0, -1919, %o1 +; CHECK64-NEXT: add %i0, 128, %o1 ; CHECK64-NEXT: add %sp, -48, %sp ; CHECK64-NEXT: call foo ; CHECK64-NEXT: mov %g0, %o0 diff --git a/llvm/test/CodeGen/SPARC/stack-align.ll b/llvm/test/CodeGen/SPARC/stack-align.ll index c141cd25a06f52..e360d35fb09718 100644 --- a/llvm/test/CodeGen/SPARC/stack-align.ll +++ b/llvm/test/CodeGen/SPARC/stack-align.ll @@ -27,7 +27,7 @@ define void @stack_realign(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 % ; CHECK64-NEXT: add %sp, 1967, %i0 ; CHECK64-NEXT: and %i0, -64, %i0 ; CHECK64-NEXT: add %i0, -2047, %sp -; CHECK64-NEXT: add %i0, -1919, %o1 +; CHECK64-NEXT: add %i0, 128, %o1 ; CHECK64-NEXT: add %sp, -48, %sp ; CHECK64-NEXT: call stack_realign_helper ; CHECK64-NEXT: ld [%fp+2227], %o0 From 80f1564f3125f28e83ab7169138afd9b898c5c55 Mon Sep 17 00:00:00 2001 From: Koakuma Date: Mon, 16 Sep 2024 06:32:15 +0700 Subject: [PATCH 6/8] Fix calculation for alignment over 128 bytes --- llvm/lib/Target/Sparc/SparcISelLowering.cpp | 47 +++++++++---------- .../CodeGen/SPARC/2013-05-17-CallFrame.ll | 4 +- llvm/test/CodeGen/SPARC/alloca-align.ll | 32 ++++++------- llvm/test/CodeGen/SPARC/stack-align.ll | 14 +++--- 4 files changed, 45 insertions(+), 52 deletions(-) diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/llvm/lib/Target/Sparc/SparcISelLowering.cpp index 565b2cc88d3264..5e34a68e90bb7c 100644 --- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp +++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp @@ -2770,22 +2770,8 @@ static SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG, EVT VT = Size->getValueType(0); SDLoc dl(Op); - int64_t Bias = Subtarget->getStackPointerBias(); unsigned SPReg = SP::O6; SDValue SP = DAG.getCopyFromReg(Chain, dl, SPReg, VT); - SDValue AllocatedPtr = DAG.getNode(ISD::SUB, dl, VT, SP, Size); - - bool IsOveraligned = MaybeAlignment.has_value(); - SDValue AlignedPtr = - IsOveraligned - ? DAG.getNode(ISD::AND, dl, VT, - DAG.getNode(ISD::SUB, dl, VT, - DAG.getNode(ISD::ADD, dl, VT, AllocatedPtr, - DAG.getConstant(Bias, dl, VT)), - Alignment), - DAG.getNode(ISD::SUB, dl, VT, - DAG.getConstant(0, dl, VT), Alignment)) - : AllocatedPtr; // The resultant pointer needs to be above the register spill area // at the bottom of the stack. @@ -2819,17 +2805,30 @@ static SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG, regSpillArea = 96; } - // If we are allocating overaligned memory then the AlignedPtr calculation - // adds the bias into SP, so we need to restore biased SP by decrementing - // AlignedPtr back here. - SDValue NewSP = - DAG.getNode(ISD::SUB, dl, VT, AlignedPtr, - DAG.getConstant(IsOveraligned ? Bias : 0, dl, VT)); - Chain = DAG.getCopyToReg(SP.getValue(1), dl, SPReg, NewSP); + int64_t Bias = Subtarget->getStackPointerBias(); + + // Debias and increment SP past the reserved spill area. + // We need the SP to point to the first usable region before calculating + // anything to prevent any of the pointers from becoming out of alignment when + // we rebias the SP later on. + SDValue StartOfUsableStack = DAG.getNode( + ISD::ADD, dl, VT, SP, DAG.getConstant(regSpillArea + Bias, dl, VT)); + SDValue AllocatedPtr = + DAG.getNode(ISD::SUB, dl, VT, StartOfUsableStack, Size); + + bool IsOveraligned = MaybeAlignment.has_value(); + SDValue AlignedPtr = + IsOveraligned + ? DAG.getNode(ISD::AND, dl, VT, AllocatedPtr, + DAG.getNode(ISD::SUB, dl, VT, + DAG.getConstant(0, dl, VT), Alignment)) + : AllocatedPtr; - SDValue NewVal = DAG.getNode(ISD::ADD, dl, VT, NewSP, - DAG.getConstant(regSpillArea + Bias, dl, VT)); - SDValue Ops[2] = { NewVal, Chain }; + // Now that we are done, restore the bias and reserved spill area. + SDValue NewSP = DAG.getNode(ISD::SUB, dl, VT, AlignedPtr, + DAG.getConstant(regSpillArea + Bias, dl, VT)); + Chain = DAG.getCopyToReg(SP.getValue(1), dl, SPReg, NewSP); + SDValue Ops[2] = {AlignedPtr, Chain}; return DAG.getMergeValues(Ops, dl); } diff --git a/llvm/test/CodeGen/SPARC/2013-05-17-CallFrame.ll b/llvm/test/CodeGen/SPARC/2013-05-17-CallFrame.ll index 39782f2ad08c62..9ebedfb68102fe 100644 --- a/llvm/test/CodeGen/SPARC/2013-05-17-CallFrame.ll +++ b/llvm/test/CodeGen/SPARC/2013-05-17-CallFrame.ll @@ -12,8 +12,8 @@ define void @variable_alloca_with_adj_call_stack(i32 %num) nounwind { ; V8-NEXT: add %i0, 7, %i0 ; V8-NEXT: and %i0, -8, %i0 ; V8-NEXT: sub %sp, %i0, %i0 -; V8-NEXT: add %i0, 96, %o0 -; V8-NEXT: mov %i0, %sp +; V8-NEXT: add %i0, -8, %sp +; V8-NEXT: add %i0, 88, %o0 ; V8-NEXT: add %sp, -16, %sp ; V8-NEXT: st %o0, [%sp+104] ; V8-NEXT: st %o0, [%sp+100] diff --git a/llvm/test/CodeGen/SPARC/alloca-align.ll b/llvm/test/CodeGen/SPARC/alloca-align.ll index d90704dcf45449..f6330f16df4737 100644 --- a/llvm/test/CodeGen/SPARC/alloca-align.ll +++ b/llvm/test/CodeGen/SPARC/alloca-align.ll @@ -6,26 +6,24 @@ define void @variable_alloca_with_overalignment(i32 %num) nounwind { ; CHECK32-LABEL: variable_alloca_with_overalignment: ; CHECK32: ! %bb.0: ; CHECK32-NEXT: save %sp, -96, %sp -; CHECK32-NEXT: add %sp, -72, %i1 -; CHECK32-NEXT: and %i1, -64, %i1 -; CHECK32-NEXT: add %i1, 96, %o0 -; CHECK32-NEXT: mov %i1, %sp +; CHECK32-NEXT: add %sp, 80, %i1 +; CHECK32-NEXT: and %i1, -64, %o0 +; CHECK32-NEXT: add %o0, -96, %sp ; CHECK32-NEXT: add %i0, 7, %i0 ; CHECK32-NEXT: and %i0, -8, %i0 ; CHECK32-NEXT: sub %sp, %i0, %i0 -; CHECK32-NEXT: add %i0, 96, %o1 +; CHECK32-NEXT: add %i0, -8, %sp ; CHECK32-NEXT: call foo -; CHECK32-NEXT: mov %i0, %sp +; CHECK32-NEXT: add %i0, 88, %o1 ; CHECK32-NEXT: ret ; CHECK32-NEXT: restore ; ; CHECK64-LABEL: variable_alloca_with_overalignment: ; CHECK64: ! %bb.0: ; CHECK64-NEXT: save %sp, -128, %sp -; CHECK64-NEXT: add %sp, 1967, %i1 -; CHECK64-NEXT: and %i1, -64, %i1 -; CHECK64-NEXT: add %i1, -2047, %sp -; CHECK64-NEXT: add %i1, 128, %o0 +; CHECK64-NEXT: add %sp, 2159, %i1 +; CHECK64-NEXT: and %i1, -64, %o0 +; CHECK64-NEXT: add %o0, -2175, %sp ; CHECK64-NEXT: srl %i0, 0, %i0 ; CHECK64-NEXT: add %i0, 15, %i0 ; CHECK64-NEXT: sethi 4194303, %i1 @@ -57,10 +55,9 @@ define void @variable_alloca_with_overalignment_2(i32 %num) nounwind { ; CHECK32-NEXT: add %i0, 7, %i0 ; CHECK32-NEXT: and %i0, -8, %i0 ; CHECK32-NEXT: sub %sp, %i0, %i0 -; CHECK32-NEXT: add %i0, -64, %i0 -; CHECK32-NEXT: and %i0, -64, %i0 -; CHECK32-NEXT: add %i0, 96, %o1 -; CHECK32-NEXT: mov %i0, %sp +; CHECK32-NEXT: add %i0, 88, %i0 +; CHECK32-NEXT: and %i0, -64, %o1 +; CHECK32-NEXT: add %o1, -96, %sp ; CHECK32-NEXT: call foo ; CHECK32-NEXT: mov %g0, %o0 ; CHECK32-NEXT: ret @@ -79,10 +76,9 @@ define void @variable_alloca_with_overalignment_2(i32 %num) nounwind { ; CHECK64-NEXT: or %i2, %i1, %i1 ; CHECK64-NEXT: and %i0, %i1, %i0 ; CHECK64-NEXT: sub %sp, %i0, %i0 -; CHECK64-NEXT: add %i0, 1983, %i0 -; CHECK64-NEXT: and %i0, -64, %i0 -; CHECK64-NEXT: add %i0, -2047, %sp -; CHECK64-NEXT: add %i0, 128, %o1 +; CHECK64-NEXT: add %i0, 2175, %i0 +; CHECK64-NEXT: and %i0, -64, %o1 +; CHECK64-NEXT: add %o1, -2175, %sp ; CHECK64-NEXT: add %sp, -48, %sp ; CHECK64-NEXT: call foo ; CHECK64-NEXT: mov %g0, %o0 diff --git a/llvm/test/CodeGen/SPARC/stack-align.ll b/llvm/test/CodeGen/SPARC/stack-align.ll index e360d35fb09718..c861b2d0296f0b 100644 --- a/llvm/test/CodeGen/SPARC/stack-align.ll +++ b/llvm/test/CodeGen/SPARC/stack-align.ll @@ -13,21 +13,19 @@ define void @stack_realign(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 % ; CHECK32: ! %bb.0: ! %entry ; CHECK32-NEXT: save %sp, -96, %sp ; CHECK32-NEXT: ld [%fp+92], %o0 -; CHECK32-NEXT: add %sp, -72, %i0 -; CHECK32-NEXT: and %i0, -64, %i0 -; CHECK32-NEXT: add %i0, 96, %o1 +; CHECK32-NEXT: add %sp, 80, %i0 +; CHECK32-NEXT: and %i0, -64, %o1 ; CHECK32-NEXT: call stack_realign_helper -; CHECK32-NEXT: mov %i0, %sp +; CHECK32-NEXT: add %o1, -96, %sp ; CHECK32-NEXT: ret ; CHECK32-NEXT: restore ; ; CHECK64-LABEL: stack_realign: ; CHECK64: ! %bb.0: ! %entry ; CHECK64-NEXT: save %sp, -128, %sp -; CHECK64-NEXT: add %sp, 1967, %i0 -; CHECK64-NEXT: and %i0, -64, %i0 -; CHECK64-NEXT: add %i0, -2047, %sp -; CHECK64-NEXT: add %i0, 128, %o1 +; CHECK64-NEXT: add %sp, 2159, %i0 +; CHECK64-NEXT: and %i0, -64, %o1 +; CHECK64-NEXT: add %o1, -2175, %sp ; CHECK64-NEXT: add %sp, -48, %sp ; CHECK64-NEXT: call stack_realign_helper ; CHECK64-NEXT: ld [%fp+2227], %o0 From f671f2d9cd02831a413adffc02c7caf156a9c3e8 Mon Sep 17 00:00:00 2001 From: Koakuma Date: Sat, 12 Oct 2024 21:49:32 +0700 Subject: [PATCH 7/8] XFAIL alloca_vla_interact.cpp asan test for SPARC --- compiler-rt/test/asan/TestCases/alloca_vla_interact.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/compiler-rt/test/asan/TestCases/alloca_vla_interact.cpp b/compiler-rt/test/asan/TestCases/alloca_vla_interact.cpp index 96ac4c7db291a0..b98bb726dcebc3 100644 --- a/compiler-rt/test/asan/TestCases/alloca_vla_interact.cpp +++ b/compiler-rt/test/asan/TestCases/alloca_vla_interact.cpp @@ -3,6 +3,9 @@ // // REQUIRES: stable-runtime +// See https://github.com/llvm/llvm-project/issues/110956 +// XFAIL: target=sparc{{.*}} + // This testcase checks correct interaction between VLAs and allocas. #include From 54c7669a244a7838dec55fc8de3ab9eaeafa127a Mon Sep 17 00:00:00 2001 From: Koakuma Date: Tue, 29 Oct 2024 06:58:00 +0700 Subject: [PATCH 8/8] Apply suggestions --- llvm/lib/Target/Sparc/SparcFrameLowering.cpp | 8 +------- llvm/lib/Target/Sparc/SparcISelLowering.cpp | 3 +-- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/llvm/lib/Target/Sparc/SparcFrameLowering.cpp b/llvm/lib/Target/Sparc/SparcFrameLowering.cpp index 399d55c439cbb4..4ff389605e944c 100644 --- a/llvm/lib/Target/Sparc/SparcFrameLowering.cpp +++ b/llvm/lib/Target/Sparc/SparcFrameLowering.cpp @@ -227,8 +227,7 @@ bool SparcFrameLowering::hasFP(const MachineFunction &MF) const { const MachineFrameInfo &MFI = MF.getFrameInfo(); return MF.getTarget().Options.DisableFramePointerElim(MF) || - RegInfo->hasStackRealignment(MF) || MFI.hasVarSizedObjects() || - MFI.isFrameAddressTaken(); + MFI.hasVarSizedObjects() || MFI.isFrameAddressTaken(); } StackOffset @@ -254,11 +253,6 @@ SparcFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI, } else if (isFixed) { // Otherwise, argument access should always use %fp. UseFP = true; - } else if (RegInfo->hasStackRealignment(MF)) { - // If there is dynamic stack realignment, all local object - // references need to be via %sp, to take account of the - // re-alignment. - UseFP = false; } else { // Finally, default to using %fp. UseFP = true; diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/llvm/lib/Target/Sparc/SparcISelLowering.cpp index 5e34a68e90bb7c..44f083e4f70cdb 100644 --- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp +++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp @@ -2820,8 +2820,7 @@ static SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG, SDValue AlignedPtr = IsOveraligned ? DAG.getNode(ISD::AND, dl, VT, AllocatedPtr, - DAG.getNode(ISD::SUB, dl, VT, - DAG.getConstant(0, dl, VT), Alignment)) + DAG.getConstant(-MaybeAlignment->value(), dl, VT)) : AllocatedPtr; // Now that we are done, restore the bias and reserved spill area.