[llvm] [X86][APX] Fix segfault in foldMemoryOperandImpl for two-address NDD fold (PR #190562)
via llvm-commits
llvm-commits at lists.llvm.org
Sun Apr 5 16:46:40 PDT 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-x86
Author: Michael (MichaelShires)
<details>
<summary>Changes</summary>
The NoNDDM code path in foldMemoryOperandImpl assumed NewMI->getOperand(1) is always a register. When IsTwoAddr is true, fuseTwoAddrInst replaces operands 0-4 with memory address components, so getOperand(1) is the immediate, not a register. Calling setReg() causes a segfault in removeOperandFromUseList.
Skip the NoNDDM COPY block when IsTwoAddr is true, since the two-address fold already correctly handles the dest==src1 constraint.
I believe the issue was introduced with #<!-- -->189222 , the 'NoNDDM' block calls 'NewMI->getOperand(1).setReg()', but after 'fuseTwoAddrInst', operand 1 is an immediate, not a register.
Passes all APX regression tests. Unit test included in commit. Fixes issue #<!-- -->190557.
First time submitting a PR to the LLVM project, please let me know if I need to fix something! Tagging @<!-- -->phoebewang and @<!-- -->RKSimon as potential review candidates.
---
Full diff: https://github.com/llvm/llvm-project/pull/190562.diff
2 Files Affected:
- (modified) llvm/lib/Target/X86/X86InstrInfo.cpp (+1-1)
- (added) llvm/test/CodeGen/X86/apx/ndd-fold-twoaddr-crash.ll (+71)
``````````diff
diff --git a/llvm/lib/Target/X86/X86InstrInfo.cpp b/llvm/lib/Target/X86/X86InstrInfo.cpp
index 3b48a333147b5..5b6858f59e6d6 100644
--- a/llvm/lib/Target/X86/X86InstrInfo.cpp
+++ b/llvm/lib/Target/X86/X86InstrInfo.cpp
@@ -7592,7 +7592,7 @@ MachineInstr *X86InstrInfo::foldMemoryOperandImpl(
NewMI->getOperand(0).setSubReg(X86::sub_32bit);
}
- if (NoNDDM) {
+ if (NoNDDM && !IsTwoAddr) {
Register SrcReg = MI.getOperand(1).getReg();
if (MI.killsRegister(SrcReg, /*TRI=*/nullptr))
return NewMI;
diff --git a/llvm/test/CodeGen/X86/apx/ndd-fold-twoaddr-crash.ll b/llvm/test/CodeGen/X86/apx/ndd-fold-twoaddr-crash.ll
new file mode 100644
index 0000000000000..77eaea404a4a1
--- /dev/null
+++ b/llvm/test/CodeGen/X86/apx/ndd-fold-twoaddr-crash.ll
@@ -0,0 +1,71 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+ndd -verify-machineinstrs | FileCheck %s
+;
+; Verify that folding NDD instructions to non-NDD with memory operands does not
+; crash when the fold goes through the two-address path (IsTwoAddr=true).
+; This is a regression test for a segfault in foldMemoryOperandImpl where
+; NewMI->getOperand(1).setReg() was called on a memory operand instead of a
+; register operand after fuseTwoAddrInst.
+
+define void @ndd_fold_twoaddr(ptr %0, i64 %1, ptr %2, i64 %3, i1 %4) {
+; CHECK-LABEL: ndd_fold_twoaddr:
+; CHECK: # %bb.0:
+; CHECK-NEXT: pushq %rbp
+; CHECK-NEXT: .cfi_def_cfa_offset 16
+; CHECK-NEXT: pushq %r15
+; CHECK-NEXT: .cfi_def_cfa_offset 24
+; CHECK-NEXT: pushq %r14
+; CHECK-NEXT: .cfi_def_cfa_offset 32
+; CHECK-NEXT: pushq %r13
+; CHECK-NEXT: .cfi_def_cfa_offset 40
+; CHECK-NEXT: pushq %r12
+; CHECK-NEXT: .cfi_def_cfa_offset 48
+; CHECK-NEXT: pushq %rbx
+; CHECK-NEXT: .cfi_def_cfa_offset 56
+; CHECK-NEXT: subq $24, %rsp
+; CHECK-NEXT: .cfi_def_cfa_offset 80
+; CHECK-NEXT: .cfi_offset %rbx, -56
+; CHECK-NEXT: .cfi_offset %r12, -48
+; CHECK-NEXT: .cfi_offset %r13, -40
+; CHECK-NEXT: .cfi_offset %r14, -32
+; CHECK-NEXT: .cfi_offset %r15, -24
+; CHECK-NEXT: .cfi_offset %rbp, -16
+; CHECK-NEXT: movl %r8d, %ebx
+; CHECK-NEXT: movq %rcx, %r14
+; CHECK-NEXT: movq %rdx, %r15
+; CHECK-NEXT: movq %rsi, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
+; CHECK-NEXT: movq %rdi, %r13
+; CHECK-NEXT: movq $0, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Folded Spill
+; CHECK-NEXT: movq %rcx, %r12
+; CHECK-NEXT: movq %rcx, %rbp
+; CHECK-NEXT: .p2align 4
+; CHECK-NEXT: .LBB0_2: # =>This Inner Loop Header: Depth=1
+; CHECK-NEXT: movq %rbp, %rdi
+; CHECK-NEXT: movq %r13, %rsi
+; CHECK-NEXT: callq *%r15
+; CHECK-NEXT: addq %r14, %rbp
+; CHECK-NEXT: testb $1, %bl
+; CHECK-NEXT: jne .LBB0_2
+; CHECK-NEXT: # %bb.1: # in Loop: Header=BB0_2 Depth=1
+; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rax # 8-byte Reload
+; CHECK-NEXT: addq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Folded Reload
+; CHECK-NEXT: addq %rax, %r12
+; CHECK-NEXT: movq %r12, %rbp
+; CHECK-NEXT: jmp .LBB0_2
+ br label %6
+
+6:
+ %7 = phi ptr [ %10, %9 ], [ null, %5 ]
+ %8 = icmp ugt ptr %7, null
+ br label %11
+
+9:
+ %10 = getelementptr i8, ptr %7, i64 %1
+ br label %6
+
+11:
+ %12 = phi ptr [ %13, %11 ], [ %7, %6 ]
+ %13 = getelementptr i8, ptr %12, i64 %3
+ %14 = tail call i32 %2(ptr %13, ptr %0)
+ br i1 %4, label %11, label %9
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/190562
More information about the llvm-commits
mailing list