brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.4 KiB · ecebaa7 Raw
211 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -passes=instcombine -S | FileCheck %s3 4; Test merging GEP of GEP with constant indices.5 6target datalayout = "i24:8:8"7 8%struct.A = type { [123 x i8], i32 }9%struct.B = type { i8, [3 x i16], %struct.A, float }10%struct.C = type { i8, i32, i32 }11 12; result = (ptr) p + 313define ptr @mergeBasic(ptr %p) {14; CHECK-LABEL: @mergeBasic(15; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds nuw i8, ptr [[P:%.*]], i64 1216; CHECK-NEXT:    ret ptr [[TMP1]]17;18  %1 = getelementptr inbounds i32, ptr %p, i64 119  %2 = getelementptr inbounds i32, ptr %1, i64 220  ret ptr %221}22 23; Converted to ptr and merged.24; result = (ptr) p + 1025define ptr @mergeDifferentTypes(ptr %p) {26; CHECK-LABEL: @mergeDifferentTypes(27; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds nuw i8, ptr [[P:%.*]], i64 1028; CHECK-NEXT:    ret ptr [[TMP1]]29;30  %1 = getelementptr inbounds i8, ptr %p, i64 231  %2 = getelementptr inbounds i64, ptr %1, i64 132  ret ptr %233}34 35; Converted to ptr and merged.36; result = (ptr) p + 1037define ptr @mergeReverse(ptr %p) {38; CHECK-LABEL: @mergeReverse(39; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds nuw i8, ptr [[P:%.*]], i64 1040; CHECK-NEXT:    ret ptr [[TMP1]]41;42  %1 = getelementptr inbounds i64, ptr %p, i64 143  %2 = getelementptr inbounds i8, ptr %1, i64 244  ret ptr %245}46 47; Offsets of first and last GEP cancel out.48; result = p49define ptr @zeroSum(ptr %p) {50; CHECK-LABEL: @zeroSum(51; CHECK-NEXT:    ret ptr [[P:%.*]]52;53  %1 = getelementptr inbounds i32, ptr %p, i64 154  %2 = getelementptr inbounds i8, ptr %1, i64 -455  ret ptr %256}57 58; result = (ptr) ((ptr) p + 1) + 1759define ptr @array1(ptr %p) {60; CHECK-LABEL: @array1(61; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds nuw i8, ptr [[P:%.*]], i64 3762; CHECK-NEXT:    ret ptr [[TMP1]]63;64  %1 = getelementptr inbounds [20 x i8], ptr %p, i64 1, i64 165  %2 = getelementptr inbounds i64, ptr %1, i64 266  ret ptr %267}68 69; Converted to ptr and merged.70; result = (ptr) p + 2071define ptr @array2(ptr %p) {72; CHECK-LABEL: @array2(73; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds nuw i8, ptr [[P:%.*]], i64 2074; CHECK-NEXT:    ret ptr [[TMP1]]75;76  %1 = getelementptr inbounds i64, ptr %p, i64 277  %2 = getelementptr inbounds [3 x i8], ptr %1, i64 1, i64 178  ret ptr %279}80 81; Converted to ptr and merged.82; result = (ptr) p + 3683define ptr @struct1(ptr %p) {84; CHECK-LABEL: @struct1(85; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds nuw i8, ptr [[P:%.*]], i64 3686; CHECK-NEXT:    ret ptr [[TMP1]]87;88  %1 = getelementptr inbounds i64, ptr %p, i64 389  %2 = getelementptr inbounds %struct.C, ptr %1, i64 190  ret ptr %291}92 93; result = &((struct.A*) p - 1).member194define ptr @struct2(ptr %p) {95; CHECK-LABEL: @struct2(96; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[P:%.*]], i64 -497; CHECK-NEXT:    ret ptr [[TMP1]]98;99  %1 = getelementptr inbounds %struct.A, ptr %p, i64 0, i32 1100  %2 = getelementptr inbounds i8, ptr %1, i64 -128101  ret ptr %2102}103 104; result = (ptr) &((struct.B) p)[0].member2.member0 + 7105define ptr @structStruct(ptr %p) {106; CHECK-LABEL: @structStruct(107; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds nuw i8, ptr [[P:%.*]], i64 15108; CHECK-NEXT:    ret ptr [[TMP1]]109;110  %1 = getelementptr inbounds %struct.B, ptr %p, i64 0, i32 2, i32 0, i64 3111  %2 = getelementptr inbounds %struct.A, ptr %1, i64 0, i32 0, i64 4112  ret ptr %2113}114 115; First GEP offset is not divisible by last GEP's source element size, but first116; GEP points to an array such that the last GEP offset is divisible by the117; array's element size, so the first GEP can be rewritten with an extra index.118; result = (ptr) &((struct.B*) p)[i].member1 + 2119define ptr @appendIndex(ptr %p, i64 %i) {120; CHECK-LABEL: @appendIndex(121; CHECK-NEXT:    [[DOTSPLIT:%.*]] = getelementptr inbounds [[STRUCT_B:%.*]], ptr [[P:%.*]], i64 [[I:%.*]]122; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds nuw i8, ptr [[DOTSPLIT]], i64 6123; CHECK-NEXT:    ret ptr [[TMP1]]124;125  %1 = getelementptr inbounds %struct.B, ptr %p, i64 %i, i32 1126  %2 = getelementptr inbounds i32, ptr %1, i64 1127  ret ptr %2128}129 130; Offset of either GEP is not divisible by the other's size, converted to ptr131; and merged.132; Here i24 is 8-bit aligned.133; result = (ptr) p + 7134define ptr @notDivisible(ptr %p) {135; CHECK-LABEL: @notDivisible(136; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds nuw i8, ptr [[P:%.*]], i64 7137; CHECK-NEXT:    ret ptr [[TMP1]]138;139  %1 = getelementptr inbounds i24, ptr %p, i64 1140  %2 = getelementptr inbounds i32, ptr %1, i64 1141  ret ptr %2142}143 144define ptr @partialConstant2(ptr %p, i64 %a) {145; CHECK-LABEL: @partialConstant2(146; CHECK-NEXT:    [[DOTIDX:%.*]] = shl nsw i64 [[A:%.*]], 5147; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 20148; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr i8, ptr [[TMP1]], i64 [[DOTIDX]]149; CHECK-NEXT:    ret ptr [[TMP2]]150;151  %1 = getelementptr inbounds i32, ptr %p, i64 1152  %2 = getelementptr inbounds [4 x i64], ptr %1, i64 %a, i64 2153  ret ptr %2154}155 156define ptr @partialConstant3(ptr %p) {157; CHECK-LABEL: @partialConstant3(158; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds nuw i8, ptr [[P:%.*]], i64 4159; CHECK-NEXT:    [[TMP2:%.*]] = ptrtoint ptr [[TMP1]] to i64160; CHECK-NEXT:    [[DOTIDX:%.*]] = shl nsw i64 [[TMP2]], 5161; CHECK-NEXT:    [[TMP4:%.*]] = getelementptr i8, ptr [[TMP1]], i64 [[DOTIDX]]162; CHECK-NEXT:    [[TMP3:%.*]] = getelementptr i8, ptr [[TMP4]], i64 16163; CHECK-NEXT:    ret ptr [[TMP3]]164;165  %1 = getelementptr inbounds i32, ptr %p, i64 1166  %2 = ptrtoint ptr %1 to i64167  %3 = getelementptr inbounds [4 x i64], ptr %1, i64 %2, i64 2168  ret ptr %3169}170 171; Two GEP instructions can be merged if one is constant-indexed and the other172; is an aggregate type with a constant last index, and the resulting pointer173; address by adding the constant offset aliases the address of another member.174; result = &((struct.C*) p + a).member2175define ptr @partialConstantMemberAliasing1(ptr %p, i64 %a) {176; CHECK-LABEL: @partialConstantMemberAliasing1(177; CHECK-NEXT:    [[DOTSPLIT:%.*]] = getelementptr inbounds [[STRUCT_C:%.*]], ptr [[P:%.*]], i64 [[A:%.*]]178; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds nuw i8, ptr [[DOTSPLIT]], i64 8179; CHECK-NEXT:    ret ptr [[TMP1]]180;181  %1 = getelementptr inbounds %struct.C, ptr %p, i64 %a, i32 1182  %2 = getelementptr inbounds i32, ptr %1, i64 1183  ret ptr %2184}185 186; Negative test. Similar to above, but the new address does not alias the187; address of another member.188define ptr @partialConstantMemberAliasing2(ptr %p, i64 %a) {189; CHECK-LABEL: @partialConstantMemberAliasing2(190; CHECK-NEXT:    [[DOTSPLIT:%.*]] = getelementptr inbounds [[STRUCT_C:%.*]], ptr [[P:%.*]], i64 [[A:%.*]]191; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr inbounds nuw i8, ptr [[DOTSPLIT]], i64 5192; CHECK-NEXT:    ret ptr [[TMP2]]193;194  %1 = getelementptr inbounds %struct.C, ptr %p, i64 %a, i32 1195  %2 = getelementptr inbounds i8, ptr %1, i64 1196  ret ptr %2197}198 199; Negative test. Similar to above, but the new address falls outside the address200; range of the object currently pointed by the non-constant GEP.201define ptr @partialConstantMemberAliasing3(ptr %p, i64 %a) {202; CHECK-LABEL: @partialConstantMemberAliasing3(203; CHECK-NEXT:    [[DOTSPLIT:%.*]] = getelementptr inbounds [[STRUCT_C:%.*]], ptr [[P:%.*]], i64 [[A:%.*]]204; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr inbounds nuw i8, ptr [[DOTSPLIT]], i64 12205; CHECK-NEXT:    ret ptr [[TMP2]]206;207  %1 = getelementptr inbounds %struct.C, ptr %p, i64 %a, i32 2208  %2 = getelementptr inbounds i32, ptr %1, i64 1209  ret ptr %2210}211