Skip to content

release/22.x: [PowerPC] Drop invalid range metadata when lowering i64 load to fp in INT_TO_FP (#198705)#199985

Merged
c-rhodes merged 1 commit into
llvm:release/22.xfrom
llvmbot:issue198705
Jun 1, 2026
Merged

release/22.x: [PowerPC] Drop invalid range metadata when lowering i64 load to fp in INT_TO_FP (#198705)#199985
c-rhodes merged 1 commit into
llvm:release/22.xfrom
llvmbot:issue198705

Conversation

@llvmbot

@llvmbot llvmbot commented May 27, 2026

Copy link
Copy Markdown
Member

Backport 78f5f77

Requested by: @amy-kwan

@llvmbot

llvmbot commented May 27, 2026

Copy link
Copy Markdown
Member Author

@lei137 What do you think about merging this PR to the release branch?

@llvmorg-github-actions

Copy link
Copy Markdown

@llvm/pr-subscribers-backend-powerpc

Author: llvmbot

Changes

Backport 78f5f77

Requested by: @amy-kwan


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

2 Files Affected:

  • (modified) llvm/lib/Target/PowerPC/PPCISelLowering.cpp (+3-1)
  • (added) llvm/test/CodeGen/PowerPC/ppc-i64-to-fp.ll (+100)
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index bdba040529d00..8ca207ec67c96 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -8822,8 +8822,10 @@ SDValue PPCTargetLowering::LowerINT_TO_FP(SDValue Op,
 
     MachineFunction &MF = DAG.getMachineFunction();
     if (canReuseLoadAddress(SINT, MVT::i64, RLI, DAG)) {
+      // Drop range metadata, as this metadata becomes invalid for f64 bit
+      // reinterpretation of i64 values.
       Bits = DAG.getLoad(MVT::f64, dl, RLI.Chain, RLI.Ptr, RLI.MPI,
-                         RLI.Alignment, RLI.MMOFlags(), RLI.AAInfo, RLI.Ranges);
+                         RLI.Alignment, RLI.MMOFlags(), RLI.AAInfo, nullptr);
       if (RLI.ResChain)
         DAG.makeEquivalentMemoryOrdering(RLI.ResChain, Bits.getValue(1));
     } else if (Subtarget.hasLFIWAX() &&
diff --git a/llvm/test/CodeGen/PowerPC/ppc-i64-to-fp.ll b/llvm/test/CodeGen/PowerPC/ppc-i64-to-fp.ll
new file mode 100644
index 0000000000000..b6f58938d03bf
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/ppc-i64-to-fp.ll
@@ -0,0 +1,100 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -mcpu=pwr8 -ppc-asm-full-reg-names -mtriple=powerpc64le-unknown-linux-gnu < %s | \
+; RUN:   FileCheck %s --check-prefix=COMMON
+; RUN: llc -mcpu=pwr8 -ppc-asm-full-reg-names -mtriple=powerpc64-ibm-aix < %s | \
+; RUN:   FileCheck %s --check-prefix=COMMON
+; RUN: llc -mcpu=pwr8 -ppc-asm-full-reg-names -mtriple=powerpc-ibm-aix < %s | \
+; RUN:   FileCheck %s --check-prefix=CHECK-AIX32
+
+; Test that assertions related to the range metadata when converting from i64
+; to i32 does not occur.
+
+define float @case_i64_uitofp_f32(ptr %p) {
+; COMMON-LABEL: case_i64_uitofp_f32:
+; COMMON:       # %bb.0: # %entry
+; COMMON-NEXT:    lfd f0, 0(r3)
+; COMMON-NEXT:    xscvuxdsp f1, f0
+; COMMON-NEXT:    blr
+;
+; CHECK-AIX32-LABEL: case_i64_uitofp_f32:
+; CHECK-AIX32:       # %bb.0: # %entry
+; CHECK-AIX32-NEXT:    lwz r4, 4(r3)
+; CHECK-AIX32-NEXT:    stw r4, -4(r1)
+; CHECK-AIX32-NEXT:    lwz r3, 0(r3)
+; CHECK-AIX32-NEXT:    stw r3, -8(r1)
+; CHECK-AIX32-NEXT:    lfd f0, -8(r1)
+; CHECK-AIX32-NEXT:    xscvuxdsp f1, f0
+; CHECK-AIX32-NEXT:    blr
+entry:
+  %x = load i64, ptr %p, align 8, !range !0
+  %y = uitofp i64 %x to float
+  ret float %y
+}
+
+define double @case_i64_sitofp_f64(ptr %p) {
+; COMMON-LABEL: case_i64_sitofp_f64:
+; COMMON:       # %bb.0: # %entry
+; COMMON-NEXT:    lfd f0, 0(r3)
+; COMMON-NEXT:    xscvsxddp f1, f0
+; COMMON-NEXT:    blr
+;
+; CHECK-AIX32-LABEL: case_i64_sitofp_f64:
+; CHECK-AIX32:       # %bb.0: # %entry
+; CHECK-AIX32-NEXT:    lwz r4, 4(r3)
+; CHECK-AIX32-NEXT:    stw r4, -4(r1)
+; CHECK-AIX32-NEXT:    lwz r3, 0(r3)
+; CHECK-AIX32-NEXT:    stw r3, -8(r1)
+; CHECK-AIX32-NEXT:    lfd f0, -8(r1)
+; CHECK-AIX32-NEXT:    xscvsxddp f1, f0
+; CHECK-AIX32-NEXT:    blr
+entry:
+  %x = load i64, ptr %p, align 8, !range !0
+  %y = sitofp i64 %x to double
+  ret double %y
+}
+
+define double @case_i64_uitofp_f64(ptr %p) {
+; COMMON-LABEL: case_i64_uitofp_f64:
+; COMMON:       # %bb.0: # %entry
+; COMMON-NEXT:    lfd f0, 0(r3)
+; COMMON-NEXT:    xscvuxddp f1, f0
+; COMMON-NEXT:    blr
+;
+; CHECK-AIX32-LABEL: case_i64_uitofp_f64:
+; CHECK-AIX32:       # %bb.0: # %entry
+; CHECK-AIX32-NEXT:    lwz r4, 4(r3)
+; CHECK-AIX32-NEXT:    stw r4, -4(r1)
+; CHECK-AIX32-NEXT:    lwz r3, 0(r3)
+; CHECK-AIX32-NEXT:    stw r3, -8(r1)
+; CHECK-AIX32-NEXT:    lfd f0, -8(r1)
+; CHECK-AIX32-NEXT:    xscvuxddp f1, f0
+; CHECK-AIX32-NEXT:    blr
+entry:
+  %x = load i64, ptr %p, align 8, !range !0
+  %y = uitofp i64 %x to double
+  ret double %y
+}
+
+define float @case_i64_sitofp_f32(ptr %p) {
+; COMMON-LABEL: case_i64_sitofp_f32:
+; COMMON:       # %bb.0: # %entry
+; COMMON-NEXT:    lfd f0, 0(r3)
+; COMMON-NEXT:    xscvsxdsp f1, f0
+; COMMON-NEXT:    blr
+;
+; CHECK-AIX32-LABEL: case_i64_sitofp_f32:
+; CHECK-AIX32:       # %bb.0: # %entry
+; CHECK-AIX32-NEXT:    lwz r4, 4(r3)
+; CHECK-AIX32-NEXT:    stw r4, -4(r1)
+; CHECK-AIX32-NEXT:    lwz r3, 0(r3)
+; CHECK-AIX32-NEXT:    stw r3, -8(r1)
+; CHECK-AIX32-NEXT:    lfd f0, -8(r1)
+; CHECK-AIX32-NEXT:    xscvsxdsp f1, f0
+; CHECK-AIX32-NEXT:    blr
+entry:
+  %x = load i64, ptr %p, align 8, !range !0
+  %y = sitofp i64 %x to float
+  ret float %y
+}
+
+!0 = !{i64 1, i64 0}

@github-project-automation github-project-automation Bot moved this from Needs Triage to Needs Merge in LLVM Release Status May 27, 2026
@amy-kwan

Copy link
Copy Markdown
Member

FYI: The assertion this patch attempts to fix is:

Assertion failed: (!MMO->getRanges() || (mdconst::extract<ConstantInt>(MMO->getRanges()->getOperand(0)) ->getBitWidth() == MemVT.getScalarSizeInBits() && MemVT.isInteger())) && "Range metadata and load type must match!"

This assert was originally seen when building Rust on AIX.

… INT_TO_FP (llvm#198705)

When lowering an i64 load in LowerINT_TO_FP, we were forwarding the
original !range metadata to a new f64 load. This is invalid because the
metadata no longer matches the value type/semantics, and can trigger
assertions when lowering i64 to fp (double or float) conversions.

This patch fixes this by passing a nullptr for the Ranges operand when
calling getLoad() and adds extra test cases to cover signed/unsigned i64
to f32/f64 conversions and to ensure they do not assert when the !range
metadata is present.

The assertion this patch attempts to fix is:
```
Assertion failed: (!MMO->getRanges() || (mdconst::extract<ConstantInt>(MMO->getRanges()->getOperand(0)) ->getBitWidth() == MemVT.getScalarSizeInBits() && MemVT.isInteger())) && "Range metadata and load type must match!"
```
This assert was originally seen when building Rust on AIX.

(cherry picked from commit 78f5f77)
@c-rhodes
c-rhodes merged commit 294ae8d into llvm:release/22.x Jun 1, 2026
1 check was pending
@github-project-automation github-project-automation Bot moved this from Needs Merge to Done in LLVM Release Status Jun 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Development

Successfully merging this pull request may close these issues.

4 participants