skc7 created this revision.
skc7 added reviewers: sameerds, arsenm.
Herald added subscribers: dexonsmith, lxfind, jdoerfert, zzheng, hiraditya.
skc7 requested review of this revision.
Herald added subscribers: llvm-commits, cfe-commits, wdng.
Herald added projects: clang, LLVM.

When the addrspacecast instruction was added, the ability to bitcast between 
pointers from different address spaces was removed.
There are cases, where after analysis, cast between pointers from different 
address spaces can be concluded to be a no-op cast.
If bitcast can be allowed in these scenarios, it would help further optimise 
the IR in Transform passes since its a no-op cast.
This enhancement to bitcast will require that pointers to the two address 
spaces have the same bit widths(can be queried from DataLayout).
Frontend should never misuse the bitcast wherever addrspace cast would have 
been more appropriate.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D114533

Files:
  clang/lib/CodeGen/CGAtomic.cpp
  llvm/docs/LangRef.rst
  llvm/include/llvm/Analysis/TargetFolder.h
  llvm/include/llvm/IR/ConstantFolder.h
  llvm/include/llvm/IR/Constants.h
  llvm/include/llvm/IR/IRBuilder.h
  llvm/include/llvm/IR/IRBuilderFolder.h
  llvm/include/llvm/IR/InstrTypes.h
  llvm/include/llvm/IR/Instructions.h
  llvm/include/llvm/IR/NoFolder.h
  llvm/lib/Analysis/ConstantFolding.cpp
  llvm/lib/Analysis/LoopUnrollAnalyzer.cpp
  llvm/lib/AsmParser/LLParser.cpp
  llvm/lib/IR/AutoUpgrade.cpp
  llvm/lib/IR/Constants.cpp
  llvm/lib/IR/Instructions.cpp
  llvm/lib/IR/Verifier.cpp
  llvm/lib/Transforms/Coroutines/Coroutines.cpp
  llvm/lib/Transforms/Utils/VNCoercion.cpp
  llvm/test/Transforms/GVN/gvn-eliminate-inttoptr-ptrtoint-for-load.ll
  llvm/test/Transforms/GVN/gvn-eliminate-inttoptr-ptrtoint-for-vector-load.ll
  
llvm/test/Transforms/GVN/gvn-eliminate-inttoptr-ptrtoint-for-vector-ptr-load.ll
  llvm/test/Verifier/bitcast-vector-pointer-as-neg.ll
  llvm/test/Verifier/bitcast-vector-pointer-different-addrspace-illegal.ll
  llvm/test/Verifier/bitcast-vector-pointer-neg.ll
  llvm/test/Verifier/bitcast-vector-pointer-pos.ll
  llvm/test/Verifier/bitcast-vector-pointer-same-addrspace.ll
  llvm/unittests/IR/InstructionsTest.cpp

