[llvm-branch-commits] [llvm] release/23.x: [MIPS] Fix GP-relative selection after select/add combine (#215414) (PR #220795)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Wed Sep 2 21:03:08 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-mips
Author: llvmbot
<details>
<summary>Changes</summary>
Backport c5b1e01ed897f417c370a225c6cdaaa14a1c142d
Requested by: @<!-- -->brad0
---
Full diff: https://github.com/llvm/llvm-project/pull/220795.diff
4 Files Affected:
- (modified) llvm/lib/Target/Mips/MipsISelDAGToDAG.cpp (+49)
- (modified) llvm/lib/Target/Mips/MipsISelDAGToDAG.h (+2)
- (modified) llvm/test/CodeGen/Mips/cmov.ll (+6)
- (modified) llvm/test/CodeGen/Mips/llvm-ir/select-globaladdr.ll (+3-4)
``````````diff
diff --git a/llvm/lib/Target/Mips/MipsISelDAGToDAG.cpp b/llvm/lib/Target/Mips/MipsISelDAGToDAG.cpp
index 36706243232c0..4e90d78048199 100644
--- a/llvm/lib/Target/Mips/MipsISelDAGToDAG.cpp
+++ b/llvm/lib/Target/Mips/MipsISelDAGToDAG.cpp
@@ -224,6 +224,55 @@ bool MipsDAGToDAGISel::selectVecAddAsVecSubIfProfitable(SDNode *Node) {
return true;
}
+void MipsDAGToDAGISel::PreprocessISelDAG() {
+ // The generic DAG combiner folds
+ //
+ // select C, (add $gp, %gp_rel(A)), (add $gp, %gp_rel(B))
+ //
+ // into
+ //
+ // add $gp, (select C, %gp_rel(A), %gp_rel(B)).
+ //
+ // A GP-relative relocation is only selectable as an operand of the add.
+ // Restore the original form before instruction selection so the relocation
+ // is never selected on its own.
+ bool MadeChange = false;
+ for (SDNode &Node : llvm::make_early_inc_range(CurDAG->allnodes())) {
+ if (Node.getOpcode() != ISD::ADD)
+ continue;
+
+ SDValue Base = Node.getOperand(0);
+ SDValue Sel = Node.getOperand(1);
+ if (Base.getOpcode() == ISD::SELECT)
+ std::swap(Base, Sel);
+
+ const auto *BaseReg = dyn_cast<RegisterSDNode>(Base);
+ if (!BaseReg ||
+ (BaseReg->getReg() != Mips::GP && BaseReg->getReg() != Mips::GP_64) ||
+ Sel.getOpcode() != ISD::SELECT)
+ continue;
+
+ SDValue TrueValue = Sel.getOperand(1);
+ SDValue FalseValue = Sel.getOperand(2);
+ if (TrueValue.getOpcode() != MipsISD::GPRel &&
+ FalseValue.getOpcode() != MipsISD::GPRel)
+ continue;
+
+ SDLoc DL(&Node);
+ EVT VT = Node.getValueType(0);
+ SDNodeFlags Flags = Node.getFlags();
+ TrueValue = CurDAG->getNode(ISD::ADD, DL, VT, Base, TrueValue, Flags);
+ FalseValue = CurDAG->getNode(ISD::ADD, DL, VT, Base, FalseValue, Flags);
+ SDValue NewSel =
+ CurDAG->getSelect(DL, VT, Sel.getOperand(0), TrueValue, FalseValue);
+ CurDAG->ReplaceAllUsesOfValueWith(SDValue(&Node, 0), NewSel);
+ MadeChange = true;
+ }
+
+ if (MadeChange)
+ CurDAG->RemoveDeadNodes();
+}
+
/// Select instructions not customized! Used for
/// expanded, promoted and normal instructions
void MipsDAGToDAGISel::Select(SDNode *Node) {
diff --git a/llvm/lib/Target/Mips/MipsISelDAGToDAG.h b/llvm/lib/Target/Mips/MipsISelDAGToDAG.h
index f19d72d94f806..1c90835526e43 100644
--- a/llvm/lib/Target/Mips/MipsISelDAGToDAG.h
+++ b/llvm/lib/Target/Mips/MipsISelDAGToDAG.h
@@ -124,6 +124,8 @@ class MipsDAGToDAGISel : public SelectionDAGISel {
/// add X, <-1, -1...> --> sub X, <1, 1...>
bool selectVecAddAsVecSubIfProfitable(SDNode *Node);
+ void PreprocessISelDAG() override;
+
void Select(SDNode *N) override;
virtual bool trySelect(SDNode *Node) = 0;
diff --git a/llvm/test/CodeGen/Mips/cmov.ll b/llvm/test/CodeGen/Mips/cmov.ll
index ee60b353b86b6..fba0526e7f5bc 100644
--- a/llvm/test/CodeGen/Mips/cmov.ll
+++ b/llvm/test/CodeGen/Mips/cmov.ll
@@ -5,6 +5,7 @@
; RUN: llc -mtriple=mips64el -mcpu=mips4 -relocation-model=pic < %s | FileCheck %s -check-prefixes=ALL,64-CMOV
; RUN: llc -mtriple=mips64el -mcpu=mips64 -relocation-model=pic < %s | FileCheck %s -check-prefixes=ALL,64-CMOV
; RUN: llc -mtriple=mips64el -mcpu=mips64r6 -relocation-model=pic < %s | FileCheck %s -check-prefixes=ALL,64-CMP
+; RUN: llc -mtriple=mips -mcpu=mips32 -relocation-model=static -mgpopt -mattr=+noabicalls < %s | FileCheck %s -check-prefix=GPREL
@i1 = global [3 x i32] [i32 1, i32 2, i32 3], align 4
@i3 = common global ptr null, align 4
@@ -51,6 +52,11 @@ entry:
; ALL-LABEL: cmov2:
+; GPREL-LABEL: cmov2:
+; GPREL-DAG: addiu $[[D:[0-9]+]], $gp, %gp_rel(d)
+; GPREL-DAG: addiu $[[C:[0-9]+]], $gp, %gp_rel(c)
+; GPREL: movn $[[D]], $[[C]], $4
+
; 32-CMOV-DAG: addiu $[[R1:[0-9]+]], ${{[0-9]+}}, %got(d)
; 32-CMOV-DAG: addiu $[[R0:[0-9]+]], ${{[0-9]+}}, %got(c)
; 32-CMOV-DAG: movn $[[R1]], $[[R0]], $4
diff --git a/llvm/test/CodeGen/Mips/llvm-ir/select-globaladdr.ll b/llvm/test/CodeGen/Mips/llvm-ir/select-globaladdr.ll
index 7e6a6b0dbcecd..a43525f4e2bbe 100644
--- a/llvm/test/CodeGen/Mips/llvm-ir/select-globaladdr.ll
+++ b/llvm/test/CodeGen/Mips/llvm-ir/select-globaladdr.ll
@@ -10,11 +10,10 @@ define ptr @tst_select_ptr_ptr(i1 %tobool.not) {
; MIPS64: # %bb.0: # %entry
; MIPS64-NEXT: sll $1, $4, 0
; MIPS64-NEXT: andi $1, $1, 1
-; MIPS64-NEXT: daddiu $2, $zero, %gp_rel(.str)
-; MIPS64-NEXT: daddiu $3, $zero, %gp_rel(.str.1)
-; MIPS64-NEXT: movn $2, $3, $1
+; MIPS64-NEXT: daddiu $2, $gp, %gp_rel(.str)
+; MIPS64-NEXT: daddiu $3, $gp, %gp_rel(.str.1)
; MIPS64-NEXT: jr $ra
-; MIPS64-NEXT: daddu $2, $gp, $2
+; MIPS64-NEXT: movn $2, $3, $1
entry:
%cond = select i1 %tobool.not, ptr @.str.1, ptr @.str
ret ptr %cond
``````````
</details>
https://github.com/llvm/llvm-project/pull/220795
More information about the llvm-branch-commits
mailing list