[llvm] [Hexagon] Fix hasFP to respect frame-pointer attribute unconditionally (PR #181524)
via llvm-commits
llvm-commits at lists.llvm.org
Sat Feb 14 21:09:46 PST 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-hexagon
Author: Brian Cain (androm3da)
<details>
<summary>Changes</summary>
HexagonFrameLowering::hasFPImpl() incorrectly gated the DisableFramePointerElim check behind MFI.getStackSize() > 0. This meant leaf functions with no stack allocation would not get a frame pointer even when "frame-pointer"="all" (-fno-omit-frame-pointer) was set, violating the user/ABI request. Every other LLVM target checks DisableFramePointerElim unconditionally.
Move the DisableFramePointerElim and EliminateFramePointer checks outside the getStackSize() > 0 guard so they are always evaluated. Update affected tests whose CHECK patterns change due to the now- correct allocframe emission.
---
Full diff: https://github.com/llvm/llvm-project/pull/181524.diff
5 Files Affected:
- (modified) llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp (+8-4)
- (modified) llvm/test/CodeGen/Hexagon/bfloat_vec.ll (+63-44)
- (modified) llvm/test/CodeGen/Hexagon/constp-extract.ll (+3-3)
- (added) llvm/test/CodeGen/Hexagon/frame-pointer-attr.ll (+28)
- (modified) llvm/test/CodeGen/Hexagon/hasfp-crash1.ll (+1-1)
``````````diff
diff --git a/llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp b/llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp
index df612262def5e..027bc116036c4 100644
--- a/llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp
@@ -1153,11 +1153,15 @@ bool HexagonFrameLowering::hasFPImpl(const MachineFunction &MF) const {
if (HasAlloca || HasExtraAlign)
return true;
+ // If FP-elimination is disabled, we have to use FP. This must not be
+ // gated on stack size: the user/ABI-requested frame pointer is needed
+ // regardless of whether the function currently has a stack frame.
+ // Every other target checks DisableFramePointerElim unconditionally.
+ const TargetMachine &TM = MF.getTarget();
+ if (TM.Options.DisableFramePointerElim(MF) || !EliminateFramePointer)
+ return true;
+
if (MFI.getStackSize() > 0) {
- // If FP-elimination is disabled, we have to use FP at this point.
- const TargetMachine &TM = MF.getTarget();
- if (TM.Options.DisableFramePointerElim(MF) || !EliminateFramePointer)
- return true;
if (EnableStackOVFSanitizer)
return true;
}
diff --git a/llvm/test/CodeGen/Hexagon/bfloat_vec.ll b/llvm/test/CodeGen/Hexagon/bfloat_vec.ll
index 47be92aaf0b31..1e5cb3c197261 100644
--- a/llvm/test/CodeGen/Hexagon/bfloat_vec.ll
+++ b/llvm/test/CodeGen/Hexagon/bfloat_vec.ll
@@ -7,81 +7,86 @@ define dso_local void @bf16_vec_add(ptr noundef %c, ptr noundef %a, ptr noundef
; CHECK-LABEL: bf16_vec_add:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: {
-; CHECK-NEXT: [[R7:r[0-9]+]] = #-4
-; CHECK-NEXT: [[V0:v[0-9]+]] = vmemu([[R2:r[0-9]+]]+#0)
+; CHECK-NEXT: r7 = #-4
+; CHECK-NEXT: r6 = ##131071
+; CHECK-NEXT: allocframe(#0)
; CHECK-NEXT: }
; CHECK-NEXT: {
-; CHECK-NEXT: [[R2]] = ##32768
-; CHECK-NEXT: [[V1:v[0-9]+]] = vmemu([[R1:r[0-9]+]]+#0)
+; CHECK-NEXT: r5 = #16
+; CHECK-NEXT: v0 = vmemu(r2+#0)
; CHECK-NEXT: }
; CHECK-NEXT: {
-; CHECK-NEXT: [[R6:r[0-9]+]] = ##131071
-; CHECK-NEXT: [[V2:v[0-9]+]] = vxor([[V0]],[[V0]])
-; CHECK-NEXT: [[V3:v[0-9]+]] = vxor([[V1]],[[V1]])
+; CHECK-NEXT: v26 = vsplat(r6)
+; CHECK-NEXT: r2 = ##32768
; CHECK-NEXT: }
; CHECK-NEXT: {
-; CHECK-NEXT: [[V25:v[0-9]+]] = vsplat([[R2]])
-; CHECK-NEXT: [[R5:r[0-9]+]] = #16
-; CHECK-NEXT: [[V5_4:v[0-9]+:[0-9]+]].h = vshuffoe([[V0]].h,[[V2]].h)
+; CHECK-NEXT: v25 = vsplat(r2)
+; CHECK-NEXT: v2 = vxor(v0,v0)
+; CHECK-NEXT: v1 = vmemu(r1+#0)
; CHECK-NEXT: }
; CHECK-NEXT: {
-; CHECK-NEXT: [[V26:v[0-9]+]] = vsplat([[R6]])
-; CHECK-NEXT: [[R4:r[0-9]+]] = #32767
-; CHECK-NEXT: [[V31_30:v[0-9]+:[0-9]+]].h = vshuffoe([[V1]].h,[[V3]].h)
+; CHECK-NEXT: r4 = #32767
+; CHECK-NEXT: v5:4.h = vshuffoe(v0.h,v2.h)
+; CHECK-NEXT: v3 = vxor(v1,v1)
; CHECK-NEXT: }
; CHECK-NEXT: {
-; CHECK-NEXT: [[V5_4]] = vshuff([[V5:v[0-9]+]],[[V4:v[0-9]+]],[[R7]])
+; CHECK-NEXT: v31:30.h = vshuffoe(v1.h,v3.h)
; CHECK-NEXT: }
; CHECK-NEXT: {
-; CHECK-NEXT: [[V31:v[0-9]+]].h = vsplat([[R4]])
-; CHECK-NEXT: [[V3_2:v[0-9]+:[0-9]+]] = vshuff([[V31]],[[V30:v[0-9]+]],[[R7]])
+; CHECK-NEXT: v5:4 = vshuff(v5,v4,r7)
; CHECK-NEXT: }
; CHECK-NEXT: {
-; CHECK-NEXT: [[V2]].qf32 = vadd([[V2]].sf,[[V4]].sf)
+; CHECK-NEXT: v31.h = vsplat(r4)
+; CHECK-NEXT: v3:2 = vshuff(v31,v30,r7)
; CHECK-NEXT: }
; CHECK-NEXT: {
-; CHECK-NEXT: [[V3]].qf32 = vadd([[V3]].sf,[[V5]].sf)
+; CHECK-NEXT: v2.qf32 = vadd(v2.sf,v4.sf)
; CHECK-NEXT: }
; CHECK-NEXT: {
-; CHECK-NEXT: [[V2]].sf = [[V2]].qf32
+; CHECK-NEXT: v3.qf32 = vadd(v3.sf,v5.sf)
; CHECK-NEXT: }
; CHECK-NEXT: {
-; CHECK-NEXT: [[V3]].sf = [[V3]].qf32
-; CHECK-NEXT: [[V27:v[0-9]+]] = vand([[V2]],[[V25]])
-; CHECK-NEXT: [[V28:v[0-9]+]] = vand([[V2]],[[V26]])
-; CHECK-NEXT: [[Q2:q[0-9]+]] = vcmp.eq([[V2]].sf,[[V2]].sf)
+; CHECK-NEXT: v2.sf = v2.qf32
; CHECK-NEXT: }
; CHECK-NEXT: {
-; CHECK-NEXT: [[V29:v[0-9]+]] = vand([[V3]],[[V25]])
-; CHECK-NEXT: [[V1]] = vand([[V3]],[[V26]])
-; CHECK-NEXT: [[Q0:q[0-9]+]] = vcmp.eq([[V28]].w,[[V25]].w)
-; CHECK-NEXT: [[V4]].w = vadd([[V2]].w,[[V27]].w)
+; CHECK-NEXT: v3.sf = v3.qf32
+; CHECK-NEXT: v27 = vand(v2,v25)
+; CHECK-NEXT: v28 = vand(v2,v26)
+; CHECK-NEXT: q2 = vcmp.eq(v2.sf,v2.sf)
; CHECK-NEXT: }
; CHECK-NEXT: {
-; CHECK-NEXT: [[V5]].w = vadd([[V3]].w,[[V29]].w)
-; CHECK-NEXT: [[Q1:q[0-9]+]] = vcmp.eq([[V1]].w,[[V25]].w)
-; CHECK-NEXT: [[V30:v[0-9]+]] = vmux([[Q0]],[[V2]],[[V4]])
-; CHECK-NEXT: [[Q3:q[0-9]+]] = vcmp.eq([[V3]].sf,[[V3]].sf)
+; CHECK-NEXT: v29 = vand(v3,v25)
+; CHECK-NEXT: v1 = vand(v3,v26)
+; CHECK-NEXT: q0 = vcmp.eq(v28.w,v25.w)
+; CHECK-NEXT: v4.w = vadd(v2.w,v27.w)
; CHECK-NEXT: }
; CHECK-NEXT: {
-; CHECK-NEXT: [[V1]] = vmux([[Q1]],[[V3]],[[V5]])
+; CHECK-NEXT: v5.w = vadd(v3.w,v29.w)
+; CHECK-NEXT: q1 = vcmp.eq(v1.w,v25.w)
+; CHECK-NEXT: v30 = vmux(q0,v2,v4)
+; CHECK-NEXT: q3 = vcmp.eq(v3.sf,v3.sf)
; CHECK-NEXT: }
; CHECK-NEXT: {
-; CHECK-NEXT: [[V0]].uw = vlsr([[V30]].uw,[[R5]])
+; CHECK-NEXT: v1 = vmux(q1,v3,v5)
; CHECK-NEXT: }
; CHECK-NEXT: {
-; CHECK-NEXT: [[V1]].uw = vlsr([[V1]].uw,[[R5]])
-; CHECK-NEXT: [[V0]] = vmux([[Q2]],[[V0]],[[V31]])
+; CHECK-NEXT: v0.uw = vlsr(v30.uw,r5)
; CHECK-NEXT: }
; CHECK-NEXT: {
-; CHECK-NEXT: [[V1]] = vmux([[Q3]],[[V1]],[[V31]])
+; CHECK-NEXT: v1.uw = vlsr(v1.uw,r5)
+; CHECK-NEXT: v0 = vmux(q2,v0,v31)
; CHECK-NEXT: }
; CHECK-NEXT: {
-; CHECK-NEXT: [[V0]].uh = vpack([[V1]].w,[[V0]].w):sat
+; CHECK-NEXT: v1 = vmux(q3,v1,v31)
; CHECK-NEXT: }
; CHECK-NEXT: {
-; CHECK-NEXT: jumpr [[R31:r[0-9]+]]
-; CHECK-NEXT: vmemu([[R0:r[0-9]+]]+#0) = [[V0]]
+; CHECK-NEXT: v0.uh = vpack(v1.w,v0.w):sat
+; CHECK-NEXT: }
+; CHECK-NEXT: {
+; CHECK-NEXT: vmemu(r0+#0) = v0
+; CHECK-NEXT: }
+; CHECK-NEXT: {
+; CHECK-NEXT: r31:30 = dealloc_return(r30):raw
; CHECK-NEXT: }
@@ -95,11 +100,25 @@ entry:
define dso_local void @copy1d(ptr noundef readonly captures(none) %X, ptr noundef writeonly captures(none) %Y) local_unnamed_addr #0 {
; CHECK-LABEL: copy1d:
-; CHECK: v[[X_HI:[0-9]+]] = vmemu(r0+#1)
-; CHECK: v[[X_LO:[0-9]+]] = vmemu(r0+#0)
-; CHECK: vmemu(r1+#1) = v[[X_HI]]
-; CHECK: jumpr [[RET:r[0-9]+]]
-; CHECK: vmemu(r1+#0) = v[[X_LO]]
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: {
+; CHECK-NEXT: allocframe(r29,#0):raw
+; CHECK-NEXT: }
+; CHECK-NEXT: {
+; CHECK-NEXT: v0 = vmemu(r0+#1)
+; CHECK-NEXT: }
+; CHECK-NEXT: {
+; CHECK-NEXT: v1 = vmemu(r0+#0)
+; CHECK-NEXT: }
+; CHECK-NEXT: {
+; CHECK-NEXT: vmemu(r1+#1) = v0
+; CHECK-NEXT: }
+; CHECK-NEXT: {
+; CHECK-NEXT: vmemu(r1+#0) = v1
+; CHECK-NEXT: }
+; CHECK-NEXT: {
+; CHECK-NEXT: r31:30 = dealloc_return(r30):raw
+; CHECK-NEXT: }
entry:
%0 = load <128 x half>, ptr %X, align 2
store <128 x half> %0, ptr %Y, align 2
diff --git a/llvm/test/CodeGen/Hexagon/constp-extract.ll b/llvm/test/CodeGen/Hexagon/constp-extract.ll
index c72afdc7cfa81..d3e183868d04a 100644
--- a/llvm/test/CodeGen/Hexagon/constp-extract.ll
+++ b/llvm/test/CodeGen/Hexagon/constp-extract.ll
@@ -11,13 +11,13 @@ entry:
; extractu(0x000ABCD0, 16, 4)
; should evaluate to 0xABCD (dec 43981)
%0 = call i32 @llvm.hexagon.S2.extractu(i32 703696, i32 16, i32 4)
-; CHECK: 43981
-; CHECK-NOT: extractu
+; CHECK-DAG: 43981
store i32 %0, ptr @x, align 4
; extract(0x000ABCD0, 16, 4)
; should evaluate to 0xFFFFABCD (dec 4294945741 or -21555)
%1 = call i32 @llvm.hexagon.S4.extract(i32 703696, i32 16, i32 4)
-; CHECK: -21555
+; CHECK-DAG: -21555
+; CHECK-NOT: extractu
; CHECK-NOT: extract
store i32 %1, ptr @y, align 4
ret void
diff --git a/llvm/test/CodeGen/Hexagon/frame-pointer-attr.ll b/llvm/test/CodeGen/Hexagon/frame-pointer-attr.ll
new file mode 100644
index 0000000000000..fa9ed2e5802ad
--- /dev/null
+++ b/llvm/test/CodeGen/Hexagon/frame-pointer-attr.ll
@@ -0,0 +1,28 @@
+; RUN: llc -mtriple=hexagon -O2 -o - %s | FileCheck %s
+
+; The "frame-pointer"="all" attribute (i.e. -fno-omit-frame-pointer) must be
+; respected even for leaf functions that have no stack usage. Hexagon's
+; hasFPImpl was incorrectly gating the DisableFramePointerElim check behind
+; MFI.getStackSize() > 0, so leaf functions with no stack would skip the
+; check and omit the frame pointer.
+
+; CHECK-LABEL: leaf_fp:
+; CHECK: allocframe
+define i32 @leaf_fp(i32 %a, i32 %b) #0 {
+entry:
+ %add = add nsw i32 %a, %b
+ ret i32 %add
+}
+
+; Verify that without the attribute, the leaf function still omits the
+; frame pointer (the optimization is preserved).
+; CHECK-LABEL: leaf_no_fp:
+; CHECK-NOT: allocframe
+define i32 @leaf_no_fp(i32 %a, i32 %b) #1 {
+entry:
+ %add = add nsw i32 %a, %b
+ ret i32 %add
+}
+
+attributes #0 = { nounwind "frame-pointer"="all" }
+attributes #1 = { nounwind }
diff --git a/llvm/test/CodeGen/Hexagon/hasfp-crash1.ll b/llvm/test/CodeGen/Hexagon/hasfp-crash1.ll
index 6755ad0eb178d..77186bc013eb6 100644
--- a/llvm/test/CodeGen/Hexagon/hasfp-crash1.ll
+++ b/llvm/test/CodeGen/Hexagon/hasfp-crash1.ll
@@ -1,7 +1,7 @@
; RUN: llc -mtriple=hexagon < %s | FileCheck %s
;
; Check that this testcase does not crash.
-; CHECK: jumpr r31
+; CHECK: dealloc_return
target triple = "hexagon"
``````````
</details>
https://github.com/llvm/llvm-project/pull/181524
More information about the llvm-commits
mailing list