Index: llvm/unittests/IR/InstructionsTest.cpp
===================================================================
--- llvm/unittests/IR/InstructionsTest.cpp
+++ llvm/unittests/IR/InstructionsTest.cpp
@@ -189,6 +189,10 @@
 TEST(InstructionsTest, CastInst) {
   LLVMContext C;
 
+  DataLayout DL("e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-"
+                "p6:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-"
+                "v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-ni:7");
+
   Type *Int8Ty = Type::getInt8Ty(C);
   Type *Int16Ty = Type::getInt16Ty(C);
   Type *Int32Ty = Type::getInt32Ty(C);
@@ -217,7 +221,11 @@
   Type *Int32PtrAS1Ty = PointerType::get(Int32Ty, 1);
   Type *Int64PtrAS1Ty = PointerType::get(Int64Ty, 1);
 
+  Type *Int32PtrAS2Ty = PointerType::get(Int32Ty, 2);
+  Type *Int32PtrAS3Ty = PointerType::get(Int32Ty, 3);
+
   Type *V2Int32PtrAS1Ty = FixedVectorType::get(Int32PtrAS1Ty, 2);
+  Type *V2Int32PtrAS2Ty = FixedVectorType::get(Int32PtrAS2Ty, 2);
   Type *V2Int64PtrAS1Ty = FixedVectorType::get(Int64PtrAS1Ty, 2);
   Type *V4Int32PtrAS1Ty = FixedVectorType::get(Int32PtrAS1Ty, 4);
   Type *VScaleV4Int32PtrAS1Ty = ScalableVectorType::get(Int32PtrAS1Ty, 4);
@@ -238,50 +246,52 @@
   EXPECT_EQ(CastInst::Trunc, CastInst::getCastOpcode(c64, true, V8x8Ty, true));
   EXPECT_EQ(CastInst::SExt, CastInst::getCastOpcode(c8, true, V8x64Ty, true));
 
-  EXPECT_FALSE(CastInst::isBitCastable(V8x8Ty, X86MMXTy));
-  EXPECT_FALSE(CastInst::isBitCastable(X86MMXTy, V8x8Ty));
-  EXPECT_FALSE(CastInst::isBitCastable(Int64Ty, X86MMXTy));
-  EXPECT_FALSE(CastInst::isBitCastable(V8x64Ty, V8x8Ty));
-  EXPECT_FALSE(CastInst::isBitCastable(V8x8Ty, V8x64Ty));
-
-  // Check address space casts are rejected since we don't know the sizes here
-  EXPECT_FALSE(CastInst::isBitCastable(Int32PtrTy, Int32PtrAS1Ty));
-  EXPECT_FALSE(CastInst::isBitCastable(Int32PtrAS1Ty, Int32PtrTy));
-  EXPECT_FALSE(CastInst::isBitCastable(V2Int32PtrTy, V2Int32PtrAS1Ty));
-  EXPECT_FALSE(CastInst::isBitCastable(V2Int32PtrAS1Ty, V2Int32PtrTy));
-  EXPECT_TRUE(CastInst::isBitCastable(V2Int32PtrAS1Ty, V2Int64PtrAS1Ty));
+  EXPECT_FALSE(CastInst::isBitCastable(V8x8Ty, X86MMXTy, DL));
+  EXPECT_FALSE(CastInst::isBitCastable(X86MMXTy, V8x8Ty, DL));
+  EXPECT_FALSE(CastInst::isBitCastable(Int64Ty, X86MMXTy, DL));
+  EXPECT_FALSE(CastInst::isBitCastable(V8x64Ty, V8x8Ty, DL));
+  EXPECT_FALSE(CastInst::isBitCastable(V8x8Ty, V8x64Ty, DL));
+
+  // Check validity of casts here
+  EXPECT_TRUE(CastInst::isBitCastable(Int32PtrAS2Ty, Int32PtrAS3Ty, DL));
+  EXPECT_FALSE(CastInst::isBitCastable(Int32PtrAS1Ty, Int32PtrAS2Ty, DL));
+  EXPECT_TRUE(CastInst::isBitCastable(Int32PtrTy, Int32PtrAS1Ty, DL));
+  EXPECT_TRUE(CastInst::isBitCastable(Int32PtrAS1Ty, Int32PtrTy, DL));
+  EXPECT_TRUE(CastInst::isBitCastable(V2Int32PtrTy, V2Int32PtrAS1Ty, DL));
+  EXPECT_TRUE(CastInst::isBitCastable(V2Int32PtrAS1Ty, V2Int32PtrTy, DL));
+  EXPECT_TRUE(CastInst::isBitCastable(V2Int32PtrAS1Ty, V2Int64PtrAS1Ty, DL));
+  EXPECT_FALSE(CastInst::isBitCastable(V2Int32PtrAS1Ty, V2Int32PtrAS2Ty, DL));
   EXPECT_EQ(CastInst::AddrSpaceCast, CastInst::getCastOpcode(v2ptr32, true,
                                                              V2Int32PtrAS1Ty,
                                                              true));
 
   // Test mismatched number of elements for pointers
-  EXPECT_FALSE(CastInst::isBitCastable(V2Int32PtrAS1Ty, V4Int64PtrAS1Ty));
-  EXPECT_FALSE(CastInst::isBitCastable(V4Int64PtrAS1Ty, V2Int32PtrAS1Ty));
-  EXPECT_FALSE(CastInst::isBitCastable(V2Int32PtrAS1Ty, V4Int32PtrAS1Ty));
-  EXPECT_FALSE(CastInst::isBitCastable(Int32PtrTy, V2Int32PtrTy));
-  EXPECT_FALSE(CastInst::isBitCastable(V2Int32PtrTy, Int32PtrTy));
-
-  EXPECT_TRUE(CastInst::isBitCastable(Int32PtrTy, Int64PtrTy));
-  EXPECT_FALSE(CastInst::isBitCastable(DoubleTy, FloatTy));
-  EXPECT_FALSE(CastInst::isBitCastable(FloatTy, DoubleTy));
-  EXPECT_TRUE(CastInst::isBitCastable(FloatTy, FloatTy));
-  EXPECT_TRUE(CastInst::isBitCastable(FloatTy, FloatTy));
-  EXPECT_TRUE(CastInst::isBitCastable(FloatTy, Int32Ty));
-  EXPECT_TRUE(CastInst::isBitCastable(Int16Ty, HalfTy));
-  EXPECT_TRUE(CastInst::isBitCastable(Int32Ty, FloatTy));
-  EXPECT_TRUE(CastInst::isBitCastable(V2Int32Ty, Int64Ty));
-
-  EXPECT_TRUE(CastInst::isBitCastable(V2Int32Ty, V4Int16Ty));
-  EXPECT_FALSE(CastInst::isBitCastable(Int32Ty, Int64Ty));
-  EXPECT_FALSE(CastInst::isBitCastable(Int64Ty, Int32Ty));
-
-  EXPECT_FALSE(CastInst::isBitCastable(V2Int32PtrTy, Int64Ty));
-  EXPECT_FALSE(CastInst::isBitCastable(Int64Ty, V2Int32PtrTy));
-  EXPECT_TRUE(CastInst::isBitCastable(V2Int64PtrTy, V2Int32PtrTy));
-  EXPECT_TRUE(CastInst::isBitCastable(V2Int32PtrTy, V2Int64PtrTy));
-  EXPECT_FALSE(CastInst::isBitCastable(V2Int32Ty, V2Int64Ty));
-  EXPECT_FALSE(CastInst::isBitCastable(V2Int64Ty, V2Int32Ty));
-
+  EXPECT_FALSE(CastInst::isBitCastable(V2Int32PtrAS1Ty, V4Int64PtrAS1Ty, DL));
+  EXPECT_FALSE(CastInst::isBitCastable(V4Int64PtrAS1Ty, V2Int32PtrAS1Ty, DL));
+  EXPECT_FALSE(CastInst::isBitCastable(V2Int32PtrAS1Ty, V4Int32PtrAS1Ty, DL));
+  EXPECT_FALSE(CastInst::isBitCastable(Int32PtrTy, V2Int32PtrTy, DL));
+  EXPECT_FALSE(CastInst::isBitCastable(V2Int32PtrTy, Int32PtrTy, DL));
+
+  EXPECT_TRUE(CastInst::isBitCastable(Int32PtrTy, Int64PtrTy, DL));
+  EXPECT_FALSE(CastInst::isBitCastable(DoubleTy, FloatTy, DL));
+  EXPECT_FALSE(CastInst::isBitCastable(FloatTy, DoubleTy, DL));
+  EXPECT_TRUE(CastInst::isBitCastable(FloatTy, FloatTy, DL));
+  EXPECT_TRUE(CastInst::isBitCastable(FloatTy, FloatTy, DL));
+  EXPECT_TRUE(CastInst::isBitCastable(FloatTy, Int32Ty, DL));
+  EXPECT_TRUE(CastInst::isBitCastable(Int16Ty, HalfTy, DL));
+  EXPECT_TRUE(CastInst::isBitCastable(Int32Ty, FloatTy, DL));
+  EXPECT_TRUE(CastInst::isBitCastable(V2Int32Ty, Int64Ty, DL));
+
+  EXPECT_TRUE(CastInst::isBitCastable(V2Int32Ty, V4Int16Ty, DL));
+  EXPECT_FALSE(CastInst::isBitCastable(Int32Ty, Int64Ty, DL));
+  EXPECT_FALSE(CastInst::isBitCastable(Int64Ty, Int32Ty, DL));
+
+  EXPECT_FALSE(CastInst::isBitCastable(V2Int32PtrTy, Int64Ty, DL));
+  EXPECT_FALSE(CastInst::isBitCastable(Int64Ty, V2Int32PtrTy, DL));
+  EXPECT_TRUE(CastInst::isBitCastable(V2Int64PtrTy, V2Int32PtrTy, DL));
+  EXPECT_TRUE(CastInst::isBitCastable(V2Int32PtrTy, V2Int64PtrTy, DL));
+  EXPECT_FALSE(CastInst::isBitCastable(V2Int32Ty, V2Int64Ty, DL));
+  EXPECT_FALSE(CastInst::isBitCastable(V2Int64Ty, V2Int32Ty, DL));
 
   EXPECT_FALSE(CastInst::castIsValid(Instruction::BitCast,
                                      Constant::getNullValue(V4Int32PtrTy),
@@ -345,6 +355,14 @@
                                      Constant::getNullValue(VScaleV4Int16Ty),
                                      V4Int16Ty));
 
+  // Bit casting between pointers from different addrspace
+  EXPECT_TRUE(CastInst::castIsValid(Instruction::BitCast,
+                                    Constant::getNullValue(Int32PtrAS2Ty),
+                                    Int32PtrAS3Ty, DL));
+  EXPECT_FALSE(CastInst::castIsValid(Instruction::BitCast,
+                                     Constant::getNullValue(Int32PtrAS1Ty),
+                                     Int32PtrAS2Ty, DL));
+
   // Bit casting scalable vectors to scalable vectors.
   EXPECT_TRUE(CastInst::castIsValid(Instruction::BitCast,
                                     Constant::getNullValue(VScaleV4Int16Ty),
Index: llvm/test/Verifier/bitcast-vector-pointer-same-addrspace.ll
===================================================================
--- /dev/null
+++ llvm/test/Verifier/bitcast-vector-pointer-same-addrspace.ll
@@ -0,0 +1,13 @@
+; RUN: not llvm-as -disable-output %s 2>&1 | FileCheck %s
+
+target datalayout = "e-p:32:32:32-p1:16:16:16-p2:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:32:64-v128:32:128-a0:0:32-n8:16:32"
+
+; CHECK: error: invalid cast opcode for cast from '<4 x i32 addrspace(1)*>' to '<2 x i32 addrspace(1)*>'
+
+; Converting 4 element array of pointers from addrspace 1 to 2 element array in addrspace 1
+; is invalid since the vector sizes dont match
+define <2 x i32 addrspace(1)*> @vector_illegal_bitcast_1(<4 x i32 addrspace(1)*> %p) {
+   %cast = bitcast <4 x i32 addrspace(1)*> %p to <2 x i32 addrspace(1)*>
+   ret <2 x i32 addrspace(1)*> %cast
+}
+
Index: llvm/test/Verifier/bitcast-vector-pointer-pos.ll
===================================================================
--- llvm/test/Verifier/bitcast-vector-pointer-pos.ll
+++ llvm/test/Verifier/bitcast-vector-pointer-pos.ll
@@ -12,3 +12,7 @@
   ret i64* %b
 }
 
+define <2 x i32 addrspace(2)*> @vector_legal_bitcast_vector_of_pointers_to_vector_of_pointers(<2 x i32*> %a) {
+  %c = bitcast <2 x i32*> %a to <2 x i32 addrspace(2)*>
+  ret <2 x i32 addrspace(2)*> %c
+}
Index: llvm/test/Verifier/bitcast-vector-pointer-neg.ll
===================================================================
--- llvm/test/Verifier/bitcast-vector-pointer-neg.ll
+++ llvm/test/Verifier/bitcast-vector-pointer-neg.ll
@@ -1,10 +1,12 @@
-; RUN: not llvm-as -disable-output %s 2>&1 | FileCheck %s
+; RUN: llvm-as -disable-output %s
 
 target datalayout = "e-p:32:32:32-p1:16:16:16-p2:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:32:64-v128:32:128-a0:0:32-n8:16:32"
 
-; CHECK: error: invalid cast opcode for cast from '<2 x i32*>' to 'i64*'
+; The pointer in addrspace 1 of the size 16 while pointer in addrspace 2 of the size 32.
+; Converting 4 element array of pointers from addrspace 2 to 2 element array in addrspace 2
+; has the same total bit length
 
-define i64* @illegal_bitcast_vector_of_pointers_to_pointer(<2 x i32*> %a) {
-  %b = bitcast <2 x i32*> %a to i64*
-  ret i64* %b
-}
+define <2 x i32 addrspace(2)*> @vector_legal_bitcast_as_1_to_2(<4 x i32 addrspace(1)*> %p) {
+   %cast = bitcast <4 x i32 addrspace(1)*> %p to <2 x i32 addrspace(2)*>
+   ret <2 x i32 addrspace(2)*> %cast
+}
\ No newline at end of file
Index: llvm/test/Verifier/bitcast-vector-pointer-different-addrspace-illegal.ll
===================================================================
--- /dev/null
+++ llvm/test/Verifier/bitcast-vector-pointer-different-addrspace-illegal.ll
@@ -0,0 +1,9 @@
+; RUN: not llvm-as -disable-output %s 2>&1 | FileCheck %s
+
+target datalayout = "e-p:32:32:32-p1:16:16:16-p2:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:32:64-v128:32:128-a0:0:32-n8:16:32"
+
+; CHECK: error: invalid cast opcode for cast from '<4 x i32 addrspace(1)*>' to '<4 x i32 addrspace(2)*>'
+define <4 x i32 addrspace(2)*> @vector_illegal_bitcast_as_1_to_2(<4 x i32 addrspace(1)*> %p) {
+   %cast = bitcast <4 x i32 addrspace(1)*> %p to <4 x i32 addrspace(2)*>
+   ret <4 x i32 addrspace(2)*> %cast
+}
\ No newline at end of file
Index: llvm/test/Verifier/bitcast-vector-pointer-as-neg.ll
===================================================================
--- llvm/test/Verifier/bitcast-vector-pointer-as-neg.ll
+++ llvm/test/Verifier/bitcast-vector-pointer-as-neg.ll
@@ -1,14 +1,12 @@
-; RUN: not llvm-as -disable-output %s 2>&1 | FileCheck %s
+; RUN: llvm-as -disable-output %s
 
 target datalayout = "e-p:32:32:32-p1:16:16:16-p2:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:32:64-v128:32:128-a0:0:32-n8:16:32"
 
-; CHECK: error: invalid cast opcode for cast from '<4 x i32 addrspace(1)*>' to '<2 x i32 addrspace(2)*>'
-
 ; The pointer in addrspace 1 of the size 16 while pointer in addrspace 2 of the size 32.
 ; Converting 4 element array of pointers from addrspace 2 to 2 element array in addrspace 2
-; has the same total bit length but bitcast still does not allow conversion into
-; different addrspace.
-define <2 x i32 addrspace(2)*> @vector_illegal_bitcast_as_1_to_2(<4 x i32 addrspace(1)*> %p) {
+; has the same total bit length
+
+define <2 x i32 addrspace(2)*> @vector_legal_bitcast_as_1_to_2(<4 x i32 addrspace(1)*> %p) {
    %cast = bitcast <4 x i32 addrspace(1)*> %p to <2 x i32 addrspace(2)*>
    ret <2 x i32 addrspace(2)*> %cast
 }
Index: llvm/test/Transforms/GVN/gvn-eliminate-inttoptr-ptrtoint-for-vector-ptr-load.ll
===================================================================
--- /dev/null
+++ llvm/test/Transforms/GVN/gvn-eliminate-inttoptr-ptrtoint-for-vector-ptr-load.ll
@@ -0,0 +1,46 @@
+; RUN: opt -S -gvn < %s | FileCheck %s
+
+; GVN replaces a load that depends on previous store with intoptr/ptrtoint instructions.
+; Instead, replace load with bitcast of pointers from different addrspaces.
+
+target datalayout = "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-ni:7"
+
+%struct.S.coerce = type { <2 x i32*> addrspace(1)* }
+
+define void @test(%struct.S.coerce %s.coerce) #0 {
+; CHECK-LABEL: @test(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    %s.sroa.0 = alloca <2 x i32*>*, align 8, addrspace(5)
+; CHECK-NEXT:    %0 = extractvalue %struct.S.coerce %s.coerce, 0
+; CHECK-NEXT:    %1 = bitcast <2 x i32*>* addrspace(5)* %s.sroa.0 to <2 x i32*> addrspace(1)* addrspace(5)*
+; CHECK-NEXT:    %2 = addrspacecast <2 x i32*> addrspace(1)* addrspace(5)* %1 to <2 x i32*> addrspace(1)**
+; CHECK-NEXT:    store <2 x i32*> addrspace(1)* %0, <2 x i32*> addrspace(1)** %2, align 8
+; CHECK-NEXT:    %3 = bitcast <2 x i32*> addrspace(1)* %0 to <2 x i32*>*
+; CHECK-NEXT:    %4 = load <2 x i32*>, <2 x i32*>* %3, align 4, !tbaa !2
+; CHECK-NEXT:    store <2 x i32*> %4, <2 x i32*>* %3, align 4, !tbaa !2
+; CHECK-NEXT:    ret void
+;
+
+entry:
+  %s.sroa.0 = alloca <2 x i32*>*, align 8, addrspace(5)
+
+  %0 = extractvalue %struct.S.coerce %s.coerce, 0
+  %1 = bitcast <2 x i32*>* addrspace(5)* %s.sroa.0 to <2 x i32*> addrspace(1)* addrspace(5)*
+  %2 = addrspacecast <2 x i32*> addrspace(1)* addrspace(5)* %1 to <2 x i32*> addrspace(1)**
+  store <2 x i32*> addrspace(1)* %0, <2 x i32*> addrspace(1)** %2, align 8
+  
+  %3 = load <2 x i32*>*, <2 x i32*>* addrspace(5)* %s.sroa.0, align 8, !tbaa !2
+  %4 = load <2 x i32*>, <2 x i32*>* %3, align 4, !tbaa !2
+  store <2 x i32*> %4, <2 x i32*>* %3, align 4, !tbaa !2
+  ret void
+}
+
+!llvm.module.flags = !{!0}
+!llvm.ident = !{!1}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{!"clang version 11.0.0 (g...@github.com:llvm/llvm-project.git 25e22613dfdb4083056e8a951aeb246bea4019f3)"}
+!2 = !{!3, !3, i64 0}
+!3 = !{!"int", !4, i64 0}
+!4 = !{!"omnipotent char", !5, i64 0}
+!5 = !{!"Simple C++ TBAA"}
\ No newline at end of file
Index: llvm/test/Transforms/GVN/gvn-eliminate-inttoptr-ptrtoint-for-vector-load.ll
===================================================================
--- /dev/null
+++ llvm/test/Transforms/GVN/gvn-eliminate-inttoptr-ptrtoint-for-vector-load.ll
@@ -0,0 +1,49 @@
+; RUN: opt -S -gvn < %s | FileCheck %s
+
+; GVN replaces a load that depends on previous store with intoptr/ptrtoint instructions.
+; Instead, replace load with bitcast of pointers from different addrspaces.
+
+target datalayout = "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-ni:7"
+
+%struct.S.coerce = type { <2 x i32> addrspace(1)* }
+
+define void @test(%struct.S.coerce %s.coerce) #0 {
+; CHECK-LABEL: @test(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    %s.sroa.0 = alloca <2 x i32>*, align 8, addrspace(5)
+; CHECK-NEXT:    %0 = extractvalue %struct.S.coerce %s.coerce, 0
+; CHECK-NEXT:    %1 = bitcast <2 x i32>* addrspace(5)* %s.sroa.0 to <2 x i32> addrspace(1)* addrspace(5)*
+; CHECK-NEXT:    %2 = addrspacecast <2 x i32> addrspace(1)* addrspace(5)* %1 to <2 x i32> addrspace(1)**
+; CHECK-NEXT:    store <2 x i32> addrspace(1)* %0, <2 x i32> addrspace(1)** %2, align 8
+; CHECK-NEXT:    %3 = bitcast <2 x i32> addrspace(1)* %0 to <2 x i32>*
+; CHECK-NEXT:    %4 = load <2 x i32>, <2 x i32>* %3, align 4, !tbaa !2
+; CHECK-NEXT:    %inc = add nsw <2 x i32> %4, <i32 1, i32 1>
+; CHECK-NEXT:    store <2 x i32> %inc, <2 x i32>* %3, align 4, !tbaa !2
+; CHECK-NEXT:    ret void
+;
+
+entry:
+  %s.sroa.0 = alloca <2 x i32>*, align 8, addrspace(5)
+
+  %0 = extractvalue %struct.S.coerce %s.coerce, 0
+  %1 = bitcast <2 x i32>* addrspace(5)* %s.sroa.0 to <2 x i32> addrspace(1)* addrspace(5)*
+  %2 = addrspacecast <2 x i32> addrspace(1)* addrspace(5)* %1 to <2 x i32> addrspace(1)**
+  store <2 x i32> addrspace(1)* %0, <2 x i32> addrspace(1)** %2, align 8
+  
+  %3 = load <2 x i32>*, <2 x i32>* addrspace(5)* %s.sroa.0, align 8, !tbaa !2
+  %4 = load <2 x i32>, <2 x i32>* %3, align 4, !tbaa !2
+  %inc = add nsw <2 x i32> %4, <i32 1, i32 1>
+  store <2 x i32> %inc, <2 x i32>* %3, align 4, !tbaa !2
+    
+  ret void
+}
+
+!llvm.module.flags = !{!0}
+!llvm.ident = !{!1}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{!"clang version 11.0.0 (g...@github.com:llvm/llvm-project.git 25e22613dfdb4083056e8a951aeb246bea4019f3)"}
+!2 = !{!3, !3, i64 0}
+!3 = !{!"int", !4, i64 0}
+!4 = !{!"omnipotent char", !5, i64 0}
+!5 = !{!"Simple C++ TBAA"}
\ No newline at end of file
Index: llvm/test/Transforms/GVN/gvn-eliminate-inttoptr-ptrtoint-for-load.ll
===================================================================
--- /dev/null
+++ llvm/test/Transforms/GVN/gvn-eliminate-inttoptr-ptrtoint-for-load.ll
@@ -0,0 +1,49 @@
+; RUN: opt -S -gvn < %s | FileCheck %s
+
+; GVN replaces a load that depends on previous store with intoptr/ptrtoint instructions.
+; Instead, replace load with bitcast of pointers from different addrspaces.
+
+target datalayout = "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-ni:7"
+
+%struct.S.coerce = type { i32 addrspace(1)* }
+
+define void @test(%struct.S.coerce %s.coerce) #0 {
+; CHECK-LABEL: @test(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    %s.sroa.0 = alloca i32*, align 8, addrspace(5)
+; CHECK-NEXT:    %0 = extractvalue %struct.S.coerce %s.coerce, 0
+; CHECK-NEXT:    %1 = bitcast i32* addrspace(5)* %s.sroa.0 to i32 addrspace(1)* addrspace(5)*
+; CHECK-NEXT:    %2 = addrspacecast i32 addrspace(1)* addrspace(5)* %1 to i32 addrspace(1)**
+; CHECK-NEXT:    store i32 addrspace(1)* %0, i32 addrspace(1)** %2, align 8
+; CHECK-NEXT:    %3 = bitcast i32 addrspace(1)* %0 to i32*
+; CHECK-NEXT:    %4 = load i32, i32* %3, align 4, !tbaa !2
+; CHECK-NEXT:    %inc = add nsw i32 %4, 1
+; CHECK-NEXT:    store i32 %inc, i32* %3, align 4, !tbaa !2
+; CHECK-NEXT:    ret void
+;
+
+entry:
+  %s.sroa.0 = alloca i32*, align 8, addrspace(5)
+
+  %0 = extractvalue %struct.S.coerce %s.coerce, 0
+  %1 = bitcast i32* addrspace(5)* %s.sroa.0 to i32 addrspace(1)* addrspace(5)*
+  %2 = addrspacecast i32 addrspace(1)* addrspace(5)* %1 to i32 addrspace(1)**
+  store i32 addrspace(1)* %0, i32 addrspace(1)** %2, align 8
+  
+  %3 = load i32*, i32* addrspace(5)* %s.sroa.0, align 8, !tbaa !2
+  %4 = load i32, i32* %3, align 4, !tbaa !2
+  %inc = add nsw i32 %4, 1
+  store i32 %inc, i32* %3, align 4, !tbaa !2
+    
+  ret void
+}
+
+!llvm.module.flags = !{!0}
+!llvm.ident = !{!1}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{!"clang version 11.0.0 (g...@github.com:llvm/llvm-project.git 25e22613dfdb4083056e8a951aeb246bea4019f3)"}
+!2 = !{!3, !3, i64 0}
+!3 = !{!"int", !4, i64 0}
+!4 = !{!"omnipotent char", !5, i64 0}
+!5 = !{!"Simple C++ TBAA"}
\ No newline at end of file
Index: llvm/lib/Transforms/Utils/VNCoercion.cpp
===================================================================
--- llvm/lib/Transforms/Utils/VNCoercion.cpp
+++ llvm/lib/Transforms/Utils/VNCoercion.cpp
@@ -75,6 +75,11 @@
   // If this is already the right type, just return it.
   Type *StoredValTy = StoredVal->getType();
 
+  // Return if a bitcast has been introduced before and if types matches.
+  if (StoredValTy == LoadedTy) {
+    return StoredVal;
+  }
+
   uint64_t StoredValSize = DL.getTypeSizeInBits(StoredValTy).getFixedSize();
   uint64_t LoadedValSize = DL.getTypeSizeInBits(LoadedTy).getFixedSize();
 
@@ -414,9 +419,22 @@
     return SrcVal;
   }
 
+  // If two pointers are in different address spaces
+  // and if bitcast is valid, introduce a bitcast.
+  if (SrcVal->getType()->isPtrOrPtrVectorTy() && LoadTy->isPtrOrPtrVectorTy() &&
+      (cast<PointerType>(SrcVal->getType())->getAddressSpace() !=
+       cast<PointerType>(LoadTy)->getAddressSpace())) {
+    if (CastInst::castIsValid(Instruction::BitCast, SrcVal->getType(), LoadTy,
+                              DL)) {
+      SrcVal = Helper.CreateBitCast(SrcVal, LoadTy, DL);
+      return SrcVal;
+    }
+  }
+
   uint64_t StoreSize =
       (DL.getTypeSizeInBits(SrcVal->getType()).getFixedSize() + 7) / 8;
   uint64_t LoadSize = (DL.getTypeSizeInBits(LoadTy).getFixedSize() + 7) / 8;
+
   // Compute which bits of the stored value are being used by the load.  Convert
   // to an integer type to start with.
   if (SrcVal->getType()->isPtrOrPtrVectorTy())
Index: llvm/lib/Transforms/Coroutines/Coroutines.cpp
===================================================================
--- llvm/lib/Transforms/Coroutines/Coroutines.cpp
+++ llvm/lib/Transforms/Coroutines/Coroutines.cpp
@@ -441,7 +441,8 @@
           // The optimizer likes to eliminate bitcasts leading into variadic
           // calls, but that messes with our invariants.  Re-insert the
           // bitcast and ignore this type mismatch.
-          if (CastInst::isBitCastable(SrcTy, *RI)) {
+          if (CastInst::isBitCastable(SrcTy, *RI,
+                                      F.getParent()->getDataLayout())) {
             auto BCI = new BitCastInst(*SI, *RI, "", Suspend);
             SI->set(BCI);
             continue;
Index: llvm/lib/IR/Verifier.cpp
===================================================================
--- llvm/lib/IR/Verifier.cpp
+++ llvm/lib/IR/Verifier.cpp
@@ -2140,7 +2140,7 @@
 void Verifier::visitConstantExpr(const ConstantExpr *CE) {
   if (CE->getOpcode() == Instruction::BitCast)
     Assert(CastInst::castIsValid(Instruction::BitCast, CE->getOperand(0),
-                                 CE->getType()),
+                                 CE->getType(), DL),
            "Invalid bitcast", CE);
 }
 
@@ -3031,9 +3031,9 @@
 }
 
 void Verifier::visitBitCastInst(BitCastInst &I) {
-  Assert(
-      CastInst::castIsValid(Instruction::BitCast, I.getOperand(0), I.getType()),
-      "Invalid bitcast", &I);
+  Assert(CastInst::castIsValid(Instruction::BitCast, I.getOperand(0),
+                               I.getType(), DL),
+         "Invalid bitcast", &I);
   visitInstruction(I);
 }
 
Index: llvm/lib/IR/Instructions.cpp
===================================================================
--- llvm/lib/IR/Instructions.cpp
+++ llvm/lib/IR/Instructions.cpp
@@ -2893,7 +2893,7 @@
                           Type *SrcTy,
                           Type *DestTy,
                           const DataLayout &DL) {
-  assert(castIsValid(Opcode, SrcTy, DestTy) && "method precondition");
+  assert(castIsValid(Opcode, SrcTy, DestTy, DL) && "method precondition");
   switch (Opcode) {
     default: llvm_unreachable("Invalid CastOp");
     case Instruction::Trunc:
@@ -3198,6 +3198,34 @@
   }
 }
 
+CastInst *CastInst::Create(Instruction::CastOps op, Value *S, Type *Ty,
+                           const DataLayout &DL, const Twine &Name,
+                           Instruction *InsertBefore) {
+  assert(castIsValid(op, S, Ty, DL) && "Invalid cast!");
+
+  // Construct and return the appropriate CastInst subclass
+  switch (op) {
+  case BitCast:
+    return new BitCastInst(S, Ty, DL, Name, InsertBefore);
+  default:
+    CastInst::Create(op, S, Ty, Name, InsertBefore);
+  }
+}
+
+CastInst *CastInst::Create(Instruction::CastOps op, Value *S, Type *Ty,
+                           const DataLayout &DL, const Twine &Name,
+                           BasicBlock *InsertAtEnd) {
+  assert(castIsValid(op, S, Ty, DL) && "Invalid cast!");
+
+  // Construct and return the appropriate CastInst subclass
+  switch (op) {
+  case BitCast:
+    return new BitCastInst(S, Ty, DL, Name, InsertAtEnd);
+  default:
+    CastInst::Create(op, S, Ty, Name, InsertAtEnd);
+  }
+}
+
 CastInst *CastInst::CreateZExtOrBitCast(Value *S, Type *Ty,
                                         const Twine &Name,
                                         Instruction *InsertBefore) {
@@ -3374,7 +3402,7 @@
   return Create(opcode, C, Ty, Name, InsertAtEnd);
 }
 
-bool CastInst::isBitCastable(Type *SrcTy, Type *DestTy) {
+bool CastInst::isBitCastable(Type *SrcTy, Type *DestTy, const DataLayout &DL) {
   if (!SrcTy->isFirstClassType() || !DestTy->isFirstClassType())
     return false;
 
@@ -3393,7 +3421,12 @@
 
   if (PointerType *DestPtrTy = dyn_cast<PointerType>(DestTy)) {
     if (PointerType *SrcPtrTy = dyn_cast<PointerType>(SrcTy)) {
-      return SrcPtrTy->getAddressSpace() == DestPtrTy->getAddressSpace();
+      if (SrcPtrTy->getAddressSpace() == DestPtrTy->getAddressSpace()) {
+        return true;
+      } else {
+        return DL.getPointerTypeSizeInBits(SrcTy) ==
+               DL.getPointerTypeSizeInBits(DestTy);
+      }
     }
   }
 
@@ -3426,7 +3459,7 @@
       return (IntTy->getBitWidth() == DL.getPointerTypeSizeInBits(PtrTy) &&
               !DL.isNonIntegralPointerType(PtrTy));
 
-  return isBitCastable(SrcTy, DestTy);
+  return isBitCastable(SrcTy, DestTy, DL);
 }
 
 // Provide a way to get a "cast" where the cast opcode is inferred from the
@@ -3538,8 +3571,7 @@
 /// could be broken out into the separate constructors but it is useful to have
 /// it in one place and to eliminate the redundant code for getting the sizes
 /// of the types involved.
-bool
-CastInst::castIsValid(Instruction::CastOps op, Type *SrcTy, Type *DstTy) {
+bool CastInst::castIsValid(Instruction::CastOps op, Type *SrcTy, Type *DstTy) {
   if (!SrcTy->isFirstClassType() || !DstTy->isFirstClassType() ||
       SrcTy->isAggregateType() || DstTy->isAggregateType())
     return false;
@@ -3638,6 +3670,57 @@
   }
 }
 
+bool CastInst::castIsValid(Instruction::CastOps op, Type *SrcTy, Type *DstTy,
+                           const DataLayout &DL) {
+  if (!SrcTy->isFirstClassType() || !DstTy->isFirstClassType() ||
+      SrcTy->isAggregateType() || DstTy->isAggregateType())
+    return false;
+
+  // Get the size of the types in bits, and whether we are dealing
+  // with vector types, we'll need this later.
+  bool SrcIsVec = isa<VectorType>(SrcTy);
+  bool DstIsVec = isa<VectorType>(DstTy);
+
+  // If these are vector types, get the lengths of the vectors (using zero for
+  // scalar types means that checking that vector lengths match also checks that
+  // scalars are not being converted to vectors or vectors to scalars).
+  ElementCount SrcEC = SrcIsVec ? cast<VectorType>(SrcTy)->getElementCount()
+                                : ElementCount::getFixed(0);
+  ElementCount DstEC = DstIsVec ? cast<VectorType>(DstTy)->getElementCount()
+                                : ElementCount::getFixed(0);
+
+  switch (op) {
+  default:
+    return castIsValid(op, SrcTy, DstTy);
+  case Instruction::BitCast: {
+    PointerType *SrcPtrTy = dyn_cast<PointerType>(SrcTy->getScalarType());
+    PointerType *DstPtrTy = dyn_cast<PointerType>(DstTy->getScalarType());
+
+    // BitCast implies a no-op cast of type only. No bits change.
+    // However, you can't cast pointers to anything but pointers.
+    if (!SrcPtrTy != !DstPtrTy)
+      return false;
+
+    // For non-pointer cases, the cast is okay if the source and destination bit
+    // widths are identical.
+    if (!SrcPtrTy)
+      return SrcTy->getPrimitiveSizeInBits() == DstTy->getPrimitiveSizeInBits();
+
+    // If source or destionation is vector of pointers, compute the total bit
+    // width of vector elements. else if not vector, use the Pointer size from
+    // data layout.
+    unsigned SrcTypeSize =
+        SrcIsVec ? SrcEC.getKnownMinValue() * DL.getPointerTypeSizeInBits(SrcTy)
+                 : DL.getPointerTypeSizeInBits(SrcTy);
+    unsigned DstTypeSize =
+        DstIsVec ? DstEC.getKnownMinValue() * DL.getPointerTypeSizeInBits(DstTy)
+                 : DL.getPointerTypeSizeInBits(DstTy);
+
+    return SrcTypeSize == DstTypeSize;
+  }
+  }
+}
+
 TruncInst::TruncInst(
   Value *S, Type *Ty, const Twine &Name, Instruction *InsertBefore
 ) : CastInst(Ty, Trunc, S, Name, InsertBefore) {
@@ -3781,6 +3864,18 @@
   assert(castIsValid(getOpcode(), S, Ty) && "Illegal BitCast");
 }
 
+BitCastInst::BitCastInst(Value *S, Type *Ty, const DataLayout &DL,
+                         const Twine &Name, Instruction *InsertBefore)
+    : CastInst(Ty, BitCast, S, Name, InsertBefore) {
+  assert(castIsValid(getOpcode(), S->getType(), Ty, DL) && "Illegal BitCast");
+}
+
+BitCastInst::BitCastInst(Value *S, Type *Ty, const DataLayout &DL,
+                         const Twine &Name, BasicBlock *InsertAtEnd)
+    : CastInst(Ty, BitCast, S, Name, InsertAtEnd) {
+  assert(castIsValid(getOpcode(), S->getType(), Ty, DL) && "Illegal BitCast");
+}
+
 AddrSpaceCastInst::AddrSpaceCastInst(
   Value *S, Type *Ty, const Twine &Name, Instruction *InsertBefore
 ) : CastInst(Ty, AddrSpaceCast, S, Name, InsertBefore) {
Index: llvm/lib/IR/Constants.cpp
===================================================================
--- llvm/lib/IR/Constants.cpp
+++ llvm/lib/IR/Constants.cpp
@@ -2024,6 +2024,46 @@
   }
 }
 
+Constant *ConstantExpr::getCast(unsigned oc, Constant *C, Type *Ty,
+                                const DataLayout &DL, bool OnlyIfReduced) {
+  Instruction::CastOps opc = Instruction::CastOps(oc);
+  assert(Instruction::isCast(opc) && "opcode out of range");
+  assert(C && Ty && "Null arguments to getCast");
+  assert(CastInst::castIsValid(opc, C->getType(), Ty, DL) &&
+         "Invalid constantexpr cast!");
+
+  switch (opc) {
+  default:
+    llvm_unreachable("Invalid cast opcode");
+  case Instruction::Trunc:
+    return getTrunc(C, Ty, OnlyIfReduced);
+  case Instruction::ZExt:
+    return getZExt(C, Ty, OnlyIfReduced);
+  case Instruction::SExt:
+    return getSExt(C, Ty, OnlyIfReduced);
+  case Instruction::FPTrunc:
+    return getFPTrunc(C, Ty, OnlyIfReduced);
+  case Instruction::FPExt:
+    return getFPExtend(C, Ty, OnlyIfReduced);
+  case Instruction::UIToFP:
+    return getUIToFP(C, Ty, OnlyIfReduced);
+  case Instruction::SIToFP:
+    return getSIToFP(C, Ty, OnlyIfReduced);
+  case Instruction::FPToUI:
+    return getFPToUI(C, Ty, OnlyIfReduced);
+  case Instruction::FPToSI:
+    return getFPToSI(C, Ty, OnlyIfReduced);
+  case Instruction::PtrToInt:
+    return getPtrToInt(C, Ty, OnlyIfReduced);
+  case Instruction::IntToPtr:
+    return getIntToPtr(C, Ty, OnlyIfReduced);
+  case Instruction::BitCast:
+    return getBitCast(C, Ty, DL, OnlyIfReduced);
+  case Instruction::AddrSpaceCast:
+    return getAddrSpaceCast(C, Ty, OnlyIfReduced);
+  }
+}
+
 Constant *ConstantExpr::getZExtOrBitCast(Constant *C, Type *Ty) {
   if (C->getType()->getScalarSizeInBits() == Ty->getScalarSizeInBits())
     return getBitCast(C, Ty);
@@ -2242,6 +2282,19 @@
   return getFoldedCast(Instruction::BitCast, C, DstTy, OnlyIfReduced);
 }
 
+Constant *ConstantExpr::getBitCast(Constant *C, Type *DstTy,
+                                   const DataLayout &DL, bool OnlyIfReduced) {
+  assert(CastInst::castIsValid(Instruction::BitCast, C->getType(), DstTy, DL) &&
+         "Invalid constantexpr bitcast!");
+
+  // It is common to ask for a bitcast of a value to its own type, handle this
+  // speedily.
+  if (C->getType() == DstTy)
+    return C;
+
+  return getFoldedCast(Instruction::BitCast, C, DstTy, OnlyIfReduced);
+}
+
 Constant *ConstantExpr::getAddrSpaceCast(Constant *C, Type *DstTy,
                                          bool OnlyIfReduced) {
   assert(CastInst::castIsValid(Instruction::AddrSpaceCast, C, DstTy) &&
Index: llvm/lib/IR/AutoUpgrade.cpp
===================================================================
--- llvm/lib/IR/AutoUpgrade.cpp
+++ llvm/lib/IR/AutoUpgrade.cpp
@@ -4099,7 +4099,7 @@
       // value to the return type of the old function.
       if (NewFuncTy->getReturnType() != CI->getType() &&
           !CastInst::castIsValid(Instruction::BitCast, CI,
-                                 NewFuncTy->getReturnType()))
+                                 NewFuncTy->getReturnType(), M.getDataLayout()))
         continue;
 
       bool InvalidCast = false;
@@ -4113,7 +4113,8 @@
           // Don't upgrade the intrinsic if it's not valid to bitcast the argument
           // to the parameter type of the new function.
           if (!CastInst::castIsValid(Instruction::BitCast, Arg,
-                                     NewFuncTy->getParamType(I))) {
+                                     NewFuncTy->getParamType(I),
+                                     M.getDataLayout())) {
             InvalidCast = true;
             break;
           }
