172 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-attributes --check-globals2; RUN: opt -passes=ipsccp -S %s | FileCheck %s3 4; Test cases to ensure argmemonly/inaccessiblemem_or_argmemonly attributes are5; dropped, if a function argument is replaced by a constant.6;7; PR467178 9@g = internal global i32 010 11; Here the pointer argument %arg will be replaced by a constant. We need to12; drop argmemonly.13;.14; CHECK: @[[G:[a-zA-Z0-9_$"\\.-]+]] = internal global i32 015;.16define internal void @ptrarg.1(ptr %arg, i32 %val) argmemonly nounwind {17; CHECK: Function Attrs: nounwind memory(readwrite, inaccessiblemem: none, target_mem0: none, target_mem1: none)18; CHECK-LABEL: @ptrarg.1(19; CHECK-NEXT: store i32 10, ptr @g, align 420; CHECK-NEXT: ret void21;22 store i32 %val, ptr %arg23 ret void24}25 26define i32 @caller.1(i32 %n) {27; CHECK-LABEL: @caller.1(28; CHECK-NEXT: store i32 1, ptr @g, align 429; CHECK-NEXT: tail call void @ptrarg.1(ptr @g, i32 10)30; CHECK-NEXT: [[G_VAL:%.*]] = load i32, ptr @g, align 431; CHECK-NEXT: ret i32 [[G_VAL]]32;33 store i32 1, ptr @g34 tail call void @ptrarg.1(ptr @g, i32 10)35 %g.val = load i32, ptr @g36 ret i32 %g.val37}38 39 40; Here only the non-pointer argument %val is replaced, no need41; to drop the argmemonly attribute.42define internal void @ptrarg.2(ptr %arg, i32 %val) argmemonly nounwind {43; CHECK: Function Attrs: nounwind memory(argmem: readwrite)44; CHECK-LABEL: @ptrarg.2(45; CHECK-NEXT: store i32 10, ptr [[ARG:%.*]], align 446; CHECK-NEXT: ret void47;48 store i32 %val, ptr %arg49 ret void50}51 52define void @caller.2(ptr %ptr) {53; CHECK-LABEL: @caller.2(54; CHECK-NEXT: tail call void @ptrarg.2(ptr [[PTR:%.*]], i32 10)55; CHECK-NEXT: ret void56;57 tail call void @ptrarg.2(ptr %ptr, i32 10)58 ret void59}60 61 62; Here the pointer argument %arg will be replaced by a constant. We need to63; drop inaccessiblemem_or_argmemonly.64define internal void @ptrarg.3(ptr %arg, i32 %val) inaccessiblemem_or_argmemonly nounwind {65; CHECK: Function Attrs: nounwind memory(readwrite, target_mem0: none, target_mem1: none)66; CHECK-LABEL: @ptrarg.3(67; CHECK-NEXT: store i32 10, ptr @g, align 468; CHECK-NEXT: ret void69;70 store i32 %val, ptr %arg71 ret void72}73 74define i32 @caller.3(i32 %n) {75; CHECK-LABEL: @caller.3(76; CHECK-NEXT: store i32 1, ptr @g, align 477; CHECK-NEXT: tail call void @ptrarg.3(ptr @g, i32 10)78; CHECK-NEXT: [[G_VAL:%.*]] = load i32, ptr @g, align 479; CHECK-NEXT: ret i32 [[G_VAL]]80;81 store i32 1, ptr @g82 tail call void @ptrarg.3(ptr @g, i32 10)83 %g.val = load i32, ptr @g84 ret i32 %g.val85}86 87 88; Here only the non-pointer argument %val is replaced, no need89; to drop the inaccessiblemem_or_argmemonly attribute.90define internal void @ptrarg.4(ptr %arg, i32 %val) inaccessiblemem_or_argmemonly nounwind {91; CHECK: Function Attrs: nounwind memory(argmem: readwrite, inaccessiblemem: readwrite)92; CHECK-LABEL: @ptrarg.4(93; CHECK-NEXT: store i32 10, ptr [[ARG:%.*]], align 494; CHECK-NEXT: ret void95;96 store i32 %val, ptr %arg97 ret void98}99 100define void @caller.4(ptr %ptr) {101; CHECK-LABEL: @caller.4(102; CHECK-NEXT: tail call void @ptrarg.4(ptr [[PTR:%.*]], i32 10)103; CHECK-NEXT: ret void104;105 tail call void @ptrarg.4(ptr %ptr, i32 10)106 ret void107}108 109 110; Here the pointer argument %arg will be replaced by a constant. We need to111; drop inaccessiblemem_or_argmemonly.112define internal void @ptrarg.5(ptr %arg, i32 %val) argmemonly inaccessiblemem_or_argmemonly nounwind {113; CHECK: Function Attrs: nounwind memory(readwrite, inaccessiblemem: none, target_mem0: none, target_mem1: none)114; CHECK-LABEL: @ptrarg.5(115; CHECK-NEXT: store i32 10, ptr @g, align 4116; CHECK-NEXT: ret void117;118 store i32 %val, ptr %arg119 ret void120}121 122define i32 @caller.5(i32 %n) {123; CHECK-LABEL: @caller.5(124; CHECK-NEXT: store i32 1, ptr @g, align 4125; CHECK-NEXT: tail call void @ptrarg.5(ptr @g, i32 10)126; CHECK-NEXT: [[G_VAL:%.*]] = load i32, ptr @g, align 4127; CHECK-NEXT: ret i32 [[G_VAL]]128;129 store i32 1, ptr @g130 tail call void @ptrarg.5(ptr @g, i32 10)131 %g.val = load i32, ptr @g132 ret i32 %g.val133}134 135 136; Make sure callsite attributes are also dropped when a pointer argument is137; replaced.138define internal void @ptrarg.6.cs.attributes(ptr %arg, i32 %val) {139; CHECK-LABEL: @ptrarg.6.cs.attributes(140; CHECK-NEXT: unreachable141;142 store i32 %val, ptr %arg143 ret void144}145 146define i32 @caller.6.cs.attributes(i32 %n) {147; CHECK-LABEL: @caller.6.cs.attributes(148; CHECK-NEXT: store i32 1, ptr @g, align 4149; CHECK-NEXT: tail call void @ptrarg.5(ptr @g, i32 10) #[[ATTR0:[0-9]+]]150; CHECK-NEXT: tail call void @ptrarg.5(ptr @g, i32 10) #[[ATTR2:[0-9]+]]151; CHECK-NEXT: tail call void @ptrarg.5(ptr @g, i32 10) #[[ATTR0]]152; CHECK-NEXT: tail call void @ptrarg.5(ptr @g, i32 10) #[[ATTR4:[0-9]+]]153; CHECK-NEXT: [[G_VAL:%.*]] = load i32, ptr @g, align 4154; CHECK-NEXT: ret i32 [[G_VAL]]155;156 store i32 1, ptr @g157 tail call void @ptrarg.5(ptr @g, i32 10) argmemonly inaccessiblemem_or_argmemonly nounwind158 tail call void @ptrarg.5(ptr @g, i32 10) inaccessiblemem_or_argmemonly nounwind159 tail call void @ptrarg.5(ptr @g, i32 10) argmemonly nounwind160 tail call void @ptrarg.5(ptr @g, i32 10) nounwind161 %g.val = load i32, ptr @g162 ret i32 %g.val163}164 165;.166; CHECK: attributes #[[ATTR0]] = { nounwind memory(readwrite, inaccessiblemem: none, target_mem0: none, target_mem1: none) }167; CHECK: attributes #[[ATTR1:[0-9]+]] = { nounwind memory(argmem: readwrite) }168; CHECK: attributes #[[ATTR2]] = { nounwind memory(readwrite, target_mem0: none, target_mem1: none) }169; CHECK: attributes #[[ATTR3:[0-9]+]] = { nounwind memory(argmem: readwrite, inaccessiblemem: readwrite) }170; CHECK: attributes #[[ATTR4]] = { nounwind }171;.172