Repository navigation
Conversation
|
@llvm/pr-subscribers-backend-sparc Author: Brad Smith (brad0) ChangesparseCondBranch() rebuilt the register operand of a branch-on-register When the register is undef (ProcessImplicitDefs marks the use undef Copy the whole MachineOperand into Cond and add it back with add(), as Fixes #233111 Full diff: https://github.com/llvm/llvm-project/pull/240077.diff 2 Files Affected:
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
+}
|
|
✅ 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>
3c4fd7e to
c431ee6
Compare
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