Index: llvm/lib/AsmParser/LLParser.cpp
===================================================================
--- llvm/lib/AsmParser/LLParser.cpp
+++ llvm/lib/AsmParser/LLParser.cpp
@@ -6735,13 +6735,16 @@
       parseType(DestTy))
     return true;
 
-  if (!CastInst::castIsValid((Instruction::CastOps)Opc, Op, DestTy)) {
-    CastInst::castIsValid((Instruction::CastOps)Opc, Op, DestTy);
+  if (!CastInst::castIsValid((Instruction::CastOps)Opc, Op, DestTy,
+                             M->getDataLayout())) {
+    CastInst::castIsValid((Instruction::CastOps)Opc, Op, DestTy,
+                          M->getDataLayout());
     return error(Loc, "invalid cast opcode for cast from '" +
                           getTypeString(Op->getType()) + "' to '" +
                           getTypeString(DestTy) + "'");
   }
-  Inst = CastInst::Create((Instruction::CastOps)Opc, Op, DestTy);
+  Inst = CastInst::Create((Instruction::CastOps)Opc, Op, DestTy,
+                          M->getDataLayout());
   return false;
 }
 
Index: llvm/lib/Analysis/LoopUnrollAnalyzer.cpp
===================================================================
--- llvm/lib/Analysis/LoopUnrollAnalyzer.cpp
+++ llvm/lib/Analysis/LoopUnrollAnalyzer.cpp
@@ -153,8 +153,8 @@
   // The cast can be invalid, because SimplifiedValues contains results of SCEV
   // analysis, which operates on integers (and, e.g., might convert i8* null to
   // i32 0).
