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