[llvm] [PowerPC] Preserve load output chain in vcmpequb combine (PR #187010)
Nikita Popov via llvm-commits
llvm-commits at lists.llvm.org
Tue Mar 17 05:16:33 PDT 2026
https://github.com/nikic created https://github.com/llvm/llvm-project/pull/187010
Replace uses of the old load output chain with the new load output chain. A plain replacement here is fine because the transform verifies the load is one-use.
Fixes https://github.com/llvm/llvm-project/issues/186549.
>From 1c6e071b6bd3180e20d2864878fd5de15317f1f5 Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Tue, 17 Mar 2026 13:04:07 +0100
Subject: [PATCH 1/2] Add test for miscompile
---
.../CodeGen/PowerPC/load-i128-eq-chain.ll | 42 +++++++++++++++++++
1 file changed, 42 insertions(+)
create mode 100644 llvm/test/CodeGen/PowerPC/load-i128-eq-chain.ll
diff --git a/llvm/test/CodeGen/PowerPC/load-i128-eq-chain.ll b/llvm/test/CodeGen/PowerPC/load-i128-eq-chain.ll
new file mode 100644
index 0000000000000..6a14cf1b562fb
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/load-i128-eq-chain.ll
@@ -0,0 +1,42 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -mtriple=ppc64le-unknown-linux-gnu < %s | FileCheck %s
+
+define i1 @test() nounwind {
+; CHECK-LABEL: test:
+; CHECK: # %bb.0:
+; CHECK-NEXT: mflr 0
+; CHECK-NEXT: std 30, -16(1) # 8-byte Folded Spill
+; CHECK-NEXT: stdu 1, -64(1)
+; CHECK-NEXT: addi 30, 1, 32
+; CHECK-NEXT: std 0, 80(1)
+; CHECK-NEXT: mr 3, 30
+; CHECK-NEXT: bl call
+; CHECK-NEXT: nop
+; CHECK-NEXT: mr 3, 30
+; CHECK-NEXT: bl call
+; CHECK-NEXT: nop
+; CHECK-NEXT: lxvd2x 34, 0, 30
+; CHECK-NEXT: lxvd2x 35, 0, 30
+; CHECK-NEXT: vcmpequb. 2, 2, 3
+; CHECK-NEXT: mfocrf 3, 2
+; CHECK-NEXT: rlwinm 3, 3, 25, 31, 31
+; CHECK-NEXT: addi 1, 1, 64
+; CHECK-NEXT: ld 0, 16(1)
+; CHECK-NEXT: ld 30, -16(1) # 8-byte Folded Reload
+; CHECK-NEXT: mtlr 0
+; CHECK-NEXT: blr
+ %a1 = alloca [16 x i8], align 16
+ %a2 = alloca [16 x i8], align 16
+ call void @llvm.lifetime.start.p0(i64 16, ptr %a2)
+ call void @call(ptr %a2)
+ %l1 = load i128, ptr %a2, align 16
+ call void @llvm.lifetime.end.p0(i64 16, ptr %a2)
+ call void @llvm.lifetime.start.p0(i64 16, ptr %a1)
+ call void @call(ptr %a1)
+ %l2 = load i128, ptr %a1, align 16
+ call void @llvm.lifetime.end.p0(i64 16, ptr %a1)
+ %res = icmp eq i128 %l1, %l2
+ ret i1 %res
+}
+
+declare void @call(ptr)
>From 4786c7701197a406e4ee3af6c6f471db8227371a Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Tue, 17 Mar 2026 13:13:22 +0100
Subject: [PATCH 2/2] Preserve chain
---
llvm/lib/Target/PowerPC/PPCISelLowering.cpp | 4 +++-
.../CodeGen/PowerPC/load-i128-eq-chain.ll | 21 ++++++++++++-------
2 files changed, 16 insertions(+), 9 deletions(-)
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index 200d026dadd7b..927168bf8438f 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -15755,8 +15755,10 @@ SDValue convertTwoLoadsAndCmpToVCMPEQUB(SelectionDAG &DAG, SDNode *N,
assert(Operand.getOpcode() == ISD::LOAD && "Must be LoadSDNode here.");
auto *LoadNode = cast<LoadSDNode>(Operand);
- return DAG.getLoad(MVT::v16i8, DL, LoadNode->getChain(),
+ SDValue NewLoad = DAG.getLoad(MVT::v16i8, DL, LoadNode->getChain(),
LoadNode->getBasePtr(), LoadNode->getMemOperand());
+ DAG.ReplaceAllUsesOfValueWith(Operand.getValue(1), NewLoad.getValue(1));
+ return NewLoad;
};
// Following code transforms the DAG
diff --git a/llvm/test/CodeGen/PowerPC/load-i128-eq-chain.ll b/llvm/test/CodeGen/PowerPC/load-i128-eq-chain.ll
index 6a14cf1b562fb..6fc3e07cb21f5 100644
--- a/llvm/test/CodeGen/PowerPC/load-i128-eq-chain.ll
+++ b/llvm/test/CodeGen/PowerPC/load-i128-eq-chain.ll
@@ -1,28 +1,33 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
; RUN: llc -mtriple=ppc64le-unknown-linux-gnu < %s | FileCheck %s
+; Make sure the loads happen after each call, not after both calls.
define i1 @test() nounwind {
; CHECK-LABEL: test:
; CHECK: # %bb.0:
; CHECK-NEXT: mflr 0
-; CHECK-NEXT: std 30, -16(1) # 8-byte Folded Spill
-; CHECK-NEXT: stdu 1, -64(1)
-; CHECK-NEXT: addi 30, 1, 32
-; CHECK-NEXT: std 0, 80(1)
+; CHECK-NEXT: stdu 1, -96(1)
+; CHECK-NEXT: std 0, 112(1)
+; CHECK-NEXT: std 30, 80(1) # 8-byte Folded Spill
+; CHECK-NEXT: li 3, 64
+; CHECK-NEXT: addi 30, 1, 48
+; CHECK-NEXT: stxvd2x 63, 1, 3 # 16-byte Folded Spill
; CHECK-NEXT: mr 3, 30
; CHECK-NEXT: bl call
; CHECK-NEXT: nop
+; CHECK-NEXT: lxvd2x 63, 0, 30
; CHECK-NEXT: mr 3, 30
; CHECK-NEXT: bl call
; CHECK-NEXT: nop
; CHECK-NEXT: lxvd2x 34, 0, 30
-; CHECK-NEXT: lxvd2x 35, 0, 30
-; CHECK-NEXT: vcmpequb. 2, 2, 3
+; CHECK-NEXT: li 4, 64
+; CHECK-NEXT: ld 30, 80(1) # 8-byte Folded Reload
+; CHECK-NEXT: vcmpequb. 2, 31, 2
+; CHECK-NEXT: lxvd2x 63, 1, 4 # 16-byte Folded Reload
; CHECK-NEXT: mfocrf 3, 2
; CHECK-NEXT: rlwinm 3, 3, 25, 31, 31
-; CHECK-NEXT: addi 1, 1, 64
+; CHECK-NEXT: addi 1, 1, 96
; CHECK-NEXT: ld 0, 16(1)
-; CHECK-NEXT: ld 30, -16(1) # 8-byte Folded Reload
; CHECK-NEXT: mtlr 0
; CHECK-NEXT: blr
%a1 = alloca [16 x i8], align 16
More information about the llvm-commits
mailing list