https://github.com/llvmbot created https://github.com/llvm/llvm-project/pull/220795
Backport c5b1e01ed897f417c370a225c6cdaaa14a1c142d Requested by: @brad0 >From a48be23922e6a98849c8c081375e038c6892ae91 Mon Sep 17 00:00:00 2001 From: david04g <[email protected]> Date: Wed, 2 Sep 2026 20:54:03 -0700 Subject: [PATCH] [MIPS] Fix GP-relative selection after select/add combine (#215414) ## Summary - Rewrite `$gp + select(...)` before MIPS instruction selection when a select arm contains a GP-relative relocation. - Keep each `MipsISD::GPRel` attached to a selectable add operation. - Add MIPS32 regression coverage and update the resulting MIPS64 checks. ## Background The generic DAG combiner can transform: select C, (add $gp, %gp_rel(A)), (add $gp, %gp_rel(B)) into: add $gp, (select C, %gp_rel(A), %gp_rel(B)) This leaves `MipsISD::GPRel` as a standalone value, which MIPS instruction selection cannot match. The new MIPS DAG-to-DAG preprocessing step restores the distributive form before selection. This follows the MIPS-local fixup direction discussed in #212163 and avoids introducing a target-independent hook. ## Testing - Built `llc` on current `upstream/main`. - Ran the exact MIPS32 static `-mgpopt -mattr=+noabicalls` reproducer. - Ran: - `llvm/test/CodeGen/Mips/cmov.ll` - `llvm/test/CodeGen/Mips/llvm-ir/select-globaladdr.ll` - Ran `check-llvm-codegen-mips`: - 1040 discovered - 1033 passed - 3 unsupported - 4 expected failures - 0 unexpected failures Fixes #212057 AI disclosure: I used OpenAI Codex to help with issue analysis, patch development/review, and local validation. I personally reviewed and understand the final code, tests, and PR description and take responsibility for the contribution. (cherry picked from commit c5b1e01ed897f417c370a225c6cdaaa14a1c142d) --- llvm/lib/Target/Mips/MipsISelDAGToDAG.cpp | 49 +++++++++++++++++++ llvm/lib/Target/Mips/MipsISelDAGToDAG.h | 2 + llvm/test/CodeGen/Mips/cmov.ll | 6 +++ .../CodeGen/Mips/llvm-ir/select-globaladdr.ll | 7 ++- 4 files changed, 60 insertions(+), 4 deletions(-) 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 _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
