204 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -passes=aggressive-instcombine -S -data-layout="e" | FileCheck %s --check-prefixes=CHECK,LE3; RUN: opt < %s -passes=aggressive-instcombine -S -data-layout="E" | FileCheck %s --check-prefixes=CHECK,BE4 5 6@constarray1 = internal constant [8 x i8] c"\01\00\01\00\01\00\01\00", align 47@constarray2 = internal constant [8 x i8] c"\FF\FF\01\00\01\00\01\00", align 48 9@g = internal constant i32 4210@constptrarray = internal constant [4 x ptr] [ptr @g, ptr @g, ptr @g, ptr @g], align 411 12@constpackedstruct = internal constant <{[8 x i8]}> <{[8 x i8] c"\01\00\01\00\01\00\01\00"}>, align 413@conststruct = internal constant {i16, [8 x i8]} {i16 1, [8 x i8] c"\01\00\01\00\01\00\01\00"}, align 414 15%struct = type { i128 }16@global = internal constant %struct { i128 1 }17; TODO: this should be folded, but currently i128 is not folded.18define i32 @no-gep-128-struct(i64 %idx){19; CHECK-LABEL: @no-gep-128-struct(20; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr @global, align 421; CHECK-NEXT: ret i32 [[TMP1]]22;23 %1 = load i32, ptr @global, align 424 ret i32 %125}26 27define i8 @inbounds_gep_load_i8_align2(i64 %idx){28; CHECK-LABEL: @inbounds_gep_load_i8_align2(29; CHECK-NEXT: ret i8 130;31 %1 = getelementptr inbounds i8, ptr @constarray1, i64 %idx32 %2 = load i8, ptr %1, align 233 ret i8 %234}35 36; can't be folded because access with i8 strides is not patterned.37define 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 141; CHECK-NEXT: ret i8 [[TMP2]]42;43 %1 = getelementptr inbounds i8, ptr @constarray1, i64 %idx44 %2 = load i8, ptr %1, align 145 ret i8 %246}47 48; can't be folded because volatile load cannot assure same results.49define 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 253; CHECK-NEXT: ret i8 [[TMP2]]54;55 %1 = getelementptr inbounds i8, ptr @constarray1, i64 %idx56 %2 = load volatile i8, ptr %1, align 257 ret i8 %258}59 60declare ptr @llvm.ptrmask.p0.i64(ptr , i64)61 62; can't be folded because ptrmask can change ptr, while preserving provenance63; This invalidates GEP indices analysis64define 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 169; CHECK-NEXT: ret i8 [[TMP3]]70;71 %1 = call ptr @llvm.ptrmask.p0.i64(ptr @constarray1, i64 %mask)72 %2 = getelementptr inbounds i16, ptr %1, i64 %idx73 %3 = load i8, ptr %2, align 174 ret i8 %375}76 77define i32 @inbounds_gep_i16_load_i32_align1(i64 %idx){78; LE-LABEL: @inbounds_gep_i16_load_i32_align1(79; LE-NEXT: ret i32 6553780;81; BE-LABEL: @inbounds_gep_i16_load_i32_align1(82; BE-NEXT: ret i32 1677747283;84 %1 = getelementptr inbounds i16, ptr @constarray1, i64 %idx85 %2 = load i32, ptr %1, align 186 ret i32 %287}88 89define i32 @inbounds_gep_i32_load_i32_align8(i64 %idx){90; LE-LABEL: @inbounds_gep_i32_load_i32_align8(91; LE-NEXT: ret i32 6553792;93; BE-LABEL: @inbounds_gep_i32_load_i32_align8(94; BE-NEXT: ret i32 1677747295;96 %1 = getelementptr inbounds i32, ptr @constarray1, i64 %idx97 %2 = load i32, ptr %1, align 898 ret i32 %299}100 101define 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 65537104;105; BE-LABEL: @inbounds_gep_i32_load_i32_const_offset(106; BE-NEXT: ret i32 16777472107;108 %1 = getelementptr inbounds i16, ptr @constarray2, i64 1109 %2 = getelementptr inbounds i32, ptr %1, i64 %idx110 %3 = load i32, ptr %2, align 4111 ret i32 %3112}113 114define i32 @gep_load_i32_align2_const_offset(i64 %idx){115; LE-LABEL: @gep_load_i32_align2_const_offset(116; LE-NEXT: ret i32 65537117;118; BE-LABEL: @gep_load_i32_align2_const_offset(119; BE-NEXT: ret i32 16777472120;121 %1 = getelementptr i16, ptr @constarray1, i64 -2122 %2 = getelementptr [3 x i16], ptr %1, i64 %idx123 %3 = load i32, ptr %2, align 2124 ret i32 %3125}126 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.130define 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 -2133; CHECK-NEXT: [[TMP2:%.*]] = getelementptr [3 x i16], ptr [[TMP1]], i64 [[IDX:%.*]]134; CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[TMP2]], align 2135; CHECK-NEXT: ret i32 [[TMP3]]136;137 %1 = getelementptr i16, ptr @constarray2, i64 -2138 %2 = getelementptr [3 x i16], ptr %1, i64 %idx139 %3 = load i32, ptr %2, align 2140 ret i32 %3141}142 143define i32 @gep_load_i32_align2_const_offset_nusw(i64 %idx){144; LE-LABEL: @gep_load_i32_align2_const_offset_nusw(145; LE-NEXT: ret i32 65537146;147; BE-LABEL: @gep_load_i32_align2_const_offset_nusw(148; BE-NEXT: ret i32 16777472149;150 %1 = getelementptr nusw i16, ptr @constarray2, i64 -2151 %2 = getelementptr nusw [3 x i16], ptr %1, i64 %idx152 %3 = load i32, ptr %2, align 2153 ret i32 %3154}155 156 157define i32 @inbounds_gep_i32_load_i32_const_ptr_array(i64 %idx){158; CHECK-LABEL: @inbounds_gep_i32_load_i32_const_ptr_array(159; CHECK-NEXT: ret i32 42160;161 %1 = getelementptr inbounds ptr, ptr @constptrarray, i64 %idx162 %2 = load ptr, ptr %1, align 4163 %3 = load i32, ptr %2, align 4164 ret i32 %3165}166 167define i32 @inbounds_gep_i32_load_i32_align4_packedstruct(i64 %idx){168; LE-LABEL: @inbounds_gep_i32_load_i32_align4_packedstruct(169; LE-NEXT: ret i32 65537170;171; BE-LABEL: @inbounds_gep_i32_load_i32_align4_packedstruct(172; BE-NEXT: ret i32 16777472173;174 %1 = getelementptr inbounds i32, ptr @constpackedstruct, i64 %idx175 %2 = load i32, ptr %1, align 4176 ret i32 %2177}178 179; can't be folded because results are not equal180define i32 @inbounds_gep_i8_load_i32_align1_packedstruct(i64 %idx){181; CHECK-LABEL: @inbounds_gep_i8_load_i32_align1_packedstruct(182; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr @constpackedstruct, i64 [[IDX:%.*]]183; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[TMP1]], align 1184; CHECK-NEXT: ret i32 [[TMP2]]185;186 %1 = getelementptr inbounds i8, ptr @constpackedstruct, i64 %idx187 %2 = load i32, ptr %1, align 1188 ret i32 %2189}190 191define i32 @inbounds_gep_i32_load_i32_align4_struct_with_const_offset(i64 %idx){192; LE-LABEL: @inbounds_gep_i32_load_i32_align4_struct_with_const_offset(193; LE-NEXT: ret i32 65537194;195; BE-LABEL: @inbounds_gep_i32_load_i32_align4_struct_with_const_offset(196; BE-NEXT: ret i32 16777472197;198 %1 = getelementptr inbounds i16, ptr @conststruct, i64 1199 %2 = getelementptr inbounds i32, ptr %1, i64 %idx200 %3 = load i32, ptr %2, align 4201 ret i32 %3202}203 204