Skip to content

Invalidate range metadata when folding bitcast into load #133095

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

Merged
merged 3 commits into from
Mar 27, 2025

Conversation

LU-JOHN
Copy link
Contributor

@LU-JOHN LU-JOHN commented Mar 26, 2025

When folding bitcast into a load, range metadata may not match new load type. If so, invalidate the range metadata.

Signed-off-by: John Lu <John.Lu@amd.com>
@llvmbot
Copy link
Member

llvmbot commented Mar 26, 2025

@llvm/pr-subscribers-llvm-selectiondag

Author: None (LU-JOHN)

Changes

When folding bitcast into a load, range metadata may not match new load type. If so, invalidate the range metadata.


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

2 Files Affected:

  • (modified) llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp (+9)
  • (added) llvm/test/CodeGen/X86/fold_bitcast_md_range.ll (+31)
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index bf49642634291..a8e516b8c2937 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -15964,6 +15964,15 @@ SDValue DAGCombiner::visitBITCAST(SDNode *N) {
 
     if (TLI.isLoadBitCastBeneficial(N0.getValueType(), VT, DAG,
                                     *LN0->getMemOperand())) {
+      // If the range metadata type does not match the new memory
+      // operation type, remove the range metadata.
+      if (const MDNode *MD = LN0->getRanges()) {
+        ConstantInt *Lower = mdconst::extract<ConstantInt>(MD->getOperand(0));
+        if (Lower->getBitWidth() != VT.getScalarSizeInBits() ||
+            !VT.isInteger()) {
+          LN0->getMemOperand()->clearRanges();
+        }
+      }
       SDValue Load =
           DAG.getLoad(VT, SDLoc(N), LN0->getChain(), LN0->getBasePtr(),
                       LN0->getMemOperand());
diff --git a/llvm/test/CodeGen/X86/fold_bitcast_md_range.ll b/llvm/test/CodeGen/X86/fold_bitcast_md_range.ll
new file mode 100644
index 0000000000000..3417acb4e2744
--- /dev/null
+++ b/llvm/test/CodeGen/X86/fold_bitcast_md_range.ll
@@ -0,0 +1,31 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc -mtriple=x86_64-apple-macosx10.12.0 -O0 < %s | FileCheck %s
+
+; Ensure that when a bitcast is folded into a load, range metadata is invalidated
+; if it does not match the new type.
+
+target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
+
+define void @fold_bitcast_range_metadata() {
+; CHECK-LABEL: fold_bitcast_range_metadata:
+; CHECK:       ## %bb.0: ## %start
+; CHECK-NEXT:    movaps 0, %xmm0
+; CHECK-NEXT:    movaps {{.*#+}} xmm1 = [1,0,0,0]
+; CHECK-NEXT:    pcmpeqb %xmm1, %xmm0
+; CHECK-NEXT:    pmovmskb %xmm0, %eax
+; CHECK-NEXT:    subl $65535, %eax ## imm = 0xFFFF
+; CHECK-NEXT:    jne LBB0_1
+; CHECK-NEXT:    jmp LBB0_1
+; CHECK-NEXT:  LBB0_1: ## %bb1
+; CHECK-NEXT:    retq
+start:
+  %0 = load i128, ptr null, align 16, !range !0, !noundef !1
+  %1 = icmp eq i128 %0, 1
+  br i1 %1, label %bb1, label %bb1
+
+bb1:                                              ; preds = %start, %start
+  ret void
+}
+
+!0 = !{i128 0, i128 3}
+!1 = !{}

@llvmbot
Copy link
Member

llvmbot commented Mar 26, 2025

@llvm/pr-subscribers-backend-x86

Author: None (LU-JOHN)

Changes

When folding bitcast into a load, range metadata may not match new load type. If so, invalidate the range metadata.


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

2 Files Affected:

  • (modified) llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp (+9)
  • (added) llvm/test/CodeGen/X86/fold_bitcast_md_range.ll (+31)
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index bf49642634291..a8e516b8c2937 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -15964,6 +15964,15 @@ SDValue DAGCombiner::visitBITCAST(SDNode *N) {
 
     if (TLI.isLoadBitCastBeneficial(N0.getValueType(), VT, DAG,
                                     *LN0->getMemOperand())) {
+      // If the range metadata type does not match the new memory
+      // operation type, remove the range metadata.
+      if (const MDNode *MD = LN0->getRanges()) {
+        ConstantInt *Lower = mdconst::extract<ConstantInt>(MD->getOperand(0));
+        if (Lower->getBitWidth() != VT.getScalarSizeInBits() ||
+            !VT.isInteger()) {
+          LN0->getMemOperand()->clearRanges();
+        }
+      }
       SDValue Load =
           DAG.getLoad(VT, SDLoc(N), LN0->getChain(), LN0->getBasePtr(),
                       LN0->getMemOperand());
diff --git a/llvm/test/CodeGen/X86/fold_bitcast_md_range.ll b/llvm/test/CodeGen/X86/fold_bitcast_md_range.ll
new file mode 100644
index 0000000000000..3417acb4e2744
--- /dev/null
+++ b/llvm/test/CodeGen/X86/fold_bitcast_md_range.ll
@@ -0,0 +1,31 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc -mtriple=x86_64-apple-macosx10.12.0 -O0 < %s | FileCheck %s
+
+; Ensure that when a bitcast is folded into a load, range metadata is invalidated
+; if it does not match the new type.
+
+target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
+
+define void @fold_bitcast_range_metadata() {
+; CHECK-LABEL: fold_bitcast_range_metadata:
+; CHECK:       ## %bb.0: ## %start
+; CHECK-NEXT:    movaps 0, %xmm0
+; CHECK-NEXT:    movaps {{.*#+}} xmm1 = [1,0,0,0]
+; CHECK-NEXT:    pcmpeqb %xmm1, %xmm0
+; CHECK-NEXT:    pmovmskb %xmm0, %eax
+; CHECK-NEXT:    subl $65535, %eax ## imm = 0xFFFF
+; CHECK-NEXT:    jne LBB0_1
+; CHECK-NEXT:    jmp LBB0_1
+; CHECK-NEXT:  LBB0_1: ## %bb1
+; CHECK-NEXT:    retq
+start:
+  %0 = load i128, ptr null, align 16, !range !0, !noundef !1
+  %1 = icmp eq i128 %0, 1
+  br i1 %1, label %bb1, label %bb1
+
+bb1:                                              ; preds = %start, %start
+  ret void
+}
+
+!0 = !{i128 0, i128 3}
+!1 = !{}

@LU-JOHN
Copy link
Contributor Author

LU-JOHN commented Mar 26, 2025

Fixes crash that started with #128908

Signed-off-by: John Lu <John.Lu@amd.com>
@LU-JOHN LU-JOHN requested a review from arsenm March 26, 2025 17:15
@durin42
Copy link
Contributor

durin42 commented Mar 26, 2025

I've confirmed we can bootstrap Rust again with this applied, thanks!

Copy link
Contributor

@arsenm arsenm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-O0 shouldn't be necessary (and it's kind of a DAG perma-bug that this fold happens at -O0)

Signed-off-by: John Lu <John.Lu@amd.com>
@LU-JOHN LU-JOHN requested a review from arsenm March 27, 2025 02:12
@arsenm arsenm merged commit 2df25a4 into llvm:main Mar 27, 2025
8 of 11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:X86 llvm:SelectionDAG SelectionDAGISel as well
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants