[llvm] [PowerPC] Avoid working on deleted node in ext bool trunc combine (PR #160050)

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Mon Sep 22 01:25:33 PDT 2025


https://github.com/nikic created https://github.com/llvm/llvm-project/pull/160050

This code was already creating HandleSDNodes to handle the case where a node gets replaced with an equivalent node. However, the code before the handles are created also performs RAUW operations, which can end up CSEing and deleting nodes.

Fix this issue by moving the handle creation earlier.

>From 5bc4ecde2a7c548aab204db3d8f32a8f49508386 Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Mon, 22 Sep 2025 10:21:39 +0200
Subject: [PATCH] [PowerPC] Avoid working on deleted node in ext bool trunc
 combine

This code was already creating HandleSDNodes to handle the case
where a node gets replaced with an equivalent node. However, the
code before the handles are created also performs RAUW operations,
which can end up CSEing and deleting nodes.

Fix this issue by moving the handle creation earlier.
---
 llvm/lib/Target/PowerPC/PPCISelLowering.cpp | 10 +++++----
 llvm/test/CodeGen/PowerPC/pr160040.ll       | 24 +++++++++++++++++++++
 2 files changed, 30 insertions(+), 4 deletions(-)
 create mode 100644 llvm/test/CodeGen/PowerPC/pr160040.ll

diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index fa104e4f69d7f..47e107d11f71b 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -15407,6 +15407,12 @@ SDValue PPCTargetLowering::DAGCombineExtBoolTrunc(SDNode *N,
     }
   }
 
+  // Convert PromOps to handles before doing any RAUW operations, as these
+  // may CSE with existing nodes, deleting the originals.
+  std::list<HandleSDNode> PromOpHandles;
+  for (auto &PromOp : PromOps)
+    PromOpHandles.emplace_back(PromOp);
+
   // Replace all inputs, either with the truncation operand, or a
   // truncation or extension to the final output type.
   for (unsigned i = 0, ie = Inputs.size(); i != ie; ++i) {
@@ -15430,10 +15436,6 @@ SDValue PPCTargetLowering::DAGCombineExtBoolTrunc(SDNode *N,
         DAG.getAnyExtOrTrunc(InSrc, dl, N->getValueType(0)));
   }
 
-  std::list<HandleSDNode> PromOpHandles;
-  for (auto &PromOp : PromOps)
-    PromOpHandles.emplace_back(PromOp);
-
   // Replace all operations (these are all the same, but have a different
   // (promoted) return type). DAG.getNode will validate that the types of
   // a binary operator match, so go through the list in reverse so that
diff --git a/llvm/test/CodeGen/PowerPC/pr160040.ll b/llvm/test/CodeGen/PowerPC/pr160040.ll
new file mode 100644
index 0000000000000..865239b37112c
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/pr160040.ll
@@ -0,0 +1,24 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -mtriple=powerpc64le-unknown-linux-gnu < %s | FileCheck %s
+
+; Make sure this does not crash.
+define i32 @test(i32 %arg) {
+; CHECK-LABEL: test:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    rlwinm 4, 3, 13, 19, 19
+; CHECK-NEXT:    rlwinm 3, 3, 2, 30, 30
+; CHECK-NEXT:    xori 4, 4, 4096
+; CHECK-NEXT:    xori 3, 3, 2
+; CHECK-NEXT:    rlwimi 3, 4, 0, 31, 29
+; CHECK-NEXT:    blr
+  %icmp = icmp sgt i32 %arg, -1
+  %select = select i1 %icmp, i16 1, i16 0
+  %select1 = select i1 %icmp, i16 16384, i16 0
+  %lshr = lshr i16 %select1, 1
+  %zext = zext i16 %lshr to i32
+  %lshr2 = lshr i32 %zext, 1
+  %shl = shl i16 %select, 1
+  %zext3 = zext i16 %shl to i32
+  %or = or i32 %lshr2, %zext3
+  ret i32 %or
+}



More information about the llvm-commits mailing list