[llvm] f95850c - [SROA] Teach SROA to perform no-op pointer conversion.
Michael Liao via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 22 22:49:49 PDT 2020
Author: Michael Liao
Date: 2020-06-23T01:49:27-04:00
New Revision: f95850ce9c7593d3d8d2f83c55197970f373b9ad
URL: https://github.com/llvm/llvm-project/commit/f95850ce9c7593d3d8d2f83c55197970f373b9ad
DIFF: https://github.com/llvm/llvm-project/commit/f95850ce9c7593d3d8d2f83c55197970f373b9ad.diff
LOG: [SROA] Teach SROA to perform no-op pointer conversion.
Summary:
- When promoting a pointer from memory to register, SROA skips pointers
from different address spaces. However, as `ptrtoint` and `inttoptr`
are defined as no-op casts if that integer type has the same as the
pointer value, generate the pair of `ptrtoint`/`inttoptr` (no-op cast)
sequence to convert pointers from different address spaces if they
have the same size.
Reviewers: arsenm, chandlerc, lebedev.ri
Subscribers:
Differential Revision: https://reviews.llvm.org/D81943
Added:
Modified:
llvm/lib/Transforms/Scalar/SROA.cpp
llvm/test/Transforms/SROA/address-spaces.ll
llvm/test/Transforms/SROA/alloca-address-space.ll
llvm/test/Transforms/SROA/non-integral-pointers.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/Scalar/SROA.cpp b/llvm/lib/Transforms/Scalar/SROA.cpp
index ed0ca36a4914..b28df00e9e25 100644
--- a/llvm/lib/Transforms/Scalar/SROA.cpp
+++ b/llvm/lib/Transforms/Scalar/SROA.cpp
@@ -1703,8 +1703,15 @@ static bool canConvertValue(const DataLayout &DL, Type *OldTy, Type *NewTy) {
NewTy = NewTy->getScalarType();
if (NewTy->isPointerTy() || OldTy->isPointerTy()) {
if (NewTy->isPointerTy() && OldTy->isPointerTy()) {
- return cast<PointerType>(NewTy)->getPointerAddressSpace() ==
- cast<PointerType>(OldTy)->getPointerAddressSpace();
+ unsigned OldAS = OldTy->getPointerAddressSpace();
+ unsigned NewAS = NewTy->getPointerAddressSpace();
+ // Convert pointers if they are pointers from the same address space or
+ //
diff erent integral (not non-integral) address spaces with the same
+ // pointer size.
+ return OldAS == NewAS ||
+ (!DL.isNonIntegralAddressSpace(OldAS) &&
+ !DL.isNonIntegralAddressSpace(NewAS) &&
+ DL.getPointerSize(OldAS) == DL.getPointerSize(NewAS));
}
// We can convert integers to integral pointers, but not to non-integral
@@ -1772,6 +1779,22 @@ static Value *convertValue(const DataLayout &DL, IRBuilderTy &IRB, Value *V,
return IRB.CreatePtrToInt(V, NewTy);
}
+ if (OldTy->isPtrOrPtrVectorTy() && NewTy->isPtrOrPtrVectorTy()) {
+ unsigned OldAS = OldTy->getPointerAddressSpace();
+ unsigned NewAS = NewTy->getPointerAddressSpace();
+ // To convert pointers with
diff erent address spaces (they are already
+ // checked convertible, i.e. they have the same pointer size), so far we
+ // cannot use `bitcast` (which has restrict on the same address space) or
+ // `addrspacecast` (which is not always no-op casting). Instead, use a pair
+ // of no-op `ptrtoint`/`inttoptr` casts through an integer with the same bit
+ // size.
+ if (OldAS != NewAS) {
+ assert(DL.getPointerSize(OldAS) == DL.getPointerSize(NewAS));
+ return IRB.CreateIntToPtr(IRB.CreatePtrToInt(V, DL.getIntPtrType(OldTy)),
+ NewTy);
+ }
+ }
+
return IRB.CreateBitCast(V, NewTy);
}
diff --git a/llvm/test/Transforms/SROA/address-spaces.ll b/llvm/test/Transforms/SROA/address-spaces.ll
index 9cd9137833a2..9404b2062ec8 100644
--- a/llvm/test/Transforms/SROA/address-spaces.ll
+++ b/llvm/test/Transforms/SROA/address-spaces.ll
@@ -1,5 +1,5 @@
; RUN: opt < %s -sroa -S | FileCheck %s
-target datalayout = "e-p:64:64:64-p1:16:16:16-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-n8:16:32:64"
+target datalayout = "e-p:64:64:64-p1:16:16:16-p3:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-n8:16:32:64"
declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture readonly, i32, i1)
declare void @llvm.memcpy.p1i8.p0i8.i32(i8 addrspace(1)* nocapture, i8* nocapture readonly, i32, i1)
@@ -71,7 +71,8 @@ for.end:
@g = common global i32 0, align 4
@l = common addrspace(3) global i32 0, align 4
-; Make sure an illegal bitcast isn't introduced
+; If pointers from
diff erent address spaces have
diff erent sizes, make sure an
+; illegal bitcast isn't introduced
define void @pr27557() {
; CHECK-LABEL: @pr27557(
; CHECK: %[[CAST:.*]] = bitcast i32** {{.*}} to i32 addrspace(3)**
@@ -84,6 +85,21 @@ define void @pr27557() {
ret void
}
+ at l2 = common addrspace(2) global i32 0, align 4
+
+; If pointers from
diff erent address spaces have the same size, that pointer
+; should be promoted through the pair of `ptrtoint`/`inttoptr`.
+define i32* @pr27557.alt() {
+; CHECK-LABEL: @pr27557.alt(
+; CHECK: ret i32* inttoptr (i64 ptrtoint (i32 addrspace(2)* @l2 to i64) to i32*)
+ %1 = alloca %union.anon, align 8
+ %2 = bitcast %union.anon* %1 to i32 addrspace(2)**
+ store i32 addrspace(2)* @l2, i32 addrspace(2)** %2, align 8
+ %3 = bitcast %union.anon* %1 to i32**
+ %4 = load i32*, i32** %3, align 8
+ ret i32* %4
+}
+
; Make sure pre-splitting doesn't try to introduce an illegal bitcast
define float @presplit(i64 addrspace(1)* %p) {
entry:
diff --git a/llvm/test/Transforms/SROA/alloca-address-space.ll b/llvm/test/Transforms/SROA/alloca-address-space.ll
index d28bc39e9633..c8e22f5b25d8 100644
--- a/llvm/test/Transforms/SROA/alloca-address-space.ll
+++ b/llvm/test/Transforms/SROA/alloca-address-space.ll
@@ -1,5 +1,5 @@
; RUN: opt < %s -sroa -S | FileCheck %s
-target datalayout = "e-p:64:64:64-p1:16:16:16-p2:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-n8:16:32:64-A2"
+target datalayout = "e-p:64:64:64-p1:16:16:16-p2:32:32-p3:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-n8:16:32:64-A2"
declare void @llvm.memcpy.p2i8.p2i8.i32(i8 addrspace(2)* nocapture, i8 addrspace(2)* nocapture readonly, i32, i1)
declare void @llvm.memcpy.p1i8.p2i8.i32(i8 addrspace(1)* nocapture, i8 addrspace(2)* nocapture readonly, i32, i1)
@@ -70,7 +70,8 @@ for.end:
@g = common global i32 0, align 4
@l = common addrspace(3) global i32 0, align 4
-; Make sure an illegal bitcast isn't introduced
+; If pointers from
diff erent address spaces have
diff erent sizes, make sure an
+; illegal bitcast isn't introduced
; CHECK-LABEL: @pr27557(
; CHECK: %[[CAST:.*]] = bitcast i32* addrspace(2)* {{.*}} to i32 addrspace(3)* addrspace(2)*
; CHECK: store i32 addrspace(3)* @l, i32 addrspace(3)* addrspace(2)* %[[CAST]]
@@ -83,6 +84,21 @@ define void @pr27557() {
ret void
}
+ at l4 = common addrspace(4) global i32 0, align 4
+
+; If pointers from
diff erent address spaces have the same size, that pointer
+; should be promoted through the pair of `ptrtoint`/`inttoptr`.
+define i32* @pr27557.alt() {
+; CHECK-LABEL: @pr27557.alt(
+; CHECK: ret i32* inttoptr (i64 ptrtoint (i32 addrspace(4)* @l4 to i64) to i32*)
+ %1 = alloca %union.anon, align 8, addrspace(2)
+ %2 = bitcast %union.anon addrspace(2)* %1 to i32 addrspace(4)* addrspace(2)*
+ store i32 addrspace(4)* @l4, i32 addrspace(4)* addrspace(2)* %2, align 8
+ %3 = bitcast %union.anon addrspace(2)* %1 to i32* addrspace(2)*
+ %4 = load i32*, i32* addrspace(2)* %3, align 8
+ ret i32* %4
+}
+
; Test load from and store to non-zero address space.
define void @test_load_store_
diff _addr_space([2 x float] addrspace(1)* %complex1, [2 x float] addrspace(1)* %complex2) {
; CHECK-LABEL: @test_load_store_
diff _addr_space
diff --git a/llvm/test/Transforms/SROA/non-integral-pointers.ll b/llvm/test/Transforms/SROA/non-integral-pointers.ll
index 166f5dc7b42e..c12e5e8e7182 100644
--- a/llvm/test/Transforms/SROA/non-integral-pointers.ll
+++ b/llvm/test/Transforms/SROA/non-integral-pointers.ll
@@ -85,4 +85,18 @@ alwaysTaken:
ret i64 addrspace(4)* null
}
+%union.anon = type { i32* }
+
+; CHECK-LABEL: @f2(
+; CHECK-NOT: ptr2int
+; CHECK-NOT: int2ptr
+define i8 *@f2(i8 addrspace(4)* %p) {
+ %1 = alloca %union.anon, align 8
+ %2 = bitcast %union.anon* %1 to i8 addrspace(4)**
+ store i8 addrspace(4)* %p, i8 addrspace(4)** %2, align 8
+ %3 = bitcast %union.anon* %1 to i8**
+ %4 = load i8*, i8** %3, align 8
+ ret i8* %4
+}
+
declare void @llvm.memset.p0i8.i64(i8*, i8, i64, i1)
More information about the llvm-commits
mailing list