-  if (CastInst::castIsValid(I.getOpcode(), Op, I.getType())) {
-    const DataLayout &DL = I.getModule()->getDataLayout();
+  const DataLayout &DL = I.getModule()->getDataLayout();
+  if (CastInst::castIsValid(I.getOpcode(), Op->getType(), I.getType(), DL)) {
     if (Value *V = SimplifyCastInst(I.getOpcode(), Op, I.getType(), DL)) {
       SimplifiedValues[&I] = V;
       return true;
Index: llvm/lib/Analysis/ConstantFolding.cpp
===================================================================
--- llvm/lib/Analysis/ConstantFolding.cpp
+++ llvm/lib/Analysis/ConstantFolding.cpp
@@ -102,8 +102,9 @@
 /// This always returns a non-null constant, but it may be a
 /// ConstantExpr if unfoldable.
 Constant *FoldBitCast(Constant *C, Type *DestTy, const DataLayout &DL) {
-  assert(CastInst::castIsValid(Instruction::BitCast, C, DestTy) &&
-         "Invalid constantexpr bitcast!");
+  assert(
+      CastInst::castIsValid(Instruction::BitCast, C->getType(), DestTy, DL) &&
+      "Invalid constantexpr bitcast!");
 
   // Catch the obvious splat cases.
   if (C->isNullValue() && !DestTy->isX86_MMXTy() && !DestTy->isX86_AMXTy())
@@ -384,7 +385,7 @@
       else if (SrcTy->isPointerTy() && DestTy->isIntegerTy())
         Cast = Instruction::PtrToInt;
 
-      if (CastInst::castIsValid(Cast, C, DestTy))
+      if (CastInst::castIsValid(Cast, C, DestTy, DL))
         return ConstantExpr::getCast(Cast, C, DestTy);
     }
 
Index: llvm/include/llvm/IR/NoFolder.h
===================================================================
--- llvm/include/llvm/IR/NoFolder.h
+++ llvm/include/llvm/IR/NoFolder.h
@@ -224,6 +224,11 @@
     return CastInst::Create(Op, C, DestTy);
   }
 
+  Instruction *CreateCast(Instruction::CastOps Op, Constant *C, Type *DestTy,
+                          const DataLayout &DL) const override {
+    return CastInst::Create(Op, C, DestTy, DL);
+  }
+
   Instruction *CreatePointerCast(Constant *C, Type *DestTy) const override {
     return CastInst::CreatePointerCast(C, DestTy);
   }
@@ -246,6 +251,11 @@
     return CreateCast(Instruction::BitCast, C, DestTy);
   }
 
+  Instruction *CreateBitCast(Constant *C, Type *DestTy,
+                             const DataLayout &DL) const override {
+    return CreateCast(Instruction::BitCast, C, DestTy, DL);
+  }
+
   Instruction *CreateIntToPtr(Constant *C, Type *DestTy) const override {
     return CreateCast(Instruction::IntToPtr, C, DestTy);
   }
Index: llvm/include/llvm/IR/Instructions.h
===================================================================
--- llvm/include/llvm/IR/Instructions.h
+++ llvm/include/llvm/IR/Instructions.h
@@ -5249,6 +5249,25 @@
     BasicBlock *InsertAtEnd       ///< The block to insert the instruction into
   );
 
