| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 |
| ; RUN: opt -S -passes=instsimplify < %s | FileCheck %s |
| ;; Check that we do not create new inttoptr instructions for unstable pointers |
| ;; or pointers with external state (even if the values are all constants). |
| ;; NOTE: for all but the zero address space, the GEP should only modify the |
| ;; low 8 bits of the pointer. |
| target datalayout = "p:16:16:16:16-p1:16:16:16:8-pu2:16:16:16:8-pe3:16:16:16:8" |
| |
| define ptr @test_null_base_normal() { |
| ; CHECK-LABEL: define ptr @test_null_base_normal() { |
| ; CHECK-NEXT: ret ptr inttoptr (i16 -2 to ptr) |
| ; |
| %gep = getelementptr i8, ptr null, i8 -2 |
| ret ptr %gep |
| } |
| define ptr @test_inttoptr_base_normal() { |
| ; CHECK-LABEL: define ptr @test_inttoptr_base_normal() { |
| ; CHECK-NEXT: ret ptr null |
| ; |
| %base = inttoptr i16 -1 to ptr |
| %gep = getelementptr i8, ptr %base, i8 1 |
| ret ptr %gep |
| } |
| |
| ;; Transformation is fine for non-integral address space, but we can only change |
| ;; the index bits: (i8 -2 == i16 254) |
| define ptr addrspace(1) @test_null_base_nonintegral() { |
| ; CHECK-LABEL: define ptr addrspace(1) @test_null_base_nonintegral() { |
| ; CHECK-NEXT: ret ptr addrspace(1) inttoptr (i16 254 to ptr addrspace(1)) |
| ; |
| %gep = getelementptr i8, ptr addrspace(1) null, i8 -2 |
| ret ptr addrspace(1) %gep |
| } |
| define ptr addrspace(1) @test_inttoptr_base_nonintegral() { |
| ; CHECK-LABEL: define ptr addrspace(1) @test_inttoptr_base_nonintegral() { |
| ; CHECK-NEXT: ret ptr addrspace(1) inttoptr (i16 -256 to ptr addrspace(1)) |
| ; |
| %base = inttoptr i16 -1 to ptr addrspace(1) |
| %gep = getelementptr i8, ptr addrspace(1) %base, i8 1 |
| ret ptr addrspace(1) %gep |
| } |
| |
| ;; For unstable pointers we should avoid any introduction of inttoptr |
| define ptr addrspace(2) @test_null_base_unstable() { |
| ; CHECK-LABEL: define ptr addrspace(2) @test_null_base_unstable() { |
| ; CHECK-NEXT: ret ptr addrspace(2) getelementptr (i8, ptr addrspace(2) null, i8 -2) |
| ; |
| %gep = getelementptr i8, ptr addrspace(2) null, i8 -2 |
| ret ptr addrspace(2) %gep |
| } |
| define ptr addrspace(2) @test_inttoptr_base_unstable() { |
| ; CHECK-LABEL: define ptr addrspace(2) @test_inttoptr_base_unstable() { |
| ; CHECK-NEXT: ret ptr addrspace(2) getelementptr (i8, ptr addrspace(2) inttoptr (i16 -1 to ptr addrspace(2)), i8 1) |
| ; |
| %base = inttoptr i16 -1 to ptr addrspace(2) |
| %gep = getelementptr i8, ptr addrspace(2) %base, i8 1 |
| ret ptr addrspace(2) %gep |
| } |
| |
| ;; The same is true for pointers with external state: no new inttoptr |
| define ptr addrspace(3) @test_null_base_external() { |
| ; CHECK-LABEL: define ptr addrspace(3) @test_null_base_external() { |
| ; CHECK-NEXT: ret ptr addrspace(3) getelementptr (i8, ptr addrspace(3) null, i8 -2) |
| ; |
| %gep = getelementptr i8, ptr addrspace(3) null, i8 -2 |
| ret ptr addrspace(3) %gep |
| } |
| |
| define ptr addrspace(3) @test_inttoptr_base_external() { |
| ; CHECK-LABEL: define ptr addrspace(3) @test_inttoptr_base_external() { |
| ; CHECK-NEXT: ret ptr addrspace(3) getelementptr (i8, ptr addrspace(3) inttoptr (i16 -1 to ptr addrspace(3)), i8 1) |
| ; |
| %base = inttoptr i16 -1 to ptr addrspace(3) |
| %gep = getelementptr i8, ptr addrspace(3) %base, i8 1 |
| ret ptr addrspace(3) %gep |
| } |
| |
| define <2 x ptr> @test_vec_null_base_normal() { |
| ; CHECK-LABEL: define <2 x ptr> @test_vec_null_base_normal() { |
| ; CHECK-NEXT: ret <2 x ptr> getelementptr (i8, <2 x ptr> zeroinitializer, <2 x i16> <i16 -2, i16 -3>) |
| ; |
| %gep = getelementptr i8, <2 x ptr> <ptr null, ptr null>, <2 x i8> <i8 -2, i8 -3> |
| ret <2 x ptr> %gep |
| } |
| define <2 x ptr> @test_vec_inttoptr_base_normal() { |
| ; CHECK-LABEL: define <2 x ptr> @test_vec_inttoptr_base_normal() { |
| ; CHECK-NEXT: ret <2 x ptr> getelementptr (i8, <2 x ptr> <ptr inttoptr (i16 -1 to ptr), ptr inttoptr (i16 -2 to ptr)>, <2 x i16> <i16 1, i16 2>) |
| ; |
| %base = inttoptr <2 x i16> <i16 -1, i16 -2> to <2 x ptr> |
| %gep = getelementptr i8, <2 x ptr> %base, <2 x i8> <i8 1, i8 2> |
| ret <2 x ptr> %gep |
| } |
| |
| ;; Transformation is fine for non-integral address space, but we can only change |
| ;; the index bits: (i8 -2 == i16 254) |
| define <2 x ptr addrspace(1)> @test_vec_null_base_nonintegral() { |
| ; CHECK-LABEL: define <2 x ptr addrspace(1)> @test_vec_null_base_nonintegral() { |
| ; CHECK-NEXT: ret <2 x ptr addrspace(1)> getelementptr (i8, <2 x ptr addrspace(1)> zeroinitializer, <2 x i8> <i8 -2, i8 -3>) |
| ; |
| %gep = getelementptr i8, <2 x ptr addrspace(1)> <ptr addrspace(1) null, ptr addrspace(1) null>, <2 x i8> <i8 -2, i8 -3> |
| ret <2 x ptr addrspace(1)> %gep |
| } |
| define <2 x ptr addrspace(1)> @test_vec_inttoptr_base_nonintegral() { |
| ; CHECK-LABEL: define <2 x ptr addrspace(1)> @test_vec_inttoptr_base_nonintegral() { |
| ; CHECK-NEXT: ret <2 x ptr addrspace(1)> getelementptr (i8, <2 x ptr addrspace(1)> <ptr addrspace(1) inttoptr (i16 -1 to ptr addrspace(1)), ptr addrspace(1) inttoptr (i16 -2 to ptr addrspace(1))>, <2 x i8> <i8 1, i8 2>) |
| ; |
| %base = inttoptr <2 x i16> <i16 -1, i16 -2> to <2 x ptr addrspace(1)> |
| %gep = getelementptr i8, <2 x ptr addrspace(1)> %base, <2 x i8> <i8 1, i8 2> |
| ret <2 x ptr addrspace(1)> %gep |
| } |
| |
| ;; For unstable pointers we should avoid any introduction of inttoptr |
| define <2 x ptr addrspace(2)> @test_vec_null_base_unstable() { |
| ; CHECK-LABEL: define <2 x ptr addrspace(2)> @test_vec_null_base_unstable() { |
| ; CHECK-NEXT: ret <2 x ptr addrspace(2)> getelementptr (i8, <2 x ptr addrspace(2)> zeroinitializer, <2 x i8> <i8 -2, i8 -3>) |
| ; |
| %gep = getelementptr i8, <2 x ptr addrspace(2)> <ptr addrspace(2) null, ptr addrspace(2) null>, <2 x i8> <i8 -2, i8 -3> |
| ret <2 x ptr addrspace(2)> %gep |
| } |
| define <2 x ptr addrspace(2)> @test_vec_inttoptr_base_unstable() { |
| ; CHECK-LABEL: define <2 x ptr addrspace(2)> @test_vec_inttoptr_base_unstable() { |
| ; CHECK-NEXT: ret <2 x ptr addrspace(2)> getelementptr (i8, <2 x ptr addrspace(2)> <ptr addrspace(2) inttoptr (i16 -1 to ptr addrspace(2)), ptr addrspace(2) inttoptr (i16 -2 to ptr addrspace(2))>, <2 x i8> <i8 1, i8 2>) |
| ; |
| %base = inttoptr <2 x i16> <i16 -1, i16 -2> to <2 x ptr addrspace(2)> |
| %gep = getelementptr i8, <2 x ptr addrspace(2)> %base, <2 x i8> <i8 1, i8 2> |
| ret <2 x ptr addrspace(2)> %gep |
| } |
| |
| ;; The same is true for pointers with external state: no new inttoptr |
| define <2 x ptr addrspace(3)> @test_vec_null_base_external() { |
| ; CHECK-LABEL: define <2 x ptr addrspace(3)> @test_vec_null_base_external() { |
| ; CHECK-NEXT: ret <2 x ptr addrspace(3)> getelementptr (i8, <2 x ptr addrspace(3)> zeroinitializer, <2 x i8> <i8 -2, i8 -3>) |
| ; |
| %gep = getelementptr i8, <2 x ptr addrspace(3)> <ptr addrspace(3) null, ptr addrspace(3) null>, <2 x i8> <i8 -2, i8 -3> |
| ret <2 x ptr addrspace(3)> %gep |
| } |
| |
| define <2 x ptr addrspace(3)> @test_vec_inttoptr_base_external() { |
| ; CHECK-LABEL: define <2 x ptr addrspace(3)> @test_vec_inttoptr_base_external() { |
| ; CHECK-NEXT: ret <2 x ptr addrspace(3)> getelementptr (i8, <2 x ptr addrspace(3)> <ptr addrspace(3) inttoptr (i16 -1 to ptr addrspace(3)), ptr addrspace(3) inttoptr (i16 -2 to ptr addrspace(3))>, <2 x i8> <i8 1, i8 2>) |
| ; |
| %base = inttoptr <2 x i16> <i16 -1, i16 -2> to <2 x ptr addrspace(3)> |
| %gep = getelementptr i8, <2 x ptr addrspace(3)> %base, <2 x i8> <i8 1, i8 2> |
| ret <2 x ptr addrspace(3)> %gep |
| } |