Skip to content

[SPARC] Preserve register operand flags in BPR branch conditions - #240077

Open
brad0 wants to merge 1 commit into
llvm:mainfrom
brad0:sparc-bpr-undef
Open

brad0 wants to merge 1 commit into
llvm:mainfrom
brad0:sparc-bpr-undef

Conversation

@brad0

@brad0 brad0 commented Nov 8, 2026

Copy link
Copy Markdown
Contributor

parseCondBranch() rebuilt the register operand of a branch-on-register
(BPR) instruction from just its register number, and insertBranch()
re-added it with addReg(), so any operand flags were lost when a branch
was analyzed and reinserted.

When the register is undef (ProcessImplicitDefs marks the use undef
after removing its IMPLICIT_DEF), PHI elimination splitting a critical
edge rewrites the terminator via updateTerminator() and the BPR ends up
reading a virtual register with no def. The machine verifier rejects
this, and without the verifier the greedy register allocator segfaults
in VirtRegAuxInfo::weightCalcHelper.

Copy the whole MachineOperand into Cond and add it back with add(), as
other targets do.

Fixes #233111

@llvmorg-github-actions

Copy link
Copy Markdown

@llvm/pr-subscribers-backend-sparc

Author: Brad Smith (brad0)

Changes

parseCondBranch() rebuilt the register operand of a branch-on-register
(BPR) instruction from just its register number, and insertBranch()
re-added it with addReg(), so any operand flags were lost when a branch
was analyzed and reinserted.

When the register is undef (ProcessImplicitDefs marks the use undef
after removing its IMPLICIT_DEF), PHI elimination splitting a critical
edge rewrites the terminator via updateTerminator() and the BPR ends up
reading a virtual register with no def. The machine verifier rejects
this, and without the verifier the greedy register allocator segfaults
in VirtRegAuxInfo::weightCalcHelper.

Copy the whole MachineOperand into Cond and add it back with add(), as
other targets do.

Fixes #233111


Full diff: https://github.com/llvm/llvm-project/pull/240077.diff

2 Files Affected:

  • (modified) llvm/lib/Target/Sparc/SparcInstrInfo.cpp (+3-6)
  • (added) llvm/test/CodeGen/SPARC/bpr-undef-reg.ll (+47)
diff --git a/llvm/lib/Target/Sparc/SparcInstrInfo.cpp b/llvm/lib/Target/Sparc/SparcInstrInfo.cpp
index d3bb79a7769e4..f124dc6d0ed59 100644
--- a/llvm/lib/Target/Sparc/SparcInstrInfo.cpp
+++ b/llvm/lib/Target/Sparc/SparcInstrInfo.cpp
@@ -229,10 +229,8 @@ static void parseCondBranch(MachineInstr *LastInst, MachineBasicBlock *&Target,
 
   // Branch on register contents need another argument to indicate
   // the register it branches on.
-  if (isRegCondBranchOpcode(Opc)) {
-      Register Reg = LastInst->getOperand(2).getReg();
-      Cond.push_back(MachineOperand::CreateReg(Reg, false));
-  }
+  if (isRegCondBranchOpcode(Opc))
+    Cond.push_back(LastInst->getOperand(2));
 
   Target = LastInst->getOperand(0).getMBB();
 }
@@ -375,8 +373,7 @@ unsigned SparcInstrInfo::insertBranch(MachineBasicBlock &MBB,
   unsigned Opc = Cond[0].getImm();
   unsigned CC = Cond[1].getImm();
   if (isRegCondBranchOpcode(Opc)) {
-    Register Reg = Cond[2].getReg();
-    BuildMI(&MBB, DL, get(Opc)).addMBB(TBB).addImm(CC).addReg(Reg);
+    BuildMI(&MBB, DL, get(Opc)).addMBB(TBB).addImm(CC).add(Cond[2]);
   } else {
     BuildMI(&MBB, DL, get(Opc)).addMBB(TBB).addImm(CC);
   }
diff --git a/llvm/test/CodeGen/SPARC/bpr-undef-reg.ll b/llvm/test/CodeGen/SPARC/bpr-undef-reg.ll
new file mode 100644
index 0000000000000..54cc314fd85b3
--- /dev/null
+++ b/llvm/test/CodeGen/SPARC/bpr-undef-reg.ll
@@ -0,0 +1,47 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc < %s -mtriple=sparcv9 -O2 -verify-machineinstrs | FileCheck %s
+
+;; The branch-on-register condition here is undef (from the poison shift
+;; amount), so ProcessImplicitDefs marks the BPR register operand as undef.
+;; PHI elimination then splits a critical edge and rebuilds the branch via
+;; analyzeBranch/insertBranch; the undef flag must survive that or the
+;; machine verifier complains about reading a virtual register without a def
+;; (and the register allocator crashes without the verifier).
+;; https://github.com/llvm/llvm-project/issues/233111
+
+define i64 @bpr_undef_reg() {
+; CHECK-LABEL: bpr_undef_reg:
+; CHECK:         .cfi_startproc
+; CHECK-NEXT:  ! %bb.0: ! %entry
+; CHECK-NEXT:    cmp %g0, 0
+; CHECK-NEXT:    bne %icc, .LBB0_3
+; CHECK-NEXT:    mov -1, %o0
+; CHECK-NEXT:  ! %bb.1: ! %entry
+; CHECK-NEXT:    brz %o0, .LBB0_3
+; CHECK-NEXT:    nop
+; CHECK-NEXT:  ! %bb.2: ! %bb
+; CHECK-NEXT:    mov %o0, %o1
+; CHECK-NEXT:    mov %g0, %o0
+; CHECK-NEXT:    retl
+; CHECK-NEXT:    movrlz %o1, 0, %o0
+; CHECK-NEXT:  .LBB0_3:
+; CHECK-NEXT:    mov %g0, %o1
+; CHECK-NEXT:    retl
+; CHECK-NEXT:    movrlz %o1, 0, %o0
+entry:
+  %sel = select i1 false, i64 0, i64 -1
+  %shr = lshr i64 0, poison
+  %cmp = icmp eq i64 %shr, 0
+  %or.cond = select i1 false, i1 true, i1 %cmp
+  br i1 %or.cond, label %exit, label %bb
+
+bb:
+  br label %exit
+
+exit:
+  %a = phi i64 [ %sel, %bb ], [ 0, %entry ]
+  %b = phi i64 [ 0, %bb ], [ -1, %entry ]
+  %neg = icmp slt i64 %a, 0
+  %res = select i1 %neg, i64 0, i64 %b
+  ret i64 %res
+}

@github-actions

github-actions Bot commented Nov 8, 2026 •

Copy link
Copy Markdown

✅ With the latest revision this PR passed the undef deprecator.

parseCondBranch() rebuilt the register operand of a branch-on-register
(BPR) instruction from just its register number, and insertBranch()
re-added it with addReg(), so any operand flags were lost when a branch
was analyzed and reinserted.

When the register is undef (ProcessImplicitDefs marks the use undef
after removing its IMPLICIT_DEF), PHI elimination splitting a critical
edge rewrites the terminator via updateTerminator() and the BPR ends up
reading a virtual register with no def. The machine verifier rejects
this, and without the verifier the greedy register allocator segfaults
in VirtRegAuxInfo::weightCalcHelper.

Copy the whole MachineOperand into Cond and add it back with add(), as
other targets do.

Fixes llvm#233111

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@brad0
brad0 requested review from doac and koachan November 8, 2026 02:11

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[SPARC] llc -O2 segfaults in VirtRegAuxInfo::weightCalcHelper on sparc64

1 participant