+  /// Constructor with DataLayout and insert-before-instruction semantics
+  BitCastInst(
+      Value *S,             ///< The value to be casted
+      Type *Ty,             ///< The type to casted to
+      const DataLayout &DL, ///< The DataLayout to check validity of bitcast
+      const Twine &NameStr = "", ///< A name for the new instruction
+      Instruction *InsertBefore =
+          nullptr ///< Where to insert the new instruction
+  );
+
+  /// Constructor with DataLayout and insert-at-end-of-block semantics
+  BitCastInst(
+      Value *S,               ///< The value to be casted
+      Type *Ty,               ///< The type to casted to
+      const DataLayout &DL,   ///< The DataLayout to check validity of bitcast
+      const Twine &NameStr,   ///< A name for the new instruction
+      BasicBlock *InsertAtEnd ///< The block to insert the instruction into
+  );
+
   // Methods for support type inquiry through isa, cast, and dyn_cast:
   static bool classof(const Instruction *I) {
     return I->getOpcode() == BitCast;
Index: llvm/include/llvm/IR/InstrTypes.h
===================================================================
--- llvm/include/llvm/IR/InstrTypes.h
+++ llvm/include/llvm/IR/InstrTypes.h
@@ -27,6 +27,7 @@
 #include "llvm/IR/Attributes.h"
 #include "llvm/IR/CallingConv.h"
 #include "llvm/IR/Constants.h"
+#include "llvm/IR/DataLayout.h"
 #include "llvm/IR/DerivedTypes.h"
 #include "llvm/IR/Function.h"
 #include "llvm/IR/Instruction.h"
@@ -471,6 +472,37 @@
     BasicBlock *InsertAtEnd  ///< The block to insert the instruction into
   );
 
