[llvm-branch-commits] [llvm] PowerPC: Fix FMA reassociation crash on an undef multiply operand (PR #216602)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Sun Aug 16 13:29:27 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-x86

Author: Matt Arsenault (arsenm)

<details>
<summary>Changes</summary>

Make sure getVRegDef succeeded.

Found by AI while working on something else.

Co-authored-by: Claude (Opus 4.8) <noreply@<!-- -->anthropic.com>

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


3 Files Affected:

- (modified) llvm/lib/CodeGen/TargetRegisterInfo.cpp (+1-1) 
- (modified) llvm/lib/Target/PowerPC/PPCInstrInfo.cpp (+1-1) 
- (added) llvm/test/CodeGen/PowerPC/fma-reassoc-undef-mul.mir (+73) 


``````````diff
diff --git a/llvm/lib/CodeGen/TargetRegisterInfo.cpp b/llvm/lib/CodeGen/TargetRegisterInfo.cpp
index 351fae37ab891..3b29b0863dd6c 100644
--- a/llvm/lib/CodeGen/TargetRegisterInfo.cpp
+++ b/llvm/lib/CodeGen/TargetRegisterInfo.cpp
@@ -631,7 +631,7 @@ Register TargetRegisterInfo::lookThruSingleUseCopyChain(
   while (true) {
     const MachineInstr *MI = MRI->getVRegDef(SrcReg);
     // Found the real definition, return it if it has a single use.
-    if (!MI->isCopyLike())
+    if (!MI || !MI->isCopyLike())
       return MRI->hasOneNonDBGUse(SrcReg) ? SrcReg : Register();
 
     Register CopySrcReg;
diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp b/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp
index f415a9776da94..85301285a8237 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp
+++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp
@@ -461,7 +461,7 @@ bool PPCInstrInfo::getFMAPatterns(MachineInstr &Root,
 
       MULInstrL = MRI->getVRegDef(MULRegL);
       MULInstrR = MRI->getVRegDef(MULRegR);
-      return true;
+      return MULInstrL && MULInstrR;
     }
     return false;
   };
diff --git a/llvm/test/CodeGen/PowerPC/fma-reassoc-undef-mul.mir b/llvm/test/CodeGen/PowerPC/fma-reassoc-undef-mul.mir
new file mode 100644
index 0000000000000..e01acc1f07297
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/fma-reassoc-undef-mul.mir
@@ -0,0 +1,73 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -mtriple=powerpc64le-unknown-linux-gnu -mcpu=pwr9 -ppc-fma-rp-factor=0.0 -O3 -run-pass=machine-combiner -o - %s | FileCheck %s
+
+# FMA reassociation must not crash when a multiply operand is an undef register
+# with no def. Both multiply operands are checked, so cover each one.
+---
+name: fma_undef_mul_lhs
+tracksRegLiveness: true
+constants:
+  - id: 0
+    value: float f0x2D9299FF
+    alignment: 4
+body: |
+  bb.0:
+    liveins: $f1, $f2, $f3, $f4, $x2
+    ; CHECK-LABEL: name: fma_undef_mul_lhs
+    ; CHECK: liveins: $f1, $f2, $f3, $f4, $x2
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:vssrc = COPY $f4
+    ; CHECK-NEXT: [[COPY1:%[0-9]+]]:vssrc = COPY $f3
+    ; CHECK-NEXT: [[COPY2:%[0-9]+]]:vssrc = COPY $f2
+    ; CHECK-NEXT: [[COPY3:%[0-9]+]]:vssrc = COPY $f1
+    ; CHECK-NEXT: [[XSSUBSP:%[0-9]+]]:vssrc = nsz contract reassoc nofpexcept XSSUBSP [[COPY1]], [[COPY]]
+    ; CHECK-NEXT: [[ADDIStocHA8_:%[0-9]+]]:g8rc_and_g8rc_nox0 = ADDIStocHA8 $x2, %const.0
+    ; CHECK-NEXT: [[DFLOADf32_:%[0-9]+]]:vssrc = DFLOADf32 target-flags(ppc-toc-lo) %const.0, killed [[ADDIStocHA8_]] :: (load (s32) from constant-pool)
+    ; CHECK-NEXT: [[XSMADDASP:%[0-9]+]]:vssrc = nsz contract reassoc nofpexcept XSMADDASP killed [[XSSUBSP]], undef %8:vssrc, killed [[DFLOADf32_]]
+    ; CHECK-NEXT: $f1 = COPY [[XSMADDASP]]
+    ; CHECK-NEXT: BLR8 implicit $lr8, implicit $rm, implicit $f1
+    %3:vssrc = COPY $f4
+    %2:vssrc = COPY $f3
+    %1:vssrc = COPY $f2
+    %0:vssrc = COPY $f1
+    %5:vssrc = nsz contract reassoc nofpexcept XSSUBSP %2, %3
+    %6:g8rc_and_g8rc_nox0 = ADDIStocHA8 $x2, %const.0
+    %7:vssrc = DFLOADf32 target-flags(ppc-toc-lo) %const.0, killed %6 :: (load (s32) from constant-pool)
+    %8:vssrc = nsz contract reassoc nofpexcept XSMADDASP killed %5, undef %4:vssrc, killed %7
+    $f1 = COPY %8
+    BLR8 implicit $lr8, implicit $rm, implicit $f1
+...
+---
+name: fma_undef_mul_rhs
+tracksRegLiveness: true
+constants:
+  - id: 0
+    value: float f0x2D9299FF
+    alignment: 4
+body: |
+  bb.0:
+    liveins: $f1, $f2, $f3, $f4, $x2
+    ; CHECK-LABEL: name: fma_undef_mul_rhs
+    ; CHECK: liveins: $f1, $f2, $f3, $f4, $x2
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:vssrc = COPY $f4
+    ; CHECK-NEXT: [[COPY1:%[0-9]+]]:vssrc = COPY $f3
+    ; CHECK-NEXT: [[COPY2:%[0-9]+]]:vssrc = COPY $f2
+    ; CHECK-NEXT: [[COPY3:%[0-9]+]]:vssrc = COPY $f1
+    ; CHECK-NEXT: [[XSSUBSP:%[0-9]+]]:vssrc = nsz contract reassoc nofpexcept XSSUBSP [[COPY1]], [[COPY]]
+    ; CHECK-NEXT: [[ADDIStocHA8_:%[0-9]+]]:g8rc_and_g8rc_nox0 = ADDIStocHA8 $x2, %const.0
+    ; CHECK-NEXT: [[DFLOADf32_:%[0-9]+]]:vssrc = DFLOADf32 target-flags(ppc-toc-lo) %const.0, killed [[ADDIStocHA8_]] :: (load (s32) from constant-pool)
+    ; CHECK-NEXT: [[XSMADDASP:%[0-9]+]]:vssrc = nsz contract reassoc nofpexcept XSMADDASP killed [[XSSUBSP]], killed [[DFLOADf32_]], undef %8:vssrc
+    ; CHECK-NEXT: $f1 = COPY [[XSMADDASP]]
+    ; CHECK-NEXT: BLR8 implicit $lr8, implicit $rm, implicit $f1
+    %3:vssrc = COPY $f4
+    %2:vssrc = COPY $f3
+    %1:vssrc = COPY $f2
+    %0:vssrc = COPY $f1
+    %5:vssrc = nsz contract reassoc nofpexcept XSSUBSP %2, %3
+    %6:g8rc_and_g8rc_nox0 = ADDIStocHA8 $x2, %const.0
+    %7:vssrc = DFLOADf32 target-flags(ppc-toc-lo) %const.0, killed %6 :: (load (s32) from constant-pool)
+    %8:vssrc = nsz contract reassoc nofpexcept XSMADDASP killed %5, killed %7, undef %4:vssrc
+    $f1 = COPY %8
+    BLR8 implicit $lr8, implicit $rm, implicit $f1
+...

``````````

</details>


https://github.com/llvm/llvm-project/pull/216602


More information about the llvm-branch-commits mailing list