666 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-attributes --version 42; RUN: opt -passes=function-attrs -S < %s | FileCheck %s3 4define void @basic(ptr %p) {5; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)6; CHECK-LABEL: define void @basic(7; CHECK-SAME: ptr writeonly captures(none) initializes((0, 8)) [[P:%.*]]) #[[ATTR0:[0-9]+]] {8; CHECK-NEXT: store i64 123, ptr [[P]], align 49; CHECK-NEXT: ret void10;11 store i64 123, ptr %p12 ret void13}14 15define void @stores_on_both_paths(ptr %p, i1 %i) {16; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)17; CHECK-LABEL: define void @stores_on_both_paths(18; CHECK-SAME: ptr writeonly captures(none) initializes((0, 8)) [[P:%.*]], i1 [[I:%.*]]) #[[ATTR0]] {19; CHECK-NEXT: entry:20; CHECK-NEXT: br i1 [[I]], label [[BB1:%.*]], label [[BB2:%.*]]21; CHECK: bb1:22; CHECK-NEXT: store i64 123, ptr [[P]], align 423; CHECK-NEXT: br label [[END:%.*]]24; CHECK: bb2:25; CHECK-NEXT: store i64 321, ptr [[P]], align 426; CHECK-NEXT: br label [[END]]27; CHECK: end:28; CHECK-NEXT: ret void29;30entry:31 br i1 %i, label %bb1, label %bb232bb1:33 store i64 123, ptr %p34 br label %end35bb2:36 store i64 321, ptr %p37 br label %end38end:39 ret void40}41 42define void @store_pointer_to_pointer(ptr %p, ptr %p2) {43; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)44; CHECK-LABEL: define void @store_pointer_to_pointer(45; CHECK-SAME: ptr [[P:%.*]], ptr writeonly captures(none) initializes((0, 8)) [[P2:%.*]]) #[[ATTR0]] {46; CHECK-NEXT: store ptr [[P]], ptr [[P2]], align 847; CHECK-NEXT: ret void48;49 store ptr %p, ptr %p250 ret void51}52 53; TODO: this is still initializes54define void @store_pointer_to_itself(ptr %p) {55; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)56; CHECK-LABEL: define void @store_pointer_to_itself(57; CHECK-SAME: ptr [[P:%.*]]) #[[ATTR0]] {58; CHECK-NEXT: store ptr [[P]], ptr [[P]], align 859; CHECK-NEXT: ret void60;61 store ptr %p, ptr %p62 ret void63}64 65define void @load_before_store(ptr %p) {66; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite)67; CHECK-LABEL: define void @load_before_store(68; CHECK-SAME: ptr captures(none) [[P:%.*]]) #[[ATTR1:[0-9]+]] {69; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[P]], align 470; CHECK-NEXT: store i32 123, ptr [[P]], align 471; CHECK-NEXT: ret void72;73 %a = load i32, ptr %p74 store i32 123, ptr %p75 ret void76}77 78define void @partial_load_before_store(ptr %p) {79; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite)80; CHECK-LABEL: define void @partial_load_before_store(81; CHECK-SAME: ptr captures(none) initializes((4, 8)) [[P:%.*]]) #[[ATTR1]] {82; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[P]], align 483; CHECK-NEXT: store i64 123, ptr [[P]], align 484; CHECK-NEXT: ret void85;86 %a = load i32, ptr %p87 store i64 123, ptr %p88 ret void89}90 91declare void @use(ptr)92 93define void @call_clobber(ptr %p) {94; CHECK-LABEL: define void @call_clobber(95; CHECK-SAME: ptr [[P:%.*]]) {96; CHECK-NEXT: call void @use(ptr [[P]])97; CHECK-NEXT: store i64 123, ptr [[P]], align 498; CHECK-NEXT: ret void99;100 call void @use(ptr %p)101 store i64 123, ptr %p102 ret void103}104 105define void @call_clobber_after_store(ptr %p) {106; CHECK-LABEL: define void @call_clobber_after_store(107; CHECK-SAME: ptr initializes((0, 8)) [[P:%.*]]) {108; CHECK-NEXT: store i64 123, ptr [[P]], align 4109; CHECK-NEXT: call void @use(ptr [[P]])110; CHECK-NEXT: ret void111;112 store i64 123, ptr %p113 call void @use(ptr %p)114 ret void115}116 117define void @store_offset(ptr %p) {118; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)119; CHECK-LABEL: define void @store_offset(120; CHECK-SAME: ptr writeonly captures(none) initializes((8, 12)) [[P:%.*]]) #[[ATTR0]] {121; CHECK-NEXT: [[G:%.*]] = getelementptr i8, ptr [[P]], i64 8122; CHECK-NEXT: store i32 123, ptr [[G]], align 4123; CHECK-NEXT: ret void124;125 %g = getelementptr i8, ptr %p, i64 8126 store i32 123, ptr %g127 ret void128}129 130define void @store_volatile(ptr %p) {131; CHECK: Function Attrs: nofree norecurse nounwind memory(argmem: readwrite, inaccessiblemem: readwrite)132; CHECK-LABEL: define void @store_volatile(133; CHECK-SAME: ptr [[P:%.*]]) #[[ATTR2:[0-9]+]] {134; CHECK-NEXT: [[G:%.*]] = getelementptr i8, ptr [[P]], i64 8135; CHECK-NEXT: store volatile i32 123, ptr [[G]], align 4136; CHECK-NEXT: ret void137;138 %g = getelementptr i8, ptr %p, i64 8139 store volatile i32 123, ptr %g140 ret void141}142 143define void @merge_store_ranges(ptr %p) {144; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)145; CHECK-LABEL: define void @merge_store_ranges(146; CHECK-SAME: ptr writeonly captures(none) initializes((0, 8)) [[P:%.*]]) #[[ATTR0]] {147; CHECK-NEXT: [[G:%.*]] = getelementptr i8, ptr [[P]], i64 4148; CHECK-NEXT: store i32 123, ptr [[G]], align 4149; CHECK-NEXT: store i32 123, ptr [[P]], align 4150; CHECK-NEXT: ret void151;152 %g = getelementptr i8, ptr %p, i64 4153 store i32 123, ptr %g154 store i32 123, ptr %p155 ret void156}157 158define void @partially_overlapping_stores_branches(ptr %p, i1 %i) {159; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite)160; CHECK-LABEL: define void @partially_overlapping_stores_branches(161; CHECK-SAME: ptr captures(none) initializes((4, 8)) [[P:%.*]], i1 [[I:%.*]]) #[[ATTR1]] {162; CHECK-NEXT: entry:163; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[P]], align 4164; CHECK-NEXT: [[G:%.*]] = getelementptr i8, ptr [[P]], i64 4165; CHECK-NEXT: br i1 [[I]], label [[BB1:%.*]], label [[BB2:%.*]]166; CHECK: bb1:167; CHECK-NEXT: store i64 123, ptr [[G]], align 4168; CHECK-NEXT: br label [[END:%.*]]169; CHECK: bb2:170; CHECK-NEXT: store i64 321, ptr [[P]], align 4171; CHECK-NEXT: br label [[END]]172; CHECK: end:173; CHECK-NEXT: ret void174;175entry:176 %a = load i32, ptr %p177 %g = getelementptr i8, ptr %p, i64 4178 br i1 %i, label %bb1, label %bb2179bb1:180 store i64 123, ptr %g181 br label %end182bb2:183 store i64 321, ptr %p184 br label %end185end:186 ret void187}188 189define void @non_overlapping_stores_branches(ptr %p, i1 %i) {190; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)191; CHECK-LABEL: define void @non_overlapping_stores_branches(192; CHECK-SAME: ptr writeonly captures(none) [[P:%.*]], i1 [[I:%.*]]) #[[ATTR0]] {193; CHECK-NEXT: entry:194; CHECK-NEXT: [[G:%.*]] = getelementptr i8, ptr [[P]], i64 8195; CHECK-NEXT: br i1 [[I]], label [[BB1:%.*]], label [[BB2:%.*]]196; CHECK: bb1:197; CHECK-NEXT: store i64 123, ptr [[G]], align 4198; CHECK-NEXT: br label [[END:%.*]]199; CHECK: bb2:200; CHECK-NEXT: store i64 321, ptr [[P]], align 4201; CHECK-NEXT: br label [[END]]202; CHECK: end:203; CHECK-NEXT: ret void204;205entry:206 %g = getelementptr i8, ptr %p, i64 8207 br i1 %i, label %bb1, label %bb2208bb1:209 store i64 123, ptr %g210 br label %end211bb2:212 store i64 321, ptr %p213 br label %end214end:215 ret void216}217 218define void @dominating_store(ptr %p, i1 %i) {219; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)220; CHECK-LABEL: define void @dominating_store(221; CHECK-SAME: ptr writeonly captures(none) initializes((0, 8)) [[P:%.*]], i1 [[I:%.*]]) #[[ATTR0]] {222; CHECK-NEXT: entry:223; CHECK-NEXT: br i1 [[I]], label [[BB1:%.*]], label [[BB2:%.*]]224; CHECK: bb1:225; CHECK-NEXT: br label [[END:%.*]]226; CHECK: bb2:227; CHECK-NEXT: br label [[END]]228; CHECK: end:229; CHECK-NEXT: store i64 321, ptr [[P]], align 4230; CHECK-NEXT: ret void231;232entry:233 br i1 %i, label %bb1, label %bb2234bb1:235 br label %end236bb2:237 br label %end238end:239 store i64 321, ptr %p240 ret void241}242 243define void @call_clobber_on_one_branch(ptr %p, i1 %i) {244; CHECK-LABEL: define void @call_clobber_on_one_branch(245; CHECK-SAME: ptr [[P:%.*]], i1 [[I:%.*]]) {246; CHECK-NEXT: entry:247; CHECK-NEXT: br i1 [[I]], label [[BB1:%.*]], label [[BB2:%.*]]248; CHECK: bb1:249; CHECK-NEXT: br label [[END:%.*]]250; CHECK: bb2:251; CHECK-NEXT: call void @use(ptr [[P]])252; CHECK-NEXT: br label [[END]]253; CHECK: end:254; CHECK-NEXT: store i64 321, ptr [[P]], align 4255; CHECK-NEXT: ret void256;257entry:258 br i1 %i, label %bb1, label %bb2259bb1:260 br label %end261bb2:262 call void @use(ptr %p)263 br label %end264end:265 store i64 321, ptr %p266 ret void267}268 269define void @merge_existing_initializes(ptr initializes((33, 36)) %p) {270; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)271; CHECK-LABEL: define void @merge_existing_initializes(272; CHECK-SAME: ptr writeonly captures(none) initializes((0, 8), (33, 36)) [[P:%.*]]) #[[ATTR0]] {273; CHECK-NEXT: store i64 123, ptr [[P]], align 4274; CHECK-NEXT: ret void275;276 store i64 123, ptr %p277 ret void278}279 280define void @negative_offset(ptr %p) {281; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)282; CHECK-LABEL: define void @negative_offset(283; CHECK-SAME: ptr writeonly captures(none) initializes((-5, 3)) [[P:%.*]]) #[[ATTR0]] {284; CHECK-NEXT: [[G:%.*]] = getelementptr i8, ptr [[P]], i64 -5285; CHECK-NEXT: store i64 123, ptr [[G]], align 4286; CHECK-NEXT: ret void287;288 %g = getelementptr i8, ptr %p, i64 -5289 store i64 123, ptr %g290 ret void291}292 293define void @non_const_gep(ptr %p, i64 %i) {294; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)295; CHECK-LABEL: define void @non_const_gep(296; CHECK-SAME: ptr writeonly captures(none) initializes((0, 8)) [[P:%.*]], i64 [[I:%.*]]) #[[ATTR0]] {297; CHECK-NEXT: [[G:%.*]] = getelementptr i8, ptr [[P]], i64 [[I]]298; CHECK-NEXT: store i64 123, ptr [[G]], align 4299; CHECK-NEXT: store i64 123, ptr [[P]], align 4300; CHECK-NEXT: ret void301;302 %g = getelementptr i8, ptr %p, i64 %i303 store i64 123, ptr %g304 store i64 123, ptr %p305 ret void306}307 308define void @call_clobber_in_entry_block(ptr %p, i1 %i) {309; CHECK-LABEL: define void @call_clobber_in_entry_block(310; CHECK-SAME: ptr [[P:%.*]], i1 [[I:%.*]]) {311; CHECK-NEXT: entry:312; CHECK-NEXT: call void @use(ptr [[P]])313; CHECK-NEXT: br i1 [[I]], label [[BB1:%.*]], label [[BB2:%.*]]314; CHECK: bb1:315; CHECK-NEXT: store i64 123, ptr [[P]], align 4316; CHECK-NEXT: br label [[END:%.*]]317; CHECK: bb2:318; CHECK-NEXT: store i64 321, ptr [[P]], align 4319; CHECK-NEXT: br label [[END]]320; CHECK: end:321; CHECK-NEXT: ret void322;323entry:324 call void @use(ptr %p)325 br i1 %i, label %bb1, label %bb2326bb1:327 store i64 123, ptr %p328 br label %end329bb2:330 store i64 321, ptr %p331 br label %end332end:333 ret void334}335 336declare void @g1(ptr initializes((0, 4)) %p)337declare void @g2(ptr initializes((8, 12)) %p)338declare void @g3(ptr initializes((0, 4)) writeonly nocapture %p)339 340define void @call_initializes(ptr %p) {341; CHECK-LABEL: define void @call_initializes(342; CHECK-SAME: ptr initializes((0, 4)) [[P:%.*]]) {343; CHECK-NEXT: call void @g1(ptr [[P]])344; CHECK-NEXT: ret void345;346 call void @g1(ptr %p)347 ret void348}349 350define void @call_initializes_clobber(ptr %p) {351; CHECK-LABEL: define void @call_initializes_clobber(352; CHECK-SAME: ptr initializes((0, 4)) [[P:%.*]]) {353; CHECK-NEXT: call void @g1(ptr [[P]])354; CHECK-NEXT: call void @g2(ptr [[P]])355; CHECK-NEXT: ret void356;357 call void @g1(ptr %p)358 call void @g2(ptr %p)359 ret void360}361 362define void @call_initializes_no_clobber_writeonly_nocapture(ptr %p) {363; CHECK-LABEL: define void @call_initializes_no_clobber_writeonly_nocapture(364; CHECK-SAME: ptr initializes((0, 4), (8, 12)) [[P:%.*]]) {365; CHECK-NEXT: call void @g3(ptr [[P]])366; CHECK-NEXT: call void @g2(ptr [[P]])367; CHECK-NEXT: ret void368;369 call void @g3(ptr %p)370 call void @g2(ptr %p)371 ret void372}373 374define void @call_initializes_escape_bundle(ptr %p) {375; CHECK-LABEL: define void @call_initializes_escape_bundle(376; CHECK-SAME: ptr [[P:%.*]]) {377; CHECK-NEXT: call void @g1(ptr [[P]]) [ "unknown"(ptr [[P]]) ]378; CHECK-NEXT: ret void379;380 call void @g1(ptr %p) ["unknown"(ptr %p)]381 ret void382}383 384define void @access_bundle() {385; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)386; CHECK-LABEL: define void @access_bundle(387; CHECK-SAME: ) #[[ATTR3:[0-9]+]] {388; CHECK-NEXT: [[SINK:%.*]] = alloca i64, align 8389; CHECK-NEXT: store i64 123, ptr [[SINK]], align 4390; CHECK-NEXT: ret void391;392 %sink = alloca i64, align 8393 store i64 123, ptr %sink394 ret void395}396 397define void @call_operand_bundle(ptr %p) {398; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn399; CHECK-LABEL: define void @call_operand_bundle(400; CHECK-SAME: ptr [[P:%.*]]) #[[ATTR4:[0-9]+]] {401; CHECK-NEXT: call void @access_bundle() [ "unknown"(ptr [[P]]) ]402; CHECK-NEXT: ret void403;404 call void @access_bundle() ["unknown"(ptr %p)]405 ret void406}407 408declare void @llvm.memset(ptr, i8, i64 ,i1)409 410define void @memset(ptr %p) {411; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)412; CHECK-LABEL: define void @memset(413; CHECK-SAME: ptr writeonly captures(none) initializes((0, 9)) [[P:%.*]]) #[[ATTR0]] {414; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[P]], i8 2, i64 9, i1 false)415; CHECK-NEXT: ret void416;417 call void @llvm.memset(ptr %p, i8 2, i64 9, i1 false)418 ret void419}420 421define void @memset_offset(ptr %p) {422; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)423; CHECK-LABEL: define void @memset_offset(424; CHECK-SAME: ptr writeonly captures(none) initializes((3, 12)) [[P:%.*]]) #[[ATTR0]] {425; CHECK-NEXT: [[G:%.*]] = getelementptr i8, ptr [[P]], i64 3426; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[G]], i8 2, i64 9, i1 false)427; CHECK-NEXT: ret void428;429 %g = getelementptr i8, ptr %p, i64 3430 call void @llvm.memset(ptr %g, i8 2, i64 9, i1 false)431 ret void432}433 434define void @memset_neg(ptr %p) {435; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)436; CHECK-LABEL: define void @memset_neg(437; CHECK-SAME: ptr writeonly captures(none) [[P:%.*]]) #[[ATTR0]] {438; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[P]], i8 2, i64 -1, i1 false)439; CHECK-NEXT: ret void440;441 call void @llvm.memset(ptr %p, i8 2, i64 -1, i1 false)442 ret void443}444 445define void @memset_volatile(ptr %p) {446; CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: write, inaccessiblemem: readwrite)447; CHECK-LABEL: define void @memset_volatile(448; CHECK-SAME: ptr writeonly [[P:%.*]]) #[[ATTR5:[0-9]+]] {449; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[P]], i8 2, i64 9, i1 true)450; CHECK-NEXT: ret void451;452 call void @llvm.memset(ptr %p, i8 2, i64 9, i1 true)453 ret void454}455 456define void @memset_non_constant(ptr %p, i64 %i) {457; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)458; CHECK-LABEL: define void @memset_non_constant(459; CHECK-SAME: ptr writeonly captures(none) [[P:%.*]], i64 [[I:%.*]]) #[[ATTR0]] {460; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[P]], i8 2, i64 [[I]], i1 false)461; CHECK-NEXT: ret void462;463 call void @llvm.memset(ptr %p, i8 2, i64 %i, i1 false)464 ret void465}466 467declare void @llvm.memcpy(ptr, ptr, i64 ,i1)468 469define void @memcpy(ptr %p, ptr %p2) {470; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite)471; CHECK-LABEL: define void @memcpy(472; CHECK-SAME: ptr writeonly captures(none) initializes((0, 9)) [[P:%.*]], ptr readonly captures(none) [[P2:%.*]]) #[[ATTR1]] {473; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[P]], ptr [[P2]], i64 9, i1 false)474; CHECK-NEXT: ret void475;476 call void @llvm.memcpy(ptr %p, ptr %p2, i64 9, i1 false)477 ret void478}479 480define void @memcpy_volatile(ptr %p, ptr %p2) {481; CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite, inaccessiblemem: readwrite)482; CHECK-LABEL: define void @memcpy_volatile(483; CHECK-SAME: ptr writeonly [[P:%.*]], ptr readonly [[P2:%.*]]) #[[ATTR6:[0-9]+]] {484; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[P]], ptr [[P2]], i64 9, i1 true)485; CHECK-NEXT: ret void486;487 call void @llvm.memcpy(ptr %p, ptr %p2, i64 9, i1 true)488 ret void489}490 491define void @memcpy_offset(ptr %p, ptr %p2) {492; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite)493; CHECK-LABEL: define void @memcpy_offset(494; CHECK-SAME: ptr writeonly captures(none) initializes((3, 12)) [[P:%.*]], ptr readonly captures(none) [[P2:%.*]]) #[[ATTR1]] {495; CHECK-NEXT: [[G:%.*]] = getelementptr i8, ptr [[P]], i64 3496; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[G]], ptr [[P2]], i64 9, i1 false)497; CHECK-NEXT: ret void498;499 %g = getelementptr i8, ptr %p, i64 3500 call void @llvm.memcpy(ptr %g, ptr %p2, i64 9, i1 false)501 ret void502}503 504define void @memcpy_src(ptr %p, ptr %p2) {505; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite)506; CHECK-LABEL: define void @memcpy_src(507; CHECK-SAME: ptr captures(none) initializes((96, 128)) [[P:%.*]], ptr captures(none) initializes((0, 96)) [[P2:%.*]]) #[[ATTR1]] {508; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[P2]], ptr [[P]], i64 96, i1 false)509; CHECK-NEXT: [[G:%.*]] = getelementptr i8, ptr [[P]], i64 64510; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[G]], ptr [[P2]], i64 64, i1 false)511; CHECK-NEXT: ret void512;513 call void @llvm.memcpy(ptr %p2, ptr %p, i64 96, i1 false)514 %g = getelementptr i8, ptr %p, i64 64515 call void @llvm.memcpy(ptr %g, ptr %p2, i64 64, i1 false)516 ret void517}518 519define void @memcpy_non_constant(ptr %p, ptr %p2, i64 %i) {520; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite)521; CHECK-LABEL: define void @memcpy_non_constant(522; CHECK-SAME: ptr writeonly captures(none) [[P:%.*]], ptr readonly captures(none) [[P2:%.*]], i64 [[I:%.*]]) #[[ATTR1]] {523; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[P]], ptr [[P2]], i64 [[I]], i1 false)524; CHECK-NEXT: ret void525;526 call void @llvm.memcpy(ptr %p, ptr %p2, i64 %i, i1 false)527 ret void528}529 530declare void @llvm.memmove(ptr, ptr, i64 ,i1)531 532define void @memmove(ptr %p, ptr %p2) {533; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite)534; CHECK-LABEL: define void @memmove(535; CHECK-SAME: ptr writeonly captures(none) initializes((0, 9)) [[P:%.*]], ptr readonly captures(none) [[P2:%.*]]) #[[ATTR1]] {536; CHECK-NEXT: call void @llvm.memmove.p0.p0.i64(ptr [[P]], ptr [[P2]], i64 9, i1 false)537; CHECK-NEXT: ret void538;539 call void @llvm.memmove(ptr %p, ptr %p2, i64 9, i1 false)540 ret void541}542 543define void @memmove_volatile(ptr %p, ptr %p2) {544; CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite, inaccessiblemem: readwrite)545; CHECK-LABEL: define void @memmove_volatile(546; CHECK-SAME: ptr writeonly [[P:%.*]], ptr readonly [[P2:%.*]]) #[[ATTR6]] {547; CHECK-NEXT: call void @llvm.memmove.p0.p0.i64(ptr [[P]], ptr [[P2]], i64 9, i1 true)548; CHECK-NEXT: ret void549;550 call void @llvm.memmove(ptr %p, ptr %p2, i64 9, i1 true)551 ret void552}553 554define void @memmove_offset(ptr %p, ptr %p2) {555; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite)556; CHECK-LABEL: define void @memmove_offset(557; CHECK-SAME: ptr writeonly captures(none) initializes((3, 12)) [[P:%.*]], ptr readonly captures(none) [[P2:%.*]]) #[[ATTR1]] {558; CHECK-NEXT: [[G:%.*]] = getelementptr i8, ptr [[P]], i64 3559; CHECK-NEXT: call void @llvm.memmove.p0.p0.i64(ptr [[G]], ptr [[P2]], i64 9, i1 false)560; CHECK-NEXT: ret void561;562 %g = getelementptr i8, ptr %p, i64 3563 call void @llvm.memmove(ptr %g, ptr %p2, i64 9, i1 false)564 ret void565}566 567define void @memmove_src(ptr %p, ptr %p2) {568; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite)569; CHECK-LABEL: define void @memmove_src(570; CHECK-SAME: ptr captures(none) initializes((96, 128)) [[P:%.*]], ptr captures(none) initializes((0, 96)) [[P2:%.*]]) #[[ATTR1]] {571; CHECK-NEXT: call void @llvm.memmove.p0.p0.i64(ptr [[P2]], ptr [[P]], i64 96, i1 false)572; CHECK-NEXT: [[G:%.*]] = getelementptr i8, ptr [[P]], i64 64573; CHECK-NEXT: call void @llvm.memmove.p0.p0.i64(ptr [[G]], ptr [[P2]], i64 64, i1 false)574; CHECK-NEXT: ret void575;576 call void @llvm.memmove(ptr %p2, ptr %p, i64 96, i1 false)577 %g = getelementptr i8, ptr %p, i64 64578 call void @llvm.memmove(ptr %g, ptr %p2, i64 64, i1 false)579 ret void580}581 582define void @memmove_non_constant(ptr %p, ptr %p2, i64 %i) {583; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite)584; CHECK-LABEL: define void @memmove_non_constant(585; CHECK-SAME: ptr writeonly captures(none) [[P:%.*]], ptr readonly captures(none) [[P2:%.*]], i64 [[I:%.*]]) #[[ATTR1]] {586; CHECK-NEXT: call void @llvm.memmove.p0.p0.i64(ptr [[P]], ptr [[P2]], i64 [[I]], i1 false)587; CHECK-NEXT: ret void588;589 call void @llvm.memmove(ptr %p, ptr %p2, i64 %i, i1 false)590 ret void591}592 593define void @callee_byval(ptr byval(i32) %p) {594; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)595; CHECK-LABEL: define void @callee_byval(596; CHECK-SAME: ptr writeonly byval(i32) captures(none) initializes((0, 4)) [[P:%.*]]) #[[ATTR0]] {597; CHECK-NEXT: store i32 0, ptr [[P]], align 4598; CHECK-NEXT: ret void599;600 store i32 0, ptr %p601 ret void602}603 604define void @caller_byval(ptr %p) {605; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)606; CHECK-LABEL: define void @caller_byval(607; CHECK-SAME: ptr readonly captures(none) [[P:%.*]]) #[[ATTR0]] {608; CHECK-NEXT: call void @callee_byval(ptr byval(i32) [[P]])609; CHECK-NEXT: ret void610;611 call void @callee_byval(ptr byval(i32) %p)612 ret void613}614 615define void @memset_offset_0_size_0(ptr %dst, ptr %src) {616; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite)617; CHECK-LABEL: define void @memset_offset_0_size_0(618; CHECK-SAME: ptr writeonly captures(none) [[DST:%.*]], ptr readonly captures(none) [[SRC:%.*]]) #[[ATTR1]] {619; CHECK-NEXT: call void @llvm.memmove.p0.p0.i64(ptr [[DST]], ptr [[SRC]], i64 0, i1 false)620; CHECK-NEXT: ret void621;622 call void @llvm.memmove.p0.p0.i64(ptr %dst, ptr %src, i64 0, i1 false)623 ret void624}625 626define void @memset_offset_1_size_0(ptr %dst, ptr %src) {627; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite)628; CHECK-LABEL: define void @memset_offset_1_size_0(629; CHECK-SAME: ptr writeonly captures(none) [[DST:%.*]], ptr readonly captures(none) [[SRC:%.*]]) #[[ATTR1]] {630; CHECK-NEXT: [[DST_1:%.*]] = getelementptr inbounds i8, ptr [[DST]], i64 1631; CHECK-NEXT: call void @llvm.memmove.p0.p0.i64(ptr [[DST_1]], ptr [[SRC]], i64 0, i1 false)632; CHECK-NEXT: ret void633;634 %dst.1 = getelementptr inbounds i8, ptr %dst, i64 1635 call void @llvm.memmove.p0.p0.i64(ptr %dst.1, ptr %src, i64 0, i1 false)636 ret void637}638 639; We should bail if the range overflows a singed 64-bit int.640define void @range_overflows_signed_64_bit_int(ptr %arg) {641; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)642; CHECK-LABEL: define void @range_overflows_signed_64_bit_int(643; CHECK-SAME: ptr writeonly captures(none) [[ARG:%.*]]) #[[ATTR0]] {644; CHECK-NEXT: [[GETELEMENTPTR:%.*]] = getelementptr i8, ptr [[ARG]], i64 9223372036854775804645; CHECK-NEXT: store i32 0, ptr [[GETELEMENTPTR]], align 4646; CHECK-NEXT: ret void647;648 %getelementptr = getelementptr i8, ptr %arg, i64 9223372036854775804649 store i32 0, ptr %getelementptr650 ret void651}652 653; We should bail if the memset range overflows a signed 64-bit int.654define void @memset_large_offset_nonzero_size(ptr %dst) {655; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)656; CHECK-LABEL: define void @memset_large_offset_nonzero_size(657; CHECK-SAME: ptr writeonly captures(none) [[DST:%.*]]) #[[ATTR0]] {658; CHECK-NEXT: [[OFFSET:%.*]] = getelementptr inbounds i8, ptr [[DST]], i64 9223372036854775805659; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[OFFSET]], i8 0, i64 3, i1 false)660; CHECK-NEXT: ret void661;662 %offset = getelementptr inbounds i8, ptr %dst, i64 9223372036854775805663 call void @llvm.memset.p0.i64(ptr %offset, i8 0, i64 3, i1 false)664 ret void665}666