+  /// Provides a way to construct any of the CastInst subclasses using an
+  /// opcode instead of the subclass's constructor. The opcode must be in the
+  /// CastOps category (Instruction::isCast(opcode) returns true). DataLayout
+  /// is used to check validity of bitcast. This constructor has
+  /// insert-before-instruction semantics to automatically
+  /// insert the new CastInst before InsertBefore (if it is non-null).
+  /// Construct any of the CastInst subclasses
+  static CastInst *Create(
+      Instruction::CastOps,   ///< The opcode of the cast instruction
+      Value *S,               ///< The value to be casted (operand 0)
+      Type *Ty,               ///< The type to which cast should be made
+      const DataLayout &DL,   ///< DataLayout to check validity of bitcast
+      const Twine &Name = "", ///< Name for the instruction
+      Instruction *InsertBefore = nullptr ///< Place to insert the instruction
+  );
+  /// Provides a way to construct any of the CastInst subclasses using an
+  /// opcode instead of the subclass's constructor. The opcode must be in the
+  /// CastOps category. DataLayout is used to check validity of bitcast.
+  /// This constructor has insert-at-end-of-block semantics
+  /// to automatically insert the new CastInst at the end of InsertAtEnd (if
+  /// its non-null).
+  /// Construct any of the CastInst subclasses
+  static CastInst *
+  Create(Instruction::CastOps,   ///< The opcode for the cast instruction
+         Value *S,               ///< The value to be casted (operand 0)
+         Type *Ty,               ///< The type to which operand is casted
+         const DataLayout &DL,   ///< DataLayout to check validity of bitcast
+         const Twine &Name,      ///< The name for the instruction
+         BasicBlock *InsertAtEnd ///< The block to insert the instruction into
+  );
+
   /// Create a ZExt or BitCast cast instruction
   static CastInst *CreateZExtOrBitCast(
     Value *S,                ///< The value to be casted (operand 0)
@@ -600,8 +632,9 @@
 
   /// Check whether a bitcast between these types is valid
   static bool isBitCastable(
-    Type *SrcTy, ///< The Type from which the value should be cast.
-    Type *DestTy ///< The Type to which the value should be cast.
+      Type *SrcTy,         ///< The Type from which the value should be cast.
+      Type *DestTy,        ///< The Type to which the value should be cast.
+      const DataLayout &DL ///< The DataLayout to check validity of bitcast
   );
 
   /// Check whether a bitcast, inttoptr, or ptrtoint cast between these
@@ -693,6 +726,17 @@
     return castIsValid(op, S->getType(), DstTy);
   }
 
