brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.5 KiB · 55d92b7 Raw
290 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt -passes=instcombine -S %s | FileCheck %s3target datalayout = "p:32:32"4 5 6define i1 @alloca_argument_compare(ptr %arg) {7; CHECK-LABEL: @alloca_argument_compare(8; CHECK-NEXT:    ret i1 false9;10  %alloc = alloca i6411  %cmp = icmp eq ptr %arg, %alloc12  ret i1 %cmp13}14 15define i1 @alloca_argument_compare_swapped(ptr %arg) {16; CHECK-LABEL: @alloca_argument_compare_swapped(17; CHECK-NEXT:    ret i1 false18;19  %alloc = alloca i6420  %cmp = icmp eq ptr %alloc, %arg21  ret i1 %cmp22}23 24define i1 @alloca_argument_compare_ne(ptr %arg) {25; CHECK-LABEL: @alloca_argument_compare_ne(26; CHECK-NEXT:    ret i1 true27;28  %alloc = alloca i6429  %cmp = icmp ne ptr %arg, %alloc30  ret i1 %cmp31}32 33define i1 @alloca_argument_compare_derived_ptrs(ptr %arg, i64 %x) {34; CHECK-LABEL: @alloca_argument_compare_derived_ptrs(35; CHECK-NEXT:    ret i1 false36;37  %alloc = alloca i64, i64 838  %p = getelementptr i64, ptr %arg, i64 %x39  %q = getelementptr i64, ptr %alloc, i64 340  %cmp = icmp eq ptr %p, %q41  ret i1 %cmp42}43 44declare void @escape(ptr)45define i1 @alloca_argument_compare_escaped_alloca(ptr %arg) {46; CHECK-LABEL: @alloca_argument_compare_escaped_alloca(47; CHECK-NEXT:    [[ALLOC:%.*]] = alloca i64, align 848; CHECK-NEXT:    call void @escape(ptr nonnull [[ALLOC]])49; CHECK-NEXT:    [[CMP:%.*]] = icmp eq ptr [[ALLOC]], [[ARG:%.*]]50; CHECK-NEXT:    ret i1 [[CMP]]51;52  %alloc = alloca i6453  call void @escape(ptr %alloc)54  %cmp = icmp eq ptr %alloc, %arg55  ret i1 %cmp56}57 58declare void @check_compares(i1, i1)59define void @alloca_argument_compare_two_compares(ptr %p) {60; CHECK-LABEL: @alloca_argument_compare_two_compares(61; CHECK-NEXT:    call void @check_compares(i1 false, i1 false)62; CHECK-NEXT:    ret void63;64  %q = alloca i64, i64 865  %r = getelementptr i64, ptr %p, i64 166  %s = getelementptr i64, ptr %q, i64 267  %cmp1 = icmp eq ptr %p, %q68  %cmp2 = icmp eq ptr %r, %s69  call void @check_compares(i1 %cmp1, i1 %cmp2)70  ret void71  ; We will only fold if there is a single cmp.72}73 74define i1 @alloca_argument_compare_escaped_through_store(ptr %arg, ptr %ptr) {75; CHECK-LABEL: @alloca_argument_compare_escaped_through_store(76; CHECK-NEXT:    [[ALLOC:%.*]] = alloca i64, align 877; CHECK-NEXT:    [[CMP:%.*]] = icmp eq ptr [[ALLOC]], [[ARG:%.*]]78; CHECK-NEXT:    [[P:%.*]] = getelementptr inbounds nuw i8, ptr [[ALLOC]], i32 879; CHECK-NEXT:    store ptr [[P]], ptr [[PTR:%.*]], align 480; CHECK-NEXT:    ret i1 [[CMP]]81;82  %alloc = alloca i6483  %cmp = icmp eq ptr %alloc, %arg84  %p = getelementptr i64, ptr %alloc, i64 185  store ptr %p, ptr %ptr86  ret i1 %cmp87}88 89declare void @llvm.lifetime.start.p0(ptr nocapture)90declare void @llvm.lifetime.end.p0(ptr nocapture)91define i1 @alloca_argument_compare_benign_instrs(ptr %arg) {92; CHECK-LABEL: @alloca_argument_compare_benign_instrs(93; CHECK-NEXT:    ret i1 false94;95  %alloc = alloca i896  call void @llvm.lifetime.start.p0(ptr %alloc)97  %cmp = icmp eq ptr %arg, %alloc98  %x = load i8, ptr %arg99  store i8 %x, ptr %alloc100  call void @llvm.lifetime.end.p0(ptr %alloc)101  ret i1 %cmp102}103 104declare ptr @allocator()105define i1 @alloca_call_compare() {106; CHECK-LABEL: @alloca_call_compare(107; CHECK-NEXT:    [[Q:%.*]] = call ptr @allocator()108; CHECK-NEXT:    ret i1 false109;110  %p = alloca i64111  %q = call ptr @allocator()112  %cmp = icmp eq ptr %p, %q113  ret i1 %cmp114}115 116 117; The next block of tests demonstrate a very subtle correctness requirement.118; We can generally assume any *single* stack layout we chose for the result of119; an alloca, but we can't simultanious assume two different ones.  As a120; result, we must make sure that we only fold conditions if we can ensure that121; we fold *all* potentially address capturing compares the same.122 123; These two functions represents either a) forging a pointer via inttoptr or124; b) indexing off an adjacent allocation.  In either case, the operation is125; obscured by an uninlined helper and not visible to instcombine.126declare ptr @hidden_inttoptr()127declare ptr @hidden_offset(ptr %other)128 129define i1 @ptrtoint_single_cmp() {130; CHECK-LABEL: @ptrtoint_single_cmp(131; CHECK-NEXT:    ret i1 false132;133  %m = alloca i8, i32 4134  %rhs = inttoptr i64 2048 to ptr135  %cmp = icmp eq ptr %m, %rhs136  ret i1 %cmp137}138 139define i1 @offset_single_cmp() {140; CHECK-LABEL: @offset_single_cmp(141; CHECK-NEXT:    ret i1 false142;143  %m = alloca i8, i32 4144  %n = alloca i8, i32 4145  %rhs = getelementptr i8, ptr %n, i32 4146  %cmp = icmp eq ptr %m, %rhs147  ret i1 %cmp148}149 150declare void @witness(i1, i1)151 152define void @consistent_fold1() {153; CHECK-LABEL: @consistent_fold1(154; CHECK-NEXT:    [[RHS2:%.*]] = call ptr @hidden_inttoptr()155; CHECK-NEXT:    call void @witness(i1 false, i1 false)156; CHECK-NEXT:    ret void157;158  %m = alloca i8, i32 4159  %rhs = inttoptr i64 2048 to ptr160  %rhs2 = call ptr @hidden_inttoptr()161  %cmp1 = icmp eq ptr %m, %rhs162  %cmp2 = icmp eq ptr %m, %rhs2163  call void @witness(i1 %cmp1, i1 %cmp2)164  ret void165}166 167define void @consistent_fold2() {168; CHECK-LABEL: @consistent_fold2(169; CHECK-NEXT:    [[N2:%.*]] = alloca [4 x i8], align 1170; CHECK-NEXT:    [[RHS2:%.*]] = call ptr @hidden_offset(ptr nonnull [[N2]])171; CHECK-NEXT:    call void @witness(i1 false, i1 false)172; CHECK-NEXT:    ret void173;174  %m = alloca i8, i32 4175  %n = alloca i8, i32 4176  %rhs = getelementptr i8, ptr %n, i32 4177  %rhs2 = call ptr @hidden_offset(ptr %n)178  %cmp1 = icmp eq ptr %m, %rhs179  %cmp2 = icmp eq ptr %m, %rhs2180  call void @witness(i1 %cmp1, i1 %cmp2)181  ret void182}183 184define void @consistent_fold3() {185; CHECK-LABEL: @consistent_fold3(186; CHECK-NEXT:    [[RHS2:%.*]] = call ptr @hidden_inttoptr()187; CHECK-NEXT:    call void @witness(i1 false, i1 false)188; CHECK-NEXT:    ret void189;190  %m = alloca i8, i32 4191  %lgp = load ptr, ptr @gp, align 8192  %rhs2 = call ptr @hidden_inttoptr()193  %cmp1 = icmp eq ptr %m, %lgp194  %cmp2 = icmp eq ptr %m, %rhs2195  call void @witness(i1 %cmp1, i1 %cmp2)196  ret void197}198 199define void @neg_consistent_fold4() {200; CHECK-LABEL: @neg_consistent_fold4(201; CHECK-NEXT:    call void @witness(i1 false, i1 false)202; CHECK-NEXT:    ret void203;204  %m = alloca i8, i32 4205  %lgp = load ptr, ptr @gp, align 8206  %cmp1 = icmp eq ptr %m, %lgp207  %cmp2 = icmp eq ptr %m, %lgp208  call void @witness(i1 %cmp1, i1 %cmp2)209  ret void210}211 212; A nocapture call can't cause a consistent result issue as it is (by213; assumption) not able to contain a comparison which might capture the214; address.215 216declare void @unknown(ptr)217 218define i1 @consistent_nocapture_inttoptr() {219; CHECK-LABEL: @consistent_nocapture_inttoptr(220; CHECK-NEXT:    [[M1:%.*]] = alloca [4 x i8], align 1221; CHECK-NEXT:    call void @unknown(ptr nonnull captures(none) [[M1]])222; CHECK-NEXT:    ret i1 false223;224  %m = alloca i8, i32 4225  call void @unknown(ptr nocapture %m)226  %rhs = inttoptr i64 2048 to ptr227  %cmp = icmp eq ptr %m, %rhs228  ret i1 %cmp229}230 231define i1 @consistent_nocapture_offset() {232; CHECK-LABEL: @consistent_nocapture_offset(233; CHECK-NEXT:    [[M1:%.*]] = alloca [4 x i8], align 1234; CHECK-NEXT:    call void @unknown(ptr nonnull captures(none) [[M1]])235; CHECK-NEXT:    ret i1 false236;237  %m = alloca i8, i32 4238  call void @unknown(ptr nocapture %m)239  %n = alloca i8, i32 4240  %rhs = getelementptr i8, ptr %n, i32 4241  %cmp = icmp eq ptr %m, %rhs242  ret i1 %cmp243}244 245@gp = global ptr null, align 8246 247define i1 @consistent_nocapture_through_global() {248; CHECK-LABEL: @consistent_nocapture_through_global(249; CHECK-NEXT:    [[M1:%.*]] = alloca [4 x i8], align 1250; CHECK-NEXT:    call void @unknown(ptr nonnull captures(none) [[M1]])251; CHECK-NEXT:    ret i1 false252;253  %m = alloca i8, i32 4254  call void @unknown(ptr nocapture %m)255  %lgp = load ptr, ptr @gp, align 8, !nonnull !{}256  %cmp = icmp eq ptr %m, %lgp257  ret i1 %cmp258}259 260define void @select_alloca_unrelated_ptr(i1 %c, ptr %p, ptr %p2) {261; CHECK-LABEL: @select_alloca_unrelated_ptr(262; CHECK-NEXT:    [[M:%.*]] = alloca i8, align 1263; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq ptr [[M]], [[P:%.*]]264; CHECK-NEXT:    [[S:%.*]] = select i1 [[C:%.*]], ptr [[M]], ptr [[P2:%.*]]265; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq ptr [[S]], [[P]]266; CHECK-NEXT:    call void @witness(i1 [[CMP1]], i1 [[CMP2]])267; CHECK-NEXT:    ret void268;269  %m = alloca i8270  %cmp1 = icmp eq ptr %m, %p271  %s = select i1 %c, ptr %m, ptr %p2272  %cmp2 = icmp eq ptr %s, %p273  call void @witness(i1 %cmp1, i1 %cmp2)274  ret void275}276 277define void @alloca_offset_icmp(ptr %p, i32 %offset) {278; CHECK-LABEL: @alloca_offset_icmp(279; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq i32 [[OFFSET:%.*]], 0280; CHECK-NEXT:    call void @witness(i1 false, i1 [[CMP2]])281; CHECK-NEXT:    ret void282;283  %m = alloca [4 x i8]284  %g = getelementptr i8, ptr %m, i32 %offset285  %cmp1 = icmp eq ptr %m, %p286  %cmp2 = icmp eq ptr %m, %g287  call void @witness(i1 %cmp1, i1 %cmp2)288  ret void289}290