brintos

brintos / llvm-project-archived public Read only

0
0
Text · 20.0 KiB · efd6445 Raw
435 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals all --version 52; REQUIRES: x86-registered-target3; RUN: opt < %s -passes=rel-lookup-table-converter -relocation-model=pic -S | FileCheck %s4target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"5target triple = "x86_64-unknown-linux-gnu"6 7@.str = private unnamed_addr constant [5 x i8] c"zero\00", align 18@.str.1 = private unnamed_addr constant [4 x i8] c"one\00", align 19@.str.2 = private unnamed_addr constant [4 x i8] c"two\00", align 110@.str.3 = private unnamed_addr constant [8 x i8] c"default\00", align 111@.str.4 = private unnamed_addr constant [6 x i8] c"three\00", align 112@.str.5 = private unnamed_addr constant [5 x i8] c"str1\00", align 113@.str.6 = private unnamed_addr constant [5 x i8] c"str2\00", align 114@.str.7 = private unnamed_addr constant [12 x i8] c"singlevalue\00", align 115@.str.8 = private unnamed_addr constant [2 x i8] c"a\00", align 116@.str.9 = private unnamed_addr constant [2 x i8] c"b\00", align 117@.str.10 = private unnamed_addr constant [2 x i8] c"c\00", align 118 19@a1 = external global i32, align 420@b1 = external global i32, align 421@c1 = external global i32, align 422@d1 = external global i32, align 423 24@a2 = internal constant i32 0, align 425@b2 = internal constant i32 0, align 426@c2 = internal constant i32 0, align 427@d2 = internal constant i32 0, align 428 29@switch.table.external_linkage = private unnamed_addr constant [3 x ptr] [ptr @a1, ptr @b1, ptr @c1], align 830 31@switch.table.internal_linkage = private unnamed_addr constant [3 x ptr] [ptr @a2, ptr @b2, ptr @c2], align 832 33@switch.table.string_table = private unnamed_addr constant [3 x ptr]34  [35  ptr @.str,36  ptr @.str.1,37  ptr @.str.238  ], align 839 40@switch.table.string_table_holes = private unnamed_addr constant [4 x ptr]41  [42  ptr @.str,43  ptr @.str.3,44  ptr @.str.2,45  ptr @.str.446  ], align 847 48@switch.table.single_value = private unnamed_addr constant [3 x ptr]49  [50  ptr @.str,51  ptr @.str.1,52  ptr @.str.253  ], align 854 55@user_defined_lookup_table.table = internal unnamed_addr constant [3 x ptr]56  [57  ptr @.str,58  ptr @.str.1,59  ptr @.str.260  ], align 1661 62@table = internal constant [2 x ptr] [63  ptr @.str.8,64  ptr @.str.965], align 1666 67@table2 = internal constant [2 x ptr] [68  ptr @.str.8,69  ptr @.str.970], align 1671 72@table3 = internal constant [2 x ptr] [73  ptr @.str.8,74  ptr @.str.975], align 1676 77@table4 = internal constant [2 x ptr] [78  ptr @.str.8,79  ptr @.str.980], align 1681 82@table5 = internal constant [2 x ptr] [83  ptr @.str.8,84  ptr @.str.985], align 1686 87@skip.table = internal constant [4 x ptr] [88  ptr @.str.8,89  ptr null,90  ptr @.str.9,91  ptr null92], align 1693 94@wrong.skip.table = internal constant [4 x ptr] [95  ptr null,96  ptr @.str.8,97  ptr null,98  ptr @.str.999], align 16100 101;.102; CHECK: @.str = private unnamed_addr constant [5 x i8] c"zero\00", align 1103; CHECK: @.str.1 = private unnamed_addr constant [4 x i8] c"one\00", align 1104; CHECK: @.str.2 = private unnamed_addr constant [4 x i8] c"two\00", align 1105; CHECK: @.str.3 = private unnamed_addr constant [8 x i8] c"default\00", align 1106; CHECK: @.str.4 = private unnamed_addr constant [6 x i8] c"three\00", align 1107; CHECK: @.str.5 = private unnamed_addr constant [5 x i8] c"str1\00", align 1108; CHECK: @.str.6 = private unnamed_addr constant [5 x i8] c"str2\00", align 1109; CHECK: @.str.7 = private unnamed_addr constant [12 x i8] c"singlevalue\00", align 1110; CHECK: @.str.8 = private unnamed_addr constant [2 x i8] c"a\00", align 1111; CHECK: @.str.9 = private unnamed_addr constant [2 x i8] c"b\00", align 1112; CHECK: @.str.10 = private unnamed_addr constant [2 x i8] c"c\00", align 1113; CHECK: @a1 = external global i32, align 4114; CHECK: @b1 = external global i32, align 4115; CHECK: @c1 = external global i32, align 4116; CHECK: @d1 = external global i32, align 4117; CHECK: @a2 = internal constant i32 0, align 4118; CHECK: @b2 = internal constant i32 0, align 4119; CHECK: @c2 = internal constant i32 0, align 4120; CHECK: @d2 = internal constant i32 0, align 4121; CHECK: @switch.table.external_linkage = private unnamed_addr constant [3 x ptr] [ptr @a1, ptr @b1, ptr @c1], align 8122; CHECK: @switch.table.internal_linkage.rel = private unnamed_addr constant [3 x i32] [i32 trunc (i64 sub (i64 ptrtoint (ptr @a2 to i64), i64 ptrtoint (ptr @switch.table.internal_linkage.rel to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr @b2 to i64), i64 ptrtoint (ptr @switch.table.internal_linkage.rel to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr @c2 to i64), i64 ptrtoint (ptr @switch.table.internal_linkage.rel to i64)) to i32)], align 4123; CHECK: @switch.table.string_table.rel = private unnamed_addr constant [3 x i32] [i32 trunc (i64 sub (i64 ptrtoint (ptr @.str to i64), i64 ptrtoint (ptr @switch.table.string_table.rel to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr @.str.1 to i64), i64 ptrtoint (ptr @switch.table.string_table.rel to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr @.str.2 to i64), i64 ptrtoint (ptr @switch.table.string_table.rel to i64)) to i32)], align 4124; CHECK: @switch.table.string_table_holes.rel = private unnamed_addr constant [4 x i32] [i32 trunc (i64 sub (i64 ptrtoint (ptr @.str to i64), i64 ptrtoint (ptr @switch.table.string_table_holes.rel to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr @.str.3 to i64), i64 ptrtoint (ptr @switch.table.string_table_holes.rel to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr @.str.2 to i64), i64 ptrtoint (ptr @switch.table.string_table_holes.rel to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr @.str.4 to i64), i64 ptrtoint (ptr @switch.table.string_table_holes.rel to i64)) to i32)], align 4125; CHECK: @switch.table.single_value.rel = private unnamed_addr constant [3 x i32] [i32 trunc (i64 sub (i64 ptrtoint (ptr @.str to i64), i64 ptrtoint (ptr @switch.table.single_value.rel to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr @.str.1 to i64), i64 ptrtoint (ptr @switch.table.single_value.rel to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr @.str.2 to i64), i64 ptrtoint (ptr @switch.table.single_value.rel to i64)) to i32)], align 4126; CHECK: @user_defined_lookup_table.table.rel = internal unnamed_addr constant [3 x i32] [i32 trunc (i64 sub (i64 ptrtoint (ptr @.str to i64), i64 ptrtoint (ptr @user_defined_lookup_table.table.rel to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr @.str.1 to i64), i64 ptrtoint (ptr @user_defined_lookup_table.table.rel to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr @.str.2 to i64), i64 ptrtoint (ptr @user_defined_lookup_table.table.rel to i64)) to i32)], align 4127; CHECK: @table.rel = internal unnamed_addr constant [2 x i32] [i32 trunc (i64 sub (i64 ptrtoint (ptr @.str.8 to i64), i64 ptrtoint (ptr @table.rel to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr @.str.9 to i64), i64 ptrtoint (ptr @table.rel to i64)) to i32)], align 4128; CHECK: @table2.rel = internal unnamed_addr constant [2 x i32] [i32 trunc (i64 sub (i64 ptrtoint (ptr @.str.8 to i64), i64 ptrtoint (ptr @table2.rel to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr @.str.9 to i64), i64 ptrtoint (ptr @table2.rel to i64)) to i32)], align 4129; CHECK: @table3.rel = internal unnamed_addr constant [2 x i32] [i32 trunc (i64 sub (i64 ptrtoint (ptr @.str.8 to i64), i64 ptrtoint (ptr @table3.rel to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr @.str.9 to i64), i64 ptrtoint (ptr @table3.rel to i64)) to i32)], align 4130; CHECK: @table4 = internal constant [2 x ptr] [ptr @.str.8, ptr @.str.9], align 16131; CHECK: @table5 = internal constant [2 x ptr] [ptr @.str.8, ptr @.str.9], align 16132; CHECK: @skip.table.rel = internal unnamed_addr constant [2 x i32] [i32 trunc (i64 sub (i64 ptrtoint (ptr @.str.8 to i64), i64 ptrtoint (ptr @skip.table.rel to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr @.str.9 to i64), i64 ptrtoint (ptr @skip.table.rel to i64)) to i32)], align 4133; CHECK: @wrong.skip.table = internal constant [4 x ptr] [ptr null, ptr @.str.8, ptr null, ptr @.str.9], align 16134;.135define ptr @external_linkage(i32 %cond) {136; CHECK-LABEL: define ptr @external_linkage(137; CHECK-SAME: i32 [[COND:%.*]]) {138; CHECK-NEXT:  [[ENTRY:.*:]]139; CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i32 [[COND]], 3140; CHECK-NEXT:    br i1 [[TMP0]], label %[[SWITCH_LOOKUP:.*]], label %[[RETURN:.*]]141; CHECK:       [[SWITCH_LOOKUP]]:142; CHECK-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds [3 x ptr], ptr @switch.table.external_linkage, i32 0, i32 [[COND]]143; CHECK-NEXT:    [[SWITCH_LOAD:%.*]] = load ptr, ptr [[SWITCH_GEP]], align 8144; CHECK-NEXT:    ret ptr [[SWITCH_LOAD]]145; CHECK:       [[RETURN]]:146; CHECK-NEXT:    ret ptr @d1147;148entry:149  %0 = icmp ult i32 %cond, 3150  br i1 %0, label %switch.lookup, label %return151 152switch.lookup:                                    ; preds = %entry153  %switch.gep = getelementptr inbounds [3 x ptr], ptr @switch.table.external_linkage, i32 0, i32 %cond154  %switch.load = load ptr, ptr %switch.gep, align 8155  ret ptr %switch.load156 157return:                                           ; preds = %entry158  ret ptr @d1159}160 161; Relative switch lookup table for integer pointers that have internal linkage162define ptr @internal_linkage(i32 %cond) {163; CHECK-LABEL: define ptr @internal_linkage(164; CHECK-SAME: i32 [[COND:%.*]]) {165; CHECK-NEXT:  [[ENTRY:.*:]]166; CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i32 [[COND]], 3167; CHECK-NEXT:    br i1 [[TMP0]], label %[[SWITCH_LOOKUP:.*]], label %[[RETURN:.*]]168; CHECK:       [[SWITCH_LOOKUP]]:169; CHECK-NEXT:    [[RELTABLE_SHIFT:%.*]] = shl i32 [[COND]], 2170; CHECK-NEXT:    [[RELTABLE_INTRINSIC:%.*]] = call ptr @llvm.load.relative.i32(ptr @switch.table.internal_linkage.rel, i32 [[RELTABLE_SHIFT]])171; CHECK-NEXT:    ret ptr [[RELTABLE_INTRINSIC]]172; CHECK:       [[RETURN]]:173; CHECK-NEXT:    ret ptr @d2174;175entry:176  %0 = icmp ult i32 %cond, 3177  br i1 %0, label %switch.lookup, label %return178 179switch.lookup:                                    ; preds = %entry180  %switch.gep = getelementptr inbounds [3 x ptr], ptr @switch.table.internal_linkage, i32 0, i32 %cond181  %switch.load = load ptr, ptr %switch.gep, align 8182  ret ptr %switch.load183 184return:                                           ; preds = %entry185  ret ptr @d2186}187 188; ; Relative switch lookup table for strings189define ptr @string_table(i32 %cond) {190; CHECK-LABEL: define ptr @string_table(191; CHECK-SAME: i32 [[COND:%.*]]) {192; CHECK-NEXT:  [[ENTRY:.*:]]193; CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i32 [[COND]], 3194; CHECK-NEXT:    br i1 [[TMP0]], label %[[SWITCH_LOOKUP:.*]], label %[[RETURN:.*]]195; CHECK:       [[SWITCH_LOOKUP]]:196; CHECK-NEXT:    [[RELTABLE_SHIFT:%.*]] = shl i32 [[COND]], 2197; CHECK-NEXT:    [[RELTABLE_INTRINSIC:%.*]] = call ptr @llvm.load.relative.i32(ptr @switch.table.string_table.rel, i32 [[RELTABLE_SHIFT]])198; CHECK-NEXT:    ret ptr [[RELTABLE_INTRINSIC]]199; CHECK:       [[RETURN]]:200; CHECK-NEXT:    ret ptr @.str.3201;202entry:203  %0 = icmp ult i32 %cond, 3204  br i1 %0, label %switch.lookup, label %return205 206switch.lookup:                                    ; preds = %entry207  %switch.gep = getelementptr inbounds [3 x ptr], ptr @switch.table.string_table, i32 0, i32 %cond208  %switch.load = load ptr, ptr %switch.gep, align 8209  ret ptr %switch.load210 211return:                                           ; preds = %entry212  ret ptr @.str.3213}214 215; Relative switch lookup table for strings with holes, where holes are filled with relative offset to default values216define ptr @string_table_holes(i32 %cond) {217; CHECK-LABEL: define ptr @string_table_holes(218; CHECK-SAME: i32 [[COND:%.*]]) {219; CHECK-NEXT:  [[ENTRY:.*:]]220; CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i32 [[COND]], 4221; CHECK-NEXT:    br i1 [[TMP0]], label %[[SWITCH_LOOKUP:.*]], label %[[RETURN:.*]]222; CHECK:       [[SWITCH_LOOKUP]]:223; CHECK-NEXT:    [[RELTABLE_SHIFT:%.*]] = shl i32 [[COND]], 2224; CHECK-NEXT:    [[RELTABLE_INTRINSIC:%.*]] = call ptr @llvm.load.relative.i32(ptr @switch.table.string_table_holes.rel, i32 [[RELTABLE_SHIFT]])225; CHECK-NEXT:    ret ptr [[RELTABLE_INTRINSIC]]226; CHECK:       [[RETURN]]:227; CHECK-NEXT:    ret ptr @.str.3228;229entry:230  %0 = icmp ult i32 %cond, 4231  br i1 %0, label %switch.lookup, label %return232 233switch.lookup:                                    ; preds = %entry234  %switch.gep = getelementptr inbounds [4 x ptr], ptr @switch.table.string_table_holes, i32 0, i32 %cond235  %switch.load = load ptr, ptr %switch.gep, align 8236  ret ptr %switch.load237 238return:                                           ; preds = %entry239  ret ptr @.str.3240}241 242 243; Single value check244; If there is a lookup table, where each element contains the same value,245; a relative lookup should not be generated246define void @single_value(i32 %cond)  {247; CHECK-LABEL: define void @single_value(248; CHECK-SAME: i32 [[COND:%.*]]) {249; CHECK-NEXT:  [[ENTRY:.*]]:250; CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i32 [[COND]], 3251; CHECK-NEXT:    br i1 [[TMP0]], label %[[SWITCH_LOOKUP:.*]], label %[[SW_EPILOG:.*]]252; CHECK:       [[SWITCH_LOOKUP]]:253; CHECK-NEXT:    [[RELTABLE_SHIFT:%.*]] = shl i32 [[COND]], 2254; CHECK-NEXT:    [[RELTABLE_INTRINSIC:%.*]] = call ptr @llvm.load.relative.i32(ptr @switch.table.single_value.rel, i32 [[RELTABLE_SHIFT]])255; CHECK-NEXT:    br label %[[SW_EPILOG]]256; CHECK:       [[SW_EPILOG]]:257; CHECK-NEXT:    [[STR1_0:%.*]] = phi ptr [ @.str.5, %[[ENTRY]] ], [ @.str.7, %[[SWITCH_LOOKUP]] ]258; CHECK-NEXT:    [[STR2_0:%.*]] = phi ptr [ @.str.6, %[[ENTRY]] ], [ [[RELTABLE_INTRINSIC]], %[[SWITCH_LOOKUP]] ]259; CHECK-NEXT:    ret void260;261 262entry:263  %0 = icmp ult i32 %cond, 3264  br i1 %0, label %switch.lookup, label %sw.epilog265 266switch.lookup:                                    ; preds = %entry267  %switch.gep = getelementptr inbounds [3 x ptr], ptr @switch.table.single_value, i32 0, i32 %cond268  %switch.load = load ptr, ptr %switch.gep, align 8269  br label %sw.epilog270 271sw.epilog:                                        ; preds = %switch.lookup, %entry272  %str1.0 = phi ptr [ @.str.5, %entry ], [ @.str.7, %switch.lookup ]273  %str2.0 = phi ptr [ @.str.6, %entry ], [ %switch.load, %switch.lookup ]274  ret void275}276 277; Relative lookup table generated for a user-defined lookup table278define ptr @user_defined_lookup_table(i32 %cond)  {279; CHECK-LABEL: define ptr @user_defined_lookup_table(280; CHECK-SAME: i32 [[COND:%.*]]) {281; CHECK-NEXT:  [[ENTRY:.*]]:282; CHECK-NEXT:    [[TMP0:%.*]] = icmp sgt i32 [[COND]], 3283; CHECK-NEXT:    br i1 [[TMP0]], label %[[COND_END:.*]], label %[[COND_FALSE:.*]]284; CHECK:       [[COND_FALSE]]:285; CHECK-NEXT:    [[IDX_PROM:%.*]] = sext i32 [[COND]] to i64286; CHECK-NEXT:    [[RELTABLE_SHIFT:%.*]] = shl i64 [[IDX_PROM]], 2287; CHECK-NEXT:    [[RELTABLE_INTRINSIC:%.*]] = call ptr @llvm.load.relative.i64(ptr @user_defined_lookup_table.table.rel, i64 [[RELTABLE_SHIFT]])288; CHECK-NEXT:    br label %[[COND_END]]289; CHECK:       [[COND_END]]:290; CHECK-NEXT:    [[COND1:%.*]] = phi ptr [ [[RELTABLE_INTRINSIC]], %[[COND_FALSE]] ], [ @.str.3, %[[ENTRY]] ]291; CHECK-NEXT:    ret ptr [[COND1]]292;293entry:294  %cmp = icmp sgt i32 %cond, 3295  br i1 %cmp, label %cond.end, label %cond.false296 297cond.false:                                       ; preds = %entry298  %idxprom = sext i32 %cond to i64299  %arrayidx = getelementptr inbounds [3 x ptr], ptr @user_defined_lookup_table.table, i64 0, i64 %idxprom300  %0 = load ptr, ptr %arrayidx, align 8, !tbaa !4301  br label %cond.end302 303cond.end:                                         ; preds = %entry, %cond.false304  %cond1 = phi ptr [ %0, %cond.false ], [ @.str.3, %entry ]305  ret ptr %cond1306}307 308; Check to ensure that call @llvm.load.relative is inserted before load, not before gep.309; When a lookup table is accessed inside a loop, and a gep is hosted outside the loop via licm,310; make sure that call @llvm.load.relative is inserted before load.311define ptr @loop_hoist(i32 %x) {312; CHECK-LABEL: define ptr @loop_hoist(313; CHECK-SAME: i32 [[X:%.*]]) {314; CHECK-NEXT:  [[ENTRY:.*]]:315; CHECK-NEXT:    [[TMP0:%.*]] = icmp sgt i32 [[X]], 1316; CHECK-NEXT:    [[RELTABLE_SHIFT:%.*]] = shl i32 [[X]], 2317; CHECK-NEXT:    br i1 [[TMP0]], label %[[IF_DONE:.*]], label %[[IF_FALSE:.*]]318; CHECK:       [[IF_FALSE]]:319; CHECK-NEXT:    [[RELTABLE_INTRINSIC:%.*]] = call ptr @llvm.load.relative.i32(ptr @table.rel, i32 [[RELTABLE_SHIFT]])320; CHECK-NEXT:    br label %[[IF_DONE]]321; CHECK:       [[IF_DONE]]:322; CHECK-NEXT:    [[TMP2:%.*]] = phi ptr [ @.str.10, %[[ENTRY]] ], [ [[RELTABLE_INTRINSIC]], %[[IF_FALSE]] ]323; CHECK-NEXT:    ret ptr [[TMP2]]324;325entry:326  %0 = icmp sgt i32 %x, 1327  %1 = getelementptr [2 x ptr], ptr @table, i32 0, i32 %x328  br i1 %0, label %if.done, label %if.false329 330if.false:331  %2 = load ptr, ptr %1332  br label %if.done333 334if.done:335  %3 = phi ptr [ @.str.10, %entry ], [ %2, %if.false ]336  ret ptr %3337}338 339; Another check to ensure that call @llvm.load.relative is inserted before load but not before gep.340; When a lookup table is accessed, and gep is not immediately followed by a load (like if there is a function call341; or an exception in between), make sure that call @llvm.load.relative is inserted before load.342declare void @may_not_return()343 344define ptr @gep_is_not_imm_followed_by_load(i32 %x) {345; CHECK-LABEL: define ptr @gep_is_not_imm_followed_by_load(346; CHECK-SAME: i32 [[X:%.*]]) {347; CHECK-NEXT:  [[ENTRY:.*:]]348; CHECK-NEXT:    [[RELTABLE_SHIFT:%.*]] = shl i32 [[X]], 2349; CHECK-NEXT:    call void @may_not_return()350; CHECK-NEXT:    [[RELTABLE_INTRINSIC:%.*]] = call ptr @llvm.load.relative.i32(ptr @table2.rel, i32 [[RELTABLE_SHIFT]])351; CHECK-NEXT:    ret ptr [[RELTABLE_INTRINSIC]]352;353entry:354  %0 = getelementptr [2 x ptr], ptr @table2, i32 0, i32 %x355  call void @may_not_return()356  %1 = load ptr, ptr %0357  ret ptr %1358}359 360define ptr @gep_no_leading_zero(i64 %index) {361; CHECK-LABEL: define ptr @gep_no_leading_zero(362; CHECK-SAME: i64 [[INDEX:%.*]]) {363; CHECK-NEXT:    [[RELTABLE_SHIFT:%.*]] = shl i64 [[INDEX]], 2364; CHECK-NEXT:    [[LOAD:%.*]] = call ptr @llvm.load.relative.i64(ptr @table3.rel, i64 [[RELTABLE_SHIFT]])365; CHECK-NEXT:    ret ptr [[LOAD]]366;367  %gep = getelementptr ptr, ptr @table3, i64 %index368  %load = load ptr, ptr %gep369  ret ptr %load370}371 372define ptr @gep_wrong_stride(i64 %index) {373; CHECK-LABEL: define ptr @gep_wrong_stride(374; CHECK-SAME: i64 [[INDEX:%.*]]) {375; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i8, ptr @table4, i64 [[INDEX]]376; CHECK-NEXT:    [[LOAD:%.*]] = load ptr, ptr [[GEP]], align 8377; CHECK-NEXT:    ret ptr [[LOAD]]378;379  %gep = getelementptr i8, ptr @table4, i64 %index380  %load = load ptr, ptr %gep381  ret ptr %load382}383 384define ptr @gep_wrong_constant_offset(i64 %index) {385; CHECK-LABEL: define ptr @gep_wrong_constant_offset(386; CHECK-SAME: i64 [[INDEX:%.*]]) {387; CHECK-NEXT:    [[GEP:%.*]] = getelementptr { ptr, i32 }, ptr @table5, i64 [[INDEX]], i32 1388; CHECK-NEXT:    [[LOAD:%.*]] = load ptr, ptr [[GEP]], align 8389; CHECK-NEXT:    ret ptr [[LOAD]]390;391  %gep = getelementptr { ptr, i32 }, ptr @table5, i64 %index, i32 1392  %load = load ptr, ptr %gep393  ret ptr %load394}395 396; This is intentionally advancing by two pointers.397define ptr @table_with_skipped_elements(i64 %index) {398; CHECK-LABEL: define ptr @table_with_skipped_elements(399; CHECK-SAME: i64 [[INDEX:%.*]]) {400; CHECK-NEXT:    [[RELTABLE_SHIFT:%.*]] = shl i64 [[INDEX]], 2401; CHECK-NEXT:    [[LOAD:%.*]] = call ptr @llvm.load.relative.i64(ptr @skip.table.rel, i64 [[RELTABLE_SHIFT]])402; CHECK-NEXT:    ret ptr [[LOAD]]403;404  %gep = getelementptr [2 x ptr], ptr @skip.table, i64 %index405  %load = load ptr, ptr %gep406  ret ptr %load407}408 409; Same as previous test, but the elements are at the wrong position in the410; table.411define ptr @table_with_skipped_elements_wrong(i64 %index) {412; CHECK-LABEL: define ptr @table_with_skipped_elements_wrong(413; CHECK-SAME: i64 [[INDEX:%.*]]) {414; CHECK-NEXT:    [[GEP:%.*]] = getelementptr [2 x ptr], ptr @wrong.skip.table, i64 [[INDEX]]415; CHECK-NEXT:    [[LOAD:%.*]] = load ptr, ptr [[GEP]], align 8416; CHECK-NEXT:    ret ptr [[LOAD]]417;418  %gep = getelementptr [2 x ptr], ptr @wrong.skip.table, i64 %index419  %load = load ptr, ptr %gep420  ret ptr %load421}422 423!llvm.module.flags = !{!0, !1}424!0 = !{i32 7, !"PIC Level", i32 2}425!1 = !{i32 1, !"Code Model", i32 1}426!4 = !{!"any pointer", !5, i64 0}427!5 = !{!"omnipotent char", !6, i64 0}428!6 = !{!"Simple C/C++ TBAA"}429;.430; CHECK: attributes #[[ATTR0:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(argmem: read) }431;.432; CHECK: [[META0:![0-9]+]] = !{i32 8, !"PIC Level", i32 2}433; CHECK: [[META1:![0-9]+]] = !{i32 1, !"Code Model", i32 1}434;.435