+  /// This method can e used to determine if a cast from SrcTy to DstTy using
+  /// Opcode op and DataLayout DL is valid or not
+  /// @returns true iff the proposed cast is valid.
+  /// Determine if a cast is valid without creating one.
+  static bool castIsValid(Instruction::CastOps op, Type *SrcTy, Type *DstTy,
+                          const DataLayout &DL);
+  static bool castIsValid(Instruction::CastOps op, Value *S, Type *DstTy,
+                          const DataLayout &DL) {
+    return castIsValid(op, S->getType(), DstTy, DL);
+  }
+
   /// Methods for support type inquiry through isa, cast, and dyn_cast:
   static bool classof(const Instruction *I) {
     return I->isCast();
Index: llvm/include/llvm/IR/IRBuilderFolder.h
===================================================================
--- llvm/include/llvm/IR/IRBuilderFolder.h
+++ llvm/include/llvm/IR/IRBuilderFolder.h
@@ -97,6 +97,8 @@
 
   virtual Value *CreateCast(Instruction::CastOps Op, Constant *C,
                             Type *DestTy) const = 0;
+  virtual Value *CreateCast(Instruction::CastOps Op, Constant *C, Type *DestTy,
+                            const DataLayout &DL) const = 0;
   virtual Value *CreatePointerCast(Constant *C, Type *DestTy) const = 0;
   virtual Value *CreatePointerBitCastOrAddrSpaceCast(Constant *C,
                                                      Type *DestTy) const = 0;
@@ -104,6 +106,8 @@
                                bool isSigned) const = 0;
   virtual Value *CreateFPCast(Constant *C, Type *DestTy) const = 0;
   virtual Value *CreateBitCast(Constant *C, Type *DestTy) const = 0;
+  virtual Value *CreateBitCast(Constant *C, Type *DestTy,
+                               const DataLayout &DL) const = 0;
   virtual Value *CreateIntToPtr(Constant *C, Type *DestTy) const = 0;
   virtual Value *CreatePtrToInt(Constant *C, Type *DestTy) const = 0;
   virtual Value *CreateZExtOrBitCast(Constant *C, Type *DestTy) const = 0;
Index: llvm/include/llvm/IR/IRBuilder.h
===================================================================
--- llvm/include/llvm/IR/IRBuilder.h
+++ llvm/include/llvm/IR/IRBuilder.h
@@ -2119,6 +2119,11 @@
     return CreateCast(Instruction::BitCast, V, DestTy, Name);
   }
 
