-
Notifications
You must be signed in to change notification settings - Fork 12.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Backport [DAGCombine] Fix multi-use miscompile in load combine (#81586) #81633
Conversation
The load combine replaces a number of original loads with one new loads and also replaces the output chains of the original loads with the output chain of the new load. This is incorrect if the original load is retained (due to multi-use), as it may get incorrectly reordered. Fix this by using makeEquivalentMemoryOrdering() instead, which will create a TokenFactor with both chains. Fixes llvm#80911. (cherry picked from commit 25b9ed6)
@llvm/pr-subscribers-backend-x86 @llvm/pr-subscribers-llvm-selectiondag Author: Nikita Popov (nikic) Changes(cherry picked from commit 25b9ed6) Full diff: https://github.com/llvm/llvm-project/pull/81633.diff 2 Files Affected:
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 98d8a6d9409f25..3135ec73a99e76 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -9253,7 +9253,7 @@ SDValue DAGCombiner::MatchLoadCombine(SDNode *N) {
// Transfer chain users from old loads to the new load.
for (LoadSDNode *L : Loads)
- DAG.ReplaceAllUsesOfValueWith(SDValue(L, 1), SDValue(NewLoad.getNode(), 1));
+ DAG.makeEquivalentMemoryOrdering(L, NewLoad);
if (!NeedsBswap)
return NewLoad;
diff --git a/llvm/test/CodeGen/X86/load-combine.ll b/llvm/test/CodeGen/X86/load-combine.ll
index 7f8115dc1ce389..b5f3e789918813 100644
--- a/llvm/test/CodeGen/X86/load-combine.ll
+++ b/llvm/test/CodeGen/X86/load-combine.ll
@@ -1282,3 +1282,35 @@ define i32 @zext_load_i32_by_i8_bswap_shl_16(ptr %arg) {
%tmp8 = or i32 %tmp7, %tmp30
ret i32 %tmp8
}
+
+define i32 @pr80911_vector_load_multiuse(ptr %ptr, ptr %clobber) nounwind {
+; CHECK-LABEL: pr80911_vector_load_multiuse:
+; CHECK: # %bb.0:
+; CHECK-NEXT: pushl %esi
+; CHECK-NEXT: movl {{[0-9]+}}(%esp), %ecx
+; CHECK-NEXT: movl {{[0-9]+}}(%esp), %edx
+; CHECK-NEXT: movl (%edx), %esi
+; CHECK-NEXT: movzwl (%edx), %eax
+; CHECK-NEXT: movl $0, (%ecx)
+; CHECK-NEXT: movl %esi, (%edx)
+; CHECK-NEXT: popl %esi
+; CHECK-NEXT: retl
+;
+; CHECK64-LABEL: pr80911_vector_load_multiuse:
+; CHECK64: # %bb.0:
+; CHECK64-NEXT: movl (%rdi), %ecx
+; CHECK64-NEXT: movzwl (%rdi), %eax
+; CHECK64-NEXT: movl $0, (%rsi)
+; CHECK64-NEXT: movl %ecx, (%rdi)
+; CHECK64-NEXT: retq
+ %load = load <4 x i8>, ptr %ptr, align 16
+ store i32 0, ptr %clobber
+ store <4 x i8> %load, ptr %ptr, align 16
+ %e1 = extractelement <4 x i8> %load, i64 1
+ %e1.ext = zext i8 %e1 to i32
+ %e1.ext.shift = shl nuw nsw i32 %e1.ext, 8
+ %e0 = extractelement <4 x i8> %load, i64 0
+ %e0.ext = zext i8 %e0 to i32
+ %res = or i32 %e1.ext.shift, %e0.ext
+ ret i32 %res
+}
|
@RKSimon What do you think about backporting this? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM for backport
(cherry picked from commit 25b9ed6)