| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2 | 
 | ; RUN: opt -passes=function-attrs -S < %s | FileCheck %s | 
 |  | 
 | @g = global ptr null		; <ptr> [#uses=1] | 
 |  | 
 | define ptr @c1(ptr %q) { | 
 | ; CHECK-LABEL: define ptr @c1 | 
 | ; CHECK-SAME: (ptr readnone returned [[Q:%.*]]) #[[ATTR0:[0-9]+]] { | 
 | ; CHECK-NEXT:    ret ptr [[Q]] | 
 | ; | 
 |   ret ptr %q | 
 | } | 
 |  | 
 | ; It would also be acceptable to mark %q as readnone. Update @c3 too. | 
 | define void @c2(ptr %q) { | 
 | ; CHECK-LABEL: define void @c2 | 
 | ; CHECK-SAME: (ptr [[Q:%.*]]) #[[ATTR1:[0-9]+]] { | 
 | ; CHECK-NEXT:    store ptr [[Q]], ptr @g, align 8 | 
 | ; CHECK-NEXT:    ret void | 
 | ; | 
 |   store ptr %q, ptr @g | 
 |   ret void | 
 | } | 
 |  | 
 | define void @c3(ptr %q) { | 
 | ; CHECK-LABEL: define void @c3 | 
 | ; CHECK-SAME: (ptr [[Q:%.*]]) #[[ATTR2:[0-9]+]] { | 
 | ; CHECK-NEXT:    call void @c2(ptr [[Q]]) | 
 | ; CHECK-NEXT:    ret void | 
 | ; | 
 |   call void @c2(ptr %q) | 
 |   ret void | 
 | } | 
 |  | 
 | define i1 @c4(ptr %q, i32 %bitno) { | 
 | ; CHECK-LABEL: define i1 @c4 | 
 | ; CHECK-SAME: (ptr [[Q:%.*]], i32 [[BITNO:%.*]]) #[[ATTR0]] { | 
 | ; CHECK-NEXT:    [[TMP:%.*]] = ptrtoint ptr [[Q]] to i32 | 
 | ; CHECK-NEXT:    [[TMP2:%.*]] = lshr i32 [[TMP]], [[BITNO]] | 
 | ; CHECK-NEXT:    [[BIT:%.*]] = trunc i32 [[TMP2]] to i1 | 
 | ; CHECK-NEXT:    br i1 [[BIT]], label [[L1:%.*]], label [[L0:%.*]] | 
 | ; CHECK:       l0: | 
 | ; CHECK-NEXT:    ret i1 false | 
 | ; CHECK:       l1: | 
 | ; CHECK-NEXT:    ret i1 true | 
 | ; | 
 |   %tmp = ptrtoint ptr %q to i32 | 
 |   %tmp2 = lshr i32 %tmp, %bitno | 
 |   %bit = trunc i32 %tmp2 to i1 | 
 |   br i1 %bit, label %l1, label %l0 | 
 | l0: | 
 |   ret i1 0 ; escaping value not caught by def-use chaining. | 
 | l1: | 
 |   ret i1 1 ; escaping value not caught by def-use chaining. | 
 | } | 
 |  | 
 | ; c4b is c4 but without the escaping part | 
 | define i1 @c4b(ptr %q, i32 %bitno) { | 
 | ; CHECK-LABEL: define i1 @c4b | 
 | ; CHECK-SAME: (ptr [[Q:%.*]], i32 [[BITNO:%.*]]) #[[ATTR0]] { | 
 | ; CHECK-NEXT:    [[TMP:%.*]] = ptrtoint ptr [[Q]] to i32 | 
 | ; CHECK-NEXT:    [[TMP2:%.*]] = lshr i32 [[TMP]], [[BITNO]] | 
 | ; CHECK-NEXT:    [[BIT:%.*]] = trunc i32 [[TMP2]] to i1 | 
 | ; CHECK-NEXT:    br i1 [[BIT]], label [[L1:%.*]], label [[L0:%.*]] | 
 | ; CHECK:       l0: | 
 | ; CHECK-NEXT:    ret i1 false | 
 | ; CHECK:       l1: | 
 | ; CHECK-NEXT:    ret i1 false | 
 | ; | 
 |   %tmp = ptrtoint ptr %q to i32 | 
 |   %tmp2 = lshr i32 %tmp, %bitno | 
 |   %bit = trunc i32 %tmp2 to i1 | 
 |   br i1 %bit, label %l1, label %l0 | 
 | l0: | 
 |   ret i1 0 ; not escaping! | 
 | l1: | 
 |   ret i1 0 ; not escaping! | 
 | } | 
 |  | 
 | @lookup_table = global [2 x i1] [ i1 0, i1 1 ] | 
 |  | 
 | define i1 @c5(ptr %q, i32 %bitno) { | 
 | ; CHECK-LABEL: define i1 @c5 | 
 | ; CHECK-SAME: (ptr [[Q:%.*]], i32 [[BITNO:%.*]]) #[[ATTR3:[0-9]+]] { | 
 | ; CHECK-NEXT:    [[TMP:%.*]] = ptrtoint ptr [[Q]] to i32 | 
 | ; CHECK-NEXT:    [[TMP2:%.*]] = lshr i32 [[TMP]], [[BITNO]] | 
 | ; CHECK-NEXT:    [[BIT:%.*]] = and i32 [[TMP2]], 1 | 
 | ; CHECK-NEXT:    [[LOOKUP:%.*]] = getelementptr [2 x i1], ptr @lookup_table, i32 0, i32 [[BIT]] | 
 | ; CHECK-NEXT:    [[VAL:%.*]] = load i1, ptr [[LOOKUP]], align 1 | 
 | ; CHECK-NEXT:    ret i1 [[VAL]] | 
 | ; | 
 |   %tmp = ptrtoint ptr %q to i32 | 
 |   %tmp2 = lshr i32 %tmp, %bitno | 
 |   %bit = and i32 %tmp2, 1 | 
 |   ; subtle escape mechanism follows | 
 |   %lookup = getelementptr [2 x i1], ptr @lookup_table, i32 0, i32 %bit | 
 |   %val = load i1, ptr %lookup | 
 |   ret i1 %val | 
 | } | 
 |  | 
 | declare void @throw_if_bit_set(ptr, i8) readonly | 
 |  | 
 | define i1 @c6(ptr %q, i8 %bit) personality ptr @__gxx_personality_v0 { | 
 | ; CHECK-LABEL: define i1 @c6 | 
 | ; CHECK-SAME: (ptr readonly [[Q:%.*]], i8 [[BIT:%.*]]) #[[ATTR5:[0-9]+]] personality ptr @__gxx_personality_v0 { | 
 | ; CHECK-NEXT:    invoke void @throw_if_bit_set(ptr [[Q]], i8 [[BIT]]) | 
 | ; CHECK-NEXT:    to label [[RET0:%.*]] unwind label [[RET1:%.*]] | 
 | ; CHECK:       ret0: | 
 | ; CHECK-NEXT:    ret i1 false | 
 | ; CHECK:       ret1: | 
 | ; CHECK-NEXT:    [[EXN:%.*]] = landingpad { ptr, i32 } | 
 | ; CHECK-NEXT:    cleanup | 
 | ; CHECK-NEXT:    ret i1 true | 
 | ; | 
 |   invoke void @throw_if_bit_set(ptr %q, i8 %bit) | 
 |   to label %ret0 unwind label %ret1 | 
 | ret0: | 
 |   ret i1 0 | 
 | ret1: | 
 |   %exn = landingpad {ptr, i32} | 
 |   cleanup | 
 |   ret i1 1 | 
 | } | 
 |  | 
 | declare i32 @__gxx_personality_v0(...) | 
 |  | 
 | define ptr @lookup_bit(ptr %q, i32 %bitno) readnone nounwind { | 
 | ; CHECK-LABEL: define nonnull ptr @lookup_bit | 
 | ; CHECK-SAME: (ptr [[Q:%.*]], i32 [[BITNO:%.*]]) #[[ATTR0]] { | 
 | ; CHECK-NEXT:    [[TMP:%.*]] = ptrtoint ptr [[Q]] to i32 | 
 | ; CHECK-NEXT:    [[TMP2:%.*]] = lshr i32 [[TMP]], [[BITNO]] | 
 | ; CHECK-NEXT:    [[BIT:%.*]] = and i32 [[TMP2]], 1 | 
 | ; CHECK-NEXT:    [[LOOKUP:%.*]] = getelementptr [2 x i1], ptr @lookup_table, i32 0, i32 [[BIT]] | 
 | ; CHECK-NEXT:    ret ptr [[LOOKUP]] | 
 | ; | 
 |   %tmp = ptrtoint ptr %q to i32 | 
 |   %tmp2 = lshr i32 %tmp, %bitno | 
 |   %bit = and i32 %tmp2, 1 | 
 |   %lookup = getelementptr [2 x i1], ptr @lookup_table, i32 0, i32 %bit | 
 |   ret ptr %lookup | 
 | } | 
 |  | 
 | define i1 @c7(ptr %q, i32 %bitno) { | 
 | ; CHECK-LABEL: define i1 @c7 | 
 | ; CHECK-SAME: (ptr readonly [[Q:%.*]], i32 [[BITNO:%.*]]) #[[ATTR6:[0-9]+]] { | 
 | ; CHECK-NEXT:    [[PTR:%.*]] = call ptr @lookup_bit(ptr [[Q]], i32 [[BITNO]]) | 
 | ; CHECK-NEXT:    [[VAL:%.*]] = load i1, ptr [[PTR]], align 1 | 
 | ; CHECK-NEXT:    ret i1 [[VAL]] | 
 | ; | 
 |   %ptr = call ptr @lookup_bit(ptr %q, i32 %bitno) | 
 |   %val = load i1, ptr %ptr | 
 |   ret i1 %val | 
 | } | 
 |  | 
 |  | 
 | define i32 @nc1(ptr %q, ptr %p, i1 %b) { | 
 | ; CHECK-LABEL: define i32 @nc1 | 
 | ; CHECK-SAME: (ptr [[Q:%.*]], ptr nocapture [[P:%.*]], i1 [[B:%.*]]) #[[ATTR7:[0-9]+]] { | 
 | ; CHECK-NEXT:  e: | 
 | ; CHECK-NEXT:    br label [[L:%.*]] | 
 | ; CHECK:       l: | 
 | ; CHECK-NEXT:    [[X:%.*]] = phi ptr [ [[P]], [[E:%.*]] ] | 
 | ; CHECK-NEXT:    [[Y:%.*]] = phi ptr [ [[Q]], [[E]] ] | 
 | ; CHECK-NEXT:    [[TMP2:%.*]] = select i1 [[B]], ptr [[X]], ptr [[Y]] | 
 | ; CHECK-NEXT:    [[VAL:%.*]] = load i32, ptr [[TMP2]], align 4 | 
 | ; CHECK-NEXT:    store i32 0, ptr [[X]], align 4 | 
 | ; CHECK-NEXT:    store ptr [[Y]], ptr @g, align 8 | 
 | ; CHECK-NEXT:    ret i32 [[VAL]] | 
 | ; | 
 | e: | 
 |   br label %l | 
 | l: | 
 |   %x = phi ptr [ %p, %e ] | 
 |   %y = phi ptr [ %q, %e ] | 
 |   %tmp2 = select i1 %b, ptr %x, ptr %y | 
 |   %val = load i32, ptr %tmp2		; <i32> [#uses=1] | 
 |   store i32 0, ptr %x | 
 |   store ptr %y, ptr @g | 
 |   ret i32 %val | 
 | } | 
 |  | 
 | define i32 @nc1_addrspace(ptr %q, ptr addrspace(1) %p, i1 %b) { | 
 | ; CHECK-LABEL: define i32 @nc1_addrspace | 
 | ; CHECK-SAME: (ptr [[Q:%.*]], ptr addrspace(1) nocapture [[P:%.*]], i1 [[B:%.*]]) #[[ATTR7]] { | 
 | ; CHECK-NEXT:  e: | 
 | ; CHECK-NEXT:    br label [[L:%.*]] | 
 | ; CHECK:       l: | 
 | ; CHECK-NEXT:    [[X:%.*]] = phi ptr addrspace(1) [ [[P]], [[E:%.*]] ] | 
 | ; CHECK-NEXT:    [[Y:%.*]] = phi ptr [ [[Q]], [[E]] ] | 
 | ; CHECK-NEXT:    [[TMP:%.*]] = addrspacecast ptr addrspace(1) [[X]] to ptr | 
 | ; CHECK-NEXT:    [[TMP2:%.*]] = select i1 [[B]], ptr [[TMP]], ptr [[Y]] | 
 | ; CHECK-NEXT:    [[VAL:%.*]] = load i32, ptr [[TMP2]], align 4 | 
 | ; CHECK-NEXT:    store i32 0, ptr [[TMP]], align 4 | 
 | ; CHECK-NEXT:    store ptr [[Y]], ptr @g, align 8 | 
 | ; CHECK-NEXT:    ret i32 [[VAL]] | 
 | ; | 
 | e: | 
 |   br label %l | 
 | l: | 
 |   %x = phi ptr addrspace(1) [ %p, %e ] | 
 |   %y = phi ptr [ %q, %e ] | 
 |   %tmp = addrspacecast ptr addrspace(1) %x to ptr		; <ptr> [#uses=2] | 
 |   %tmp2 = select i1 %b, ptr %tmp, ptr %y | 
 |   %val = load i32, ptr %tmp2		; <i32> [#uses=1] | 
 |   store i32 0, ptr %tmp | 
 |   store ptr %y, ptr @g | 
 |   ret i32 %val | 
 | } | 
 |  | 
 | define void @nc2(ptr %p, ptr %q) { | 
 | ; CHECK-LABEL: define void @nc2 | 
 | ; CHECK-SAME: (ptr nocapture [[P:%.*]], ptr [[Q:%.*]]) #[[ATTR7]] { | 
 | ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @nc1(ptr [[Q]], ptr [[P]], i1 false) | 
 | ; CHECK-NEXT:    ret void | 
 | ; | 
 |   %1 = call i32 @nc1(ptr %q, ptr %p, i1 0)		; <i32> [#uses=0] | 
 |   ret void | 
 | } | 
 |  | 
 |  | 
 | define void @nc3(ptr %p) { | 
 | ; CHECK-LABEL: define void @nc3 | 
 | ; CHECK-SAME: (ptr nocapture readonly [[P:%.*]]) { | 
 | ; CHECK-NEXT:    call void [[P]]() | 
 | ; CHECK-NEXT:    ret void | 
 | ; | 
 |   call void %p() | 
 |   ret void | 
 | } | 
 |  | 
 | declare void @external(ptr) readonly nounwind | 
 | define void @nc4(ptr %p) { | 
 | ; CHECK-LABEL: define void @nc4 | 
 | ; CHECK-SAME: (ptr nocapture readonly [[P:%.*]]) #[[ATTR9:[0-9]+]] { | 
 | ; CHECK-NEXT:    call void @external(ptr [[P]]) | 
 | ; CHECK-NEXT:    ret void | 
 | ; | 
 |   call void @external(ptr %p) | 
 |   ret void | 
 | } | 
 |  | 
 | define void @nc5(ptr %f, ptr %p) { | 
 | ; CHECK-LABEL: define void @nc5 | 
 | ; CHECK-SAME: (ptr nocapture readonly [[F:%.*]], ptr nocapture [[P:%.*]]) { | 
 | ; CHECK-NEXT:    call void [[F]](ptr [[P]]) #[[ATTR8:[0-9]+]] | 
 | ; CHECK-NEXT:    call void [[F]](ptr nocapture [[P]]) | 
 | ; CHECK-NEXT:    ret void | 
 | ; | 
 |   call void %f(ptr %p) readonly nounwind | 
 |   call void %f(ptr nocapture %p) | 
 |   ret void | 
 | } | 
 |  | 
 | ; It would be acceptable to add readnone to %y1_1 and %y1_2. | 
 | define void @test1_1(ptr %x1_1, ptr %y1_1, i1 %c) { | 
 | ; CHECK-LABEL: define void @test1_1 | 
 | ; CHECK-SAME: (ptr nocapture readnone [[X1_1:%.*]], ptr [[Y1_1:%.*]], i1 [[C:%.*]]) #[[ATTR10:[0-9]+]] { | 
 | ; CHECK-NEXT:    [[TMP1:%.*]] = call ptr @test1_2(ptr [[X1_1]], ptr [[Y1_1]], i1 [[C]]) | 
 | ; CHECK-NEXT:    store ptr null, ptr @g, align 8 | 
 | ; CHECK-NEXT:    ret void | 
 | ; | 
 |   call ptr @test1_2(ptr %x1_1, ptr %y1_1, i1 %c) | 
 |   store ptr null, ptr @g | 
 |   ret void | 
 | } | 
 |  | 
 | define ptr @test1_2(ptr %x1_2, ptr %y1_2, i1 %c) { | 
 | ; CHECK-LABEL: define ptr @test1_2 | 
 | ; CHECK-SAME: (ptr nocapture readnone [[X1_2:%.*]], ptr returned [[Y1_2:%.*]], i1 [[C:%.*]]) #[[ATTR10]] { | 
 | ; CHECK-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]] | 
 | ; CHECK:       t: | 
 | ; CHECK-NEXT:    call void @test1_1(ptr [[X1_2]], ptr [[Y1_2]], i1 [[C]]) | 
 | ; CHECK-NEXT:    store ptr null, ptr @g, align 8 | 
 | ; CHECK-NEXT:    br label [[F]] | 
 | ; CHECK:       f: | 
 | ; CHECK-NEXT:    ret ptr [[Y1_2]] | 
 | ; | 
 |   br i1 %c, label %t, label %f | 
 | t: | 
 |   call void @test1_1(ptr %x1_2, ptr %y1_2, i1 %c) | 
 |   store ptr null, ptr @g | 
 |   br label %f | 
 | f: | 
 |   ret ptr %y1_2 | 
 | } | 
 |  | 
 | define void @test2(ptr %x2) { | 
 | ; CHECK-LABEL: define void @test2 | 
 | ; CHECK-SAME: (ptr nocapture readnone [[X2:%.*]]) #[[ATTR10]] { | 
 | ; CHECK-NEXT:    call void @test2(ptr [[X2]]) | 
 | ; CHECK-NEXT:    store ptr null, ptr @g, align 8 | 
 | ; CHECK-NEXT:    ret void | 
 | ; | 
 |   call void @test2(ptr %x2) | 
 |   store ptr null, ptr @g | 
 |   ret void | 
 | } | 
 |  | 
 | define void @test3(ptr %x3, ptr %y3, ptr %z3) { | 
 | ; CHECK-LABEL: define void @test3 | 
 | ; CHECK-SAME: (ptr nocapture readnone [[X3:%.*]], ptr nocapture readnone [[Y3:%.*]], ptr nocapture readnone [[Z3:%.*]]) #[[ATTR10]] { | 
 | ; CHECK-NEXT:    call void @test3(ptr [[Z3]], ptr [[Y3]], ptr [[X3]]) | 
 | ; CHECK-NEXT:    store ptr null, ptr @g, align 8 | 
 | ; CHECK-NEXT:    ret void | 
 | ; | 
 |   call void @test3(ptr %z3, ptr %y3, ptr %x3) | 
 |   store ptr null, ptr @g | 
 |   ret void | 
 | } | 
 |  | 
 | define void @test4_1(ptr %x4_1, i1 %c) { | 
 | ; CHECK-LABEL: define void @test4_1 | 
 | ; CHECK-SAME: (ptr [[X4_1:%.*]], i1 [[C:%.*]]) #[[ATTR10]] { | 
 | ; CHECK-NEXT:    [[TMP1:%.*]] = call ptr @test4_2(ptr [[X4_1]], ptr [[X4_1]], ptr [[X4_1]], i1 [[C]]) | 
 | ; CHECK-NEXT:    store ptr null, ptr @g, align 8 | 
 | ; CHECK-NEXT:    ret void | 
 | ; | 
 |   call ptr @test4_2(ptr %x4_1, ptr %x4_1, ptr %x4_1, i1 %c) | 
 |   store ptr null, ptr @g | 
 |   ret void | 
 | } | 
 |  | 
 | define ptr @test4_2(ptr %x4_2, ptr %y4_2, ptr %z4_2, i1 %c) { | 
 | ; CHECK-LABEL: define ptr @test4_2 | 
 | ; CHECK-SAME: (ptr nocapture readnone [[X4_2:%.*]], ptr readnone returned [[Y4_2:%.*]], ptr nocapture readnone [[Z4_2:%.*]], i1 [[C:%.*]]) #[[ATTR10]] { | 
 | ; CHECK-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]] | 
 | ; CHECK:       t: | 
 | ; CHECK-NEXT:    call void @test4_1(ptr null, i1 [[C]]) | 
 | ; CHECK-NEXT:    store ptr null, ptr @g, align 8 | 
 | ; CHECK-NEXT:    br label [[F]] | 
 | ; CHECK:       f: | 
 | ; CHECK-NEXT:    ret ptr [[Y4_2]] | 
 | ; | 
 |   br i1 %c, label %t, label %f | 
 | t: | 
 |   call void @test4_1(ptr null, i1 %c) | 
 |   store ptr null, ptr @g | 
 |   br label %f | 
 | f: | 
 |   ret ptr %y4_2 | 
 | } | 
 |  | 
 | declare ptr @test5_1(ptr %x5_1) | 
 |  | 
 | define void @test5_2(ptr %x5_2) { | 
 | ; CHECK-LABEL: define void @test5_2 | 
 | ; CHECK-SAME: (ptr [[X5_2:%.*]]) { | 
 | ; CHECK-NEXT:    [[TMP1:%.*]] = call ptr @test5_1(ptr [[X5_2]]) | 
 | ; CHECK-NEXT:    store ptr null, ptr @g, align 8 | 
 | ; CHECK-NEXT:    ret void | 
 | ; | 
 |   call ptr @test5_1(ptr %x5_2) | 
 |   store ptr null, ptr @g | 
 |   ret void | 
 | } | 
 |  | 
 | declare void @test6_1(ptr %x6_1, ptr nocapture %y6_1, ...) | 
 |  | 
 | define void @test6_2(ptr %x6_2, ptr %y6_2, ptr %z6_2) { | 
 | ; CHECK-LABEL: define void @test6_2 | 
 | ; CHECK-SAME: (ptr [[X6_2:%.*]], ptr nocapture [[Y6_2:%.*]], ptr [[Z6_2:%.*]]) { | 
 | ; CHECK-NEXT:    call void (ptr, ptr, ...) @test6_1(ptr [[X6_2]], ptr [[Y6_2]], ptr [[Z6_2]]) | 
 | ; CHECK-NEXT:    store ptr null, ptr @g, align 8 | 
 | ; CHECK-NEXT:    ret void | 
 | ; | 
 |   call void (ptr, ptr, ...) @test6_1(ptr %x6_2, ptr %y6_2, ptr %z6_2) | 
 |   store ptr null, ptr @g | 
 |   ret void | 
 | } | 
 |  | 
 | define void @test_cmpxchg(ptr %p) { | 
 | ; CHECK-LABEL: define void @test_cmpxchg | 
 | ; CHECK-SAME: (ptr nocapture [[P:%.*]]) #[[ATTR11:[0-9]+]] { | 
 | ; CHECK-NEXT:    [[TMP1:%.*]] = cmpxchg ptr [[P]], i32 0, i32 1 acquire monotonic, align 4 | 
 | ; CHECK-NEXT:    ret void | 
 | ; | 
 |   cmpxchg ptr %p, i32 0, i32 1 acquire monotonic | 
 |   ret void | 
 | } | 
 |  | 
 | define void @test_cmpxchg_ptr(ptr %p, ptr %q) { | 
 | ; CHECK-LABEL: define void @test_cmpxchg_ptr | 
 | ; CHECK-SAME: (ptr nocapture [[P:%.*]], ptr [[Q:%.*]]) #[[ATTR11]] { | 
 | ; CHECK-NEXT:    [[TMP1:%.*]] = cmpxchg ptr [[P]], ptr null, ptr [[Q]] acquire monotonic, align 8 | 
 | ; CHECK-NEXT:    ret void | 
 | ; | 
 |   cmpxchg ptr %p, ptr null, ptr %q acquire monotonic | 
 |   ret void | 
 | } | 
 |  | 
 | define void @test_atomicrmw(ptr %p) { | 
 | ; CHECK-LABEL: define void @test_atomicrmw | 
 | ; CHECK-SAME: (ptr nocapture [[P:%.*]]) #[[ATTR11]] { | 
 | ; CHECK-NEXT:    [[TMP1:%.*]] = atomicrmw add ptr [[P]], i32 1 seq_cst, align 4 | 
 | ; CHECK-NEXT:    ret void | 
 | ; | 
 |   atomicrmw add ptr %p, i32 1 seq_cst | 
 |   ret void | 
 | } | 
 |  | 
 | define void @test_volatile(ptr %x) { | 
 | ; CHECK-LABEL: define void @test_volatile | 
 | ; CHECK-SAME: (ptr [[X:%.*]]) #[[ATTR12:[0-9]+]] { | 
 | ; CHECK-NEXT:  entry: | 
 | ; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i32, ptr [[X]], i64 1 | 
 | ; CHECK-NEXT:    store volatile i32 0, ptr [[GEP]], align 4 | 
 | ; CHECK-NEXT:    ret void | 
 | ; | 
 | entry: | 
 |   %gep = getelementptr i32, ptr %x, i64 1 | 
 |   store volatile i32 0, ptr %gep, align 4 | 
 |   ret void | 
 | } | 
 |  | 
 | define void @nocaptureLaunder(ptr %p) { | 
 | ; CHECK-LABEL: define void @nocaptureLaunder | 
 | ; CHECK-SAME: (ptr nocapture [[P:%.*]]) #[[ATTR13:[0-9]+]] { | 
 | ; CHECK-NEXT:  entry: | 
 | ; CHECK-NEXT:    [[B:%.*]] = call ptr @llvm.launder.invariant.group.p0(ptr [[P]]) | 
 | ; CHECK-NEXT:    store i8 42, ptr [[B]], align 1 | 
 | ; CHECK-NEXT:    ret void | 
 | ; | 
 | entry: | 
 |   %b = call ptr @llvm.launder.invariant.group.p0(ptr %p) | 
 |   store i8 42, ptr %b | 
 |   ret void | 
 | } | 
 |  | 
 | @g2 = global ptr null | 
 | define void @captureLaunder(ptr %p) { | 
 | ; CHECK-LABEL: define void @captureLaunder | 
 | ; CHECK-SAME: (ptr [[P:%.*]]) #[[ATTR14:[0-9]+]] { | 
 | ; CHECK-NEXT:    [[B:%.*]] = call ptr @llvm.launder.invariant.group.p0(ptr [[P]]) | 
 | ; CHECK-NEXT:    store ptr [[B]], ptr @g2, align 8 | 
 | ; CHECK-NEXT:    ret void | 
 | ; | 
 |   %b = call ptr @llvm.launder.invariant.group.p0(ptr %p) | 
 |   store ptr %b, ptr @g2 | 
 |   ret void | 
 | } | 
 |  | 
 | define void @nocaptureStrip(ptr %p) { | 
 | ; CHECK-LABEL: define void @nocaptureStrip | 
 | ; CHECK-SAME: (ptr nocapture writeonly [[P:%.*]]) #[[ATTR15:[0-9]+]] { | 
 | ; CHECK-NEXT:  entry: | 
 | ; CHECK-NEXT:    [[B:%.*]] = call ptr @llvm.strip.invariant.group.p0(ptr [[P]]) | 
 | ; CHECK-NEXT:    store i8 42, ptr [[B]], align 1 | 
 | ; CHECK-NEXT:    ret void | 
 | ; | 
 | entry: | 
 |   %b = call ptr @llvm.strip.invariant.group.p0(ptr %p) | 
 |   store i8 42, ptr %b | 
 |   ret void | 
 | } | 
 |  | 
 | @g3 = global ptr null | 
 | define void @captureStrip(ptr %p) { | 
 | ; CHECK-LABEL: define void @captureStrip | 
 | ; CHECK-SAME: (ptr [[P:%.*]]) #[[ATTR16:[0-9]+]] { | 
 | ; CHECK-NEXT:    [[B:%.*]] = call ptr @llvm.strip.invariant.group.p0(ptr [[P]]) | 
 | ; CHECK-NEXT:    store ptr [[B]], ptr @g3, align 8 | 
 | ; CHECK-NEXT:    ret void | 
 | ; | 
 |   %b = call ptr @llvm.strip.invariant.group.p0(ptr %p) | 
 |   store ptr %b, ptr @g3 | 
 |   ret void | 
 | } | 
 |  | 
 | define i1 @captureICmp(ptr %x) { | 
 | ; CHECK-LABEL: define i1 @captureICmp | 
 | ; CHECK-SAME: (ptr readnone [[X:%.*]]) #[[ATTR0]] { | 
 | ; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq ptr [[X]], null | 
 | ; CHECK-NEXT:    ret i1 [[TMP1]] | 
 | ; | 
 |   %1 = icmp eq ptr %x, null | 
 |   ret i1 %1 | 
 | } | 
 |  | 
 | define i1 @captureICmpRev(ptr %x) { | 
 | ; CHECK-LABEL: define i1 @captureICmpRev | 
 | ; CHECK-SAME: (ptr readnone [[X:%.*]]) #[[ATTR0]] { | 
 | ; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq ptr null, [[X]] | 
 | ; CHECK-NEXT:    ret i1 [[TMP1]] | 
 | ; | 
 |   %1 = icmp eq ptr null, %x | 
 |   ret i1 %1 | 
 | } | 
 |  | 
 | define i1 @nocaptureInboundsGEPICmp(ptr %x) { | 
 | ; CHECK-LABEL: define i1 @nocaptureInboundsGEPICmp | 
 | ; CHECK-SAME: (ptr readnone [[X:%.*]]) #[[ATTR0]] { | 
 | ; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[X]], i32 5 | 
 | ; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq ptr [[TMP1]], null | 
 | ; CHECK-NEXT:    ret i1 [[TMP2]] | 
 | ; | 
 |   %1 = getelementptr inbounds i32, ptr %x, i32 5 | 
 |   %2 = icmp eq ptr %1, null | 
 |   ret i1 %2 | 
 | } | 
 |  | 
 | define i1 @nocaptureInboundsGEPICmpRev(ptr %x) { | 
 | ; CHECK-LABEL: define i1 @nocaptureInboundsGEPICmpRev | 
 | ; CHECK-SAME: (ptr readnone [[X:%.*]]) #[[ATTR0]] { | 
 | ; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[X]], i32 5 | 
 | ; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq ptr null, [[TMP1]] | 
 | ; CHECK-NEXT:    ret i1 [[TMP2]] | 
 | ; | 
 |   %1 = getelementptr inbounds i32, ptr %x, i32 5 | 
 |   %2 = icmp eq ptr null, %1 | 
 |   ret i1 %2 | 
 | } | 
 |  | 
 | define i1 @nocaptureDereferenceableOrNullICmp(ptr dereferenceable_or_null(4) %x) { | 
 | ; CHECK-LABEL: define i1 @nocaptureDereferenceableOrNullICmp | 
 | ; CHECK-SAME: (ptr nocapture readnone dereferenceable_or_null(4) [[X:%.*]]) #[[ATTR0]] { | 
 | ; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq ptr [[X]], null | 
 | ; CHECK-NEXT:    ret i1 [[TMP1]] | 
 | ; | 
 |   %1 = icmp eq ptr %x, null | 
 |   ret i1 %1 | 
 | } | 
 |  | 
 | define i1 @captureDereferenceableOrNullICmp(ptr dereferenceable_or_null(4) %x) null_pointer_is_valid { | 
 | ; CHECK-LABEL: define i1 @captureDereferenceableOrNullICmp | 
 | ; CHECK-SAME: (ptr readnone dereferenceable_or_null(4) [[X:%.*]]) #[[ATTR17:[0-9]+]] { | 
 | ; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq ptr [[X]], null | 
 | ; CHECK-NEXT:    ret i1 [[TMP1]] | 
 | ; | 
 |   %1 = icmp eq ptr %x, null | 
 |   ret i1 %1 | 
 | } | 
 |  | 
 | declare void @capture(ptr) | 
 |  | 
 | define void @nocapture_fptr(ptr %f, ptr %p) { | 
 | ; CHECK-LABEL: define void @nocapture_fptr | 
 | ; CHECK-SAME: (ptr nocapture readonly [[F:%.*]], ptr [[P:%.*]]) { | 
 | ; CHECK-NEXT:    [[RES:%.*]] = call ptr [[F]](ptr [[P]]) | 
 | ; CHECK-NEXT:    call void @capture(ptr [[RES]]) | 
 | ; CHECK-NEXT:    ret void | 
 | ; | 
 |   %res = call ptr %f(ptr %p) | 
 |   call void @capture(ptr %res) | 
 |   ret void | 
 | } | 
 |  | 
 | define void @recurse_fptr(ptr %f, ptr %p) { | 
 | ; CHECK-LABEL: define void @recurse_fptr | 
 | ; CHECK-SAME: (ptr nocapture readonly [[F:%.*]], ptr [[P:%.*]]) { | 
 | ; CHECK-NEXT:    [[RES:%.*]] = call ptr [[F]](ptr [[P]]) | 
 | ; CHECK-NEXT:    store i8 0, ptr [[RES]], align 1 | 
 | ; CHECK-NEXT:    ret void | 
 | ; | 
 |   %res = call ptr %f(ptr %p) | 
 |   store i8 0, ptr %res | 
 |   ret void | 
 | } | 
 |  | 
 | define void @readnone_indirec(ptr %f, ptr %p) { | 
 | ; CHECK-LABEL: define void @readnone_indirec | 
 | ; CHECK-SAME: (ptr nocapture readonly [[F:%.*]], ptr readnone [[P:%.*]]) #[[ATTR18:[0-9]+]] { | 
 | ; CHECK-NEXT:    call void [[F]](ptr [[P]]) #[[ATTR21:[0-9]+]] | 
 | ; CHECK-NEXT:    ret void | 
 | ; | 
 |   call void %f(ptr %p) readnone | 
 |   ret void | 
 | } | 
 |  | 
 |  | 
 | declare ptr @llvm.launder.invariant.group.p0(ptr) | 
 | declare ptr @llvm.strip.invariant.group.p0(ptr) |