[llvm-branch-commits] [llvm] release/22.x: [Hexagon] Fix O(N^2) compile-time regression in HexagonOptAddrMode (#189531) (PR #190985)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Wed Apr 8 07:56:35 PDT 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-hexagon
Author: llvmbot
<details>
<summary>Changes</summary>
Backport 06b82d1a18791bc966e9b18ac34f63c888d10723
Requested by: @<!-- -->androm3da
---
Full diff: https://github.com/llvm/llvm-project/pull/190985.diff
2 Files Affected:
- (modified) llvm/lib/Target/Hexagon/HexagonOptAddrMode.cpp (+12-10)
- (added) llvm/test/CodeGen/Hexagon/opt-addr-mode-large-unodelist.ll (+41)
``````````diff
diff --git a/llvm/lib/Target/Hexagon/HexagonOptAddrMode.cpp b/llvm/lib/Target/Hexagon/HexagonOptAddrMode.cpp
index 53afbc433c933..0f2fc5053b003 100644
--- a/llvm/lib/Target/Hexagon/HexagonOptAddrMode.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonOptAddrMode.cpp
@@ -723,18 +723,20 @@ bool HexagonOptAddrMode::processAddUses(NodeAddr<StmtNode *> AddSN,
int64_t newOffset = OffsetOp.getImm() + AddMI->getOperand(2).getImm();
if (!isValidOffset(MI, newOffset))
return false;
-
- // Since we'll be extending the live range of Rt in the following example,
- // make sure that is safe. another definition of Rt doesn't exist between 'add'
- // and load/store instruction.
- //
- // Ex: Rx= add(Rt,#10)
- // memw(Rx+#0) = Rs
- // will be replaced with => memw(Rt+#10) = Rs
- if (!isSafeToExtLR(AddSN, AddMI, BaseReg, UNodeList))
- return false;
}
+ // Since we'll be extending the live range of Rt in the following example,
+ // make sure that is safe. another definition of Rt doesn't exist between
+ // 'add' and load/store instruction.
+ //
+ // Ex: Rx= add(Rt,#10)
+ // memw(Rx+#0) = Rs
+ // will be replaced with => memw(Rt+#10) = Rs
+ // Note: isSafeToExtLR arguments are loop-invariant; call it once after
+ // validating all uses to avoid O(N^2) behavior when UNodeList is large.
+ if (!isSafeToExtLR(AddSN, AddMI, BaseReg, UNodeList))
+ return false;
+
NodeId LRExtRegRD = 0;
// Iterate through all the UseNodes in SN and find the reaching def
// for the LRExtReg.
diff --git a/llvm/test/CodeGen/Hexagon/opt-addr-mode-large-unodelist.ll b/llvm/test/CodeGen/Hexagon/opt-addr-mode-large-unodelist.ll
new file mode 100644
index 0000000000000..16791783ee4ee
--- /dev/null
+++ b/llvm/test/CodeGen/Hexagon/opt-addr-mode-large-unodelist.ll
@@ -0,0 +1,41 @@
+; RUN: llc -mtriple=hexagon -O2 < %s | FileCheck %s
+
+; Verify that processAddUses correctly folds an A2_addi into multiple
+; store offsets. With many uses, isSafeToExtLR must be called once
+; (not once per use) to avoid O(N^2) compile time.
+
+; The A2_addi computing the base address should be eliminated; all
+; stores should use the original base register with the combined offset.
+
+; CHECK-LABEL: f0:
+; CHECK-NOT: = add(r
+; CHECK-DAG: memb(r0+#13)
+; CHECK-DAG: memb(r0+#14)
+; CHECK-DAG: memb(r0+#15)
+; CHECK-DAG: memb(r0+#16)
+; CHECK-DAG: memb(r0+#17)
+; CHECK-DAG: memb(r0+#18)
+; CHECK-DAG: memb(r0+#19)
+; CHECK-DAG: memb(r0+#20)
+
+define void @f0(ptr %base, i8 %a, i8 %b, i8 %c, i8 %d,
+ i8 %e, i8 %f, i8 %g, i8 %h) nounwind {
+entry:
+ %p0 = getelementptr inbounds i8, ptr %base, i32 13
+ store i8 %a, ptr %p0, align 1
+ %p1 = getelementptr inbounds i8, ptr %p0, i32 1
+ store i8 %b, ptr %p1, align 1
+ %p2 = getelementptr inbounds i8, ptr %p0, i32 2
+ store i8 %c, ptr %p2, align 1
+ %p3 = getelementptr inbounds i8, ptr %p0, i32 3
+ store i8 %d, ptr %p3, align 1
+ %p4 = getelementptr inbounds i8, ptr %p0, i32 4
+ store i8 %e, ptr %p4, align 1
+ %p5 = getelementptr inbounds i8, ptr %p0, i32 5
+ store i8 %f, ptr %p5, align 1
+ %p6 = getelementptr inbounds i8, ptr %p0, i32 6
+ store i8 %g, ptr %p6, align 1
+ %p7 = getelementptr inbounds i8, ptr %p0, i32 7
+ store i8 %h, ptr %p7, align 1
+ ret void
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/190985
More information about the llvm-branch-commits
mailing list