brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.4 KiB · b073889 Raw
152 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -passes=gvn -S | FileCheck %s3 4; load may be speculated, address is not null using context search.5; There is a critical edge.6define i32 @loadpre_critical_edge(ptr align 8 dereferenceable_or_null(48) %arg, i32 %N) nofree nosync {7; CHECK-LABEL: @loadpre_critical_edge(8; CHECK-NEXT:  entry:9; CHECK-NEXT:    [[CMP:%.*]] = icmp eq ptr [[ARG:%.*]], null10; CHECK-NEXT:    br i1 [[CMP]], label [[NULL_EXIT:%.*]], label [[ENTRY_HEADER_CRIT_EDGE:%.*]]11; CHECK:       entry.header_crit_edge:12; CHECK-NEXT:    [[V_PRE:%.*]] = load i32, ptr [[ARG]], align 413; CHECK-NEXT:    br label [[HEADER:%.*]]14; CHECK:       header:15; CHECK-NEXT:    [[V:%.*]] = phi i32 [ [[V_PRE]], [[ENTRY_HEADER_CRIT_EDGE]] ], [ [[SUM:%.*]], [[HEADER]] ]16; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY_HEADER_CRIT_EDGE]] ], [ [[IV_NEXT:%.*]], [[HEADER]] ]17; CHECK-NEXT:    [[NEW_V:%.*]] = call i32 @ro_foo(i32 [[IV]]) #[[ATTR0:[0-9]+]]18; CHECK-NEXT:    [[SUM]] = add i32 [[NEW_V]], [[V]]19; CHECK-NEXT:    store i32 [[SUM]], ptr [[ARG]], align 420; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 121; CHECK-NEXT:    [[COND:%.*]] = icmp eq i32 [[IV_NEXT]], [[N:%.*]]22; CHECK-NEXT:    br i1 [[COND]], label [[EXIT:%.*]], label [[HEADER]]23; CHECK:       exit:24; CHECK-NEXT:    ret i32 [[SUM]]25; CHECK:       null_exit:26; CHECK-NEXT:    ret i32 027;28entry:29  %cmp = icmp eq ptr %arg, null30  br i1 %cmp, label %null_exit, label %header31 32header:33  %iv = phi i32 [0, %entry], [%iv.next, %header]34; Call prevents to move load over due to it does not guarantee to return.35  %new_v = call i32 @ro_foo(i32 %iv) readnone36  %v = load i32, ptr %arg37  %sum = add i32 %new_v, %v38  store i32 %sum, ptr %arg39  %iv.next = add i32 %iv, 140  %cond = icmp eq i32 %iv.next, %N41  br i1 %cond, label %exit, label %header42 43exit:44  ret i32 %sum45 46null_exit:47  ret i32 048}49 50; load may be speculated, address is not null using context search.51define i32 @loadpre_basic(ptr align 8 dereferenceable_or_null(48) %arg, i32 %N) nofree nosync {52; CHECK-LABEL: @loadpre_basic(53; CHECK-NEXT:  entry:54; CHECK-NEXT:    [[CMP:%.*]] = icmp eq ptr [[ARG:%.*]], null55; CHECK-NEXT:    br i1 [[CMP]], label [[NULL_EXIT:%.*]], label [[PREHEADER:%.*]]56; CHECK:       preheader:57; CHECK-NEXT:    [[V_PRE:%.*]] = load i32, ptr [[ARG]], align 458; CHECK-NEXT:    br label [[HEADER:%.*]]59; CHECK:       header:60; CHECK-NEXT:    [[V:%.*]] = phi i32 [ [[V_PRE]], [[PREHEADER]] ], [ [[SUM:%.*]], [[HEADER]] ]61; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[PREHEADER]] ], [ [[IV_NEXT:%.*]], [[HEADER]] ]62; CHECK-NEXT:    [[NEW_V:%.*]] = call i32 @ro_foo(i32 [[IV]]) #[[ATTR0]]63; CHECK-NEXT:    [[SUM]] = add i32 [[NEW_V]], [[V]]64; CHECK-NEXT:    store i32 [[SUM]], ptr [[ARG]], align 465; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 166; CHECK-NEXT:    [[COND:%.*]] = icmp eq i32 [[IV_NEXT]], [[N:%.*]]67; CHECK-NEXT:    br i1 [[COND]], label [[EXIT:%.*]], label [[HEADER]]68; CHECK:       exit:69; CHECK-NEXT:    ret i32 [[SUM]]70; CHECK:       null_exit:71; CHECK-NEXT:    ret i32 072;73entry:74  %cmp = icmp eq ptr %arg, null75  br i1 %cmp, label %null_exit, label %preheader76 77preheader:78  br label %header79 80header:81  %iv = phi i32 [0, %preheader], [%iv.next, %header]82; Call prevents to move load over due to it does not guarantee to return.83  %new_v = call i32 @ro_foo(i32 %iv) readnone84  %v = load i32, ptr %arg85  %sum = add i32 %new_v, %v86  store i32 %sum, ptr %arg87  %iv.next = add i32 %iv, 188  %cond = icmp eq i32 %iv.next, %N89  br i1 %cond, label %exit, label %header90 91exit:92  ret i32 %sum93 94null_exit:95  ret i32 096}97 98; load cannot be speculated, check "address is not null" does not dominate the loop.99define i32 @loadpre_maybe_null(ptr align 8 dereferenceable_or_null(48) %arg, i32 %N, i1 %c) nofree nosync {100; CHECK-LABEL: @loadpre_maybe_null(101; CHECK-NEXT:  entry:102; CHECK-NEXT:    br i1 [[C:%.*]], label [[NULL_CHECK:%.*]], label [[PREHEADER:%.*]]103; CHECK:       null_check:104; CHECK-NEXT:    [[CMP:%.*]] = icmp eq ptr [[ARG:%.*]], null105; CHECK-NEXT:    br i1 [[CMP]], label [[NULL_EXIT:%.*]], label [[PREHEADER]]106; CHECK:       preheader:107; CHECK-NEXT:    br label [[HEADER:%.*]]108; CHECK:       header:109; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[PREHEADER]] ], [ [[IV_NEXT:%.*]], [[HEADER]] ]110; CHECK-NEXT:    [[NEW_V:%.*]] = call i32 @ro_foo(i32 [[IV]]) #[[ATTR0]]111; CHECK-NEXT:    [[V:%.*]] = load i32, ptr [[ARG]], align 4112; CHECK-NEXT:    [[SUM:%.*]] = add i32 [[NEW_V]], [[V]]113; CHECK-NEXT:    store i32 [[SUM]], ptr [[ARG]], align 4114; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1115; CHECK-NEXT:    [[COND:%.*]] = icmp eq i32 [[IV_NEXT]], [[N:%.*]]116; CHECK-NEXT:    br i1 [[COND]], label [[EXIT:%.*]], label [[HEADER]]117; CHECK:       exit:118; CHECK-NEXT:    ret i32 [[SUM]]119; CHECK:       null_exit:120; CHECK-NEXT:    ret i32 0121;122entry:123  br i1 %c, label %null_check, label %preheader124 125null_check:126  %cmp = icmp eq ptr %arg, null127  br i1 %cmp, label %null_exit, label %preheader128 129preheader:130  br label %header131 132header:133  %iv = phi i32 [0, %preheader], [%iv.next, %header]134; Call prevents to move load over due to it does not guarantee to return.135  %new_v = call i32 @ro_foo(i32 %iv) readnone136  %v = load i32, ptr %arg137  %sum = add i32 %new_v, %v138  store i32 %sum, ptr %arg139  %iv.next = add i32 %iv, 1140  %cond = icmp eq i32 %iv.next, %N141  br i1 %cond, label %exit, label %header142 143exit:144  ret i32 %sum145 146null_exit:147  ret i32 0148}149 150; Does not guarantee that returns.151declare i32 @ro_foo(i32) readnone152