constant-fold-address-space-pointer.ll 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. ; RUN: opt -S -instcombine %s -o - | FileCheck %s
  2. target datalayout = "e-p:32:32:32-p1:64:64:64-p2:8:8:8-p3:16:16:16-p4:16:16:16-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:32"
  3. @g = addrspace(3) global i32 89
  4. @const_zero_i8_as1 = addrspace(1) constant i8 0
  5. @const_zero_i32_as1 = addrspace(1) constant i32 0
  6. @const_zero_i8_as2 = addrspace(2) constant i8 0
  7. @const_zero_i32_as2 = addrspace(2) constant i32 0
  8. @const_zero_i8_as3 = addrspace(3) constant i8 0
  9. @const_zero_i32_as3 = addrspace(3) constant i32 0
  10. ; Test constant folding of inttoptr (ptrtoint constantexpr)
  11. ; The intermediate integer size is the same as the pointer size
  12. define i32 addrspace(3)* @test_constant_fold_inttoptr_as_pointer_same_size() {
  13. ; CHECK-LABEL: @test_constant_fold_inttoptr_as_pointer_same_size(
  14. ; CHECK-NEXT: ret i32 addrspace(3)* @const_zero_i32_as3
  15. %x = ptrtoint i32 addrspace(3)* @const_zero_i32_as3 to i32
  16. %y = inttoptr i32 %x to i32 addrspace(3)*
  17. ret i32 addrspace(3)* %y
  18. }
  19. ; The intermediate integer size is larger than the pointer size
  20. define i32 addrspace(2)* @test_constant_fold_inttoptr_as_pointer_smaller() {
  21. ; CHECK-LABEL: @test_constant_fold_inttoptr_as_pointer_smaller(
  22. ; CHECK-NEXT: ret i32 addrspace(2)* @const_zero_i32_as2
  23. %x = ptrtoint i32 addrspace(2)* @const_zero_i32_as2 to i16
  24. %y = inttoptr i16 %x to i32 addrspace(2)*
  25. ret i32 addrspace(2)* %y
  26. }
  27. ; Different address spaces that are the same size, but they are
  28. ; different so nothing should happen
  29. define i32 addrspace(4)* @test_constant_fold_inttoptr_as_pointer_smaller_different_as() {
  30. ; CHECK-LABEL: @test_constant_fold_inttoptr_as_pointer_smaller_different_as(
  31. ; CHECK-NEXT: ret i32 addrspace(4)* inttoptr (i16 ptrtoint (i32 addrspace(3)* @const_zero_i32_as3 to i16) to i32 addrspace(4)*)
  32. %x = ptrtoint i32 addrspace(3)* @const_zero_i32_as3 to i16
  33. %y = inttoptr i16 %x to i32 addrspace(4)*
  34. ret i32 addrspace(4)* %y
  35. }
  36. ; Make sure we don't introduce a bitcast between different sized
  37. ; address spaces when folding this
  38. define i32 addrspace(2)* @test_constant_fold_inttoptr_as_pointer_smaller_different_size_as() {
  39. ; CHECK-LABEL: @test_constant_fold_inttoptr_as_pointer_smaller_different_size_as(
  40. ; CHECK-NEXT: ret i32 addrspace(2)* inttoptr (i32 ptrtoint (i32 addrspace(3)* @const_zero_i32_as3 to i32) to i32 addrspace(2)*)
  41. %x = ptrtoint i32 addrspace(3)* @const_zero_i32_as3 to i32
  42. %y = inttoptr i32 %x to i32 addrspace(2)*
  43. ret i32 addrspace(2)* %y
  44. }
  45. ; The intermediate integer size is too small, nothing should happen
  46. define i32 addrspace(3)* @test_constant_fold_inttoptr_as_pointer_larger() {
  47. ; CHECK-LABEL: @test_constant_fold_inttoptr_as_pointer_larger(
  48. ; CHECK-NEXT: ret i32 addrspace(3)* inttoptr (i8 ptrtoint (i32 addrspace(3)* @const_zero_i32_as3 to i8) to i32 addrspace(3)*)
  49. %x = ptrtoint i32 addrspace(3)* @const_zero_i32_as3 to i8
  50. %y = inttoptr i8 %x to i32 addrspace(3)*
  51. ret i32 addrspace(3)* %y
  52. }
  53. define i8 @const_fold_ptrtoint() {
  54. ; CHECK-LABEL: @const_fold_ptrtoint(
  55. ; CHECK-NEXT: ret i8 4
  56. ret i8 ptrtoint (i32 addrspace(2)* inttoptr (i4 4 to i32 addrspace(2)*) to i8)
  57. }
  58. ; Test that mask happens when the destination pointer is smaller than
  59. ; the original
  60. define i8 @const_fold_ptrtoint_mask() {
  61. ; CHECK-LABEL: @const_fold_ptrtoint_mask(
  62. ; CHECK-NEXT: ret i8 1
  63. ret i8 ptrtoint (i32 addrspace(3)* inttoptr (i32 257 to i32 addrspace(3)*) to i8)
  64. }
  65. ; Address space 0 is too small for the correct mask, should mask with
  66. ; 64-bits instead of 32
  67. define i64 @const_fold_ptrtoint_mask_small_as0() {
  68. ; CHECK-LABEL: @const_fold_ptrtoint_mask_small_as0(
  69. ; CHECK: ret i64 -1
  70. ret i64 ptrtoint (i32 addrspace(1)* inttoptr (i128 -1 to i32 addrspace(1)*) to i64)
  71. }
  72. define i32 addrspace(3)* @const_inttoptr() {
  73. ; CHECK-LABEL: @const_inttoptr(
  74. ; CHECK-NEXT: ret i32 addrspace(3)* inttoptr (i16 4 to i32 addrspace(3)*)
  75. %p = inttoptr i16 4 to i32 addrspace(3)*
  76. ret i32 addrspace(3)* %p
  77. }
  78. define i16 @const_ptrtoint() {
  79. ; CHECK-LABEL: @const_ptrtoint(
  80. ; CHECK-NEXT: ret i16 ptrtoint (i32 addrspace(3)* @g to i16)
  81. %i = ptrtoint i32 addrspace(3)* @g to i16
  82. ret i16 %i
  83. }
  84. define i16 @const_inttoptr_ptrtoint() {
  85. ; CHECK-LABEL: @const_inttoptr_ptrtoint(
  86. ; CHECK-NEXT: ret i16 9
  87. ret i16 ptrtoint (i32 addrspace(3)* inttoptr (i16 9 to i32 addrspace(3)*) to i16)
  88. }
  89. define i1 @constant_fold_cmp_constantexpr_inttoptr() {
  90. ; CHECK-LABEL: @constant_fold_cmp_constantexpr_inttoptr(
  91. ; CHECK-NEXT: ret i1 true
  92. %x = icmp eq i32 addrspace(3)* inttoptr (i16 0 to i32 addrspace(3)*), null
  93. ret i1 %x
  94. }
  95. define i1 @constant_fold_inttoptr_null(i16 %i) {
  96. ; CHECK-LABEL: @constant_fold_inttoptr_null(
  97. ; CHECK-NEXT: ret i1 false
  98. %x = icmp eq i32 addrspace(3)* inttoptr (i16 99 to i32 addrspace(3)*), inttoptr (i16 0 to i32 addrspace(3)*)
  99. ret i1 %x
  100. }
  101. define i1 @constant_fold_ptrtoint_null() {
  102. ; CHECK-LABEL: @constant_fold_ptrtoint_null(
  103. ; CHECK-NEXT: ret i1 false
  104. %x = icmp eq i16 ptrtoint (i32 addrspace(3)* @g to i16), ptrtoint (i32 addrspace(3)* null to i16)
  105. ret i1 %x
  106. }
  107. define i1 @constant_fold_ptrtoint_null_2() {
  108. ; CHECK-LABEL: @constant_fold_ptrtoint_null_2(
  109. ; CHECK-NEXT: ret i1 false
  110. %x = icmp eq i16 ptrtoint (i32 addrspace(3)* null to i16), ptrtoint (i32 addrspace(3)* @g to i16)
  111. ret i1 %x
  112. }
  113. define i1 @constant_fold_ptrtoint() {
  114. ; CHECK-LABEL: @constant_fold_ptrtoint(
  115. ; CHECK-NEXT: ret i1 true
  116. %x = icmp eq i16 ptrtoint (i32 addrspace(3)* @g to i16), ptrtoint (i32 addrspace(3)* @g to i16)
  117. ret i1 %x
  118. }
  119. define i1 @constant_fold_inttoptr() {
  120. ; CHECK-LABEL: @constant_fold_inttoptr(
  121. ; CHECK-NEXT: ret i1 false
  122. %x = icmp eq i32 addrspace(3)* inttoptr (i16 99 to i32 addrspace(3)*), inttoptr (i16 27 to i32 addrspace(3)*)
  123. ret i1 %x
  124. }
  125. @g_float_as3 = addrspace(3) global float zeroinitializer
  126. @g_v4f_as3 = addrspace(3) global <4 x float> zeroinitializer
  127. define float @constant_fold_bitcast_ftoi_load() {
  128. ; CHECK-LABEL: @constant_fold_bitcast_ftoi_load(
  129. ; CHECK: load float, float addrspace(3)* bitcast (i32 addrspace(3)* @g to float addrspace(3)*), align 4
  130. %a = load float, float addrspace(3)* bitcast (i32 addrspace(3)* @g to float addrspace(3)*), align 4
  131. ret float %a
  132. }
  133. define i32 @constant_fold_bitcast_itof_load() {
  134. ; CHECK-LABEL: @constant_fold_bitcast_itof_load(
  135. ; CHECK: load i32, i32 addrspace(3)* bitcast (float addrspace(3)* @g_float_as3 to i32 addrspace(3)*), align 4
  136. %a = load i32, i32 addrspace(3)* bitcast (float addrspace(3)* @g_float_as3 to i32 addrspace(3)*), align 4
  137. ret i32 %a
  138. }
  139. define <4 x float> @constant_fold_bitcast_vector_as() {
  140. ; CHECK-LABEL: @constant_fold_bitcast_vector_as(
  141. ; CHECK: load <4 x float>, <4 x float> addrspace(3)* @g_v4f_as3, align 16
  142. %a = load <4 x float>, <4 x float> addrspace(3)* bitcast (<4 x i32> addrspace(3)* bitcast (<4 x float> addrspace(3)* @g_v4f_as3 to <4 x i32> addrspace(3)*) to <4 x float> addrspace(3)*), align 4
  143. ret <4 x float> %a
  144. }
  145. @i32_array_as3 = addrspace(3) global [10 x i32] zeroinitializer
  146. define i32 @test_cast_gep_small_indices_as() {
  147. ; CHECK-LABEL: @test_cast_gep_small_indices_as(
  148. ; CHECK: load i32, i32 addrspace(3)* getelementptr inbounds ([10 x i32], [10 x i32] addrspace(3)* @i32_array_as3, i16 0, i16 0), align 16
  149. %p = getelementptr [10 x i32], [10 x i32] addrspace(3)* @i32_array_as3, i7 0, i7 0
  150. %x = load i32, i32 addrspace(3)* %p, align 4
  151. ret i32 %x
  152. }
  153. %struct.foo = type { float, float, [4 x i32], i32 addrspace(3)* }
  154. @constant_fold_global_ptr = addrspace(3) global %struct.foo {
  155. float 0.0,
  156. float 0.0,
  157. [4 x i32] zeroinitializer,
  158. i32 addrspace(3)* getelementptr ([10 x i32], [10 x i32] addrspace(3)* @i32_array_as3, i64 0, i64 0)
  159. }
  160. define i32 @test_cast_gep_large_indices_as() {
  161. ; CHECK-LABEL: @test_cast_gep_large_indices_as(
  162. ; CHECK: load i32, i32 addrspace(3)* getelementptr inbounds ([10 x i32], [10 x i32] addrspace(3)* @i32_array_as3, i16 0, i16 0), align 16
  163. %p = getelementptr [10 x i32], [10 x i32] addrspace(3)* @i32_array_as3, i64 0, i64 0
  164. %x = load i32, i32 addrspace(3)* %p, align 4
  165. ret i32 %x
  166. }
  167. define i32 @test_constant_cast_gep_struct_indices_as() {
  168. ; CHECK-LABEL: @test_constant_cast_gep_struct_indices_as(
  169. ; CHECK: load i32, i32 addrspace(3)* getelementptr inbounds (%struct.foo, %struct.foo addrspace(3)* @constant_fold_global_ptr, i16 0, i32 2, i16 2), align 8
  170. %x = getelementptr %struct.foo, %struct.foo addrspace(3)* @constant_fold_global_ptr, i18 0, i32 2, i12 2
  171. %y = load i32, i32 addrspace(3)* %x, align 4
  172. ret i32 %y
  173. }
  174. @constant_data_as3 = addrspace(3) constant [5 x i32] [i32 1, i32 2, i32 3, i32 4, i32 5]
  175. define i32 @test_read_data_from_global_as3() {
  176. ; CHECK-LABEL: @test_read_data_from_global_as3(
  177. ; CHECK-NEXT: ret i32 2
  178. %x = getelementptr [5 x i32], [5 x i32] addrspace(3)* @constant_data_as3, i32 0, i32 1
  179. %y = load i32, i32 addrspace(3)* %x, align 4
  180. ret i32 %y
  181. }
  182. @a = addrspace(1) constant i32 9
  183. @b = addrspace(1) constant i32 23
  184. @c = addrspace(1) constant i32 34
  185. @d = addrspace(1) constant i32 99
  186. @ptr_array = addrspace(2) constant [4 x i32 addrspace(1)*] [ i32 addrspace(1)* @a, i32 addrspace(1)* @b, i32 addrspace(1)* @c, i32 addrspace(1)* @d]
  187. @indirect = addrspace(0) constant i32 addrspace(1)* addrspace(2)* getelementptr inbounds ([4 x i32 addrspace(1)*], [4 x i32 addrspace(1)*] addrspace(2)* @ptr_array, i1 0, i32 2)
  188. define i32 @constant_through_array_as_ptrs() {
  189. ; CHECK-LABEL: @constant_through_array_as_ptrs(
  190. ; CHECK-NEXT: ret i32 34
  191. %p = load i32 addrspace(1)* addrspace(2)*, i32 addrspace(1)* addrspace(2)* addrspace(0)* @indirect, align 4
  192. %a = load i32 addrspace(1)*, i32 addrspace(1)* addrspace(2)* %p, align 4
  193. %b = load i32, i32 addrspace(1)* %a, align 4
  194. ret i32 %b
  195. }
  196. @shared_mem = external addrspace(3) global [0 x i8]
  197. define float @canonicalize_addrspacecast(i32 %i) {
  198. ; CHECK-LABEL: @canonicalize_addrspacecast
  199. ; CHECK-NEXT: getelementptr inbounds float, float* addrspacecast (float addrspace(3)* bitcast ([0 x i8] addrspace(3)* @shared_mem to float addrspace(3)*) to float*), i32 %i
  200. %p = getelementptr inbounds float, float* addrspacecast ([0 x i8] addrspace(3)* @shared_mem to float*), i32 %i
  201. %v = load float, float* %p
  202. ret float %v
  203. }