aboutsummaryrefslogtreecommitdiff
path: root/test/Transforms/NaCl/expand-getelementptr.ll
blob: 9f5a4bd8d254cf7e6f2ecf7af0e584bf2eabebc0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
; RUN: opt < %s -expand-getelementptr -S | FileCheck %s

target datalayout = "p:32:32:32"

%MyStruct = type { i8, i32, i8 }
%MyArray = type { [100 x i64] }
%MyArrayOneByte = type { [100 x i8] }


; Test indexing struct field
define i8* @test_struct_field(%MyStruct* %ptr) {
  %addr = getelementptr %MyStruct* %ptr, i32 0, i32 2
  ret i8* %addr
}
; CHECK: @test_struct_field
; CHECK-NEXT: %gep_int = ptrtoint %MyStruct* %ptr to i32
; CHECK-NEXT: %gep = add i32 %gep_int, 8
; CHECK-NEXT: %addr = inttoptr i32 %gep to i8*
; CHECK-NEXT: ret i8* %addr


; Test non-constant index into an array
define i64* @test_array_index(%MyArray* %ptr, i32 %index) {
  %addr = getelementptr %MyArray* %ptr, i32 0, i32 0, i32 %index
  ret i64* %addr
}
; CHECK: @test_array_index
; CHECK-NEXT: %gep_int = ptrtoint %MyArray* %ptr to i32
; CHECK-NEXT: %gep_array = mul i32 %index, 8
; CHECK-NEXT: %gep = add i32 %gep_int, %gep_array
; CHECK-NEXT: %addr = inttoptr i32 %gep to i64*
; CHECK-NEXT: ret i64* %addr


; Test constant index into an array (as a pointer)
define %MyStruct* @test_ptr_add(%MyStruct* %ptr) {
  %addr = getelementptr %MyStruct* %ptr, i32 2
  ret %MyStruct* %addr
}
; CHECK: @test_ptr_add
; CHECK-NEXT: %gep_int = ptrtoint %MyStruct* %ptr to i32
; CHECK-NEXT: %gep = add i32 %gep_int, 24
; CHECK-NEXT: %addr = inttoptr i32 %gep to %MyStruct*
; CHECK-NEXT: ret %MyStruct* %addr


; Test that additions and multiplications are combined properly
define i64* @test_add_and_index(%MyArray* %ptr, i32 %index) {
  %addr = getelementptr %MyArray* %ptr, i32 1, i32 0, i32 %index
  ret i64* %addr
}
; CHECK: @test_add_and_index
; CHECK-NEXT: %gep_int = ptrtoint %MyArray* %ptr to i32
; CHECK-NEXT: %gep = add i32 %gep_int, 800
; CHECK-NEXT: %gep_array = mul i32 %index, 8
; CHECK-NEXT: %gep1 = add i32 %gep, %gep_array
; CHECK-NEXT: %addr = inttoptr i32 %gep1 to i64*
; CHECK-NEXT: ret i64* %addr


; Test that we don't multiply by 1 unnecessarily
define i8* @test_add_and_index_one_byte(%MyArrayOneByte* %ptr, i32 %index) {
  %addr = getelementptr %MyArrayOneByte* %ptr, i32 1, i32 0, i32 %index
  ret i8* %addr
}
; CHECK: @test_add_and_index
; CHECK-NEXT: %gep_int = ptrtoint %MyArrayOneByte* %ptr to i32
; CHECK-NEXT: %gep = add i32 %gep_int, 100
; CHECK-NEXT: %gep1 = add i32 %gep, %index
; CHECK-NEXT: %addr = inttoptr i32 %gep1 to i8*
; CHECK-NEXT: ret i8* %addr


; Test >32-bit array index
define i64* @test_array_index64(%MyArray* %ptr, i64 %index) {
  %addr = getelementptr %MyArray* %ptr, i32 0, i32 0, i64 %index
  ret i64* %addr
}
; CHECK: @test_array_index64
; CHECK-NEXT: %gep_int = ptrtoint %MyArray* %ptr to i32
; CHECK-NEXT: %gep_trunc = trunc i64 %index to i32
; CHECK-NEXT: %gep_array = mul i32 %gep_trunc, 8
; CHECK-NEXT: %gep = add i32 %gep_int, %gep_array
; CHECK-NEXT: %addr = inttoptr i32 %gep to i64*
; CHECK-NEXT: ret i64* %addr


; Test <32-bit array index
define i64* @test_array_index16(%MyArray* %ptr, i16 %index) {
  %addr = getelementptr %MyArray* %ptr, i32 0, i32 0, i16 %index
  ret i64* %addr
}
; CHECK: @test_array_index16
; CHECK-NEXT: %gep_int = ptrtoint %MyArray* %ptr to i32
; CHECK-NEXT: %gep_sext = sext i16 %index to i32
; CHECK-NEXT: %gep_array = mul i32 %gep_sext, 8
; CHECK-NEXT: %gep = add i32 %gep_int, %gep_array
; CHECK-NEXT: %addr = inttoptr i32 %gep to i64*
; CHECK-NEXT: ret i64* %addr


; Test >32-bit constant array index
define i64* @test_array_index64_const(%MyArray* %ptr) {
  %addr = getelementptr %MyArray* %ptr, i32 0, i32 0, i64 100
  ret i64* %addr
}
; CHECK: @test_array_index64_const
; CHECK-NEXT: %gep_int = ptrtoint %MyArray* %ptr to i32
; CHECK-NEXT: %gep = add i32 %gep_int, 800
; CHECK-NEXT: %addr = inttoptr i32 %gep to i64*
; CHECK-NEXT: ret i64* %addr


; Test <32-bit constant array index -- test sign extension
define i64* @test_array_index16_const(%MyArray* %ptr) {
  %addr = getelementptr %MyArray* %ptr, i32 0, i32 0, i16 -100
  ret i64* %addr
}
; CHECK: @test_array_index16_const
; CHECK-NEXT: %gep_int = ptrtoint %MyArray* %ptr to i32
; CHECK-NEXT: %gep = add i32 %gep_int, -800
; CHECK-NEXT: %addr = inttoptr i32 %gep to i64*
; CHECK-NEXT: ret i64* %addr