Bump version to 19.1.0-rc3
[llvm-project.git] / llvm / test / Transforms / AggressiveInstCombine / patterned-load.ll
blobe43dad2ca08937960a19bf982f3099e0f5c55308
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes=aggressive-instcombine -S -data-layout="e" | FileCheck %s --check-prefixes=CHECK,LE
3 ; RUN: opt < %s -passes=aggressive-instcombine -S -data-layout="E" | FileCheck %s --check-prefixes=CHECK,BE
6 @constarray1 = internal constant [8 x i8]  c"\01\00\01\00\01\00\01\00", align 4
7 @constarray2 = internal constant [8 x i8]  c"\FF\FF\01\00\01\00\01\00", align 4
9 @g = internal constant i32 42
10 @constptrarray = internal constant [4 x ptr]  [ptr @g, ptr @g, ptr @g, ptr @g], align 4
12 @constpackedstruct = internal constant <{[8 x i8]}>  <{[8 x i8] c"\01\00\01\00\01\00\01\00"}>, align 4
13 @conststruct = internal constant {i16, [8 x i8]}  {i16 1, [8 x i8] c"\01\00\01\00\01\00\01\00"}, align 4
15 %struct = type { i128 }
16 @global = internal constant %struct { i128 1 }
17 ; TODO: this should be folded, but currently i128 is not folded.
18 define i32 @no-gep-128-struct(i64 %idx){
19 ; CHECK-LABEL: @no-gep-128-struct(
20 ; CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr @global, align 4
21 ; CHECK-NEXT:    ret i32 [[TMP1]]
23   %1 = load i32, ptr @global, align 4
24   ret i32 %1
27 define i8 @inbounds_gep_load_i8_align2(i64 %idx){
28 ; CHECK-LABEL: @inbounds_gep_load_i8_align2(
29 ; CHECK-NEXT:    ret i8 1
31   %1 = getelementptr inbounds i8, ptr @constarray1, i64 %idx
32   %2 = load i8, ptr %1, align 2
33   ret i8 %2
36 ; can't be folded because access with i8 strides is not patterned.
37 define i8 @inbounds_gep_load_i8_align1(i64 %idx){
38 ; CHECK-LABEL: @inbounds_gep_load_i8_align1(
39 ; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds i8, ptr @constarray1, i64 [[IDX:%.*]]
40 ; CHECK-NEXT:    [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 1
41 ; CHECK-NEXT:    ret i8 [[TMP2]]
43   %1 = getelementptr inbounds i8, ptr @constarray1, i64 %idx
44   %2 = load i8, ptr %1, align 1
45   ret i8 %2
48 ; can't be folded because volatile load cannot assure same results.
49 define i8 @inbounds_gep_load_i8_align2_volatile(i64 %idx){
50 ; CHECK-LABEL: @inbounds_gep_load_i8_align2_volatile(
51 ; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds i8, ptr @constarray1, i64 [[IDX:%.*]]
52 ; CHECK-NEXT:    [[TMP2:%.*]] = load volatile i8, ptr [[TMP1]], align 2
53 ; CHECK-NEXT:    ret i8 [[TMP2]]
55   %1 = getelementptr inbounds i8, ptr @constarray1, i64 %idx
56   %2 = load volatile i8, ptr %1, align 2
57   ret i8 %2
60 declare ptr @llvm.ptrmask.p0.i64(ptr , i64)
62 ; can't be folded because ptrmask can change ptr, while preserving provenance
63 ; This invalidates GEP indices analysis
64 define i8 @inbounds_gep_load_i16_align1_ptrmasked(i64 %idx, i64 %mask){
65 ; CHECK-LABEL: @inbounds_gep_load_i16_align1_ptrmasked(
66 ; CHECK-NEXT:    [[TMP1:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr @constarray1, i64 [[MASK:%.*]])
67 ; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr inbounds i16, ptr [[TMP1]], i64 [[IDX:%.*]]
68 ; CHECK-NEXT:    [[TMP3:%.*]] = load i8, ptr [[TMP2]], align 1
69 ; CHECK-NEXT:    ret i8 [[TMP3]]
71   %1 = call ptr @llvm.ptrmask.p0.i64(ptr @constarray1, i64 %mask)
72   %2 = getelementptr inbounds i16, ptr %1, i64 %idx
73   %3 = load i8, ptr %2, align 1
74   ret i8 %3
77 define i32 @inbounds_gep_i16_load_i32_align1(i64 %idx){
78 ; LE-LABEL: @inbounds_gep_i16_load_i32_align1(
79 ; LE-NEXT:    ret i32 65537
81 ; BE-LABEL: @inbounds_gep_i16_load_i32_align1(
82 ; BE-NEXT:    ret i32 16777472
84   %1 = getelementptr inbounds i16, ptr @constarray1, i64 %idx
85   %2 = load i32, ptr %1, align 1
86   ret i32 %2
89 define i32 @inbounds_gep_i32_load_i32_align8(i64 %idx){
90 ; LE-LABEL: @inbounds_gep_i32_load_i32_align8(
91 ; LE-NEXT:    ret i32 65537
93 ; BE-LABEL: @inbounds_gep_i32_load_i32_align8(
94 ; BE-NEXT:    ret i32 16777472
96   %1 = getelementptr inbounds i32, ptr @constarray1, i64 %idx
97   %2 = load i32, ptr %1, align 8
98   ret i32 %2
101 define i32 @inbounds_gep_i32_load_i32_const_offset(i64 %idx){
102 ; LE-LABEL: @inbounds_gep_i32_load_i32_const_offset(
103 ; LE-NEXT:    ret i32 65537
105 ; BE-LABEL: @inbounds_gep_i32_load_i32_const_offset(
106 ; BE-NEXT:    ret i32 16777472
108   %1 = getelementptr inbounds i16, ptr @constarray2, i64 1
109   %2 = getelementptr inbounds i32, ptr %1, i64 %idx
110   %3 = load i32, ptr %2, align 4
111   ret i32 %3
114 define i32 @gep_load_i32_align2_const_offset(i64 %idx){
115 ; LE-LABEL: @gep_load_i32_align2_const_offset(
116 ; LE-NEXT:    ret i32 65537
118 ; BE-LABEL: @gep_load_i32_align2_const_offset(
119 ; BE-NEXT:    ret i32 16777472
121   %1 = getelementptr i16, ptr @constarray1, i64 -2
122   %2 = getelementptr [3 x i16], ptr %1, i64 %idx
123   %3 = load i32, ptr %2, align 2
124   ret i32 %3
127 ; can't be folded because if gep is non-inbounds,
128 ; the offsets are silently-wrapped with two’s complement arithmetic(mod 2**64).
129 ; So the load operand can be a base pointer of constarray2.
130 define i32 @gep_load_i32_align2_const_offset_wrap(i64 %idx){
131 ; CHECK-LABEL: @gep_load_i32_align2_const_offset_wrap(
132 ; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr i16, ptr @constarray2, i64 -2
133 ; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr [3 x i16], ptr [[TMP1]], i64 [[IDX:%.*]]
134 ; CHECK-NEXT:    [[TMP3:%.*]] = load i32, ptr [[TMP2]], align 2
135 ; CHECK-NEXT:    ret i32 [[TMP3]]
137   %1 = getelementptr i16, ptr @constarray2, i64 -2
138   %2 = getelementptr [3 x i16], ptr %1, i64 %idx
139   %3 = load i32, ptr %2, align 2
140   ret i32 %3
143 define i32 @inbounds_gep_i32_load_i32_const_ptr_array(i64 %idx){
144 ; CHECK-LABEL: @inbounds_gep_i32_load_i32_const_ptr_array(
145 ; CHECK-NEXT:    ret i32 42
147   %1 = getelementptr inbounds ptr, ptr @constptrarray, i64 %idx
148   %2 = load ptr, ptr %1, align 4
149   %3 = load i32, ptr %2, align 4
150   ret i32 %3
153 define i32 @inbounds_gep_i32_load_i32_align4_packedstruct(i64 %idx){
154 ; LE-LABEL: @inbounds_gep_i32_load_i32_align4_packedstruct(
155 ; LE-NEXT:    ret i32 65537
157 ; BE-LABEL: @inbounds_gep_i32_load_i32_align4_packedstruct(
158 ; BE-NEXT:    ret i32 16777472
160   %1 = getelementptr inbounds i32, ptr @constpackedstruct, i64 %idx
161   %2 = load i32, ptr %1, align 4
162   ret i32 %2
165 ; can't be folded because results are not equal
166 define i32 @inbounds_gep_i8_load_i32_align1_packedstruct(i64 %idx){
167 ; CHECK-LABEL: @inbounds_gep_i8_load_i32_align1_packedstruct(
168 ; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds i8, ptr @constpackedstruct, i64 [[IDX:%.*]]
169 ; CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr [[TMP1]], align 1
170 ; CHECK-NEXT:    ret i32 [[TMP2]]
172   %1 = getelementptr inbounds i8, ptr @constpackedstruct, i64 %idx
173   %2 = load i32, ptr %1, align 1
174   ret i32 %2
177 define i32 @inbounds_gep_i32_load_i32_align4_struct_with_const_offset(i64 %idx){
178 ; LE-LABEL: @inbounds_gep_i32_load_i32_align4_struct_with_const_offset(
179 ; LE-NEXT:    ret i32 65537
181 ; BE-LABEL: @inbounds_gep_i32_load_i32_align4_struct_with_const_offset(
182 ; BE-NEXT:    ret i32 16777472
184   %1 = getelementptr inbounds i16, ptr @conststruct, i64 1
185   %2 = getelementptr inbounds i32, ptr %1, i64 %idx
186   %3 = load i32, ptr %2, align 4
187   ret i32 %3