[llvm] [AMDGPU][SROA] Expand cast chain handling to floating point types (PR #228113)

Domenic Nutile via llvm-commits llvm-commits at lists.llvm.org
Mon Oct 5 11:57:46 PDT 2026


https://github.com/saxlungs updated https://github.com/llvm/llvm-project/pull/228113

>From 6f5db78dd7f0b9dbc59bc27303abe5e744365232 Mon Sep 17 00:00:00 2001
From: Domenic Nutile <domenic.nutile at gmail.com>
Date: Thu, 1 Oct 2026 11:18:09 -0400
Subject: [PATCH 1/2] [AMDGPU][SROA] Expand cast chain handling to floating
 point types

CreateBitPreservingCastChain does not produce inttoptr or ptrtoint for floating-point types. When promoting structs like { float, float } to <2 x float>, this can lead to pointers being bitcast directory to <2 x float> which is invalid. This change expands the use of the intermediate to these cases
---
 llvm/lib/IR/IRBuilder.cpp                     |   8 +-
 .../AMDGPU/promote-alloca-fp-ptr-cast.ll      | 131 ++++++++++++++++++
 llvm/unittests/IR/IRBuilderTest.cpp           |  30 ++++
 3 files changed, 167 insertions(+), 2 deletions(-)
 create mode 100644 llvm/test/CodeGen/AMDGPU/promote-alloca-fp-ptr-cast.ll

diff --git a/llvm/lib/IR/IRBuilder.cpp b/llvm/lib/IR/IRBuilder.cpp
index 6653f8f21b693..07125506e6094 100644
--- a/llvm/lib/IR/IRBuilder.cpp
+++ b/llvm/lib/IR/IRBuilder.cpp
@@ -140,19 +140,23 @@ Value *IRBuilderBase::CreateBitPreservingCastChain(const DataLayout &DL,
   };
 
   // See if we need inttoptr for this type pair. May require additional bitcast.
-  if (OldTy->isIntOrIntVectorTy() && NewTy->isPtrOrPtrVectorTy()) {
+  bool OldIsIntOrFP = OldTy->isIntOrIntVectorTy() || OldTy->isFPOrFPVectorTy();
+  if (OldIsIntOrFP && NewTy->isPtrOrPtrVectorTy()) {
     // Expand <2 x i32> to i8* --> <2 x i32> to i64 to i8*
     // Expand i128 to <2 x i8*> --> i128 to <2 x i64> to <2 x i8*>
     // Expand <4 x i32> to <2 x i8*> --> <4 x i32> to <2 x i64> to <2 x i8*>
+    // Expand <2 x float> to i8* --> <2 x float> to i64 to i8*
     // Directly handle i64 to i8*
     return CreateIntToPtr(CreateBitCastLike(V, DL.getIntPtrType(NewTy)), NewTy);
   }
 
   // See if we need ptrtoint for this type pair. May require additional bitcast.
-  if (OldTy->isPtrOrPtrVectorTy() && NewTy->isIntOrIntVectorTy()) {
+  bool NewIsIntOrFP = NewTy->isIntOrIntVectorTy() || NewTy->isFPOrFPVectorTy();
+  if (OldTy->isPtrOrPtrVectorTy() && NewIsIntOrFP) {
     // Expand <2 x i8*> to i128 --> <2 x i8*> to <2 x i64> to i128
     // Expand i8* to <2 x i32> --> i8* to i64 to <2 x i32>
     // Expand <2 x i8*> to <4 x i32> --> <2 x i8*> to <2 x i64> to <4 x i32>
+    // Expand i8* to <2 x float> --> i8* to i64 to <2 x float>
     // Expand i8* to i64 --> i8* to i64 to i64
     return CreateBitCastLike(CreatePtrToInt(V, DL.getIntPtrType(OldTy)), NewTy);
   }
diff --git a/llvm/test/CodeGen/AMDGPU/promote-alloca-fp-ptr-cast.ll b/llvm/test/CodeGen/AMDGPU/promote-alloca-fp-ptr-cast.ll
new file mode 100644
index 0000000000000..eb5f5647634c4
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/promote-alloca-fp-ptr-cast.ll
@@ -0,0 +1,131 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -S -mtriple=amdgpu9.00-amd-amdhsa -passes=amdgpu-promote-alloca-to-vector,verify < %s | FileCheck %s
+
+; Promoting these allocas to a floating-point vector forces a conversion between
+; a pointer and a floating-point value or vector of the same size. A bitcast
+; cannot convert between pointers and non-pointers, so the conversion must
+; route through a pointer-sized integer via ptrtoint/inttoptr instead of
+; producing e.g. `bitcast ptr to <2 x float>`.
+
+target datalayout = "e-p:64:64-p5:32:32-A5"
+
+define amdgpu_kernel void @struct_ptr_store(ptr %p, i1 %c, ptr %out) {
+; CHECK-LABEL: define amdgpu_kernel void @struct_ptr_store(
+; CHECK-SAME: ptr [[P:%.*]], i1 [[C:%.*]], ptr [[OUT:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[A:%.*]] = freeze <2 x float> poison
+; CHECK-NEXT:    br i1 [[C]], label %[[T:.*]], label %[[F:.*]]
+; CHECK:       [[T]]:
+; CHECK-NEXT:    [[TMP0:%.*]] = ptrtoint ptr [[P]] to i64
+; CHECK-NEXT:    [[TMP1:%.*]] = bitcast i64 [[TMP0]] to <2 x float>
+; CHECK-NEXT:    br label %[[END:.*]]
+; CHECK:       [[F]]:
+; CHECK-NEXT:    [[TMP2:%.*]] = insertelement <2 x float> [[A]], float 1.000000e+00, i32 0
+; CHECK-NEXT:    [[TMP3:%.*]] = insertelement <2 x float> [[TMP2]], float 2.000000e+00, i32 1
+; CHECK-NEXT:    br label %[[END]]
+; CHECK:       [[END]]:
+; CHECK-NEXT:    [[PROMOTEALLOCA:%.*]] = phi <2 x float> [ [[TMP3]], %[[F]] ], [ [[TMP1]], %[[T]] ]
+; CHECK-NEXT:    [[TMP4:%.*]] = extractelement <2 x float> [[PROMOTEALLOCA]], i32 0
+; CHECK-NEXT:    store float [[TMP4]], ptr [[OUT]], align 4
+; CHECK-NEXT:    ret void
+;
+entry:
+  %a = alloca { float, float }, align 4, addrspace(5)
+  br i1 %c, label %t, label %f
+
+t:
+  store ptr %p, ptr addrspace(5) %a, align 4
+  br label %end
+
+f:
+  store float 1.0, ptr addrspace(5) %a, align 4
+  %g = getelementptr inbounds i8, ptr addrspace(5) %a, i32 4
+  store float 2.0, ptr addrspace(5) %g, align 4
+  br label %end
+
+end:
+  %v = load float, ptr addrspace(5) %a, align 4
+  store float %v, ptr %out, align 4
+  ret void
+}
+
+define amdgpu_kernel void @float_vec_from_ptr(ptr %argp, ptr %out) {
+; CHECK-LABEL: define amdgpu_kernel void @float_vec_from_ptr(
+; CHECK-SAME: ptr [[ARGP:%.*]], ptr [[OUT:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[A:%.*]] = freeze <2 x float> poison
+; CHECK-NEXT:    [[TMP0:%.*]] = ptrtoint ptr [[ARGP]] to i64
+; CHECK-NEXT:    [[TMP1:%.*]] = bitcast i64 [[TMP0]] to <2 x float>
+; CHECK-NEXT:    store <2 x float> [[TMP1]], ptr [[OUT]], align 8
+; CHECK-NEXT:    ret void
+;
+entry:
+  %a = alloca [2 x float], align 8, addrspace(5)
+  store ptr %argp, ptr addrspace(5) %a, align 8
+  %v = load <2 x float>, ptr addrspace(5) %a, align 8
+  store <2 x float> %v, ptr %out, align 8
+  ret void
+}
+
+define amdgpu_kernel void @ptr_from_float_vec(<2 x float> %x, ptr %out) {
+; CHECK-LABEL: define amdgpu_kernel void @ptr_from_float_vec(
+; CHECK-SAME: <2 x float> [[X:%.*]], ptr [[OUT:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[A:%.*]] = freeze <2 x float> poison
+; CHECK-NEXT:    [[TMP0:%.*]] = bitcast <2 x float> [[X]] to i64
+; CHECK-NEXT:    [[TMP1:%.*]] = inttoptr i64 [[TMP0]] to ptr
+; CHECK-NEXT:    store ptr [[TMP1]], ptr [[OUT]], align 8
+; CHECK-NEXT:    ret void
+;
+entry:
+  %a = alloca [2 x float], align 8, addrspace(5)
+  store <2 x float> %x, ptr addrspace(5) %a, align 8
+  %p = load ptr, ptr addrspace(5) %a, align 8
+  store ptr %p, ptr %out, align 8
+  ret void
+}
+
+define amdgpu_kernel void @double_vec_from_ptr_vec(<2 x ptr> %argp, ptr %out) {
+; CHECK-LABEL: define amdgpu_kernel void @double_vec_from_ptr_vec(
+; CHECK-SAME: <2 x ptr> [[ARGP:%.*]], ptr [[OUT:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[A:%.*]] = freeze <2 x double> poison
+; CHECK-NEXT:    [[TMP0:%.*]] = ptrtoint <2 x ptr> [[ARGP]] to <2 x i64>
+; CHECK-NEXT:    [[TMP1:%.*]] = bitcast <2 x i64> [[TMP0]] to <2 x double>
+; CHECK-NEXT:    store <2 x double> [[TMP1]], ptr [[OUT]], align 16
+; CHECK-NEXT:    ret void
+;
+entry:
+  %a = alloca { double, double }, align 16, addrspace(5)
+  store <2 x ptr> %argp, ptr addrspace(5) %a, align 16
+  %v = load <2 x double>, ptr addrspace(5) %a, align 16
+  store <2 x double> %v, ptr %out, align 16
+  ret void
+}
+
+define amdgpu_kernel void @ptr_vec_subvec_of_double_vec(<2 x ptr> %argp, ptr %out) {
+; CHECK-LABEL: define amdgpu_kernel void @ptr_vec_subvec_of_double_vec(
+; CHECK-SAME: <2 x ptr> [[ARGP:%.*]], ptr [[OUT:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[A:%.*]] = freeze <4 x double> poison
+; CHECK-NEXT:    [[TMP0:%.*]] = ptrtoint <2 x ptr> [[ARGP]] to <2 x i64>
+; CHECK-NEXT:    [[TMP1:%.*]] = bitcast <2 x i64> [[TMP0]] to <2 x double>
+; CHECK-NEXT:    [[TMP2:%.*]] = extractelement <2 x double> [[TMP1]], i64 0
+; CHECK-NEXT:    [[TMP3:%.*]] = insertelement <4 x double> [[A]], double [[TMP2]], i32 2
+; CHECK-NEXT:    [[TMP4:%.*]] = extractelement <2 x double> [[TMP1]], i64 1
+; CHECK-NEXT:    [[TMP5:%.*]] = insertelement <4 x double> [[TMP3]], double [[TMP4]], i32 3
+; CHECK-NEXT:    [[TMP6:%.*]] = insertelement <2 x double> poison, double [[TMP2]], i64 0
+; CHECK-NEXT:    [[TMP7:%.*]] = insertelement <2 x double> [[TMP6]], double [[TMP4]], i64 1
+; CHECK-NEXT:    [[TMP8:%.*]] = bitcast <2 x double> [[TMP7]] to <2 x i64>
+; CHECK-NEXT:    [[TMP9:%.*]] = inttoptr <2 x i64> [[TMP8]] to <2 x ptr>
+; CHECK-NEXT:    store <2 x ptr> [[TMP9]], ptr [[OUT]], align 16
+; CHECK-NEXT:    ret void
+;
+entry:
+  %a = alloca [4 x double], align 16, addrspace(5)
+  %hi = getelementptr inbounds i8, ptr addrspace(5) %a, i32 16
+  store <2 x ptr> %argp, ptr addrspace(5) %hi, align 16
+  %p = load <2 x ptr>, ptr addrspace(5) %hi, align 16
+  store <2 x ptr> %p, ptr %out, align 16
+  ret void
+}
diff --git a/llvm/unittests/IR/IRBuilderTest.cpp b/llvm/unittests/IR/IRBuilderTest.cpp
index 14a3065b989ad..f4621cd01996f 100644
--- a/llvm/unittests/IR/IRBuilderTest.cpp
+++ b/llvm/unittests/IR/IRBuilderTest.cpp
@@ -606,6 +606,36 @@ TEST_F(IRBuilderTest, GetIntTy) {
   EXPECT_EQ(IntPtrTy, IntegerType::get(Ctx, IntPtrBitSize));
 }
 
+TEST_F(IRBuilderTest, CreateBitPreservingCastChainFPTypes) {
+  M->setDataLayout("e-p:64:64");
+  IRBuilder<> Builder(BB);
+  const DataLayout &DL = M->getDataLayout();
+  Type *PtrTy = PointerType::getUnqual(Ctx);
+  Type *FloatVecTy = FixedVectorType::get(Builder.getFloatTy(), 2);
+  Type *DoubleTy = Builder.getDoubleTy();
+  Value *FloatVec =
+      Builder.CreateLoad(FloatVecTy, Constant::getNullValue(PtrTy));
+  Value *Double = Builder.CreateLoad(DoubleTy, Constant::getNullValue(PtrTy));
+  Value *Ptr = Builder.CreateLoad(PtrTy, Constant::getNullValue(PtrTy));
+
+  Value *VecToPtr = Builder.CreateBitPreservingCastChain(DL, FloatVec, PtrTy);
+  ASSERT_TRUE(isa<IntToPtrInst>(VecToPtr));
+  EXPECT_TRUE(isa<BitCastInst>(cast<IntToPtrInst>(VecToPtr)->getOperand(0)));
+  Value *PtrToVec = Builder.CreateBitPreservingCastChain(DL, Ptr, FloatVecTy);
+  ASSERT_EQ(PtrToVec->getType(), FloatVecTy);
+  ASSERT_TRUE(isa<BitCastInst>(PtrToVec));
+  EXPECT_TRUE(isa<PtrToIntInst>(cast<BitCastInst>(PtrToVec)->getOperand(0)));
+
+  Value *DoubleToPtr = Builder.CreateBitPreservingCastChain(DL, Double, PtrTy);
+  ASSERT_TRUE(isa<IntToPtrInst>(DoubleToPtr));
+  Value *PtrToDouble = Builder.CreateBitPreservingCastChain(DL, Ptr, DoubleTy);
+  ASSERT_EQ(PtrToDouble->getType(), DoubleTy);
+  ASSERT_TRUE(isa<BitCastInst>(PtrToDouble));
+
+  Builder.CreateRetVoid();
+  EXPECT_FALSE(verifyFunction(*F, &errs()));
+}
+
 TEST_F(IRBuilderTest, UnaryOperators) {
   IRBuilder<NoFolder> Builder(BB);
   Value *V = Builder.CreateLoad(GV->getValueType(), GV);

>From fdebf491687755f79a0fb591aae7c49589e40555 Mon Sep 17 00:00:00 2001
From: Domenic Nutile <domenic.nutile at gmail.com>
Date: Fri, 2 Oct 2026 13:07:32 -0400
Subject: [PATCH 2/2] Refactor based on feedback to move testing to existing
 file

---
 .../AMDGPU/promote-alloca-fp-ptr-cast.ll      | 131 ------------------
 .../AMDGPU/promote-alloca-loadstores.ll       |  48 +++++++
 llvm/unittests/IR/IRBuilderTest.cpp           |  30 ----
 3 files changed, 48 insertions(+), 161 deletions(-)
 delete mode 100644 llvm/test/CodeGen/AMDGPU/promote-alloca-fp-ptr-cast.ll

diff --git a/llvm/test/CodeGen/AMDGPU/promote-alloca-fp-ptr-cast.ll b/llvm/test/CodeGen/AMDGPU/promote-alloca-fp-ptr-cast.ll
deleted file mode 100644
index eb5f5647634c4..0000000000000
--- a/llvm/test/CodeGen/AMDGPU/promote-alloca-fp-ptr-cast.ll
+++ /dev/null
@@ -1,131 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
-; RUN: opt -S -mtriple=amdgpu9.00-amd-amdhsa -passes=amdgpu-promote-alloca-to-vector,verify < %s | FileCheck %s
-
-; Promoting these allocas to a floating-point vector forces a conversion between
-; a pointer and a floating-point value or vector of the same size. A bitcast
-; cannot convert between pointers and non-pointers, so the conversion must
-; route through a pointer-sized integer via ptrtoint/inttoptr instead of
-; producing e.g. `bitcast ptr to <2 x float>`.
-
-target datalayout = "e-p:64:64-p5:32:32-A5"
-
-define amdgpu_kernel void @struct_ptr_store(ptr %p, i1 %c, ptr %out) {
-; CHECK-LABEL: define amdgpu_kernel void @struct_ptr_store(
-; CHECK-SAME: ptr [[P:%.*]], i1 [[C:%.*]], ptr [[OUT:%.*]]) {
-; CHECK-NEXT:  [[ENTRY:.*:]]
-; CHECK-NEXT:    [[A:%.*]] = freeze <2 x float> poison
-; CHECK-NEXT:    br i1 [[C]], label %[[T:.*]], label %[[F:.*]]
-; CHECK:       [[T]]:
-; CHECK-NEXT:    [[TMP0:%.*]] = ptrtoint ptr [[P]] to i64
-; CHECK-NEXT:    [[TMP1:%.*]] = bitcast i64 [[TMP0]] to <2 x float>
-; CHECK-NEXT:    br label %[[END:.*]]
-; CHECK:       [[F]]:
-; CHECK-NEXT:    [[TMP2:%.*]] = insertelement <2 x float> [[A]], float 1.000000e+00, i32 0
-; CHECK-NEXT:    [[TMP3:%.*]] = insertelement <2 x float> [[TMP2]], float 2.000000e+00, i32 1
-; CHECK-NEXT:    br label %[[END]]
-; CHECK:       [[END]]:
-; CHECK-NEXT:    [[PROMOTEALLOCA:%.*]] = phi <2 x float> [ [[TMP3]], %[[F]] ], [ [[TMP1]], %[[T]] ]
-; CHECK-NEXT:    [[TMP4:%.*]] = extractelement <2 x float> [[PROMOTEALLOCA]], i32 0
-; CHECK-NEXT:    store float [[TMP4]], ptr [[OUT]], align 4
-; CHECK-NEXT:    ret void
-;
-entry:
-  %a = alloca { float, float }, align 4, addrspace(5)
-  br i1 %c, label %t, label %f
-
-t:
-  store ptr %p, ptr addrspace(5) %a, align 4
-  br label %end
-
-f:
-  store float 1.0, ptr addrspace(5) %a, align 4
-  %g = getelementptr inbounds i8, ptr addrspace(5) %a, i32 4
-  store float 2.0, ptr addrspace(5) %g, align 4
-  br label %end
-
-end:
-  %v = load float, ptr addrspace(5) %a, align 4
-  store float %v, ptr %out, align 4
-  ret void
-}
-
-define amdgpu_kernel void @float_vec_from_ptr(ptr %argp, ptr %out) {
-; CHECK-LABEL: define amdgpu_kernel void @float_vec_from_ptr(
-; CHECK-SAME: ptr [[ARGP:%.*]], ptr [[OUT:%.*]]) {
-; CHECK-NEXT:  [[ENTRY:.*:]]
-; CHECK-NEXT:    [[A:%.*]] = freeze <2 x float> poison
-; CHECK-NEXT:    [[TMP0:%.*]] = ptrtoint ptr [[ARGP]] to i64
-; CHECK-NEXT:    [[TMP1:%.*]] = bitcast i64 [[TMP0]] to <2 x float>
-; CHECK-NEXT:    store <2 x float> [[TMP1]], ptr [[OUT]], align 8
-; CHECK-NEXT:    ret void
-;
-entry:
-  %a = alloca [2 x float], align 8, addrspace(5)
-  store ptr %argp, ptr addrspace(5) %a, align 8
-  %v = load <2 x float>, ptr addrspace(5) %a, align 8
-  store <2 x float> %v, ptr %out, align 8
-  ret void
-}
-
-define amdgpu_kernel void @ptr_from_float_vec(<2 x float> %x, ptr %out) {
-; CHECK-LABEL: define amdgpu_kernel void @ptr_from_float_vec(
-; CHECK-SAME: <2 x float> [[X:%.*]], ptr [[OUT:%.*]]) {
-; CHECK-NEXT:  [[ENTRY:.*:]]
-; CHECK-NEXT:    [[A:%.*]] = freeze <2 x float> poison
-; CHECK-NEXT:    [[TMP0:%.*]] = bitcast <2 x float> [[X]] to i64
-; CHECK-NEXT:    [[TMP1:%.*]] = inttoptr i64 [[TMP0]] to ptr
-; CHECK-NEXT:    store ptr [[TMP1]], ptr [[OUT]], align 8
-; CHECK-NEXT:    ret void
-;
-entry:
-  %a = alloca [2 x float], align 8, addrspace(5)
-  store <2 x float> %x, ptr addrspace(5) %a, align 8
-  %p = load ptr, ptr addrspace(5) %a, align 8
-  store ptr %p, ptr %out, align 8
-  ret void
-}
-
-define amdgpu_kernel void @double_vec_from_ptr_vec(<2 x ptr> %argp, ptr %out) {
-; CHECK-LABEL: define amdgpu_kernel void @double_vec_from_ptr_vec(
-; CHECK-SAME: <2 x ptr> [[ARGP:%.*]], ptr [[OUT:%.*]]) {
-; CHECK-NEXT:  [[ENTRY:.*:]]
-; CHECK-NEXT:    [[A:%.*]] = freeze <2 x double> poison
-; CHECK-NEXT:    [[TMP0:%.*]] = ptrtoint <2 x ptr> [[ARGP]] to <2 x i64>
-; CHECK-NEXT:    [[TMP1:%.*]] = bitcast <2 x i64> [[TMP0]] to <2 x double>
-; CHECK-NEXT:    store <2 x double> [[TMP1]], ptr [[OUT]], align 16
-; CHECK-NEXT:    ret void
-;
-entry:
-  %a = alloca { double, double }, align 16, addrspace(5)
-  store <2 x ptr> %argp, ptr addrspace(5) %a, align 16
-  %v = load <2 x double>, ptr addrspace(5) %a, align 16
-  store <2 x double> %v, ptr %out, align 16
-  ret void
-}
-
-define amdgpu_kernel void @ptr_vec_subvec_of_double_vec(<2 x ptr> %argp, ptr %out) {
-; CHECK-LABEL: define amdgpu_kernel void @ptr_vec_subvec_of_double_vec(
-; CHECK-SAME: <2 x ptr> [[ARGP:%.*]], ptr [[OUT:%.*]]) {
-; CHECK-NEXT:  [[ENTRY:.*:]]
-; CHECK-NEXT:    [[A:%.*]] = freeze <4 x double> poison
-; CHECK-NEXT:    [[TMP0:%.*]] = ptrtoint <2 x ptr> [[ARGP]] to <2 x i64>
-; CHECK-NEXT:    [[TMP1:%.*]] = bitcast <2 x i64> [[TMP0]] to <2 x double>
-; CHECK-NEXT:    [[TMP2:%.*]] = extractelement <2 x double> [[TMP1]], i64 0
-; CHECK-NEXT:    [[TMP3:%.*]] = insertelement <4 x double> [[A]], double [[TMP2]], i32 2
-; CHECK-NEXT:    [[TMP4:%.*]] = extractelement <2 x double> [[TMP1]], i64 1
-; CHECK-NEXT:    [[TMP5:%.*]] = insertelement <4 x double> [[TMP3]], double [[TMP4]], i32 3
-; CHECK-NEXT:    [[TMP6:%.*]] = insertelement <2 x double> poison, double [[TMP2]], i64 0
-; CHECK-NEXT:    [[TMP7:%.*]] = insertelement <2 x double> [[TMP6]], double [[TMP4]], i64 1
-; CHECK-NEXT:    [[TMP8:%.*]] = bitcast <2 x double> [[TMP7]] to <2 x i64>
-; CHECK-NEXT:    [[TMP9:%.*]] = inttoptr <2 x i64> [[TMP8]] to <2 x ptr>
-; CHECK-NEXT:    store <2 x ptr> [[TMP9]], ptr [[OUT]], align 16
-; CHECK-NEXT:    ret void
-;
-entry:
-  %a = alloca [4 x double], align 16, addrspace(5)
-  %hi = getelementptr inbounds i8, ptr addrspace(5) %a, i32 16
-  store <2 x ptr> %argp, ptr addrspace(5) %hi, align 16
-  %p = load <2 x ptr>, ptr addrspace(5) %hi, align 16
-  store <2 x ptr> %p, ptr %out, align 16
-  ret void
-}
diff --git a/llvm/test/CodeGen/AMDGPU/promote-alloca-loadstores.ll b/llvm/test/CodeGen/AMDGPU/promote-alloca-loadstores.ll
index 0773a60453de6..228d4ef1d771f 100644
--- a/llvm/test/CodeGen/AMDGPU/promote-alloca-loadstores.ll
+++ b/llvm/test/CodeGen/AMDGPU/promote-alloca-loadstores.ll
@@ -259,3 +259,51 @@ entry:
   %tmp = load ptr addrspace(3), ptr addrspace(5) %alloca, align 8
   ret ptr addrspace(3) %tmp
 }
+
+define <2 x float> @alloca_store_ptr_load_fvec(ptr %arg) {
+; CHECK-LABEL: define <2 x float> @alloca_store_ptr_load_fvec
+; CHECK-SAME: (ptr [[ARG:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[ALLOCA:%.*]] = freeze <2 x float> poison
+; CHECK-NEXT:    [[TMP0:%.*]] = ptrtoint ptr [[ARG]] to i64
+; CHECK-NEXT:    [[TMP1:%.*]] = bitcast i64 [[TMP0]] to <2 x float>
+; CHECK-NEXT:    ret <2 x float> [[TMP1]]
+;
+entry:
+  %alloca = alloca [2 x float], align 8, addrspace(5)
+  store ptr %arg, ptr addrspace(5) %alloca, align 8
+  %tmp = load <2 x float>, ptr addrspace(5) %alloca, align 8
+  ret <2 x float> %tmp
+}
+
+define ptr @alloca_store_fvec_load_ptr(<2 x float> %arg) {
+; CHECK-LABEL: define ptr @alloca_store_fvec_load_ptr
+; CHECK-SAME: (<2 x float> [[ARG:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[ALLOCA:%.*]] = freeze <2 x float> poison
+; CHECK-NEXT:    [[TMP0:%.*]] = bitcast <2 x float> [[ARG]] to i64
+; CHECK-NEXT:    [[TMP1:%.*]] = inttoptr i64 [[TMP0]] to ptr
+; CHECK-NEXT:    ret ptr [[TMP1]]
+;
+entry:
+  %alloca = alloca [2 x float], align 8, addrspace(5)
+  store <2 x float> %arg, ptr addrspace(5) %alloca, align 8
+  %tmp = load ptr, ptr addrspace(5) %alloca, align 8
+  ret ptr %tmp
+}
+
+define <2 x ptr> @alloca_store_fvec_load_ptrvec(<4 x float> %arg) {
+; CHECK-LABEL: define <2 x ptr> @alloca_store_fvec_load_ptrvec
+; CHECK-SAME: (<4 x float> [[ARG:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[ALLOCA:%.*]] = freeze <4 x float> poison
+; CHECK-NEXT:    [[TMP0:%.*]] = bitcast <4 x float> [[ARG]] to <2 x i64>
+; CHECK-NEXT:    [[TMP1:%.*]] = inttoptr <2 x i64> [[TMP0]] to <2 x ptr>
+; CHECK-NEXT:    ret <2 x ptr> [[TMP1]]
+;
+entry:
+  %alloca = alloca [4 x float], align 16, addrspace(5)
+  store <4 x float> %arg, ptr addrspace(5) %alloca, align 16
+  %tmp = load <2 x ptr>, ptr addrspace(5) %alloca, align 16
+  ret <2 x ptr> %tmp
+}
diff --git a/llvm/unittests/IR/IRBuilderTest.cpp b/llvm/unittests/IR/IRBuilderTest.cpp
index f4621cd01996f..14a3065b989ad 100644
--- a/llvm/unittests/IR/IRBuilderTest.cpp
+++ b/llvm/unittests/IR/IRBuilderTest.cpp
@@ -606,36 +606,6 @@ TEST_F(IRBuilderTest, GetIntTy) {
   EXPECT_EQ(IntPtrTy, IntegerType::get(Ctx, IntPtrBitSize));
 }
 
-TEST_F(IRBuilderTest, CreateBitPreservingCastChainFPTypes) {
-  M->setDataLayout("e-p:64:64");
-  IRBuilder<> Builder(BB);
-  const DataLayout &DL = M->getDataLayout();
-  Type *PtrTy = PointerType::getUnqual(Ctx);
-  Type *FloatVecTy = FixedVectorType::get(Builder.getFloatTy(), 2);
-  Type *DoubleTy = Builder.getDoubleTy();
-  Value *FloatVec =
-      Builder.CreateLoad(FloatVecTy, Constant::getNullValue(PtrTy));
-  Value *Double = Builder.CreateLoad(DoubleTy, Constant::getNullValue(PtrTy));
-  Value *Ptr = Builder.CreateLoad(PtrTy, Constant::getNullValue(PtrTy));
-
-  Value *VecToPtr = Builder.CreateBitPreservingCastChain(DL, FloatVec, PtrTy);
-  ASSERT_TRUE(isa<IntToPtrInst>(VecToPtr));
-  EXPECT_TRUE(isa<BitCastInst>(cast<IntToPtrInst>(VecToPtr)->getOperand(0)));
-  Value *PtrToVec = Builder.CreateBitPreservingCastChain(DL, Ptr, FloatVecTy);
-  ASSERT_EQ(PtrToVec->getType(), FloatVecTy);
-  ASSERT_TRUE(isa<BitCastInst>(PtrToVec));
-  EXPECT_TRUE(isa<PtrToIntInst>(cast<BitCastInst>(PtrToVec)->getOperand(0)));
-
-  Value *DoubleToPtr = Builder.CreateBitPreservingCastChain(DL, Double, PtrTy);
-  ASSERT_TRUE(isa<IntToPtrInst>(DoubleToPtr));
-  Value *PtrToDouble = Builder.CreateBitPreservingCastChain(DL, Ptr, DoubleTy);
-  ASSERT_EQ(PtrToDouble->getType(), DoubleTy);
-  ASSERT_TRUE(isa<BitCastInst>(PtrToDouble));
-
-  Builder.CreateRetVoid();
-  EXPECT_FALSE(verifyFunction(*F, &errs()));
-}
-
 TEST_F(IRBuilderTest, UnaryOperators) {
   IRBuilder<NoFolder> Builder(BB);
   Value *V = Builder.CreateLoad(GV->getValueType(), GV);



More information about the llvm-commits mailing list