+  Value *CreateBitCast(Value *V, Type *DestTy, const DataLayout &DL,
+                       const Twine &Name = "") {
+    return CreateCast(Instruction::BitCast, V, DestTy, DL, Name);
+  }
+
   Value *CreateAddrSpaceCast(Value *V, Type *DestTy,
                              const Twine &Name = "") {
     return CreateCast(Instruction::AddrSpaceCast, V, DestTy, Name);
@@ -2160,6 +2165,15 @@
     return Insert(CastInst::Create(Op, V, DestTy), Name);
   }
 
+  Value *CreateCast(Instruction::CastOps Op, Value *V, Type *DestTy,
+                    const DataLayout &DL, const Twine &Name = "") {
+    if (V->getType() == DestTy)
+      return V;
+    if (auto *VC = dyn_cast<Constant>(V))
+      return Insert(Folder.CreateCast(Op, VC, DestTy, DL), Name);
+    return Insert(CastInst::Create(Op, V, DestTy, DL), Name);
+  }
+
   Value *CreatePointerCast(Value *V, Type *DestTy,
                            const Twine &Name = "") {
     if (V->getType() == DestTy)
Index: llvm/include/llvm/IR/Constants.h
===================================================================
--- llvm/include/llvm/IR/Constants.h
+++ llvm/include/llvm/IR/Constants.h
@@ -1019,6 +1019,8 @@
                                bool OnlyIfReduced = false);
   static Constant *getBitCast(Constant *C, Type *Ty,
                               bool OnlyIfReduced = false);
+  static Constant *getBitCast(Constant *C, Type *Ty, const DataLayout &DL,
+                              bool OnlyIfReduced = false);
   static Constant *getAddrSpaceCast(Constant *C, Type *Ty,
                                     bool OnlyIfReduced = false);
 
@@ -1107,6 +1109,16 @@
   static Constant *getCast(unsigned ops, Constant *C, Type *Ty,
                            bool OnlyIfReduced = false);
 
+  /// Convenience function for getting a Cast operation.
+  ///
+  /// \param ops The opcode for the conversion
+  /// \param C  The constant to be converted
+  /// \param Ty The type to which the constant is converted
+  /// \param DL The DataLayout
+  /// \param OnlyIfReduced see \a getWithOperands() docs.
+  static Constant *getCast(unsigned ops, Constant *C, Type *Ty,
+                           const DataLayout &DL, bool OnlyIfReduced = false);
+
   // Create a ZExt or BitCast cast constant expression
   static Constant *
   getZExtOrBitCast(Constant *C, ///< The constant to zext or bitcast
Index: llvm/include/llvm/IR/ConstantFolder.h
===================================================================
--- llvm/include/llvm/IR/ConstantFolder.h
+++ llvm/include/llvm/IR/ConstantFolder.h
@@ -190,6 +190,11 @@
     return ConstantExpr::getCast(Op, C, DestTy);
   }
 
+  Constant *CreateCast(Instruction::CastOps Op, Constant *C, Type *DestTy,
+                       const DataLayout &DL) const override {
+    return ConstantExpr::getCast(Op, C, DestTy, DL);
+  }
+
   Constant *CreatePointerCast(Constant *C, Type *DestTy) const override {
     return ConstantExpr::getPointerCast(C, DestTy);
   }
@@ -212,6 +217,11 @@
     return CreateCast(Instruction::BitCast, C, DestTy);
   }
 
+  Constant *CreateBitCast(Constant *C, Type *DestTy,
+                          const DataLayout &DL) const override {
+    return CreateCast(Instruction::BitCast, C, DestTy, DL);
+  }
+
   Constant *CreateIntToPtr(Constant *C, Type *DestTy) const override {
     return CreateCast(Instruction::IntToPtr, C, DestTy);
   }
Index: llvm/include/llvm/Analysis/TargetFolder.h
===================================================================
--- llvm/include/llvm/Analysis/TargetFolder.h
+++ llvm/include/llvm/Analysis/TargetFolder.h
@@ -179,6 +179,12 @@
       return C; // avoid calling Fold
     return Fold(ConstantExpr::getCast(Op, C, DestTy));
   }
+  Constant *CreateCast(Instruction::CastOps Op, Constant *C, Type *DestTy,
+                       const DataLayout &DL) const override {
+    if (C->getType() == DestTy)
+      return C; // avoid calling Fold
+    return Fold(ConstantExpr::getCast(Op, C, DestTy, DL));
+  }
   Constant *CreateIntCast(Constant *C, Type *DestTy,
                           bool isSigned) const override {
     if (C->getType() == DestTy)
@@ -198,6 +204,10 @@
   Constant *CreateBitCast(Constant *C, Type *DestTy) const override {
     return CreateCast(Instruction::BitCast, C, DestTy);
   }
+  Constant *CreateBitCast(Constant *C, Type *DestTy,
+                          const DataLayout &DL) const override {
+    return CreateCast(Instruction::BitCast, C, DestTy, DL);
+  }
   Constant *CreateIntToPtr(Constant *C, Type *DestTy) const override {
     return CreateCast(Instruction::IntToPtr, C, DestTy);
   }
Index: llvm/docs/LangRef.rst
===================================================================
--- llvm/docs/LangRef.rst
+++ llvm/docs/LangRef.rst
@@ -10993,9 +10993,12 @@
 is always a *no-op cast* because no bits change with this
 conversion. The conversion is done as if the ``value`` had been stored
 to memory and read back as type ``ty2``. Pointer (or vector of
-pointers) types may only be converted to other pointer (or vector of
-pointers) types with the same address space through this instruction.
-To convert pointers to other types, use the :ref:`inttoptr <i_inttoptr>`
+pointers) types can be converted to other pointer (or vector of
+pointers) types in the same address space or different address spaces 
+with this instruction. Conversion of pointers to different address spaces 
+are legal, but may result in undefined behaviour where such a reinterpretation 
+of bits is not supported by the target. To convert pointers to other 
+types, use the :ref:`inttoptr <i_inttoptr>`
 or :ref:`ptrtoint <i_ptrtoint>` instructions first.
 
 There is a caveat for bitcasts involving vector types in relation to
@@ -11012,6 +11015,7 @@
       %Y = bitcast i32* %x to sint*      ; yields sint*:%x
       %Z = bitcast <2 x int> %V to i64;  ; yields i64: %V (depends on endianess)
       %Z = bitcast <2 x i32*> %V to <2 x i64*> ; yields <2 x i64*>
+      %W = bitcast i32* %x to i32 addrspace(1)*    ; yields i32 addrspace(1)*:%w
 
 .. _i_addrspacecast:
 
Index: clang/lib/CodeGen/CGAtomic.cpp
===================================================================
--- clang/lib/CodeGen/CGAtomic.cpp
+++ clang/lib/CodeGen/CGAtomic.cpp
@@ -1517,10 +1517,12 @@
     if (ValTy->isIntegerTy()) {
       assert(IntVal->getType() == ValTy && "Different integer types.");
       return RValue::get(CGF.EmitFromMemory(IntVal, ValueTy));
-    } else if (ValTy->isPointerTy())
+    } else if (ValTy->isPointerTy()) {
       return RValue::get(CGF.Builder.CreateIntToPtr(IntVal, ValTy));
-    else if (llvm::CastInst::isBitCastable(IntVal->getType(), ValTy))
+    } else if (llvm::CastInst::isBitCastable(IntVal->getType(), ValTy,
+                                             CGF.CGM.getDataLayout())) {
       return RValue::get(CGF.Builder.CreateBitCast(IntVal, ValTy));
+    }
   }
 
   // Create a temporary.  This needs to be big enough to hold the
@@ -1705,7 +1707,8 @@
           LVal.isSimple() ? getValueSizeInBits() : getAtomicSizeInBits());
       if (isa<llvm::PointerType>(Value->getType()))
         return CGF.Builder.CreatePtrToInt(Value, InputIntTy);
-      else if (llvm::BitCastInst::isBitCastable(Value->getType(), InputIntTy))
+      else if (llvm::BitCastInst::isBitCastable(Value->getType(), InputIntTy,
+                                                CGF.CGM.getDataLayout()))
         return CGF.Builder.CreateBitCast(Value, InputIntTy);
     }
   }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D114533:... krishna chaitanya sankisa via Phabricator via cfe-commits

Reply via email to