[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